tge/engine/gui/core/guiCanvas.h
2017-04-17 06:17:10 -06:00

340 lines
12 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUICANVAS_H_
#define _GUICANVAS_H_
#ifndef _SIMBASE_H_
#include "console/simBase.h"
#endif
#ifndef _EVENT_H_
#include "platform/event.h"
#endif
#ifndef _GUICONTROL_H_
#include "gui/core/guiControl.h"
#endif
#ifndef _PLATFORMINPUT_H_
#include "platform/platformInput.h"
#endif
/// A canvas on which rendering occurs.
///
///
/// @section GuiCanvas_contents What a GUICanvas Can Contain...
///
/// @subsection GuiCanvas_content_contentcontrol Content Control
/// A content control is the top level GuiControl for a screen. This GuiControl
/// will be the parent control for all other GuiControls on that particular
/// screen.
///
/// @subsection GuiCanvas_content_dialogs Dialogs
///
/// A dialog is essentially another screen, only it gets overlaid on top of the
/// current content control, and all input goes to the dialog. This is most akin
/// to the "Open File" dialog box found in most operating systems. When you
/// choose to open a file, and the "Open File" dialog pops up, you can no longer
/// send input to the application, and must complete or cancel the open file
/// request. Torque keeps track of layers of dialogs. The dialog with the highest
/// layer is on top and will get all the input, unless the dialog is
/// modeless, which is a profile option.
///
/// @see GuiControlProfile
///
/// @section GuiCanvas_dirty Dirty Rectangles
///
/// The GuiCanvas is based on dirty regions.
///
/// Every frame the canvas paints only the areas of the canvas that are 'dirty'
/// or need updating. In most cases, this only is the area under the mouse cursor.
/// This is why if you look in guiCanvas.cc the call to glClear is commented out.
/// If you want a really good idea of what exactly dirty regions are and how they
/// work, un-comment that glClear line in the renderFrame method of guiCanvas.cc
///
/// What you will see is a black screen, except in the dirty regions, where the
/// screen will be painted normally. If you are making an animated GuiControl
/// you need to add your control to the dirty areas of the canvas.
///
class GuiCanvas : public GuiControl
{
protected:
typedef GuiControl Parent;
typedef SimObject Grandparent;
/// @name Rendering
/// @{
///
RectI mOldUpdateRects[2];
RectI mCurUpdateRect;
F32 rLastFrameTime;
/// @}
/// @name Cursor Properties
/// @{
F32 mPixelsPerMickey; ///< This is the scale factor which relates
/// mouse movement in pixels (one unit of
/// mouse movement is a mickey) to units in
/// the GUI.
bool cursorON;
bool mShowCursor;
bool mRenderFront;
Point2F cursorPt;
Point2I lastCursorPt;
GuiCursor *defaultCursor;
GuiCursor *lastCursor;
bool lastCursorON;
/// @}
/// @name Mouse Input
/// @{
SimObjectPtr<GuiControl> mMouseCapturedControl; ///< All mouse events will go to this ctrl only
SimObjectPtr<GuiControl> mMouseControl; ///< the control the mouse was last seen in unless some other one captured it
bool mMouseControlClicked; ///< whether the current ctrl has been clicked - used by helpctrl
U32 mPrevMouseTime; ///< this determines how long the mouse has been in the same control
U32 mNextMouseTime; ///< used for onMouseRepeat()
U32 mInitialMouseDelay; ///< also used for onMouseRepeat()
bool mMouseButtonDown; ///< Flag to determine if the button is depressed
bool mMouseRightButtonDown; ///< bool to determine if the right button is depressed
bool mMouseMiddleButtonDown; ///< Middle button flag
GuiEvent mLastEvent;
U8 mLastMouseClickCount;
S32 mLastMouseDownTime;
bool mLeftMouseLast;
bool mMiddleMouseLast;
virtual void findMouseControl(const GuiEvent &event);
virtual void refreshMouseControl();
/// @}
/// @name Keyboard Input
/// @{
GuiControl *keyboardControl; ///< All keyboard events will go to this ctrl first
U32 nextKeyTime;
/// Accelerator key map
struct AccKeyMap
{
GuiControl *ctrl;
U32 index;
U32 keyCode;
U32 modifier;
};
Vector <AccKeyMap> mAcceleratorMap;
//for tooltip rendering
U32 hoverControlStart;
GuiControl* hoverControl;
Point2I hoverPosition;
bool hoverPositionSet;
U32 hoverLeftControlTime;
/// @}
public:
DECLARE_CONOBJECT(GuiCanvas);
GuiCanvas();
virtual ~GuiCanvas();
/// @name Rendering methods
///
/// @{
/// Repaints the dirty regions of the canvas
/// @param preRenderOnly If set to true, only the onPreRender methods of all the GuiControls will be called
/// @param bufferSwap If set to true, it will swap buffers at the end. This is to support canvas-subclassing.
virtual void renderFrame(bool preRenderOnly, bool bufferSwap = true);
/// Repaints the entire canvas by calling resetUpdateRegions() and then renderFrame()
virtual void paint();
/// Adds a dirty area to the canvas so it will be updated on the next frame
/// @param pos Screen-coordinates of the upper-left hand corner of the dirty area
/// @param ext Width/height of the dirty area
virtual void addUpdateRegion(Point2I pos, Point2I ext);
/// Resets the update regions so that the next call to renderFrame will
/// repaint the whole canvas
virtual void resetUpdateRegions();
/// Resizes the content control to match the canvas size.
void maintainSizing();
/// This builds a rectangle which encompasses all of the dirty regions to be
/// repainted
/// @param updateUnion (out) Rectangle which surrounds all dirty areas
virtual void buildUpdateUnion(RectI *updateUnion);
/// This will swap the buffers at the end of renderFrame. It was added for canvas
/// sub-classes in case they wanted to do some custom code before the buffer
/// flip occured.
virtual void swapBuffers();
/// @}
/// @name Canvas Content Management
/// @{
/// This sets the content control to something different
/// @param gui New content control
virtual void setContentControl(GuiControl *gui);
/// Returns the content control
virtual GuiControl *getContentControl();
/// Adds a dialog control onto the stack of dialogs
/// @param gui Dialog to add
/// @param layer Layer to put dialog on
virtual void pushDialogControl(GuiControl *gui, S32 layer = 0);
/// Removes a specific layer of dialogs
/// @param layer Layer to pop off from
virtual void popDialogControl(S32 layer = 0);
/// Removes a specific dialog control
/// @param gui Dialog to remove from the dialog stack
virtual void popDialogControl(GuiControl *gui);
///@}
/// This turns on/off front-buffer rendering
/// @param front True if all rendering should be done to the front buffer
virtual void setRenderFront(bool front) { mRenderFront = front; }
/// @name Cursor commands
/// A cursor can be on, but not be shown. If a cursor is not on, than it does not
/// process input.
/// @{
/// Sets the cursor for the canvas.
/// @param cursor New cursor to use.
virtual void setCursor(GuiCursor *cursor);
/// Returns true if the cursor is on.
virtual bool isCursorON() {return cursorON; }
/// Turns the cursor on or off.
/// @param onOff True if the cursor should be on.
virtual void setCursorON(bool onOff);
/// Sets the position of the cursor
/// @param pt Point, in screenspace for the cursor
virtual void setCursorPos(const Point2I &pt);
/// Returns the point, in screenspace, at which the cursor is located.
virtual Point2I getCursorPos() { return Point2I(S32(cursorPt.x), S32(cursorPt.y)); }
/// Enable/disable rendering of the cursor.
/// @param state True if we should render cursor
virtual void showCursor(bool state) { mShowCursor = state; }
/// Returns true if the cursor is being rendered.
virtual bool isCursorShown() { return(mShowCursor); }
/// @}
///used by the tooltip resource
Point2I getCursorExtent() { return defaultCursor->getExtent(); }
/// @name Input Processing
/// @{
/// Processes an input event
/// @see InputEvent
/// @param event Input event to process
virtual bool processInputEvent(const InputEvent *event);
/// Processes a mouse movement event
/// @see MouseMoveEvent
/// @param event Mouse move event to process
virtual void processMouseMoveEvent(const MouseMoveEvent *event);
/// @}
/// @name Mouse Methods
/// @{
/// When a control gets the mouse lock this means that that control gets
/// ALL mouse input and no other control recieves any input.
/// @param lockingControl Control to lock mouse to
virtual void mouseLock(GuiControl *lockingControl);
/// Unlocks the mouse from a control
/// @param lockingControl Control to unlock from
virtual void mouseUnlock(GuiControl *lockingControl);
/// Returns the control which the mouse is over
virtual GuiControl* getMouseControl() { return mMouseControl; }
/// Returns the control which the mouse is locked to if any
virtual GuiControl* getMouseLockedControl() { return mMouseCapturedControl; }
/// Returns true if the left mouse button is down
virtual bool mouseButtonDown(void) { return mMouseButtonDown; }
/// Returns true if the right mouse button is down
virtual bool mouseRightButtonDown(void) { return mMouseRightButtonDown; }
virtual void checkLockMouseMove(const GuiEvent &event);
/// @}
/// @name Mouse input methods
/// These events process the events before passing them down to the
/// controls they effect. This allows for things such as the input
/// locking and such.
///
/// Each of these methods corosponds to the action in it's method name
/// and processes the GuiEvent passd as a parameter
/// @{
virtual void rootMouseUp(const GuiEvent &event);
virtual void rootMouseDown(const GuiEvent &event);
virtual void rootMouseMove(const GuiEvent &event);
virtual void rootMouseDragged(const GuiEvent &event);
virtual void rootRightMouseDown(const GuiEvent &event);
virtual void rootRightMouseUp(const GuiEvent &event);
virtual void rootRightMouseDragged(const GuiEvent &event);
virtual void rootMiddleMouseDown(const GuiEvent &event);
virtual void rootMiddleMouseUp(const GuiEvent &event);
virtual void rootMiddleMouseDragged(const GuiEvent &event);
virtual void rootMouseWheelUp(const GuiEvent &event);
virtual void rootMouseWheelDown(const GuiEvent &event);
/// @}
/// @name Keyboard input methods
/// First responders
///
/// A first responder is a the GuiControl which responds first to input events
/// before passing them off for further processing.
/// @{
/// Moves the first responder to the next tabable controle
virtual bool tabNext(void);
/// Moves the first responder to the previous tabable control
virtual bool tabPrev(void);
/// Setups a keyboard accelerator which maps to a GuiControl.
///
/// @param ctrl GuiControl to map to.
/// @param index
/// @param keyCode Key code.
/// @param modifier Shift, ctrl, etc.
virtual void addAcceleratorKey(GuiControl *ctrl, U32 index, U32 keyCode, U32 modifier);
/// Sets the first responder.
/// @param firstResponder Control to designate as first responder
virtual void setFirstResponder(GuiControl *firstResponder);
/// @}
};
extern GuiCanvas *Canvas;
#endif