Bladeren bron

Adds gui3DProjectionCtrl so a gui control can be tracked to a point in 3d space

Areloch 6 jaren geleden
bovenliggende
commit
0760f35da0
2 gewijzigde bestanden met toevoegingen van 375 en 0 verwijderingen
  1. 298 0
      Engine/source/gui/controls/gui3DProjectionCtrl.cpp
  2. 77 0
      Engine/source/gui/controls/gui3DProjectionCtrl.h

+ 298 - 0
Engine/source/gui/controls/gui3DProjectionCtrl.cpp

@@ -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 - 0
Engine/source/gui/controls/gui3DProjectionCtrl.h

@@ -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_