mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-04 20:57:49 +00:00
187 lines
5.2 KiB
C++
187 lines
5.2 KiB
C++
/* Copyright 2003-2009 ROBLOX Corporation, All Rights Reserved */
|
|
#include "stdafx.h"
|
|
|
|
#include "V8DataModel/HandlesBase.h"
|
|
#include "V8World/Primitive.h"
|
|
#include "V8DataModel/Workspace.h"
|
|
#include "V8DataModel/PartInstance.h"
|
|
#include "V8DataModel/MouseCommand.h"
|
|
#include "Network/Players.h"
|
|
#include "AppDraw/DrawAdorn.h"
|
|
#include "Util/HitTest.h"
|
|
|
|
namespace RBX {
|
|
|
|
const char* const sHandlesBase = "HandlesBase";
|
|
|
|
HandlesBase::HandlesBase(const char* name)
|
|
: DescribedNonCreatable<HandlesBase, PartAdornment, sHandlesBase>(name)
|
|
, mouseOver(NORM_UNDEFINED)
|
|
, serverGuiObject(false)
|
|
{
|
|
}
|
|
|
|
bool HandlesBase::findTargetHandle(const shared_ptr<InputObject>& inputObject, Vector3& hitPointWorld, NormalId& hitNormalId)
|
|
{
|
|
if (PartInstance* part = adornee.lock().get()) {
|
|
Workspace *workspace = Workspace::findWorkspace(this);
|
|
if(!workspace) return false;
|
|
|
|
RbxRay gridRay(MouseCommand::getUnitMouseRay(inputObject,workspace));
|
|
if (HandleHitTest::hitTestHandleLocal( part->getPartPrimitive()->getExtentsLocal(),
|
|
part->getLocation(),
|
|
getHandleType(),
|
|
gridRay,
|
|
hitPointWorld,
|
|
hitNormalId,
|
|
getHandlesNormalIdMask()))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool HandlesBase::getDistanceFromHandle(const shared_ptr<InputObject>& inputObject, NormalId localNormalId, const Vector3& hitPointWorld, float& distance)
|
|
{
|
|
if (PartInstance* part = adornee.lock().get()) {
|
|
Workspace *workspace = Workspace::findWorkspace(this);
|
|
if(!workspace) return false;
|
|
|
|
Vector3 worldNormal = Math::getWorldNormal(localNormalId, part->getLocation());
|
|
RbxRay axisRay = RBX::RbxRay::fromOriginAndDirection(hitPointWorld, worldNormal);
|
|
RbxRay gridRay = MouseCommand::getUnitMouseRay(inputObject,workspace);
|
|
Vector3 closePoint = RBX::Math::closestPointOnRay(axisRay, gridRay);
|
|
Vector3 handleToCurrent = closePoint - hitPointWorld;
|
|
distance = axisRay.direction().dot(handleToCurrent);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool HandlesBase::getFacePosFromHandle(const shared_ptr<InputObject>& inputObject, NormalId faceId, const Vector3& hitPointWorld, Vector2& relativePos, Vector2& absolutePos)
|
|
{
|
|
if (PartInstance* part = adornee.lock().get()) {
|
|
Workspace *workspace = Workspace::findWorkspace(this);
|
|
if(!workspace) return false;
|
|
|
|
Vector3 worldNormal = Math::getWorldNormal(faceId, part->getLocation());
|
|
Plane facePlaneWorld(worldNormal, hitPointWorld);
|
|
RbxRay gridRay = MouseCommand::getUnitMouseRay(inputObject,workspace);
|
|
Vector3 intersectWorld = gridRay.intersectionPlane(facePlaneWorld); // note - subtle change made to intersection with plane code 2/15/10 DB
|
|
if(!intersectWorld.isFinite())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Vector3 intersectObject = part->getLocation().pointToObjectSpace(intersectWorld);
|
|
Vector3 intersectFace = objectToUvw(intersectObject, faceId);
|
|
|
|
Vector3 hitPointObject = part->getLocation().pointToObjectSpace(hitPointWorld);
|
|
Vector3 hitPointFace = objectToUvw(hitPointObject, faceId);
|
|
|
|
relativePos = (intersectFace - hitPointFace).xy();
|
|
absolutePos = intersectFace.xy();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool HandlesBase::getAngleRadiusFromHandle(const shared_ptr<InputObject>& inputObject, NormalId faceId, const Vector3& hitPointWorld, float& angle, float& radius, float& absangle, float& absradius)
|
|
{
|
|
Vector2 relpos;
|
|
Vector2 abspos;
|
|
if(getFacePosFromHandle(inputObject, faceId, hitPointWorld, relpos, abspos))
|
|
{
|
|
Vector2 origpos = abspos-relpos;
|
|
|
|
absradius = abspos.length();
|
|
absangle = 0;
|
|
if(std::abs(absradius) > 0.00001)
|
|
{
|
|
absangle = atan2(abspos.y, abspos.x);
|
|
}
|
|
|
|
float origradius = origpos.length();
|
|
float origangle = 0;
|
|
if(std::abs(origradius) > 0.00001)
|
|
{
|
|
origangle = atan2(origpos.y, origpos.x);
|
|
}
|
|
|
|
angle = absangle-origangle;
|
|
radius = absradius-origradius;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
bool HandlesBase::canProcessMeAndDescendants() const
|
|
{
|
|
return (adornee.lock()) && (getHandlesNormalIdMask() != NORM_NONE_MASK) && getVisible();
|
|
}
|
|
|
|
void HandlesBase::render2d(Adorn* adorn)
|
|
{
|
|
Workspace* workspace = Workspace::findWorkspace(this);
|
|
shared_ptr<PartInstance> part = adornee.lock();
|
|
|
|
if(part){
|
|
DrawAdorn::handles2d(
|
|
part->getPartSizeXml(),
|
|
part->getCoordinateFrame(),
|
|
*(workspace->getConstCamera()),
|
|
adorn,
|
|
getHandleType(),
|
|
color,
|
|
false,
|
|
getHandlesNormalIdMask());
|
|
}
|
|
}
|
|
|
|
void HandlesBase::render3dAdorn(Adorn* adorn)
|
|
{
|
|
Workspace* workspace = Workspace::findWorkspace(this);
|
|
shared_ptr<PartInstance> part = adornee.lock();
|
|
NormalId highlightedNormalId = mouseOver;
|
|
|
|
if (mouseDownCaptureInfo &&
|
|
mouseDownCaptureInfo->hitNormalId != NORM_UNDEFINED)
|
|
{
|
|
highlightedNormalId = mouseDownCaptureInfo->hitNormalId;
|
|
}
|
|
|
|
if(part){
|
|
RBX::DrawAdorn::handles3d(
|
|
part->getPartSizeXml(),
|
|
part->getCoordinateFrame(),
|
|
adorn,
|
|
getHandleType(),
|
|
workspace->getConstCamera()->coordinateFrame().translation,
|
|
color,
|
|
getHandleType() == HANDLE_ROTATE,
|
|
getHandlesNormalIdMask(),
|
|
highlightedNormalId);
|
|
}
|
|
}
|
|
|
|
void HandlesBase::setServerGuiObject()
|
|
{
|
|
serverGuiObject = true;
|
|
}
|
|
|
|
void HandlesBase::onAncestorChanged(const AncestorChanged& event)
|
|
{
|
|
Super::onAncestorChanged(event);
|
|
|
|
if(!serverGuiObject && Network::Players::serverIsPresent(this,false)){
|
|
setServerGuiObject();
|
|
}
|
|
}
|
|
|
|
}
|