gizmo.h

Engine/source/gui/worldEditor/gizmo.h

More...

Classes:

Public Enumerations

enum
GizmoAlignment {
  World = 0
  Object 
  AlignEnumCount 
}
enum
GizmoMode {
  NoneMode = 0
  MoveMode 
  RotateMode 
  ScaleMode 
  ModeEnumCount 
}

Detailed Description

Public Enumerations

GizmoAlignment

Enumerator

World = 0
Object
AlignEnumCount
GizmoMode

Enumerator

NoneMode = 0
MoveMode
RotateMode
ScaleMode
ModeEnumCount

Public Functions

DefineEnumType(GizmoAlignment )

DefineEnumType(GizmoMode )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#ifndef _GIZMO_H_
 25#define _GIZMO_H_
 26
 27#ifndef _SIMBASE_H_
 28#include "console/simBase.h"
 29#endif
 30
 31#ifndef _MMATRIX_H_
 32#include "math/mMatrix.h"
 33#endif
 34
 35#ifndef _COLOR_H_
 36#include "core/color.h"
 37#endif
 38
 39#ifndef _GUITYPES_H_
 40#include "gui/core/guiTypes.h"
 41#endif
 42
 43#ifndef _MATHUTILS_H_
 44#include "math/mathUtils.h"
 45#endif
 46
 47#ifndef _DYNAMIC_CONSOLETYPES_H_
 48#include "console/dynamicTypes.h"
 49#endif
 50
 51
 52enum GizmoMode
 53{
 54   NoneMode = 0,
 55   MoveMode,    // 1
 56   RotateMode,  // 2
 57   ScaleMode,   // 3
 58   ModeEnumCount 
 59};
 60
 61enum GizmoAlignment
 62{
 63   World = 0,
 64   Object,
 65   AlignEnumCount
 66};
 67
 68DefineEnumType( GizmoMode );
 69DefineEnumType( GizmoAlignment );
 70
 71
 72//
 73class GizmoProfile : public SimObject
 74{
 75   typedef SimObject Parent;
 76
 77public:
 78
 79   GizmoProfile();
 80   virtual ~GizmoProfile() {}
 81
 82   DECLARE_CONOBJECT( GizmoProfile );
 83
 84   virtual bool onAdd();
 85
 86   static void initPersistFields();
 87   static void consoleInit();
 88
 89   /// Set flags to default values.
 90   void restoreDefaultState();
 91
 92   // Data Fields
 93
 94   GizmoMode mode;
 95   GizmoAlignment alignment;
 96
 97   F32 rotateScalar;
 98   F32 scaleScalar;
 99   U32 screenLen;
100   ColorI axisColors[3];
101   ColorI activeColor;   
102   ColorI inActiveColor;
103   ColorI centroidColor;
104   ColorI centroidHighlightColor;
105   Resource<GFont> font;
106
107   bool snapToGrid;
108   F32 scaleSnap;
109   bool allowSnapScale;
110   F32 rotationSnap;
111   bool allowSnapRotations;
112
113   bool renderWhenUsed;
114   bool renderInfoText;
115
116   Point3F gridSize;
117   bool renderPlane;
118   bool renderPlaneHashes;
119   ColorI gridColor;
120   F32 planeDim;   
121   bool renderSolid;
122
123   /// Whether to render a transparent grid overlay when using the move gizmo.
124   bool renderMoveGrid;
125
126   enum Flags {
127      CanRotate         = 1 << 0, // 0
128      CanRotateX        = 1 << 1,
129      CanRotateY        = 1 << 2,
130      CanRotateZ        = 1 << 3,
131      CanRotateScreen   = 1 << 4,
132      CanRotateUniform  = 1 << 5,
133      CanScale          = 1 << 6,
134      CanScaleX         = 1 << 7,
135      CanScaleY         = 1 << 8,
136      CanScaleZ         = 1 << 9,
137      CanScaleUniform   = 1 << 10,
138      CanTranslate      = 1 << 11,
139      CanTranslateX     = 1 << 12, 
140      CanTranslateY     = 1 << 13, 
141      CanTranslateZ     = 1 << 14,
142      CanTranslateUniform = 1 << 15,
143      PlanarHandlesOn   = 1 << 16
144   };
145
146   S32 flags;
147
148   bool hideDisabledAxes;
149
150   bool allAxesScaleUniform;
151};
152
153
154// This class contains code for rendering and manipulating a 3D gizmo, it
155// is usually used as a helper within a TSEdit-derived control.
156//
157// The Gizmo has a MatrixF transform and Point3F scale on which it will
158// operate by passing it Gui3DMouseEvent(s).
159//
160// The idea is to set the Gizmo transform/scale to that of another 3D object 
161// which is being manipulated, pass mouse events into the Gizmo, read the
162// new transform/scale out, and set it to onto the object.
163// And of course the Gizmo can be rendered.
164//
165// Gizmo derives from SimObject only because this allows its properties
166// to be initialized directly from script via fields.
167
168class Gizmo : public SimObject
169{
170   typedef SimObject Parent;
171
172   friend class WorldEditor;
173
174public:   
175
176   enum Selection {
177      None     = -1,
178      Axis_X   = 0,
179      Axis_Y   = 1,
180      Axis_Z   = 2,
181      Plane_XY = 3,  // Normal = Axis_Z
182      Plane_XZ = 4,  // Normal = Axis_Y
183      Plane_YZ = 5,  // Normal = Axis_X
184      Centroid = 6,
185      Custom1  = 7,  // screen-aligned rotation
186      Custom2  = 8
187   };  
188
189   Gizmo();
190   ~Gizmo();
191
192   DECLARE_CONOBJECT( Gizmo );
193
194   // SimObject
195   bool onAdd();
196   void onRemove();
197   static void initPersistFields();
198
199   // Mutators
200   void set( const MatrixF &objMat, const Point3F &worldPos, const Point3F &objScale ); 
201   void setProfile( GizmoProfile *profile ) 
202   { 
203      AssertFatal( profile != NULL, "NULL passed to Gizmo::setProfile - Gizmo must always have a profile!" );
204      mProfile = profile; 
205   }
206
207   // Accessors
208   
209   GizmoProfile*  getProfile()               { return mProfile; }
210
211   GizmoMode      getMode() const            { return mCurrentMode; }
212
213   GizmoAlignment getAlignment() const       { return mCurrentAlignment; }
214
215   /// Returns current object to world transform of the object being manipulated.
216   const MatrixF& getTransform() const       { return mCurrentTransform; }
217   
218   Point3F        getPosition() const        { return mCurrentTransform.getPosition(); }   
219   
220   const Point3F& getScale() const           { return mScale; }
221   
222   
223   // Returns change in position in last call to on3DMouseDragged.
224   const Point3F& getOffset() const          { return mDeltaPos; }
225   
226   // Returns change is position since on3DMouseDown.
227   const Point3F& getTotalOffset() const     { return mDeltaTotalPos; }
228   
229   const Point3F& getDeltaScale() const      { return mDeltaScale; }
230   
231   const Point3F& getDeltaTotalScale() const { return mDeltaTotalScale; }
232   
233   const Point3F& getDeltaRot() const        { return mDeltaRot; }
234
235   const Point3F& getDeltaTotalRot() const   { return mDeltaTotalRot; }
236
237   /// Set whether to render the grid plane.
238   void setGridPlaneEnabled( bool value ) { mGridPlaneEnabled = value; }
239
240   /// Set whether to a transparent grid overlay when using the move gizmo.
241   void setMoveGridEnabled( bool value ) { mMoveGridEnabled = value; }
242
243   /// Set the size of the move grid along one dimension.  The total size of the
244   /// move grid is @a value * @a value.
245   void setMoveGridSize( F32 value ) { mMoveGridSize = value; }
246
247   /// Set the spacing between grid lines on the move grid.
248   void setMoveGridSpacing( F32 value ) { mMoveGridSpacing = value; }
249
250   // Gizmo Interface methods...
251
252   // Set the current highlight mode on the gizmo's centroid handle
253   void setCentroidHandleHighlight( bool state ) { mHighlightCentroidHandle = state; }
254
255   // Must be called before on3DMouseDragged to save state
256   void on3DMouseDown( const Gui3DMouseEvent &event );
257
258   // So Gizmo knows the current mouse button state.
259   void on3DMouseUp( const Gui3DMouseEvent &event );
260   
261   // Test Gizmo for collisions and set the Gizmo Selection (the part under the cursor)
262   void on3DMouseMove( const Gui3DMouseEvent &event );
263   
264   // Make changes to the Gizmo transform/scale (depending on mode)
265   void on3DMouseDragged( const Gui3DMouseEvent &event );
266
267   // Returns an enum describing the part of the Gizmo that is Selected
268   // ( under the cursor ). This should be called AFTER calling onMouseMove
269   // or collideAxisGizmo
270   //
271   // -1 None
272   // 0  Axis_X
273   // 1  Axis_Y
274   // 2  Axis_Z
275   // 3  Plane_XY
276   // 4  Plane_XZ
277   // 5  Plane_YZ
278   Selection getSelection();
279   void setSelection( Selection sel ) { mSelectionIdx = sel; }
280
281   // Returns the object space vector corresponding to a Selection.
282   Point3F selectionToAxisVector( Selection axis ); 
283
284   // These provide the user an easy way to check if the Gizmo's transform
285   // or scale have changed by calling markClean prior to calling
286   // on3DMouseDragged, and calling isDirty after.   
287   bool isDirty() { return mDirty; }
288   void markClean() { mDirty = false; } 
289
290   // Renders the 3D Gizmo in the scene, GFX must be setup for proper
291   // 3D rendering before calling this!
292   // Calling this will change the GFXStateBlock!
293   void renderGizmo( const MatrixF &cameraTransform, F32 camerFOV = 1.5f );
294
295   // Renders text associated with the Gizmo, GFX must be setup for proper
296   // 2D rendering before calling this!
297   // Calling this will change the GFXStateBlock!
298   void renderText( const RectI &viewPort, const MatrixF &modelView, const MatrixF &projection );
299
300   // Returns true if the mouse event collides with any part of the Gizmo
301   // and sets the Gizmo's current Selection.
302   // You can call this or on3DMouseMove, they are identical   
303   bool collideAxisGizmo( const Gui3DMouseEvent & event );
304
305protected:
306
307   void _calcAxisInfo();
308   void _setStateBlock();
309   void _renderPrimaryAxis();
310   void _renderAxisArrows();
311   void _renderAxisBoxes();
312   void _renderAxisCircles();
313   void _renderAxisText();   
314   void _renderPlane();
315   Point3F _snapPoint( const Point3F &pnt ) const;
316   F32 _snapFloat( const F32 &val, const F32 &snap ) const;
317   GizmoAlignment _filteredAlignment();
318   void _updateState( bool collideGizmo = true );
319   void _updateEnabledAxices();
320
321   F32 _getProjectionLength( F32 dist ) const
322   {
323      if( GFX->isFrustumOrtho() )
324         return mLastCameraFOV * dist * 0.002f;
325      else
326      {
327         Point3F dir = mOrigin - mCameraPos;
328         return ( dist * dir.len() ) / mLastWorldToScreenScale.y;
329      }
330   }
331
332protected:
333
334   GizmoProfile *mProfile;
335
336   MatrixF mObjectMat;
337   MatrixF mObjectMatInv;
338   MatrixF mTransform;
339   MatrixF mCurrentTransform;
340   MatrixF mSavedTransform;
341   
342   GizmoAlignment mCurrentAlignment;
343   GizmoMode mCurrentMode;
344
345   MatrixF mCameraMat;
346   Point3F mCameraPos;
347
348   Point3F mScale;
349   Point3F mSavedScale;
350   Point3F mDeltaScale;
351   Point3F mDeltaTotalScale;
352   Point3F mLastScale;
353   Point3F mScaleInfluence;
354 
355   EulerF mRot;
356   EulerF mSavedRot;
357   EulerF mDeltaRot;
358   EulerF mDeltaTotalRot;
359   F32 mDeltaAngle;
360   F32 mLastAngle;
361   Point2I mMouseDownPos;
362   Point3F mMouseDownProjPnt;
363   Point3F mDeltaPos;   
364   Point3F mDeltaTotalPos;
365   Point3F mProjPnt;
366   Point3F mOrigin;
367   Point3F mProjAxisVector[3];
368   F32 mProjLen;
369   S32 mSelectionIdx;
370   bool mDirty;
371   Gui3DMouseEvent mLastMouseEvent;
372   GFXStateBlockRef mStateBlock;
373   GFXStateBlockRef mSolidStateBlock;
374
375   PlaneF mMouseCollidePlane;
376   MathUtils::Line mMouseCollideLine;
377
378   bool mMouseDown;
379
380   F32 mSign;
381   
382   /// If false, don't render the grid plane even if it is enabled in the profile.
383   bool mGridPlaneEnabled;
384
385   /// If false, don't render a transparent grid overlay when using the move gizmo.
386   bool mMoveGridEnabled;
387
388   /// Size of the move grid along one dimension.
389   F32 mMoveGridSize;
390
391   /// Spacing between grid lines on the move grid.
392   U32 mMoveGridSpacing;
393
394   bool mAxisEnabled[3];
395   bool mUniformHandleEnabled;
396   bool mScreenRotateHandleEnabled;
397      
398   // Used to override rendering of handles.
399   bool mHighlightCentroidHandle;   
400   bool mHighlightAll;
401
402   // Initialized in renderGizmo and saved for later use when projecting
403   // to screen space for selection testing.
404   MatrixF mLastWorldMat;
405   MatrixF mLastProjMat;
406   RectI mLastViewport;
407   Point2F mLastWorldToScreenScale;
408   F32 mLastCameraFOV;
409
410   // Screenspace cursor collision information used in rotation mode.
411   Point3F mElipseCursorCollidePntSS;
412   Point3F mElipseCursorCollideVecSS;
413
414   /// A large hard coded distance used to test 
415   /// gizmo axis selection.
416   static F32 smProjectDistance;
417};
418
419#endif // _GIZMO_H_
420