guiCanvas.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 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 _GUICANVAS_H_
  23. #define _GUICANVAS_H_
  24. #ifndef _SIMBASE_H_
  25. #include "sim/simBase.h"
  26. #endif
  27. #ifndef _EVENT_H_
  28. #include "platform/event.h"
  29. #endif
  30. #ifndef _GUICONTROL_H_
  31. #include "gui/guiControl.h"
  32. #endif
  33. #ifndef _PLATFORMINPUT_H_
  34. #include "platform/platformInput.h"
  35. #endif
  36. /// A canvas on which rendering occurs.
  37. ///
  38. ///
  39. /// @section GuiCanvas_contents What a GUICanvas Can Contain...
  40. ///
  41. /// @subsection GuiCanvas_content_contentcontrol Content Control
  42. /// A content control is the top level GuiControl for a screen. This GuiControl
  43. /// will be the parent control for all other GuiControls on that particular
  44. /// screen.
  45. ///
  46. /// @subsection GuiCanvas_content_dialogs Dialogs
  47. ///
  48. /// A dialog is essentially another screen, only it gets overlaid on top of the
  49. /// current content control, and all input goes to the dialog. This is most akin
  50. /// to the "Open File" dialog box found in most operating systems. When you
  51. /// choose to open a file, and the "Open File" dialog pops up, you can no longer
  52. /// send input to the application, and must complete or cancel the open file
  53. /// request. Torque keeps track of layers of dialogs. The dialog with the highest
  54. /// layer is on top and will get all the input, unless the dialog is
  55. /// modeless, which is a profile option.
  56. ///
  57. /// @see GuiControlProfile
  58. ///
  59. /// @section GuiCanvas_dirty Dirty Rectangles
  60. ///
  61. /// The GuiCanvas is based on dirty regions.
  62. ///
  63. /// Every frame the canvas paints only the areas of the canvas that are 'dirty'
  64. /// or need updating. In most cases, this only is the area under the mouse cursor.
  65. /// This is why if you look in guiCanvas.cc the call to glClear is commented out.
  66. /// If you want a really good idea of what exactly dirty regions are and how they
  67. /// work, un-comment that glClear line in the renderFrame method of guiCanvas.cc
  68. ///
  69. /// What you will see is a black screen, except in the dirty regions, where the
  70. /// screen will be painted normally. If you are making an animated GuiControl
  71. /// you need to add your control to the dirty areas of the canvas.
  72. ///
  73. class GuiCanvas : public GuiControl
  74. {
  75. protected:
  76. typedef GuiControl Parent;
  77. typedef SimObject Grandparent;
  78. /// Background color.
  79. ColorF mBackgroundColor;
  80. bool mUseBackgroundColor;
  81. /// @name Rendering
  82. /// @{
  83. ///
  84. RectI mOldUpdateRects[2];
  85. RectI mCurUpdateRect;
  86. F32 rLastFrameTime;
  87. /// @}
  88. /// @name Cursor Properties
  89. /// @{
  90. F32 mPixelsPerMickey; ///< This is the scale factor which relates
  91. /// mouse movement in pixels (one unit of
  92. /// mouse movement is a mickey) to units in
  93. /// the GUI.
  94. bool cursorON;
  95. bool mShowCursor;
  96. bool mRenderFront;
  97. Point2F cursorPt;
  98. Point2I lastCursorPt;
  99. GuiCursor *defaultCursor;
  100. GuiCursor *lastCursor;
  101. bool lastCursorON;
  102. bool mUseNativeCursor;
  103. /// @}
  104. /// @name Mouse Input
  105. /// @{
  106. SimObjectPtr<GuiControl> mMouseCapturedControl; ///< All mouse events will go to this ctrl only
  107. SimObjectPtr<GuiControl> mMouseControl; ///< the control the mouse was last seen in unless some other one captured it
  108. bool mMouseControlClicked; ///< whether the current ctrl has been clicked - used by helpctrl
  109. U32 mPrevMouseTime; ///< this determines how long the mouse has been in the same control
  110. U32 mNextMouseTime; ///< used for onMouseRepeat()
  111. U32 mInitialMouseDelay; ///< also used for onMouseRepeat()
  112. bool mMouseButtonDown; ///< Flag to determine if the button is depressed
  113. bool mMouseRightButtonDown; ///< bool to determine if the right button is depressed
  114. bool mMouseMiddleButtonDown; ///< Middle button flag
  115. GuiEvent mLastEvent;
  116. U8 mLastMouseClickCount;
  117. S32 mLastMouseDownTime;
  118. bool mLeftMouseLast;
  119. bool mMiddleMouseLast;
  120. bool mRightMouseLast;
  121. Point2F mMouseDownPoint;
  122. S32 mDoubleClickWidth;
  123. S32 mDoubleClickHeight;
  124. S32 mDoubleClickTime;
  125. Point2F mPrevMouseMovePosition; ///< Holds the previous position of the mouse the last time a mouse move event was processed.
  126. S32 mTouchDetectionSize; ///< Changes in the x or y position of the mouse greater than this value will could be touch events.
  127. bool mPotentialTouchEvent; ///< True if the mouse made a jump that looks like a touch event.
  128. U8 mPotentialMouseEventCount; ///< Counts how many small mouse movements have occured in a row that to determine if touch has been abandoned.
  129. bool mHideCursorBecauseOfTouch; ///< Touch event has been detected. Hide the cursor.
  130. virtual void findMouseControl(const GuiEvent &event);
  131. bool DoesControlStackContainControl(GuiControl* stack, const GuiControl* ctrl);
  132. virtual void refreshMouseControl();
  133. /// @}
  134. /// @name Keyboard Input
  135. /// @{
  136. GuiControl *keyboardControl; ///< All keyboard events will go to this ctrl first
  137. U32 nextKeyTime;
  138. /// Accelerator key map
  139. struct AccKeyMap
  140. {
  141. GuiControl *ctrl;
  142. U32 index;
  143. U32 keyCode;
  144. U32 modifier;
  145. inline bool IsKeyCodeEqual(U32 testCode)
  146. {
  147. return (testCode == keyCode ||
  148. (keyCode == KEY_ALT && (testCode == KEY_RALT || testCode == KEY_LALT)) ||
  149. (keyCode == KEY_SHIFT && (testCode == KEY_RSHIFT || testCode == KEY_LSHIFT)) ||
  150. (keyCode == KEY_CONTROL && (testCode == KEY_RCONTROL || testCode == KEY_LCONTROL)) ||
  151. (keyCode == KEY_MAC_OPT && (testCode == KEY_MAC_ROPT || testCode == KEY_MAC_LOPT)));
  152. }
  153. };
  154. Vector <AccKeyMap> mAcceleratorMap;
  155. //for tooltip rendering
  156. U32 hoverControlStart;
  157. GuiControl* hoverControl;
  158. Point2I hoverPosition;
  159. bool hoverPositionSet;
  160. U32 hoverLeftControlTime;
  161. /// @}
  162. public:
  163. DECLARE_CONOBJECT(GuiCanvas);
  164. GuiCanvas();
  165. virtual ~GuiCanvas();
  166. static void initPersistFields();
  167. /// Background color.
  168. inline void setBackgroundColor( const ColorF& backgroundColor ) { mBackgroundColor = backgroundColor; }
  169. inline const ColorF& getBackgroundColor( void ) const { return mBackgroundColor; }
  170. inline void setUseBackgroundColor( const bool useBackgroundColor ) { mUseBackgroundColor = useBackgroundColor; }
  171. inline bool getUseBackgroundColor( void ) const { return mUseBackgroundColor; }
  172. /// @name Rendering methods
  173. ///
  174. /// @{
  175. /// Repaints the dirty regions of the canvas
  176. /// @param preRenderOnly If set to true, only the onPreRender methods of all the GuiControls will be called
  177. /// @param bufferSwap If set to true, it will swap buffers at the end. This is to support canvas-subclassing.
  178. virtual void renderFrame(bool preRenderOnly, bool bufferSwap = true);
  179. /// Repaints the entire canvas by calling resetUpdateRegions() and then renderFrame()
  180. virtual void paint();
  181. /// Adds a dirty area to the canvas so it will be updated on the next frame
  182. /// @param pos Screen-coordinates of the upper-left hand corner of the dirty area
  183. /// @param ext Width/height of the dirty area
  184. virtual void addUpdateRegion(Point2I pos, Point2I ext);
  185. /// Resets the update regions so that the next call to renderFrame will
  186. /// repaint the whole canvas
  187. virtual void resetUpdateRegions();
  188. /// Resizes the content control to match the canvas size.
  189. void maintainSizing();
  190. /// This builds a rectangle which encompasses all of the dirty regions to be
  191. /// repainted
  192. /// @param updateUnion (out) Rectangle which surrounds all dirty areas
  193. virtual void buildUpdateUnion(RectI *updateUnion);
  194. /// This will swap the buffers at the end of renderFrame. It was added for canvas
  195. /// sub-classes in case they wanted to do some custom code before the buffer
  196. /// flip occured.
  197. virtual void swapBuffers();
  198. /// @}
  199. /// @name Canvas Content Management
  200. /// @{
  201. /// This sets the content control to something different
  202. /// @param gui New content control
  203. virtual void setContentControl(GuiControl *gui);
  204. /// Returns the content control
  205. virtual GuiControl *getContentControl();
  206. /// Adds a dialog control onto the stack of dialogs
  207. /// @param gui Dialog to add
  208. /// @param layer Layer to put dialog on
  209. virtual void pushDialogControl(GuiControl *gui, S32 layer = 0);
  210. /// Removes a specific layer of dialogs
  211. /// @param layer Layer to pop off from
  212. virtual void popDialogControl(S32 layer = 0);
  213. /// Removes a specific dialog control
  214. /// @param gui Dialog to remove from the dialog stack
  215. virtual void popDialogControl(GuiControl *gui);
  216. ///@}
  217. /// This turns on/off front-buffer rendering
  218. /// @param front True if all rendering should be done to the front buffer
  219. virtual void setRenderFront(bool front) { mRenderFront = front; }
  220. /// @name Cursor commands
  221. /// A cursor can be on, but not be shown. If a cursor is not on, than it does not
  222. /// process input.
  223. /// @{
  224. /// Sets the cursor for the canvas.
  225. /// @param cursor New cursor to use.
  226. virtual void setCursor(GuiCursor *cursor);
  227. virtual bool getUseNativeCursor(void);
  228. virtual void useNativeCursor(bool useNative);
  229. /// Returns true if the cursor is on.
  230. virtual bool isCursorON() {return cursorON; }
  231. /// Sets the time allowed between clicks to be considered a double click.
  232. void setDoubleClickTime(S32 time) { mDoubleClickTime = time; };
  233. /// Sets the amount of movement allowed that won't cancel a double click.
  234. void setDoubleClickWidth(S32 width) { mDoubleClickWidth = width; };
  235. void setDoubleClickHeight(S32 height) { mDoubleClickHeight = height; };
  236. /// Turns the cursor on or off.
  237. /// @param onOff True if the cursor should be on.
  238. virtual void setCursorON(bool onOff);
  239. /// Sets the position of the cursor
  240. /// @param pt Point, in screenspace for the cursor
  241. virtual void setCursorPos(const Point2I &pt);
  242. /// Returns the point, in screenspace, at which the cursor is located.
  243. virtual Point2I getCursorPos() { return Point2I(S32(cursorPt.x), S32(cursorPt.y)); }
  244. /// Enable/disable rendering of the cursor.
  245. /// @param state True if we should render cursor
  246. virtual void showCursor(bool state) { mShowCursor = state; }
  247. /// Returns true if the cursor is being rendered.
  248. virtual bool isCursorShown() { return(mShowCursor); }
  249. /// @}
  250. ///used by the tooltip resource
  251. Point2I getCursorExtent() { return defaultCursor->getExtent(); }
  252. /// @name Input Processing
  253. /// @{
  254. /// Processes an input event
  255. /// @see InputEvent
  256. /// @param event Input event to process
  257. virtual bool processInputEvent(const InputEvent *event);
  258. /// Processes a mouse movement event
  259. /// @see MouseMoveEvent
  260. /// @param event Mouse move event to process
  261. virtual void processMouseMoveEvent(const MouseMoveEvent *event);
  262. virtual void processScreenTouchEvent(const ScreenTouchEvent *event);
  263. /// @}
  264. /// @name Mouse Methods
  265. /// @{
  266. /// When a control gets the mouse lock this means that that control gets
  267. /// ALL mouse input and no other control recieves any input.
  268. /// @param lockingControl Control to lock mouse to
  269. virtual void mouseLock(GuiControl *lockingControl);
  270. /// Unlocks the mouse from a control
  271. /// @param lockingControl Control to unlock from
  272. virtual void mouseUnlock(GuiControl *lockingControl);
  273. /// Returns the control which the mouse is over
  274. virtual GuiControl* getMouseControl() { return mMouseControl; }
  275. /// Returns the control which the mouse is locked to if any
  276. virtual GuiControl* getMouseLockedControl() { return mMouseCapturedControl; }
  277. /// Returns true if the left mouse button is down
  278. virtual bool mouseButtonDown(void) { return mMouseButtonDown; }
  279. /// Returns true if the right mouse button is down
  280. virtual bool mouseRightButtonDown(void) { return mMouseRightButtonDown; }
  281. virtual void checkLockMouseMove(const GuiEvent &event);
  282. /// @}
  283. /// @name Mouse input methods
  284. /// These events process the events before passing them down to the
  285. /// controls they effect. This allows for things such as the input
  286. /// locking and such.
  287. ///
  288. /// Each of these methods corosponds to the action in it's method name
  289. /// and processes the GuiEvent passd as a parameter
  290. /// @{
  291. virtual void rootMouseUp(const GuiEvent &event);
  292. virtual void rootMouseDown(const GuiEvent &event);
  293. virtual void rootMouseMove(const GuiEvent &event);
  294. virtual void rootMouseDragged(const GuiEvent &event);
  295. virtual void rootScreenTouchUp(const GuiEvent &event);
  296. virtual void rootScreenTouchDown(const GuiEvent &event);
  297. virtual void rootScreenTouchMove(const GuiEvent &event);
  298. virtual void rootRightMouseDown(const GuiEvent &event);
  299. virtual void rootRightMouseUp(const GuiEvent &event);
  300. virtual void rootRightMouseDragged(const GuiEvent &event);
  301. virtual void rootMiddleMouseDown(const GuiEvent &event);
  302. virtual void rootMiddleMouseUp(const GuiEvent &event);
  303. virtual void rootMiddleMouseDragged(const GuiEvent &event);
  304. virtual void rootMouseWheelUp(const GuiEvent &event);
  305. virtual void rootMouseWheelDown(const GuiEvent &event);
  306. /// @}
  307. /// @name Keyboard input methods
  308. /// First responders
  309. ///
  310. /// A first responder is a the GuiControl which responds first to input events
  311. /// before passing them off for further processing.
  312. /// @{
  313. /// Moves the first responder to the next tabable controle
  314. virtual bool tabNext(void);
  315. /// Moves the first responder to the previous tabable control
  316. virtual bool tabPrev(void);
  317. /// Setups a keyboard accelerator which maps to a GuiControl.
  318. ///
  319. /// @param ctrl GuiControl to map to.
  320. /// @param index
  321. /// @param keyCode Key code.
  322. /// @param modifier Shift, ctrl, etc.
  323. virtual void addAcceleratorKey(GuiControl *ctrl, U32 index, U32 keyCode, U32 modifier);
  324. /// Sets the first responder.
  325. /// @param firstResponder Control to designate as first responder
  326. virtual void setFirstResponder(GuiControl *firstResponder);
  327. /// @}
  328. };
  329. extern GuiCanvas *Canvas;
  330. #endif