mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-05 05:07:48 +00:00
GEEKING
This commit is contained in:
@@ -0,0 +1,450 @@
|
||||
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Tool/DragUtilities.h"
|
||||
#include "Tool/Dragger.h"
|
||||
#include "V8DataModel/PartInstance.h"
|
||||
#include "V8DataModel/Workspace.h"
|
||||
#include "V8DataModel/MouseCommand.h"
|
||||
#include "V8World/ContactManager.h"
|
||||
#include "V8World/Primitive.h"
|
||||
#include "V8World/World.h"
|
||||
#include "V8World/Tolerance.h"
|
||||
#include "Tool/ToolsArrow.h"
|
||||
|
||||
namespace RBX {
|
||||
|
||||
|
||||
Vector3 DragUtilities::safeMoveYDrop(const PartArray& parts, const Vector3& tryDrag, ContactManager& contactManager, const float customPlaneHeight)
|
||||
{
|
||||
G3D::Array<Primitive*> primitives;
|
||||
DragUtilities::partsToPrimitives(parts, primitives);
|
||||
RBXASSERT(primitives.size() > 0);
|
||||
|
||||
Vector3 answer = Dragger::safeMoveYDrop(primitives, tryDrag, contactManager, customPlaneHeight);
|
||||
RBXASSERT(!contactManager.intersectingOthers(primitives, Tolerance::maxOverlapOrGap()));
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vector3 DragUtilities::hitObjectOrPlane(const PartArray& parts, const RbxRay& unitMouseRay, const ContactManager& contactManager, bool snapToGrid)
|
||||
{
|
||||
Vector3 hit;
|
||||
std::vector<const Primitive*> primitives;
|
||||
partsToPrimitives(parts, primitives);
|
||||
hitObjectOrPlane( contactManager,
|
||||
unitMouseRay,
|
||||
primitives,
|
||||
hit,
|
||||
snapToGrid);
|
||||
return hit;
|
||||
}
|
||||
|
||||
bool DragUtilities::hitObject(const PartArray& parts, const RbxRay& unitMouseRay, const ContactManager& contactManager, Vector3& hit, bool snapToGrid)
|
||||
{
|
||||
std::vector<const Primitive*> primitives;
|
||||
partsToPrimitives(parts, primitives);
|
||||
return hitObject(contactManager, unitMouseRay, primitives, hit, snapToGrid);
|
||||
}
|
||||
|
||||
|
||||
bool DragUtilities::anyPartAlive(const PartArray& parts)
|
||||
{
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
if (PartInstance::nonNullInWorkspace(parts[i].lock())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
World* DragUtilities::partsToPrimitives(const PartArray& parts, G3D::Array<Primitive*>& primitives)
|
||||
{
|
||||
RBXASSERT(primitives.size() == 0);
|
||||
World* answer = NULL;
|
||||
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
const shared_ptr<PartInstance>& part = parts[i].lock();
|
||||
if (PartInstance::nonNullInWorkspace(part)) {
|
||||
primitives.append(part->getPartPrimitive());
|
||||
answer = answer ? answer : Workspace::getWorldIfInWorkspace(part.get());
|
||||
RBXASSERT(answer);
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
void DragUtilities::partsToPrimitives(const PartArray& parts, std::vector<const Primitive*>& primitives)
|
||||
{
|
||||
RBXASSERT(primitives.size() == 0);
|
||||
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
const shared_ptr<PartInstance>& part = parts[i].lock();
|
||||
if (PartInstance::nonNullInWorkspace(part)) {
|
||||
primitives.push_back(part->getPartPrimitive());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DragUtilities::partsToPrimitives(const PartArray& parts, std::vector<Primitive*>& primitives)
|
||||
{
|
||||
RBXASSERT(primitives.size() == 0);
|
||||
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
const shared_ptr<PartInstance>& part = parts[i].lock();
|
||||
if (PartInstance::nonNullInWorkspace(part)) {
|
||||
primitives.push_back(part->getPartPrimitive());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DragUtilities::pvsToParts(const std::vector<PVInstance*>& pvInstances, PartArray& parts)
|
||||
{
|
||||
for (size_t i = 0; i < pvInstances.size(); ++i) {
|
||||
PartInstance::findParts(pvInstances[i], parts);
|
||||
}
|
||||
|
||||
removeDuplicateParts(parts);
|
||||
}
|
||||
|
||||
void DragUtilities::instancesToParts(const std::vector<Instance*>& instances, PartArray& parts)
|
||||
{
|
||||
for (size_t i = 0; i < instances.size(); ++i) {
|
||||
PartInstance::findParts(instances[i], parts);
|
||||
}
|
||||
|
||||
removeDuplicateParts(parts);
|
||||
}
|
||||
|
||||
void DragUtilities::instancesToParts(const Instances& instances, PartArray& parts)
|
||||
{
|
||||
for (size_t i = 0; i < instances.size(); ++i)
|
||||
PartInstance::findParts(instances[i].get(), parts);
|
||||
|
||||
removeDuplicateParts(parts);
|
||||
}
|
||||
|
||||
void DragUtilities::removeDuplicateParts(PartArray& parts)
|
||||
{
|
||||
if (parts.size() > 1)
|
||||
{
|
||||
// create a set, as per different results on web inserting manually seems to be more efficient as compared to creating via constructor
|
||||
std::set<weak_ptr<PartInstance> > tempParts;
|
||||
for (size_t i = 0; i < parts.size(); ++i)
|
||||
tempParts.insert(parts[i]);
|
||||
parts.assign(tempParts.begin(), tempParts.end());
|
||||
}
|
||||
}
|
||||
|
||||
bool DragUtilities::notJoined(const PartArray& parts)
|
||||
{
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
const shared_ptr<PartInstance>& part = parts[i].lock();
|
||||
if (PartInstance::nonNullInWorkspace(part)) {
|
||||
if (part->getPartPrimitive()->hasAutoJoints()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DragUtilities::notJoinedToOutsiders(const PartArray& parts)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void DragUtilities::unJoinFromOutsiders(const PartArray& parts)
|
||||
{
|
||||
G3D::Array<Primitive*> primitives;
|
||||
World* world = partsToPrimitives(parts, primitives);
|
||||
if (world) {
|
||||
world->destroyAutoJointsToWorld(primitives);
|
||||
}
|
||||
|
||||
RBXASSERT(notJoinedToOutsiders(parts));
|
||||
}
|
||||
|
||||
|
||||
void DragUtilities::joinToOutsiders(const PartArray& parts)
|
||||
{
|
||||
if (!AdvArrowTool::advCreateJointsMode)
|
||||
return;
|
||||
|
||||
G3D::Array<Primitive*> primitives;
|
||||
World* world = partsToPrimitives(parts, primitives);
|
||||
if (world) {
|
||||
world->createAutoJointsToWorld(primitives);
|
||||
}
|
||||
|
||||
RBXASSERT(notJoinedToOutsiders(parts));
|
||||
}
|
||||
|
||||
void DragUtilities::unJoin(const PartArray& parts)
|
||||
{
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
const shared_ptr<PartInstance>& part = parts[i].lock();
|
||||
if (PartInstance::nonNullInWorkspace(part)) {
|
||||
part->destroyJoints();
|
||||
}
|
||||
}
|
||||
RBXASSERT(notJoined(parts));
|
||||
}
|
||||
|
||||
void DragUtilities::join(const PartArray& parts)
|
||||
{
|
||||
if (!AdvArrowTool::advCreateJointsMode)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
const shared_ptr<PartInstance>& part = parts[i].lock();
|
||||
if (PartInstance::nonNullInWorkspace(part)) {
|
||||
part->join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DragUtilities::joinWithInPartsOnly(const PartArray& parts)
|
||||
{
|
||||
if (!AdvArrowTool::advCreateJointsMode)
|
||||
return;
|
||||
|
||||
G3D::Array<Primitive*> primitives;
|
||||
World* world = partsToPrimitives(parts, primitives);
|
||||
if (world) {
|
||||
world->createAutoJointsToPrimitives(primitives);
|
||||
}
|
||||
}
|
||||
|
||||
void DragUtilities::setDragging(const PartArray& parts)
|
||||
{
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
const shared_ptr<PartInstance>& part = parts[i].lock();
|
||||
if (PartInstance::nonNullInWorkspace(part)) {
|
||||
part->setDragging(true);
|
||||
part->setNetworkIsSleeping(false); // twiddle this bit - I'm dragging client side
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DragUtilities::stopDragging(const PartArray& parts)
|
||||
{
|
||||
|
||||
for (size_t i = 0; i < parts.size(); ++i) {
|
||||
const shared_ptr<PartInstance>& part = parts[i].lock();
|
||||
if (PartInstance::nonNullInWorkspace(part)) {
|
||||
part->setDragging(false);
|
||||
if (parts.size() == 1) {
|
||||
part->setLinearVelocity(Vector3::zero());
|
||||
part->setRotationalVelocity(Vector3::zero());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DragUtilities::alignToGrid(PartInstance* part)
|
||||
{
|
||||
const CoordinateFrame& partCoord = part->getCoordinateFrame();
|
||||
CoordinateFrame alignedCoord = Math::snapToGrid(partCoord, Tolerance::mainGrid());
|
||||
if (alignedCoord != partCoord)
|
||||
{
|
||||
part->setCoordinateFrame(alignedCoord);
|
||||
}
|
||||
}
|
||||
|
||||
static float fRound(float a,int precision)
|
||||
{ return (a > 0.f) ? ceil(a*precision - 0.5f)/precision : floor(a*precision + 0.5f)/precision; }
|
||||
|
||||
void DragUtilities::moveByDelta(PartInstance* part, const Vector3& delta, bool snapToWorld)
|
||||
{
|
||||
CoordinateFrame coord = part->getCoordinateFrame();
|
||||
coord.translation += delta;
|
||||
// try correcting floating point issues
|
||||
coord.translation.x = fRound(coord.translation.x, 1e+6f);
|
||||
coord.translation.y = fRound(coord.translation.y, 1e+6f);
|
||||
coord.translation.z = fRound(coord.translation.z, 1e+6f);
|
||||
part->setCoordinateFrame(coord);
|
||||
}
|
||||
|
||||
|
||||
void DragUtilities::clean(PartInstance* part)
|
||||
{
|
||||
if (part->aligned()) {
|
||||
alignToGrid(part);
|
||||
}
|
||||
}
|
||||
|
||||
void DragUtilities::clean(const PartArray& parts)
|
||||
{
|
||||
// Only clean single parts. Multiple parts should
|
||||
// stick together when moving.
|
||||
if (parts.size() == 1)
|
||||
{
|
||||
const shared_ptr<PartInstance>& part = parts[0].lock();
|
||||
if (part.get())
|
||||
{
|
||||
clean(part.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DragUtilities::move(const PartArray& parts,
|
||||
CoordinateFrame from,
|
||||
CoordinateFrame to)
|
||||
{
|
||||
for (size_t i = 0; i < parts.size(); ++i)
|
||||
{
|
||||
const shared_ptr<PartInstance>& part = parts[i].lock();
|
||||
if (part.get())
|
||||
{
|
||||
CoordinateFrame meInFrom = from.toObjectSpace(part->getCoordinateFrame());
|
||||
Math::orthonormalizeIfNecessary(meInFrom.rotation);
|
||||
part->setCoordinateFrame(to * meInFrom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// same as ::move, but without orthonormalize
|
||||
void DragUtilities::move2(const PartArray& parts,
|
||||
CoordinateFrame from,
|
||||
CoordinateFrame to)
|
||||
{
|
||||
for (size_t i = 0; i < parts.size(); ++i)
|
||||
{
|
||||
const shared_ptr<PartInstance>& part = parts[i].lock();
|
||||
if (part.get())
|
||||
{
|
||||
CoordinateFrame meInFrom = from.toObjectSpace(part->getCoordinateFrame());
|
||||
//Math::orthonormalizeIfNecessary(meInFrom.rotation);
|
||||
part->setCoordinateFrame(to * meInFrom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DragUtilities::hitObjectOrPlane(const ContactManager& contactManager,
|
||||
const RbxRay& unitSearchRay,
|
||||
const std::vector<const Primitive*>& ignorePrims,
|
||||
Vector3& hit,
|
||||
bool snapToGrid)
|
||||
{
|
||||
RBXASSERT(unitSearchRay.direction().isUnit());
|
||||
RbxRay searchRay = MouseCommand::getSearchRay(unitSearchRay); // length determines how far to search;
|
||||
|
||||
if (!contactManager.getHit( searchRay,
|
||||
&ignorePrims,
|
||||
NULL,
|
||||
hit))
|
||||
{
|
||||
if (!Math::intersectRayPlane(searchRay, Plane(Vector3::unitY(), Vector3::zero()), hit)) {
|
||||
hit = Vector3::zero();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if( snapToGrid )
|
||||
hit = DragUtilities::toGrid(hit);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DragUtilities::hitObject( const ContactManager& contactManager,
|
||||
const RbxRay& unitSearchRay,
|
||||
const std::vector<const Primitive*>& ignorePrims,
|
||||
Vector3& hit,
|
||||
bool snapToGrid)
|
||||
{
|
||||
RBXASSERT(unitSearchRay.direction().isUnit());
|
||||
RbxRay searchRay = MouseCommand::getSearchRay(unitSearchRay); // length determines how far to search;
|
||||
|
||||
if (!contactManager.getHit( searchRay,
|
||||
&ignorePrims,
|
||||
NULL,
|
||||
hit))
|
||||
return false;
|
||||
|
||||
if( snapToGrid )
|
||||
hit = DragUtilities::toGrid(hit);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Extents DragUtilities::computeExtents(const PartArray& parts)
|
||||
{
|
||||
G3D::Array<Primitive*> primitives;
|
||||
partsToPrimitives(parts, primitives);
|
||||
|
||||
return Dragger::computeExtents(primitives);
|
||||
}
|
||||
|
||||
|
||||
void DragUtilities::getPrimitives(const Instance* instance, std::vector<Primitive*>& primitives)
|
||||
{
|
||||
// TODO: This cast blows. We should refactor getPrimitives to use back_insert_iterator or a for_each pattern...
|
||||
std::vector<const Primitive*>& constPrimitives = reinterpret_cast<std::vector<const Primitive*>&>(primitives);
|
||||
getPrimitivesConst(instance, constPrimitives);
|
||||
}
|
||||
|
||||
void DragUtilities::getPrimitivesConst(const Instance* instance, std::vector<const Primitive*>& primitives)
|
||||
{
|
||||
const PartInstance* part = Instance::fastDynamicCast<PartInstance>(instance);
|
||||
if ( part && part->getDragUtilitiesSupport() ) {
|
||||
primitives.push_back(part->getConstPartPrimitive());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < instance->numChildren(); i++) {
|
||||
getPrimitivesConst(instance->getChild(i), primitives);
|
||||
}
|
||||
}
|
||||
Vector3 DragUtilities::toGrid(const Vector3 &point, const Vector3& grid)
|
||||
{
|
||||
if (grid != Vector3::zero())
|
||||
return Math::toGrid(point, grid);
|
||||
|
||||
return Math::toGrid(point, getGrid());
|
||||
}
|
||||
|
||||
Vector3 DragUtilities::getGrid()
|
||||
{
|
||||
static Vector3 v1(1.0f, 1.0f, 1.0f);
|
||||
static Vector3 v2(0.20f, 0.20f, 0.20f);
|
||||
static Vector3 v3(Tolerance::maxOverlapOrGap(), Tolerance::maxOverlapOrGap(), Tolerance::maxOverlapOrGap());
|
||||
|
||||
if (AdvArrowToolBase::advGridMode == DRAG::ONE_STUD)
|
||||
return v1;
|
||||
|
||||
if (AdvArrowToolBase::advGridMode == DRAG::QUARTER_STUD)
|
||||
return v2;
|
||||
|
||||
if (AdvArrowToolBase::advGridMode == DRAG::OFF)
|
||||
return v3;
|
||||
|
||||
return v3;
|
||||
}
|
||||
|
||||
Vector3 DragUtilities::toLocalGrid(const Vector3& deltaIn)
|
||||
{
|
||||
if (AdvArrowToolBase::advGridMode == DRAG::OFF)
|
||||
return deltaIn;
|
||||
|
||||
Vector3 delta = deltaIn;
|
||||
float length = delta.length();
|
||||
|
||||
delta.unitize();
|
||||
|
||||
// We assume that grid is uniform for now.
|
||||
RBXASSERT(DragUtilities::getGrid().x == DragUtilities::getGrid().y &&
|
||||
DragUtilities::getGrid().y == DragUtilities::getGrid().z &&
|
||||
DragUtilities::getGrid().z == DragUtilities::getGrid().x);
|
||||
|
||||
float gridSize = DragUtilities::getGrid().x;
|
||||
length = length / gridSize;
|
||||
length = ((float)Math::iRound(length)) * gridSize;
|
||||
delta = delta * length;
|
||||
return delta;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user