gizmo.h 12 KB

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