gui3DProjectionCtrl.cpp
Engine/source/gui/controls/gui3DProjectionCtrl.cpp
Public Functions
DefineEngineMethod(Gui3DProjectionCtrl , getAttachedTo , S32 , () , "()" )
DefineEngineMethod(Gui3DProjectionCtrl , setAttachedTo , void , (SceneObject *target) , (nullAsType< SceneObject * >()) , "(object)" )
Detailed Description
Public Functions
DefineEngineMethod(Gui3DProjectionCtrl , getAttachedTo , S32 , () , "()" )
DefineEngineMethod(Gui3DProjectionCtrl , setAttachedTo , void , (SceneObject *target) , (nullAsType< SceneObject * >()) , "(object)" )
IMPLEMENT_CONOBJECT(Gui3DProjectionCtrl )
1 2//----------------------------------------------------------------------------- 3// Gui3DProjectionCtrl 4// Doppelganger Inc 5// Orion Elenzil 200701 6// 7// This control is meant to be merely a container for other controls. 8// What's neat is that it's easy to 'attach' this control to a point in world-space 9// or, more interestingly, to an object such as a player. 10// 11// Usage: 12// * Create the Gui3DProjectionControl - by default it will be at 0, 0, 0. 13// * You can change where it's located by setting the field "offsetWorld". 14// - note you can specify that right in the .gui file 15// * You can attach it to any SceneObject by calling "setAttachedTo()". 16// 17// Behaviour: 18// * If you're attaching it to a player, by default it will center on the player's head. 19// * If you attach it to an object, by default it will delete itself if the object is deleted. 20// * Doesn't occlude w/r/t 3D objects. 21// 22// Console Methods: 23// * SetAttachedTo(SceneObject) 24// * GetAttachedTo() 25// 26// Params: 27// * pointWorld - read/write point in worldspace. read-only if attached to an object. 28// * offsetObject - an offset in objectspace. default 0, 0, 0. 29// * offsetWorld - an offset in worldspace. default 0, 0, 0. 30// * offsetScreen - an offset in screenspace. default 0, 0. 31// * hAlign - horizontal alignment. 0 = left, 1 = center, 2 = right. default center. 32// * vAlign - vertical alignment. 0 = top, 1 = center, 2 = bottomt. default center. 33// * useEyePoint - H & V usage of the eyePoint, if player object. default 0, 1. (ie - use only the vertical component) 34// * autoDelete - self-delete when attachedTo object is deleted. default true. 35// 36// Todo: 37// * occlusion - hide the control when its anchor point is occluded. 38// * integrate w/ zbuffer - this would actually be a change to the whole GuiControl system. 39// * allow attaching to arbitrary nodes in a skeleton. 40// * avoid projection when the object is out of the frustum. 41// 42// oxe 20070111 43//----------------------------------------------------------------------------- 44 45#include "console/console.h" 46#include "console/consoleTypes.h" 47#include "scene/sceneObject.h" 48#include "T3D/player.h" 49#include "gui/controls/gui3DProjectionCtrl.h" 50 51IMPLEMENT_CONOBJECT(Gui3DProjectionCtrl); 52 53//----------------------------------------------------------------------------- 54 55Gui3DProjectionCtrl::Gui3DProjectionCtrl() 56{ 57 mTSCtrl = NULL; 58 mAttachedTo = NULL; 59 mAttachedToPlayer = NULL; 60 mAutoDelete = true; 61 mHAlign = center; 62 mVAlign = center; 63 mUseEyePoint.x = 0; 64 mUseEyePoint.y = 1; 65 66 mPtWorld .set(0, 0, 0); 67 mPtProj .set(0, 0); 68 mOffsetObject.set(0, 0, 0); 69 mOffsetWorld .set(0, 0, 0); 70 mOffsetScreen.set(0, 0); 71} 72 73void Gui3DProjectionCtrl::initPersistFields() 74{ 75 Parent::initPersistFields(); 76 addGroup("3DProjection"); 77 addField("pointWorld" , TypePoint3F , Offset(mPtWorld , Gui3DProjectionCtrl)); 78 addField("offsetObject" , TypePoint3F , Offset(mOffsetObject , Gui3DProjectionCtrl)); 79 addField("offsetWorld" , TypePoint3F , Offset(mOffsetWorld , Gui3DProjectionCtrl)); 80 addField("offsetScreen" , TypePoint2I , Offset(mOffsetScreen , Gui3DProjectionCtrl)); 81 addField("hAlign" , TypeS32 , Offset(mHAlign , Gui3DProjectionCtrl)); 82 addField("vAlign" , TypeS32 , Offset(mVAlign , Gui3DProjectionCtrl)); 83 addField("useEyePoint" , TypePoint2I , Offset(mUseEyePoint , Gui3DProjectionCtrl)); 84 addField("autoDelete" , TypeBool , Offset(mAutoDelete , Gui3DProjectionCtrl)); 85 endGroup("3DProjection"); 86} 87 88void Gui3DProjectionCtrl::onRender(Point2I offset, const RectI &updateRect) 89{ 90 doPositioning(); 91 doProjection(); 92 doAlignment(); 93 94 Parent::onRender(offset, updateRect); 95} 96 97void Gui3DProjectionCtrl::resizeDuringRender() 98{ 99 doPositioning(); 100 doProjection (); 101 doAlignment (); 102} 103 104 105 106bool Gui3DProjectionCtrl::onWake() 107{ 108 // walk up the GUI tree until we find a GuiTSCtrl. 109 110 mTSCtrl = NULL; 111 GuiControl* walkCtrl = getParent(); 112 AssertFatal(walkCtrl != NULL, "Gui3DProjectionCtrl::onWake() - NULL parent"); 113 bool doMore = true; 114 115 while (doMore) 116 { 117 mTSCtrl = dynamic_cast<GuiTSCtrl*>(walkCtrl); 118 walkCtrl = walkCtrl->getParent(); 119 doMore = (mTSCtrl == NULL) && (walkCtrl != NULL); 120 } 121 122 if (!mTSCtrl) 123 Con::errorf("Gui3DProjectionCtrl::onWake() - no TSCtrl parent"); 124 125 return Parent::onWake(); 126} 127 128void Gui3DProjectionCtrl::onSleep() 129{ 130 mTSCtrl = NULL; 131 return Parent::onSleep(); 132} 133 134void Gui3DProjectionCtrl::onDeleteNotify(SimObject* obj) 135{ 136 // - SimSet assumes that obj is a member of THIS, which in our case ain't true. 137 // oxe 20070116 - the following doesn't compile on GCC. 138 // SimSet::Parent::onDeleteNotify(obj); 139 140 if (!obj) 141 { 142 Con::warnf("Gui3DProjectionCtrl::onDeleteNotify - got NULL"); 143 return; 144 } 145 146 if (obj != mAttachedTo) 147 { 148 if (mAttachedTo != NULL) 149 Con::warnf("Gui3DProjectionCtrl::onDeleteNotify - got unexpected object: %d vs. %d", obj->getId(), mAttachedTo->getId()); 150 return; 151 } 152 153 if (mAutoDelete) 154 this->deleteObject(); 155} 156 157//----------------------------------------------------------------------------- 158 159void Gui3DProjectionCtrl::doPositioning() 160{ 161 if (mAttachedTo == NULL) 162 return; 163 164 Point3F ptBase; // the regular position of the object. 165 Point3F ptEye; // the render position of the eye node, if a player object. 166 Point3F pt; // combination of ptBase and ptEye. 167 168 MatrixF mat; // utility 169 170 mAttachedTo->getRenderTransform().getColumn(3, &ptBase); 171 172 if (mAttachedToPlayer != NULL) 173 { 174 mAttachedToPlayer->getRenderEyeTransform(&mat); 175 mat.getColumn(3, &ptEye); 176 } 177 else 178 { 179 ptEye = ptBase; 180 } 181 182 // use some components from ptEye but other position from ptBase 183 pt = ptBase; 184 if (mUseEyePoint.x != 0) 185 { 186 pt.x = ptEye.x; 187 pt.y = ptEye.y; 188 } 189 if (mUseEyePoint.y != 0) 190 { 191 pt.z = ptEye.z; 192 } 193 194 // object-space offset 195 Point3F offsetObj; 196 QuatF quat(mAttachedTo->getRenderTransform()); 197 quat.mulP(mOffsetObject, &offsetObj); 198 pt += offsetObj; 199 200 201 // world-space offset 202 pt += mOffsetWorld; 203 204 mPtWorld = pt; 205} 206 207 208void Gui3DProjectionCtrl::doProjection() 209{ 210 if (!mTSCtrl) 211 return; 212 213 Point3F pt; 214 215 if (!mTSCtrl->project(mPtWorld, &pt)) 216 return; 217 218 mPtProj.x = (S32)(pt.x + 0.5f); 219 mPtProj.y = (S32)(pt.y + 0.5f); 220} 221 222void Gui3DProjectionCtrl::doAlignment() 223{ 224 // alignment 225 Point2I offsetAlign; 226 switch(mHAlign) 227 { 228 default: 229 case center: 230 offsetAlign.x = -getBounds().extent.x / 2; 231 break; 232 case min: 233 offsetAlign.x = 0; 234 break; 235 case max: 236 offsetAlign.x = -getBounds().extent.x; 237 break; 238 } 239 240 switch(mVAlign) 241 { 242 default: 243 case center: 244 offsetAlign.y = -getBounds().extent.y / 2; 245 break; 246 case min: 247 offsetAlign.y = 0; 248 break; 249 case max: 250 offsetAlign.y = -getBounds().extent.y; 251 break; 252 } 253 254 // projected point 255 mPtScreen = mPtProj; 256 257 // alignment offset 258 mPtScreen += offsetAlign; 259 260 // screen offset 261 mPtScreen += mOffsetScreen; 262 263// setTrgPosition(mPtScreen); 264 RectI bounds = getBounds(); 265 bounds.point = mPtScreen; 266 setBounds(bounds); 267} 268 269//----------------------------------------------------------------------------- 270 271void Gui3DProjectionCtrl::setAttachedTo(SceneObject* obj) 272{ 273 if (obj == mAttachedTo) 274 return; 275 276 if (mAttachedTo) 277 clearNotify(mAttachedTo); 278 279 mAttachedTo = obj; 280 mAttachedToPlayer = dynamic_cast<Player*>(obj); 281 282 if (mAttachedTo) 283 deleteNotify(mAttachedTo); 284} 285 286DefineEngineMethod(Gui3DProjectionCtrl, setAttachedTo, void, (SceneObject* target), (nullAsType<SceneObject*>()), "(object)") 287{ 288 if(target) 289 object->setAttachedTo(target); 290} 291 292DefineEngineMethod(Gui3DProjectionCtrl, getAttachedTo, S32, (),, "()") 293{ 294 SceneObject* obj = object->getAttachedTo(); 295 if (!obj) 296 return 0; 297 else 298 return obj->getId(); 299} 300