//----------------------------------------------------------------------------- // 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 mMouseCapturedControl; ///< All mouse events will go to this ctrl only SimObjectPtr 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 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