gizmo.h 12 KB

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