guiCanvas.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  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. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  23. // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  24. // Copyright (C) 2015 Faust Logic, Inc.
  25. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  26. #ifndef _GUICANVAS_H_
  27. #define _GUICANVAS_H_
  28. #ifndef _SIMBASE_H_
  29. #include "console/simBase.h"
  30. #endif
  31. #ifndef _GUICONTROL_H_
  32. #include "gui/core/guiControl.h"
  33. #endif
  34. #ifndef _PLATFORMINPUT_H_
  35. #include "platform/platformInput.h"
  36. #endif
  37. #ifndef _SIGNAL_H_
  38. #include "core/util/tSignal.h"
  39. #endif
  40. #include "platform/input/IProcessInput.h"
  41. #include "windowManager/platformWindowMgr.h"
  42. #include "gfx/gfxFence.h"
  43. /// A canvas on which rendering occurs.
  44. ///
  45. ///
  46. /// @section GuiCanvas_contents What a GUICanvas Can Contain...
  47. ///
  48. /// @subsection GuiCanvas_content_contentcontrol Content Control
  49. /// A content control is the top level GuiControl for a screen. This GuiControl
  50. /// will be the parent control for all other GuiControls on that particular
  51. /// screen.
  52. ///
  53. /// @subsection GuiCanvas_content_dialogs Dialogs
  54. ///
  55. /// A dialog is essentially another screen, only it gets overlaid on top of the
  56. /// current content control, and all input goes to the dialog. This is most akin
  57. /// to the "Open File" dialog box found in most operating systems. When you
  58. /// choose to open a file, and the "Open File" dialog pops up, you can no longer
  59. /// send input to the application, and must complete or cancel the open file
  60. /// request. Torque keeps track of layers of dialogs. The dialog with the highest
  61. /// layer is on top and will get all the input, unless the dialog is
  62. /// modeless, which is a profile option.
  63. ///
  64. /// @see GuiControlProfile
  65. ///
  66. /// @section GuiCanvas_dirty Dirty Rectangles
  67. ///
  68. /// The GuiCanvas is based on dirty regions.
  69. ///
  70. /// Every frame the canvas paints only the areas of the canvas that are 'dirty'
  71. /// or need updating. In most cases, this only is the area under the mouse cursor.
  72. /// This is why if you look in guiCanvas.cc the call to glClear is commented out.
  73. /// If you want a really good idea of what exactly dirty regions are and how they
  74. /// work, un-comment that glClear line in the renderFrame method of guiCanvas.cc
  75. ///
  76. /// What you will see is a black screen, except in the dirty regions, where the
  77. /// screen will be painted normally. If you are making an animated GuiControl
  78. /// you need to add your control to the dirty areas of the canvas.
  79. ///
  80. class guiCanvas;
  81. class Point2I;
  82. typedef Signal<void(GuiCanvas* canvas)> CanvasSizeChangeSignal;
  83. typedef Signal<void(GuiCanvas* canvas, bool isActive)> CanvasSetActiveSignal;
  84. class GuiCanvas : public GuiControl, public IProcessInput
  85. {
  86. protected:
  87. typedef GuiControl Parent;
  88. /// @name Rendering
  89. /// @{
  90. RectI mOldUpdateRects[2];
  91. RectI mCurUpdateRect;
  92. U32 mLastRenderMs;
  93. /// @}
  94. /// @name Cursor Properties
  95. /// @{
  96. bool mCursorEnabled;
  97. bool mShowCursor;
  98. bool mRenderFront;
  99. Point2F mCursorPt; ///< Current cursor position in local coordinates.
  100. Point2I mLastCursorPt;
  101. GuiCursor *mDefaultCursor;
  102. GuiCursor *mLastCursor;
  103. bool mLastCursorEnabled;
  104. bool mForceMouseToGUI;
  105. bool mClampTorqueCursor;
  106. bool mAlwaysHandleMouseButtons;
  107. bool mDisplayWindow;
  108. /// @}
  109. /// @name Mouse Input
  110. /// @{
  111. SimObjectPtr<GuiControl> mMouseCapturedControl; ///< All mouse events will go to this ctrl only
  112. SimObjectPtr<GuiControl> mMouseControl; ///< the control the mouse was last seen in unless some other one captured it
  113. bool mMouseControlClicked; ///< whether the current ctrl has been clicked - used by helpctrl
  114. U32 mPrevMouseTime; ///< this determines how long the mouse has been in the same control
  115. bool mMouseButtonDown; ///< Flag to determine if the button is depressed
  116. bool mMouseRightButtonDown; ///< bool to determine if the right button is depressed
  117. bool mMouseMiddleButtonDown; ///< Middle button flag
  118. GuiEvent mLastEvent;
  119. U8 mLastMouseClickCount;
  120. S32 mLastMouseDownTime;
  121. bool mLeftMouseLast;
  122. bool mMiddleMouseLast;
  123. bool mRightMouseLast;
  124. Point2F mMouseDownPoint;
  125. /// Processes keyboard input events. Helper method for processInputEvent
  126. ///
  127. /// \param inputEvent Information on the input even to be processed.
  128. /// \return True if the event was handled or false if it was not.
  129. virtual bool processKeyboardEvent(InputEventInfo &inputEvent);
  130. /// Processes mouse input events. Helper method for processInputEvent
  131. ///
  132. /// \param inputEvent Information on the input even to be processed.
  133. /// \return True if the event was handled or false if it was not.
  134. virtual bool processMouseEvent(InputEventInfo &inputEvent);
  135. /// Processes gamepad input events. Helper method for processInputEvent
  136. ///
  137. /// \param inputEvent Information on the input even to be processed.
  138. /// \return True if the event was handled or false if it was not.
  139. virtual bool processGamepadEvent(InputEventInfo &inputEvent);
  140. virtual void findMouseControl(const GuiEvent &event);
  141. virtual void refreshMouseControl();
  142. /// @}
  143. /// @name Keyboard Input
  144. /// @{
  145. /// Accelerator key map
  146. struct AccKeyMap
  147. {
  148. GuiControl *ctrl;
  149. U32 index;
  150. U32 keyCode;
  151. U32 modifier;
  152. };
  153. Vector <AccKeyMap> mAcceleratorMap;
  154. //for tooltip rendering
  155. U32 mHoverControlStart;
  156. GuiControl* mHoverControl;
  157. Point2I mHoverPosition;
  158. bool mHoverPositionSet;
  159. U32 mHoverLeftControlTime;
  160. public:
  161. /// Setting for how to handle 'enableKeyboardTranslation' and 'setNativeAcceleratorsEnabled' requests.
  162. enum KeyTranslationMode
  163. {
  164. TranslationMode_Platform,
  165. TranslationMode_Callback,
  166. TranslationMode_Ignore,
  167. };
  168. protected:
  169. KeyTranslationMode mKeyTranslationMode;
  170. KeyTranslationMode mNativeAcceleratorMode;
  171. /// @}
  172. // Internal event handling callbacks for use with PlatformWindow.
  173. void handleResize (WindowId did, S32 width, S32 height);
  174. void handleAppEvent (WindowId did, S32 event);
  175. void handlePaintEvent (WindowId did);
  176. PlatformWindow *mPlatformWindow;
  177. GFXFence **mFences;
  178. S32 mNextFenceIdx;
  179. S32 mNumFences;
  180. static bool setProtectedNumFences( void *object, const char *index, const char *data );
  181. virtual void setupFences();
  182. void checkLockMouseMove( const GuiEvent& event );
  183. //Signal used to let others know this canvas has changed size.
  184. static CanvasSizeChangeSignal smCanvasSizeChangeSignal;
  185. static CanvasSetActiveSignal smCanvasSetActiveSignal;
  186. GuiControl *mMenuBarCtrl;
  187. GuiControl* mMenuBackground;
  188. bool mConstrainMouse;
  189. typedef Signal< void(SetModification modification, SimSet* set, SimObject* object) > SetModificationSignal;
  190. public:
  191. DECLARE_CONOBJECT(GuiCanvas);
  192. DECLARE_CATEGORY( "Gui Core" );
  193. GuiCanvas();
  194. virtual ~GuiCanvas();
  195. bool onAdd() override;
  196. void onRemove() override;
  197. #ifdef TORQUE_TOOLS
  198. void setMenuBar(SimObject *obj);
  199. SimObject* getMenuBar() { return mMenuBarCtrl; }
  200. #endif
  201. static void initPersistFields();
  202. static CanvasSizeChangeSignal& getCanvasSizeChangeSignal() { return smCanvasSizeChangeSignal; }
  203. static CanvasSetActiveSignal& getCanvasSetActiveSignal() { return smCanvasSetActiveSignal; }
  204. /// @name Rendering methods
  205. ///
  206. /// @{
  207. void constrainMouse(bool constrained) { mConstrainMouse = constrained; };
  208. void constrainMouseCoords(Point2I mousePoint);
  209. /// Repaints the dirty regions of the canvas
  210. /// @param preRenderOnly If set to true, only the onPreRender methods of all the GuiControls will be called
  211. /// @param bufferSwap If set to true, it will swap buffers at the end. This is to support canvas-subclassing.
  212. virtual void renderFrame(bool preRenderOnly, bool bufferSwap = true);
  213. /// Repaints the canvas by calling the platform window display event.
  214. virtual void paint();
  215. /// Repaints the canvas skipping rendering if the target time
  216. /// has not yet elapsed.
  217. /// @param elapsedMS The time since the last frame.
  218. virtual void repaint(U32 elapsedMS);
  219. /// This signal is triggered at the beginning and end of each render frame
  220. ///
  221. /// @param beginFrame true at the beginning of the frame, false at the end
  222. ///
  223. typedef Signal <void ( bool beginFrame )> GuiCanvasFrameSignal;
  224. static GuiCanvasFrameSignal& getGuiCanvasFrameSignal();
  225. /// Adds a dirty area to the canvas so it will be updated on the next frame
  226. /// @param pos Screen-coordinates of the upper-left hand corner of the dirty area
  227. /// @param ext Width/height of the dirty area
  228. virtual void addUpdateRegion(Point2I pos, Point2I ext);
  229. /// Resets the update regions so that the next call to renderFrame will
  230. /// repaint the whole canvas
  231. virtual void resetUpdateRegions();
  232. /// Resizes the content control to match the canvas size.
  233. void maintainSizing();
  234. /// This builds a rectangle which encompasses all of the dirty regions to be
  235. /// repainted
  236. /// @param updateUnion (out) Rectangle which surrounds all dirty areas
  237. virtual void buildUpdateUnion(RectI *updateUnion);
  238. /// This will swap the buffers at the end of renderFrame. It was added for canvas
  239. /// sub-classes in case they wanted to do some custom code before the buffer
  240. /// flip occured.
  241. virtual void swapBuffers();
  242. /// @}
  243. /// @name Canvas Content Management
  244. /// @{
  245. /// This returns the PlatformWindow owned by this Canvas
  246. virtual PlatformWindow *getPlatformWindow()
  247. {
  248. return mPlatformWindow;
  249. }
  250. /// This sets the content control to something different
  251. /// @param gui New content control
  252. virtual void setContentControl(GuiControl *gui);
  253. /// Returns the content control
  254. virtual GuiControl *getContentControl();
  255. /// Adds a dialog control onto the stack of dialogs
  256. /// @param gui Dialog to add
  257. /// @param layer Layer to put dialog on
  258. /// @param center Center dialog on canvas.
  259. virtual void pushDialogControl(GuiControl *gui, S32 layer = 0, bool center = false);
  260. /// Removes a specific layer of dialogs
  261. /// @param layer Layer to pop off from
  262. virtual void popDialogControl(S32 layer = 0);
  263. /// Removes a specific dialog control
  264. /// @param gui Dialog to remove from the dialog stack
  265. virtual void popDialogControl(GuiControl *gui);
  266. ///@}
  267. /// This turns on/off front-buffer rendering
  268. /// @param front True if all rendering should be done to the front buffer
  269. virtual void setRenderFront(bool front) { mRenderFront = front; }
  270. /// @name Cursor commands
  271. /// A cursor can be on, but not be shown. If a cursor is not on, than it does not
  272. /// process input.
  273. /// @{
  274. /// Sets the cursor for the canvas.
  275. /// @param cursor New cursor to use.
  276. virtual void setCursor(GuiCursor *cursor);
  277. S32 mCursorChanged;
  278. /// Returns true if the cursor is on.
  279. virtual bool isCursorON() { return mCursorEnabled; }
  280. /// Sets if mouse events should be passed to the GUI even if the cursor is off.
  281. /// @param onOff True if events should be passed to the GUI if the cursor is off
  282. virtual void setForceMouseToGUI(bool onOff);
  283. /// Sets if the Torque cursor should be clamped to the window.
  284. /// @param onOff True if the Torque cursor should be clamped against the window
  285. virtual void setClampTorqueCursor(bool onOff);
  286. /// Returns if the Torque cursor is clamped to the window
  287. virtual bool getClampTorqueCursor() { return mClampTorqueCursor; }
  288. /// Turns the cursor on or off.
  289. /// @param onOff True if the cursor should be on.
  290. virtual void setCursorON(bool onOff);
  291. /// Sets the position of the cursor
  292. /// @param pt Point, in screenspace for the cursor
  293. virtual void setCursorPos(const Point2I &pt);
  294. /// Returns the point, in screenspace, at which the cursor is located.
  295. virtual Point2I getCursorPos();
  296. /// Returns the point, in local coordinates, at which the cursor is located
  297. virtual Point2I getCursorPosLocal() { return Point2I(S32(mCursorPt.x), S32(mCursorPt.y)); }
  298. /// Enable/disable rendering of the cursor.
  299. /// @param state True if we should render cursor
  300. virtual void showCursor(bool state);
  301. /// Returns true if the cursor is being rendered.
  302. virtual bool isCursorShown();
  303. void cursorClick(S32 buttonId, bool isDown);
  304. void cursorNudge(F32 x, F32 y);
  305. /// @}
  306. ///used by the tooltip resource
  307. Point2I getCursorExtent() { return mDefaultCursor->getExtent(); }
  308. /// @name Input Processing
  309. /// @{
  310. /// Processes an input event
  311. /// @see InputEvent
  312. /// @param event Input event to process
  313. bool processInputEvent(InputEventInfo &inputEvent) override;
  314. /// @}
  315. /// @name Mouse Methods
  316. /// @{
  317. /// When a control gets the mouse lock this means that that control gets
  318. /// ALL mouse input and no other control receives any input.
  319. /// @param lockingControl Control to lock mouse to
  320. virtual void mouseLock(GuiControl *lockingControl);
  321. /// Unlocks the mouse from a control
  322. /// @param lockingControl Control to unlock from
  323. virtual void mouseUnlock(GuiControl *lockingControl);
  324. /// Returns the control which the mouse is over
  325. virtual GuiControl* getMouseControl() { return mMouseControl; }
  326. /// Returns the control which the mouse is locked to if any
  327. virtual GuiControl* getMouseLockedControl() { return mMouseCapturedControl; }
  328. /// Returns true if the left mouse button is down
  329. virtual bool mouseButtonDown(void) { return mMouseButtonDown; }
  330. /// Returns true if the right mouse button is down
  331. virtual bool mouseRightButtonDown(void) { return mMouseRightButtonDown; }
  332. /// @}
  333. /// @name Mouse input methods
  334. /// These events process the events before passing them down to the
  335. /// controls they effect. This allows for things such as the input
  336. /// locking and such.
  337. ///
  338. /// Each of these methods corresponds to the action in it's method name
  339. /// and processes the GuiEvent passed as a parameter
  340. /// @{
  341. virtual void rootMouseUp(const GuiEvent &event);
  342. virtual void rootMouseDown(const GuiEvent &event);
  343. virtual void rootMouseMove(const GuiEvent &event);
  344. virtual void rootMouseDragged(const GuiEvent &event);
  345. virtual void rootRightMouseDown(const GuiEvent &event);
  346. virtual void rootRightMouseUp(const GuiEvent &event);
  347. virtual void rootRightMouseDragged(const GuiEvent &event);
  348. virtual void rootMiddleMouseDown(const GuiEvent &event);
  349. virtual void rootMiddleMouseUp(const GuiEvent &event);
  350. virtual void rootMiddleMouseDragged(const GuiEvent &event);
  351. virtual bool rootMouseWheelUp(const GuiEvent &event);
  352. virtual bool rootMouseWheelDown(const GuiEvent &event);
  353. /// @}
  354. /// @name Keyboard input methods
  355. /// First responders
  356. ///
  357. /// A first responder is a the GuiControl which responds first to input events
  358. /// before passing them off for further processing.
  359. /// @{
  360. /// Moves the first responder to the next tabable controle
  361. virtual bool tabNext(void);
  362. /// Moves the first responder to the previous tabable control
  363. virtual bool tabPrev(void);
  364. /// Setups a keyboard accelerator which maps to a GuiControl.
  365. ///
  366. /// @param ctrl GuiControl to map to.
  367. /// @param index
  368. /// @param keyCode Key code.
  369. /// @param modifier Shift, ctrl, etc.
  370. virtual void addAcceleratorKey(GuiControl *ctrl, U32 index, U32 keyCode, U32 modifier);
  371. /// Sets the first responder.
  372. /// @param firstResponder Control to designate as first responder
  373. void setFirstResponder(GuiControl *firstResponder) override;
  374. /// This is used to toggle processing of native OS accelerators, not
  375. /// to be confused with the Torque accelerator key system, to keep them
  376. /// from swallowing up keystrokes. Both GuiTextEditCtrl and GuiTextPadCtrl
  377. /// use this method.
  378. virtual void setNativeAcceleratorsEnabled( bool enabled );
  379. /// @}
  380. ///
  381. virtual Point2I getWindowSize();
  382. virtual void enableKeyboardTranslation();
  383. virtual void disableKeyboardTranslation();
  384. virtual void setWindowTitle(const char *newTitle);
  385. DECLARE_CALLBACK(bool, onSetKeyboardTranslationEnabled, (bool enable));
  386. DECLARE_CALLBACK(bool, onSetNativeAcceleratorsEnabled, (bool enable));
  387. private:
  388. static const U32 MAX_GAMEPADS = 4; ///< The maximum number of supported gamepads
  389. protected:
  390. bool mConsumeLastInputEvent;
  391. S32 mLastInputDeviceType;
  392. public:
  393. void clearMouseRightButtonDown(void) { mMouseRightButtonDown = false; }
  394. void clearMouseButtonDown(void) { mMouseButtonDown = false; }
  395. void setConsumeLastInputEvent(bool flag) { mConsumeLastInputEvent = flag; }
  396. bool getLastCursorPoint(Point2I& pt) const { pt = mLastCursorPt; return mLastCursorEnabled; }
  397. StringTableEntry getLastInputDeviceType();
  398. void setActive(bool value) override;
  399. };
  400. typedef GuiCanvas::KeyTranslationMode KeyboardTranslationMode;
  401. DefineEnumType(KeyboardTranslationMode);
  402. #endif