mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
340 lines
15 KiB
C++
340 lines
15 KiB
C++
//-----------------------------------------------------------------------------
|
|
// 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<GFXVertexPC> 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
|