mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-13 15:44:36 +00:00
Adds gui3DProjectionCtrl so a gui control can be tracked to a point in 3d space
This commit is contained in:
parent
775ca57047
commit
0760f35da0
2 changed files with 375 additions and 0 deletions
298
Engine/source/gui/controls/gui3DProjectionCtrl.cpp
Normal file
298
Engine/source/gui/controls/gui3DProjectionCtrl.cpp
Normal file
|
|
@ -0,0 +1,298 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Gui3DProjectionCtrl
|
||||||
|
// Doppelganger Inc
|
||||||
|
// Orion Elenzil 200701
|
||||||
|
//
|
||||||
|
// This control is meant to be merely a container for other controls.
|
||||||
|
// What's neat is that it's easy to 'attach' this control to a point in world-space
|
||||||
|
// or, more interestingly, to an object such as a player.
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// * Create the Gui3DProjectionControl - by default it will be at 0, 0, 0.
|
||||||
|
// * You can change where it's located by setting the field "offsetWorld".
|
||||||
|
// - note you can specify that right in the .gui file
|
||||||
|
// * You can attach it to any SceneObject by calling "setAttachedTo()".
|
||||||
|
//
|
||||||
|
// Behaviour:
|
||||||
|
// * If you're attaching it to a player, by default it will center on the player's head.
|
||||||
|
// * If you attach it to an object, by default it will delete itself if the object is deleted.
|
||||||
|
// * Doesn't occlude w/r/t 3D objects.
|
||||||
|
//
|
||||||
|
// Console Methods:
|
||||||
|
// * SetAttachedTo(SceneObject)
|
||||||
|
// * GetAttachedTo()
|
||||||
|
//
|
||||||
|
// Params:
|
||||||
|
// * pointWorld - read/write point in worldspace. read-only if attached to an object.
|
||||||
|
// * offsetObject - an offset in objectspace. default 0, 0, 0.
|
||||||
|
// * offsetWorld - an offset in worldspace. default 0, 0, 0.
|
||||||
|
// * offsetScreen - an offset in screenspace. default 0, 0.
|
||||||
|
// * hAlign - horizontal alignment. 0 = left, 1 = center, 2 = right. default center.
|
||||||
|
// * vAlign - vertical alignment. 0 = top, 1 = center, 2 = bottomt. default center.
|
||||||
|
// * useEyePoint - H & V usage of the eyePoint, if player object. default 0, 1. (ie - use only the vertical component)
|
||||||
|
// * autoDelete - self-delete when attachedTo object is deleted. default true.
|
||||||
|
//
|
||||||
|
// Todo:
|
||||||
|
// * occlusion - hide the control when its anchor point is occluded.
|
||||||
|
// * integrate w/ zbuffer - this would actually be a change to the whole GuiControl system.
|
||||||
|
// * allow attaching to arbitrary nodes in a skeleton.
|
||||||
|
// * avoid projection when the object is out of the frustum.
|
||||||
|
//
|
||||||
|
// oxe 20070111
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "console/console.h"
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
#include "scene/SceneObject.h"
|
||||||
|
#include "T3D/player.h"
|
||||||
|
#include "gui/controls/Gui3DProjectionCtrl.h"
|
||||||
|
|
||||||
|
IMPLEMENT_CONOBJECT(Gui3DProjectionCtrl);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Gui3DProjectionCtrl::Gui3DProjectionCtrl()
|
||||||
|
{
|
||||||
|
mTSCtrl = NULL;
|
||||||
|
mAttachedTo = NULL;
|
||||||
|
mAttachedToPlayer = NULL;
|
||||||
|
mAutoDelete = true;
|
||||||
|
mHAlign = center;
|
||||||
|
mVAlign = center;
|
||||||
|
mUseEyePoint.x = 0;
|
||||||
|
mUseEyePoint.y = 1;
|
||||||
|
|
||||||
|
mPtWorld .set(0, 0, 0);
|
||||||
|
mPtProj .set(0, 0);
|
||||||
|
mOffsetObject.set(0, 0, 0);
|
||||||
|
mOffsetWorld .set(0, 0, 0);
|
||||||
|
mOffsetScreen.set(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gui3DProjectionCtrl::initPersistFields()
|
||||||
|
{
|
||||||
|
Parent::initPersistFields();
|
||||||
|
addGroup("3DProjection");
|
||||||
|
addField("pointWorld" , TypePoint3F , Offset(mPtWorld , Gui3DProjectionCtrl));
|
||||||
|
addField("offsetObject" , TypePoint3F , Offset(mOffsetObject , Gui3DProjectionCtrl));
|
||||||
|
addField("offsetWorld" , TypePoint3F , Offset(mOffsetWorld , Gui3DProjectionCtrl));
|
||||||
|
addField("offsetScreen" , TypePoint2I , Offset(mOffsetScreen , Gui3DProjectionCtrl));
|
||||||
|
addField("hAlign" , TypeS32 , Offset(mHAlign , Gui3DProjectionCtrl));
|
||||||
|
addField("vAlign" , TypeS32 , Offset(mVAlign , Gui3DProjectionCtrl));
|
||||||
|
addField("useEyePoint" , TypePoint2I , Offset(mUseEyePoint , Gui3DProjectionCtrl));
|
||||||
|
addField("autoDelete" , TypeBool , Offset(mAutoDelete , Gui3DProjectionCtrl));
|
||||||
|
endGroup("3DProjection");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gui3DProjectionCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||||
|
{
|
||||||
|
doPositioning();
|
||||||
|
doProjection();
|
||||||
|
doAlignment();
|
||||||
|
|
||||||
|
Parent::onRender(offset, updateRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gui3DProjectionCtrl::resizeDuringRender()
|
||||||
|
{
|
||||||
|
doPositioning();
|
||||||
|
doProjection ();
|
||||||
|
doAlignment ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool Gui3DProjectionCtrl::onWake()
|
||||||
|
{
|
||||||
|
// walk up the GUI tree until we find a GuiTSCtrl.
|
||||||
|
|
||||||
|
mTSCtrl = NULL;
|
||||||
|
GuiControl* walkCtrl = getParent();
|
||||||
|
AssertFatal(walkCtrl != NULL, "Gui3DProjectionCtrl::onWake() - NULL parent");
|
||||||
|
bool doMore = true;
|
||||||
|
|
||||||
|
while (doMore)
|
||||||
|
{
|
||||||
|
mTSCtrl = dynamic_cast<GuiTSCtrl*>(walkCtrl);
|
||||||
|
walkCtrl = walkCtrl->getParent();
|
||||||
|
doMore = (mTSCtrl == NULL) && (walkCtrl != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mTSCtrl)
|
||||||
|
Con::errorf("Gui3DProjectionCtrl::onWake() - no TSCtrl parent");
|
||||||
|
|
||||||
|
return Parent::onWake();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gui3DProjectionCtrl::onSleep()
|
||||||
|
{
|
||||||
|
mTSCtrl = NULL;
|
||||||
|
return Parent::onSleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gui3DProjectionCtrl::onDeleteNotify(SimObject* obj)
|
||||||
|
{
|
||||||
|
// - SimSet assumes that obj is a member of THIS, which in our case ain't true.
|
||||||
|
// oxe 20070116 - the following doesn't compile on GCC.
|
||||||
|
// SimSet::Parent::onDeleteNotify(obj);
|
||||||
|
|
||||||
|
if (!obj)
|
||||||
|
{
|
||||||
|
Con::warnf("Gui3DProjectionCtrl::onDeleteNotify - got NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj != mAttachedTo)
|
||||||
|
{
|
||||||
|
if (mAttachedTo != NULL)
|
||||||
|
Con::warnf("Gui3DProjectionCtrl::onDeleteNotify - got unexpected object: %d vs. %d", obj->getId(), mAttachedTo->getId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAutoDelete)
|
||||||
|
this->deleteObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Gui3DProjectionCtrl::doPositioning()
|
||||||
|
{
|
||||||
|
if (mAttachedTo == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Point3F ptBase; // the regular position of the object.
|
||||||
|
Point3F ptEye; // the render position of the eye node, if a player object.
|
||||||
|
Point3F pt; // combination of ptBase and ptEye.
|
||||||
|
|
||||||
|
MatrixF mat; // utility
|
||||||
|
|
||||||
|
mAttachedTo->getRenderTransform().getColumn(3, &ptBase);
|
||||||
|
|
||||||
|
if (mAttachedToPlayer != NULL)
|
||||||
|
{
|
||||||
|
mAttachedToPlayer->getRenderEyeTransform(&mat);
|
||||||
|
mat.getColumn(3, &ptEye);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptEye = ptBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use some components from ptEye but other position from ptBase
|
||||||
|
pt = ptBase;
|
||||||
|
if (mUseEyePoint.x != 0)
|
||||||
|
{
|
||||||
|
pt.x = ptEye.x;
|
||||||
|
pt.y = ptEye.y;
|
||||||
|
}
|
||||||
|
if (mUseEyePoint.y != 0)
|
||||||
|
{
|
||||||
|
pt.z = ptEye.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// object-space offset
|
||||||
|
Point3F offsetObj;
|
||||||
|
QuatF quat(mAttachedTo->getRenderTransform());
|
||||||
|
quat.mulP(mOffsetObject, &offsetObj);
|
||||||
|
pt += offsetObj;
|
||||||
|
|
||||||
|
|
||||||
|
// world-space offset
|
||||||
|
pt += mOffsetWorld;
|
||||||
|
|
||||||
|
mPtWorld = pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Gui3DProjectionCtrl::doProjection()
|
||||||
|
{
|
||||||
|
if (!mTSCtrl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Point3F pt;
|
||||||
|
|
||||||
|
if (!mTSCtrl->project(mPtWorld, &pt))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mPtProj.x = (S32)(pt.x + 0.5f);
|
||||||
|
mPtProj.y = (S32)(pt.y + 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gui3DProjectionCtrl::doAlignment()
|
||||||
|
{
|
||||||
|
// alignment
|
||||||
|
Point2I offsetAlign;
|
||||||
|
switch(mHAlign)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case center:
|
||||||
|
offsetAlign.x = -getBounds().extent.x / 2;
|
||||||
|
break;
|
||||||
|
case min:
|
||||||
|
offsetAlign.x = 0;
|
||||||
|
break;
|
||||||
|
case max:
|
||||||
|
offsetAlign.x = -getBounds().extent.x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(mVAlign)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case center:
|
||||||
|
offsetAlign.y = -getBounds().extent.y / 2;
|
||||||
|
break;
|
||||||
|
case min:
|
||||||
|
offsetAlign.y = 0;
|
||||||
|
break;
|
||||||
|
case max:
|
||||||
|
offsetAlign.y = -getBounds().extent.y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// projected point
|
||||||
|
mPtScreen = mPtProj;
|
||||||
|
|
||||||
|
// alignment offset
|
||||||
|
mPtScreen += offsetAlign;
|
||||||
|
|
||||||
|
// screen offset
|
||||||
|
mPtScreen += mOffsetScreen;
|
||||||
|
|
||||||
|
// setTrgPosition(mPtScreen);
|
||||||
|
RectI bounds = getBounds();
|
||||||
|
bounds.point = mPtScreen;
|
||||||
|
setBounds(bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Gui3DProjectionCtrl::setAttachedTo(SceneObject* obj)
|
||||||
|
{
|
||||||
|
if (obj == mAttachedTo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mAttachedTo)
|
||||||
|
clearNotify(mAttachedTo);
|
||||||
|
|
||||||
|
mAttachedTo = obj;
|
||||||
|
mAttachedToPlayer = dynamic_cast<Player*>(obj);
|
||||||
|
|
||||||
|
if (mAttachedTo)
|
||||||
|
deleteNotify(mAttachedTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(Gui3DProjectionCtrl, setAttachedTo, void, (SceneObject* target), (nullAsType<SceneObject*>()), "(object)")
|
||||||
|
{
|
||||||
|
if(target)
|
||||||
|
object->setAttachedTo(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(Gui3DProjectionCtrl, getAttachedTo, S32, (),, "()")
|
||||||
|
{
|
||||||
|
SceneObject* obj = object->getAttachedTo();
|
||||||
|
if (!obj)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return obj->getId();
|
||||||
|
}
|
||||||
77
Engine/source/gui/controls/gui3DProjectionCtrl.h
Normal file
77
Engine/source/gui/controls/gui3DProjectionCtrl.h
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Gui3DProjectionCtrl
|
||||||
|
// Doppelganger Inc
|
||||||
|
// Orion Elenzil 200701
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef _GUI3DPROJECTIONCTRL_H_
|
||||||
|
#define _GUI3DPROJECTIONCTRL_H_
|
||||||
|
|
||||||
|
#include "gui/core/guiTypes.h"
|
||||||
|
#include "gui/core/guiControl.h"
|
||||||
|
#include "gui/3d/guiTSControl.h"
|
||||||
|
#include "scene/sceneObject.h"
|
||||||
|
#include "T3D/player.h"
|
||||||
|
|
||||||
|
class Gui3DProjectionCtrl : public GuiControl
|
||||||
|
{
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// stock stuff
|
||||||
|
public:
|
||||||
|
Gui3DProjectionCtrl();
|
||||||
|
typedef GuiControl Parent;
|
||||||
|
|
||||||
|
DECLARE_CONOBJECT(Gui3DProjectionCtrl);
|
||||||
|
|
||||||
|
static void initPersistFields ();
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// more interesting stuff
|
||||||
|
|
||||||
|
GuiTSCtrl* mTSCtrl; /// must be a child of one of these.
|
||||||
|
SimObjectPtr<SceneObject> mAttachedTo; /// optional object we're attached to.
|
||||||
|
SimObjectPtr<Player> mAttachedToPlayer; /// same pointer as mAttachedTo, but conveniently casted to player.
|
||||||
|
|
||||||
|
Point3F mPtWorld; /// the worldspace point which we're projecting
|
||||||
|
Point2I mPtProj; /// the screenspace projected point. - note there are further modifiers before
|
||||||
|
Point2I mPtScreen;
|
||||||
|
|
||||||
|
Point3F mOffsetObject; /// object-space offset applied first to the attached point to obtain mPtWorld.
|
||||||
|
Point3F mOffsetWorld; /// world-space offset applied second to the attached point to obtain mPtWorld.
|
||||||
|
Point2I mOffsetScreen; /// screen-space offset applied to mPtProj. note we still have centering, etc.
|
||||||
|
|
||||||
|
enum alignment
|
||||||
|
{
|
||||||
|
min = 0,
|
||||||
|
center = 1,
|
||||||
|
max = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
alignment mHAlign; /// horizontal alignment
|
||||||
|
alignment mVAlign; /// horizontal alignment
|
||||||
|
|
||||||
|
bool mAutoDelete; /// optionally self-delete when mAttachedTo is deleted.
|
||||||
|
Point2I mUseEyePoint; /// optionally use the eye point. x != 0 -> horiz. y != 0 -> vert.
|
||||||
|
|
||||||
|
|
||||||
|
virtual void onRender (Point2I offset, const RectI &updateRect);
|
||||||
|
virtual void resizeDuringRender ();
|
||||||
|
|
||||||
|
virtual bool onWake ();
|
||||||
|
virtual void onSleep ();
|
||||||
|
virtual void onDeleteNotify (SimObject *object);
|
||||||
|
|
||||||
|
void doPositioning ();
|
||||||
|
void doProjection ();
|
||||||
|
void doAlignment ();
|
||||||
|
|
||||||
|
void setAttachedTo (SceneObject* obj);
|
||||||
|
SceneObject* getAttachedTo () { return mAttachedTo; }
|
||||||
|
void setWorldPt (Point3F& pt) { mPtWorld = pt; }
|
||||||
|
Point3F getWorldPt () { return mPtWorld; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_GUI3DPROJECTIONCTRL_H_
|
||||||
Loading…
Add table
Add a link
Reference in a new issue