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   bool forceSnapRotations;
113
114   bool renderWhenUsed;
115   bool renderInfoText;
116
117   Point3F gridSize;
118   bool renderPlane;
119   bool renderPlaneHashes;
120   ColorI gridColor;
121   F32 planeDim;   
122   bool renderSolid;
123
124   /// Whether to render a transparent grid overlay when using the move gizmo.
125   bool renderMoveGrid;
126
127   enum Flags {
128      CanRotate         = 1 << 0, // 0
129      CanRotateX        = 1 << 1,
130      CanRotateY        = 1 << 2,
131      CanRotateZ        = 1 << 3,
132      CanRotateScreen   = 1 << 4,
133      CanRotateUniform  = 1 << 5,
134      CanScale          = 1 << 6,
135      CanScaleX         = 1 << 7,
136      CanScaleY         = 1 << 8,
137      CanScaleZ         = 1 << 9,
138      CanScaleUniform   = 1 << 10,
139      CanTranslate      = 1 << 11,
140      CanTranslateX     = 1 << 12, 
141      CanTranslateY     = 1 << 13, 
142      CanTranslateZ     = 1 << 14,
143      CanTranslateUniform = 1 << 15,
144      PlanarHandlesOn   = 1 << 16
145   };
146
147   S32 flags;
148
149   bool hideDisabledAxes;
150
151   bool allAxesScaleUniform;
152};
153
154
155// This class contains code for rendering and manipulating a 3D gizmo, it
156// is usually used as a helper within a TSEdit-derived control.
157//
158// The Gizmo has a MatrixF transform and Point3F scale on which it will
159// operate by passing it Gui3DMouseEvent(s).
160//
161// The idea is to set the Gizmo transform/scale to that of another 3D object 
162// which is being manipulated, pass mouse events into the Gizmo, read the
163// new transform/scale out, and set it to onto the object.
164// And of course the Gizmo can be rendered.
165//
166// Gizmo derives from SimObject only because this allows its properties
167// to be initialized directly from script via fields.
168
169class Gizmo : public SimObject
170{
171   typedef SimObject Parent;
172
173   friend class WorldEditor;
174
175public:   
176
177   enum Selection {
178      None     = -1,
179      Axis_X   = 0,
180      Axis_Y   = 1,
181      Axis_Z   = 2,
182      Plane_XY = 3,  // Normal = Axis_Z
183      Plane_XZ = 4,  // Normal = Axis_Y
184      Plane_YZ = 5,  // Normal = Axis_X
185      Centroid = 6,
186      Custom1  = 7,  // screen-aligned rotation
187      Custom2  = 8
188   };  
189
190   Gizmo();
191   ~Gizmo();
192
193   DECLARE_CONOBJECT( Gizmo );
194
195   // SimObject
196   bool onAdd();
197   void onRemove();
198   static void initPersistFields();
199
200   // Mutators
201   void set( const MatrixF &objMat, const Point3F &worldPos, const Point3F &objScale ); 
202   void setProfile( GizmoProfile *profile ) 
203   { 
204      AssertFatal( profile != NULL, "NULL passed to Gizmo::setProfile - Gizmo must always have a profile!" );
205      mProfile = profile; 
206   }
207
208   // Accessors
209   
210   GizmoProfile*  getProfile()               { return mProfile; }
211
212   GizmoMode      getMode() const            { return mCurrentMode; }
213
214   GizmoAlignment getAlignment() const       { return mCurrentAlignment; }
215
216   /// Returns current object to world transform of the object being manipulated.
217   const MatrixF& getTransform() const       { return mCurrentTransform; }
218   
219   Point3F        getPosition() const        { return mCurrentTransform.getPosition(); }   
220   
221   const Point3F& getScale() const           { return mScale; }
222   
223   
224   // Returns change in position in last call to on3DMouseDragged.
225   const Point3F& getOffset() const          { return mDeltaPos; }
226   
227   // Returns change is position since on3DMouseDown.
228   const Point3F& getTotalOffset() const     { return mDeltaTotalPos; }
229   
230   const Point3F& getDeltaScale() const      { return mDeltaScale; }
231   
232   const Point3F& getDeltaTotalScale() const { return mDeltaTotalScale; }
233   
234   const Point3F& getDeltaRot() const        { return mDeltaRot; }
235
236   const Point3F& getDeltaTotalRot() const   { return mDeltaTotalRot; }
237
238   /// Set whether to render the grid plane.
239   void setGridPlaneEnabled( bool value ) { mGridPlaneEnabled = value; }
240
241   /// Set whether to a transparent grid overlay when using the move gizmo.
242   void setMoveGridEnabled( bool value ) { mMoveGridEnabled = value; }
243
244   /// Set the size of the move grid along one dimension.  The total size of the
245   /// move grid is @a value * @a value.
246   void setMoveGridSize( F32 value ) { mMoveGridSize = value; }
247
248   /// Set the spacing between grid lines on the move grid.
249   void setMoveGridSpacing( F32 value ) { mMoveGridSpacing = value; }
250
251   // Gizmo Interface methods...
252
253   // Set the current highlight mode on the gizmo's centroid handle
254   void setCentroidHandleHighlight( bool state ) { mHighlightCentroidHandle = state; }
255
256   // Must be called before on3DMouseDragged to save state
257   void on3DMouseDown( const Gui3DMouseEvent &event );
258
259   // So Gizmo knows the current mouse button state.
260   void on3DMouseUp( const Gui3DMouseEvent &event );
261   
262   // Test Gizmo for collisions and set the Gizmo Selection (the part under the cursor)
263   void on3DMouseMove( const Gui3DMouseEvent &event );
264   
265   // Make changes to the Gizmo transform/scale (depending on mode)
266   void on3DMouseDragged( const Gui3DMouseEvent &event );
267
268   // Returns an enum describing the part of the Gizmo that is Selected
269   // ( under the cursor ). This should be called AFTER calling onMouseMove
270   // or collideAxisGizmo
271   //
272   // -1 None
273   // 0  Axis_X
274   // 1  Axis_Y
275   // 2  Axis_Z
276   // 3  Plane_XY
277   // 4  Plane_XZ
278   // 5  Plane_YZ
279   Selection getSelection();
280   void setSelection( Selection sel ) { mSelectionIdx = sel; }
281
282   // Returns the object space vector corresponding to a Selection.
283   Point3F selectionToAxisVector( Selection axis ); 
284
285   // These provide the user an easy way to check if the Gizmo's transform
286   // or scale have changed by calling markClean prior to calling
287   // on3DMouseDragged, and calling isDirty after.   
288   bool isDirty() { return mDirty; }
289   void markClean() { mDirty = false; } 
290
291   // Renders the 3D Gizmo in the scene, GFX must be setup for proper
292   // 3D rendering before calling this!
293   // Calling this will change the GFXStateBlock!
294   void renderGizmo( const MatrixF &cameraTransform, F32 camerFOV = 1.5f );
295
296   // Renders text associated with the Gizmo, GFX must be setup for proper
297   // 2D rendering before calling this!
298   // Calling this will change the GFXStateBlock!
299   void renderText( const RectI &viewPort, const MatrixF &modelView, const MatrixF &projection );
300
301   // Returns true if the mouse event collides with any part of the Gizmo
302   // and sets the Gizmo's current Selection.
303   // You can call this or on3DMouseMove, they are identical   
304   bool collideAxisGizmo( const Gui3DMouseEvent & event );
305
306protected:
307
308   void _calcAxisInfo();
309   void _setStateBlock();
310   void _renderPrimaryAxis();
311   void _renderAxisArrows();
312   void _renderAxisBoxes();
313   void _renderAxisCircles();
314   void _renderAxisText();   
315   void _renderPlane();
316   Point3F _snapPoint( const Point3F &pnt ) const;
317   F32 _snapFloat( const F32 &val, const F32 &snap ) const;
318   GizmoAlignment _filteredAlignment();
319   void _updateState( bool collideGizmo = true );
320   void _updateEnabledAxices();
321
322   F32 _getProjectionLength( F32 dist ) const
323   {
324      if( GFX->isFrustumOrtho() )
325         return mLastCameraFOV * dist * 0.002f;
326      else
327      {
328         Point3F dir = mOrigin - mCameraPos;
329         return ( dist * dir.len() ) / mLastWorldToScreenScale.y;
330      }
331   }
332
333protected:
334
335   GizmoProfile *mProfile;
336
337   MatrixF mObjectMat;
338   MatrixF mObjectMatInv;
339   MatrixF mTransform;
340   MatrixF mCurrentTransform;
341   MatrixF mSavedTransform;
342   
343   GizmoAlignment mCurrentAlignment;
344   GizmoMode mCurrentMode;
345
346   MatrixF mCameraMat;
347   Point3F mCameraPos;
348
349   Point3F mScale;
350   Point3F mSavedScale;
351   Point3F mDeltaScale;
352   Point3F mDeltaTotalScale;
353   Point3F mLastScale;
354   Point3F mScaleInfluence;
355 
356   EulerF mRot;
357   EulerF mSavedRot;
358   EulerF mDeltaRot;
359   EulerF mDeltaTotalRot;
360   F32 mDeltaAngle;
361   F32 mLastAngle;
362   Point2I mMouseDownPos;
363   Point3F mMouseDownProjPnt;
364   Point3F mDeltaPos;   
365   Point3F mDeltaTotalPos;
366   Point3F mProjPnt;
367   Point3F mOrigin;
368   Point3F mProjAxisVector[3];
369   F32 mProjLen;
370   S32 mSelectionIdx;
371   bool mDirty;
372   Gui3DMouseEvent mLastMouseEvent;
373   GFXStateBlockRef mStateBlock;
374   GFXStateBlockRef mSolidStateBlock;
375
376   PlaneF mMouseCollidePlane;
377   MathUtils::Line mMouseCollideLine;
378
379   bool mMouseDown;
380
381   F32 mSign;
382   
383   /// If false, don't render the grid plane even if it is enabled in the profile.
384   bool mGridPlaneEnabled;
385
386   /// If false, don't render a transparent grid overlay when using the move gizmo.
387   bool mMoveGridEnabled;
388
389   /// Size of the move grid along one dimension.
390   F32 mMoveGridSize;
391
392   /// Spacing between grid lines on the move grid.
393   U32 mMoveGridSpacing;
394
395   bool mUniformHandleEnabled;
396   bool mScreenRotateHandleEnabled;
397   bool mAxisEnabled[3];
398      
399   // Used to override rendering of handles.
400   bool mHighlightCentroidHandle;   
401   bool mHighlightAll;
402
403   // Initialized in renderGizmo and saved for later use when projecting
404   // to screen space for selection testing.
405   MatrixF mLastWorldMat;
406   MatrixF mLastProjMat;
407   RectI mLastViewport;
408   Point2F mLastWorldToScreenScale;
409   F32 mLastCameraFOV;
410
411   // Screenspace cursor collision information used in rotation mode.
412   Point3F mElipseCursorCollidePntSS;
413   Point3F mElipseCursorCollideVecSS;
414
415   /// A large hard coded distance used to test 
416   /// gizmo axis selection.
417   static F32 smProjectDistance;
418};
419
420#endif // _GIZMO_H_
421