123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #ifndef _GUIEDITCTRL_H_
- #define _GUIEDITCTRL_H_
- #ifndef _GUICONTROL_H_
- #include "gui/core/guiControl.h"
- #endif
- #ifndef _UNDO_H_
- #include "util/undo.h"
- #endif
- #ifndef _GFX_GFXDRAWER_H_
- #include "gfx/gfxDrawUtil.h"
- #endif
- /// Native side of the GUI editor.
- class GuiEditCtrl : public GuiControl
- {
- public:
-
- typedef GuiControl Parent;
- friend class GuiEditorRuler;
- enum Justification
- {
- JUSTIFY_LEFT,
- JUSTIFY_CENTER_VERTICAL,
- JUSTIFY_RIGHT,
- JUSTIFY_TOP,
- JUSTIFY_BOTTOM,
- SPACING_VERTICAL,
- SPACING_HORIZONTAL,
- JUSTIFY_CENTER_HORIZONTAL,
- };
-
- enum guideAxis { GuideVertical, GuideHorizontal };
-
- enum mouseModes { Selecting, MovingSelection, SizingSelection, DragSelecting, DragGuide, DragClone };
- enum sizingModes { sizingNone = 0, sizingLeft = 1, sizingRight = 2, sizingTop = 4, sizingBottom = 8 };
-
- enum snappingAxis { SnapVertical, SnapHorizontal };
- enum snappingEdges { SnapEdgeMin, SnapEdgeMid, SnapEdgeMax };
- protected:
-
- enum
- {
- NUT_SIZE = 4,
- MIN_GRID_SIZE = 3
- };
-
- typedef Vector< GuiControl* > GuiControlVector;
- typedef SimObjectPtr< GuiControl > GuiControlPtr;
- bool mDrawBorderLines;
- bool mDrawGuides;
- bool mFullBoxSelection;
- GuiControlVector mSelectedControls;
- GuiControlPtr mCurrentAddSet;
- GuiControlPtr mContentControl;
- Point2I mLastMousePos;
- Point2I mLastDragPos;
- Point2I mSelectionAnchor;
- Point2I mGridSnap;
- Point2I mDragBeginPoint;
- Vector<Point2I> mDragBeginPoints;
- bool mDragAddSelection;
- bool mDragMoveUndo;
- // Guides.
-
- bool mSnapToGuides; ///< If true, edge and center snapping will work against guides.
- bool mDragGuide[ 2 ];
- U32 mDragGuideIndex[ 2 ];///< Indices of the guide's being dragged in DragGuide mouse mode.
- Vector< U32 > mGuides[ 2 ]; ///< The guides defined on the current content control.
- // Snapping
-
- bool mSnapToControls; ///< If true, edge and center snapping will work against controls.
- bool mSnapToCanvas; ///< If true, edge and center snapping will work against canvas (= content control).
- bool mSnapToEdges; ///< If true, selection edges will snap to other control edges.
- bool mSnapToCenters; ///< If true, selection centers will snap to other control centers.
- S32 mSnapSensitivity; ///< Snap distance in pixels.
-
- bool mSnapped[ 2 ]; ///< Snap flag for each axis. If true, we are currently snapped in a drag.
- S32 mSnapOffset[ 2 ]; ///< Reference point on snap line for each axis.
- GuiControlVector mSnapHits[ 2 ]; ///< Hit testing lists for each axis.
- snappingEdges mSnapEdge[ 2 ]; ///< Identification of edge being snapped for each axis.
- GuiControlPtr mSnapTargets[ 2 ]; ///< Controls providing the snap reference lines on each axis.
- // Undo
- SimGroup* mTrash;
- SimSet* mSelectedSet;
- // grid drawing
- GFXVertexBufferHandle<GFXVertexPCT> mDots;
- GFXStateBlockRef mDotSB;
- mouseModes mMouseDownMode;
- sizingModes mSizingMode;
-
- static StringTableEntry smGuidesPropertyName[ 2 ];
- // private methods
- void updateSelectedSet();
-
- S32 findGuide( guideAxis axis, const Point2I& point, U32 tolerance = 0 );
-
- RectI getSnapRegion( snappingAxis axis, const Point2I& center ) const;
- void findSnaps( snappingAxis axis, const Point2I& mousePoint, const RectI& minRegion, const RectI& midRegion, const RectI& maxRegion );
- void registerSnap( snappingAxis axis, const Point2I& mousePoint, const Point2I& point, snappingEdges edge, GuiControl* ctrl = NULL );
-
- void doSnapping( const GuiEvent& event, const RectI& selectionBounds, Point2I& delta );
- void doGuideSnap( const GuiEvent& event, const RectI& selectionBounds, const RectI& selectionBoundsGlobal, Point2I& delta );
- void doControlSnap( const GuiEvent& event, const RectI& selectionBounds, const RectI& selectionBoundsGlobal, Point2I& delta );
- void doGridSnap( const GuiEvent& event, const RectI& selectionBounds, const RectI& selectionBoundsGlobal, Point2I& delta );
- void snapToGrid( Point2I& point );
-
- void startDragMove( const Point2I& startPoint );
- void startDragRectangle( const Point2I& startPoint );
- void startDragClone( const Point2I& startPoint );
- void startMouseGuideDrag( guideAxis axis, U32 index, bool lockMouse = true );
-
- void setMouseMode( mouseModes mode );
-
- /// @name Callbacks
- /// @{
-
- DECLARE_CALLBACK( void, onHierarchyChanged, () );
- DECLARE_CALLBACK( void, onDelete, () );
- DECLARE_CALLBACK( void, onPreEdit, ( SimSet* selection ) );
- DECLARE_CALLBACK( void, onPostEdit, ( SimSet* selection ) );
- DECLARE_CALLBACK( void, onClearSelected, () );
- DECLARE_CALLBACK( void, onSelect, ( GuiControl* control ) );
- DECLARE_CALLBACK( void, onAddSelected, ( GuiControl* control ) );
- DECLARE_CALLBACK( void, onRemoveSelected, ( GuiControl* control ) );
- DECLARE_CALLBACK( void, onPreSelectionNudged, ( SimSet* selection ) );
- DECLARE_CALLBACK( void, onPostSelectionNudged, ( SimSet* selection ) );
- DECLARE_CALLBACK( void, onSelectionMoved, ( GuiControl* control ) ); //FIXME: this should be a selection SimSet
- DECLARE_CALLBACK( void, onSelectionCloned, ( SimSet* selection ) );
- DECLARE_CALLBACK( void, onTrashSelection, ( SimSet* selection ) );
- DECLARE_CALLBACK( void, onAddNewCtrl, ( GuiControl* control ) );
- DECLARE_CALLBACK( void, onAddNewCtrlSet, ( SimSet* set ) );
- DECLARE_CALLBACK( void, onSelectionResized, ( GuiControl* control ) );
- DECLARE_CALLBACK( void, onFitIntoParent, ( bool width, bool height ) );
- DECLARE_CALLBACK( void, onMouseModeChange, () );
- DECLARE_CALLBACK( void, onControlInspectPreApply, ( GuiControl* control ) );
- DECLARE_CALLBACK( void, onControlInspectPostApply, ( GuiControl* control ) );
-
- /// @}
-
- static bool inNut( const Point2I &pt, S32 x, S32 y )
- {
- S32 dx = pt.x - x;
- S32 dy = pt.y - y;
- return dx <= NUT_SIZE && dx >= -NUT_SIZE && dy <= NUT_SIZE && dy >= -NUT_SIZE;
- }
- static void drawCrossSection( U32 axis, S32 offset, const RectI& bounds, ColorI color, GFXDrawUtil* drawer )
- {
- Point2I start;
- Point2I end;
-
- if( axis == 0 )
- {
- start.x = end.x = offset;
- start.y = bounds.point.y;
- end.y = bounds.point.y + bounds.extent.y - 1;
- }
- else
- {
- start.y = end.y = offset;
- start.x = bounds.point.x;
- end.x = bounds.point.x + bounds.extent.x - 1;
- }
-
- drawer->drawLine( start, end, color );
- }
-
- static void snapDelta( snappingAxis axis, snappingEdges edge, S32 offset, const RectI& bounds, Point2I& delta )
- {
- switch( axis )
- {
- case SnapVertical:
- switch( edge )
- {
- case SnapEdgeMin:
- delta.x = offset - bounds.point.x;
- break;
-
- case SnapEdgeMid:
- delta.x = offset - bounds.point.x - bounds.extent.x / 2;
- break;
-
- case SnapEdgeMax:
- delta.x = offset - bounds.point.x - bounds.extent.x + 1;
- break;
- }
- break;
-
- case SnapHorizontal:
- switch( edge )
- {
- case SnapEdgeMin:
- delta.y = offset - bounds.point.y;
- break;
-
- case SnapEdgeMid:
- delta.y = offset - bounds.point.y - bounds.extent.y / 2;
- break;
-
- case SnapEdgeMax:
- delta.y = offset - bounds.point.y - bounds.extent.y + 1;
- break;
- }
- break;
- }
- }
- public:
- GuiEditCtrl();
-
- DECLARE_CONOBJECT(GuiEditCtrl);
- DECLARE_CATEGORY( "Gui Editor" );
- DECLARE_DESCRIPTION( "Implements the framework for the GUI editor." );
- bool onWake();
- void onSleep();
-
- static void initPersistFields();
- GuiControl* getContentControl() const { return mContentControl; }
- void setContentControl(GuiControl *ctrl);
- void setEditMode(bool value);
- S32 getSizingHitKnobs(const Point2I &pt, const RectI &box);
- void getDragRect(RectI &b);
- void drawNut(const Point2I &nut, ColorI &outlineColor, ColorI &nutColor);
- void drawNuts(RectI &box, ColorI &outlineColor, ColorI &nutColor);
- void onPreRender();
- void onRender(Point2I offset, const RectI &updateRect);
- void addNewControl(GuiControl *ctrl);
- void setCurrentAddSet(GuiControl *ctrl, bool clearSelection = true);
- GuiControl* getCurrentAddSet();
-
- // Selections.
- void select( GuiControl *ctrl );
- bool selectionContains( GuiControl *ctrl );
- bool selectionContainsParentOf( GuiControl* ctrl );
- void setSelection( GuiControl *ctrl, bool inclusive = false );
- RectI getSelectionBounds() const;
- RectI getSelectionGlobalBounds() const;
- void canHitSelectedControls( bool state = true );
- void justifySelection( Justification j );
- void moveSelection( const Point2I &delta, bool callback = true );
- void moveAndSnapSelection( const Point2I &delta, bool callback = true );
- void saveSelection( const char *filename );
- void loadSelection( const char *filename );
- void addSelection( S32 id );
- void addSelection( GuiControl* ctrl );
- void removeSelection( S32 id );
- void removeSelection( GuiControl* ctrl );
- void deleteSelection();
- void clearSelection();
- void selectAll();
- void bringToFront();
- void pushToBack();
- void moveSelectionToCtrl( GuiControl* ctrl, bool callback = true );
- void addSelectControlsInRegion( const RectI& rect, U32 hitTestFlags = 0 );
- void addSelectControlAt( const Point2I& pos );
- void resizeControlsInSelectionBy( const Point2I& delta, U32 mode );
- void fitIntoParents( bool width = true, bool height = true );
- void selectParents( bool addToSelection = false );
- void selectChildren( bool addToSelection = false );
- void cloneSelection();
- U32 getNumSelected() const { return mSelectedControls.size(); }
-
- // Guides.
-
- U32 addGuide( guideAxis axis, U32 offset ) { U32 index = mGuides[ axis ].size(); mGuides[ axis ].push_back( offset ); return index; }
- void readGuides( guideAxis axis, GuiControl* ctrl );
- void writeGuides( guideAxis axis, GuiControl* ctrl );
- void clearGuides( guideAxis axis ) { mGuides[ axis ].clear(); }
- // Undo Access.
-
- void undo();
- void redo();
- // When a control is changed by the inspector
- void controlInspectPreApply(GuiControl* object);
- void controlInspectPostApply(GuiControl* object);
- // Sizing Cursors
- void getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent);
- U32 getSelectionSize() const { return mSelectedControls.size(); }
- const Vector<GuiControl *>& getSelected() const { return mSelectedControls; }
- SimSet* getSelectedSet() { updateSelectedSet(); return mSelectedSet; }
- SimGroup* getTrash() { return mTrash; }
- GuiControl* getAddSet() const { return mCurrentAddSet; }; //JDD
- bool onKeyDown(const GuiEvent &event);
- void onMouseDown(const GuiEvent &event);
- void onMouseUp(const GuiEvent &event);
- void onMouseDragged(const GuiEvent &event);
- void onRightMouseDown(const GuiEvent &event);
-
- mouseModes getMouseMode() const { return mMouseDownMode; }
- virtual bool onAdd();
- virtual void onRemove();
- void setSnapToGrid(U32 gridsize);
- };
- #endif //_GUI_EDIT_CTRL_H
|