guiCanvas.h

Engine/source/gui/core/guiCanvas.h

More...

Classes:

class

Accelerator key map.

Public Typedefs

Signal< void(GuiCanvas *canvas)>
CanvasSizeChangeSignal 

Detailed Description

Public Typedefs

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