git mv Code\Sandbox\Editor Code/Editor
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "AxisGizmo.h"
|
||||
|
||||
// Editor
|
||||
#include "Viewport.h"
|
||||
#include "GizmoManager.h"
|
||||
#include "ViewManager.h"
|
||||
#include "Settings.h"
|
||||
#include "RenderHelpers/AxisHelper.h"
|
||||
#include "IObjectManager.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CAxisGizmo implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CAxisGizmo::m_axisGizmoCount = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CAxisGizmo::CAxisGizmo(CBaseObject* object)
|
||||
{
|
||||
assert(object != 0);
|
||||
m_object = object;
|
||||
m_pAxisHelper.reset(new CAxisHelper);
|
||||
|
||||
// Set selectable flag.
|
||||
SetFlags(EGIZMO_SELECTABLE | EGIZMO_TRANSFORM_MANIPULATOR);
|
||||
|
||||
m_axisGizmoCount++;
|
||||
m_object->AddEventListener(this);
|
||||
|
||||
m_localTM.SetIdentity();
|
||||
m_parentTM.SetIdentity();
|
||||
m_matrix.SetIdentity();
|
||||
|
||||
m_bDragging = false;
|
||||
m_bAlwaysUseLocal = false;
|
||||
m_coordSysBackUp = COORDS_VIEW;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CAxisGizmo::CAxisGizmo()
|
||||
{
|
||||
// Set selectable flag.
|
||||
SetFlags(EGIZMO_SELECTABLE);
|
||||
m_axisGizmoCount++;
|
||||
m_pAxisHelper.reset(new CAxisHelper);
|
||||
m_bDragging = false;
|
||||
m_bAlwaysUseLocal = false;
|
||||
m_coordSysBackUp = COORDS_VIEW;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CAxisGizmo::~CAxisGizmo()
|
||||
{
|
||||
if (m_object)
|
||||
{
|
||||
m_object->RemoveEventListener(this);
|
||||
}
|
||||
m_axisGizmoCount--;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAxisGizmo::OnObjectEvent([[maybe_unused]] CBaseObject* object, int event)
|
||||
{
|
||||
if (event == CBaseObject::ON_DELETE || event == CBaseObject::ON_UNSELECT)
|
||||
{
|
||||
// This gizmo must be deleted as well.
|
||||
GetIEditor()->GetObjectManager()->GetGizmoManager()->RemoveGizmo(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAxisGizmo::Display(DisplayContext& dc)
|
||||
{
|
||||
if (m_object)
|
||||
{
|
||||
const bool visible =
|
||||
!m_object->IsHidden()
|
||||
&& !m_object->IsFrozen()
|
||||
&& m_object->IsSelected();
|
||||
|
||||
if (!visible)
|
||||
{
|
||||
// This gizmo must be deleted.
|
||||
DeleteThis();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_object->IsSkipSelectionHelper())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DrawAxis(dc);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAxisGizmo::SetWorldBounds(const AABB& bbox)
|
||||
{
|
||||
m_bbox = bbox;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAxisGizmo::GetWorldBounds(AABB& bbox)
|
||||
{
|
||||
if (m_object)
|
||||
{
|
||||
m_object->GetBoundBox(bbox);
|
||||
}
|
||||
else
|
||||
{
|
||||
bbox.min = Vec3(-1000000, -1000000, -1000000);
|
||||
bbox.max = Vec3(1000000, 1000000, 1000000);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAxisGizmo::DrawAxis(DisplayContext& dc)
|
||||
{
|
||||
m_pAxisHelper->SetHighlightAxis(m_highlightAxis);
|
||||
|
||||
Matrix34 tm = GetTransformation(m_bAlwaysUseLocal ? COORDS_LOCAL : GetIEditor()->GetReferenceCoordSys(), dc.view);
|
||||
m_pAxisHelper->DrawAxis(tm, GetIEditor()->GetGlobalGizmoParameters(), dc);
|
||||
if (m_object && m_object->CheckFlags(OBJFLAG_IS_PARTICLE))
|
||||
{
|
||||
AABB objectBox;
|
||||
m_object->GetBoundBox(objectBox);
|
||||
|
||||
m_pAxisHelper->DrawDome(tm, GetIEditor()->GetGlobalGizmoParameters(), dc, objectBox);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const Matrix34& CAxisGizmo::GetMatrix() const
|
||||
{
|
||||
if (m_object)
|
||||
{
|
||||
m_matrix.SetTranslation(m_object->GetWorldTM().GetTranslation());
|
||||
}
|
||||
return m_matrix;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAxisGizmo::HitTest(HitContext& hc)
|
||||
{
|
||||
Matrix34 tm = GetTransformation(m_bAlwaysUseLocal ? COORDS_LOCAL : GetIEditor()->GetReferenceCoordSys(), hc.view);
|
||||
|
||||
CAxisHelper axis;
|
||||
bool bRes = m_pAxisHelper->HitTest(tm, GetIEditor()->GetGlobalGizmoParameters(), hc);
|
||||
if (bRes)
|
||||
{
|
||||
hc.object = m_object;
|
||||
}
|
||||
|
||||
m_highlightAxis = m_pAxisHelper->GetHighlightAxis();
|
||||
|
||||
return bRes;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAxisGizmo::HitTestManipulator(HitContext& hc)
|
||||
{
|
||||
return HitTest(hc);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CAxisGizmo::SetTransformation(RefCoordSys coordSys, const Matrix34& tm)
|
||||
{
|
||||
switch (coordSys)
|
||||
{
|
||||
case COORDS_WORLD:
|
||||
SetMatrix(tm);
|
||||
break;
|
||||
case COORDS_LOCAL:
|
||||
m_localTM = tm;
|
||||
{
|
||||
Matrix34 wtm;
|
||||
wtm.SetIdentity();
|
||||
wtm.SetTranslation(m_localTM.GetTranslation());
|
||||
SetMatrix(wtm);
|
||||
m_userTM = tm;
|
||||
}
|
||||
m_parentTM = m_localTM;
|
||||
break;
|
||||
case COORDS_PARENT:
|
||||
m_parentTM = tm;
|
||||
break;
|
||||
case COORDS_USERDEFINED:
|
||||
m_userTM = tm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Matrix34 CAxisGizmo::GetTransformation(RefCoordSys coordSys, IDisplayViewport* view /*=nullptr*/) const
|
||||
{
|
||||
if (m_object)
|
||||
{
|
||||
switch (coordSys)
|
||||
{
|
||||
case COORDS_VIEW:
|
||||
if (view)
|
||||
{
|
||||
Matrix34 tm = view->GetViewTM();
|
||||
tm.SetTranslation(m_object->GetWorldTM().GetTranslation());
|
||||
return tm;
|
||||
}
|
||||
return GetMatrix();
|
||||
break;
|
||||
case COORDS_LOCAL:
|
||||
return m_object->GetWorldTM();
|
||||
break;
|
||||
case COORDS_PARENT:
|
||||
//return m_parentTM;
|
||||
if (m_object->GetParent())
|
||||
{
|
||||
Matrix34 parentTM = m_object->GetParent()->GetWorldTM();
|
||||
parentTM.SetTranslation(m_object->GetWorldTM().GetTranslation());
|
||||
return parentTM;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetMatrix();
|
||||
}
|
||||
break;
|
||||
case COORDS_WORLD:
|
||||
return GetMatrix();
|
||||
break;
|
||||
case COORDS_USERDEFINED:
|
||||
{
|
||||
Matrix34 userTM;
|
||||
userTM.SetIdentity();
|
||||
userTM.SetTranslation(m_object->GetWorldTM().GetTranslation());
|
||||
return userTM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (coordSys)
|
||||
{
|
||||
case COORDS_VIEW:
|
||||
return GetMatrix();
|
||||
break;
|
||||
case COORDS_LOCAL:
|
||||
return m_localTM;
|
||||
break;
|
||||
case COORDS_PARENT:
|
||||
return m_parentTM;
|
||||
break;
|
||||
case COORDS_WORLD:
|
||||
return GetMatrix();
|
||||
break;
|
||||
case COORDS_USERDEFINED:
|
||||
return m_userTM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return GetMatrix();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, [[maybe_unused]] int nFlags)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor);
|
||||
|
||||
if (event == eMouseLDown)
|
||||
{
|
||||
HitContext hc;
|
||||
hc.view = view;
|
||||
hc.b2DViewport = view->GetType() != ET_ViewportCamera;
|
||||
hc.point2d = point;
|
||||
view->ViewToWorldRay(point, hc.raySrc, hc.rayDir);
|
||||
if (HitTest(hc))
|
||||
{
|
||||
if (event != eMouseLDown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// On Left mouse down.
|
||||
|
||||
// Hit axis gizmo.
|
||||
GetIEditor()->SetAxisConstraints((AxisConstrains)hc.axis);
|
||||
view->SetAxisConstrain(hc.axis);
|
||||
|
||||
if (m_bAlwaysUseLocal)
|
||||
{
|
||||
m_coordSysBackUp = GetIEditor()->GetReferenceCoordSys();
|
||||
GetIEditor()->SetReferenceCoordSys(COORDS_LOCAL);
|
||||
}
|
||||
|
||||
view->SetConstructionMatrix(COORDS_LOCAL, GetTransformation(COORDS_LOCAL));
|
||||
view->SetConstructionMatrix(COORDS_PARENT, GetTransformation(COORDS_PARENT));
|
||||
view->SetConstructionMatrix(COORDS_USERDEFINED, GetTransformation(COORDS_USERDEFINED));
|
||||
|
||||
view->BeginUndo();
|
||||
view->CaptureMouse();
|
||||
m_bDragging = true;
|
||||
m_cMouseDownPos = point;
|
||||
m_initPos = GetTransformation(COORDS_WORLD).GetTranslation();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (event == eMouseMove)
|
||||
{
|
||||
if (m_bDragging)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hit test current transform manipulator, to highlight when mouse over.
|
||||
HitContext hc;
|
||||
hc.view = view;
|
||||
hc.b2DViewport = view->GetType() != ET_ViewportCamera;
|
||||
hc.point2d = point;
|
||||
view->ViewToWorldRay(point, hc.raySrc, hc.rayDir);
|
||||
bool bHit = false;
|
||||
if (HitTest(hc))
|
||||
{
|
||||
switch (hc.manipulatorMode)
|
||||
{
|
||||
case 1:
|
||||
view->SetCurrentCursor(STD_CURSOR_MOVE);
|
||||
break;
|
||||
case 2:
|
||||
view->SetCurrentCursor(STD_CURSOR_ROTATE);
|
||||
break;
|
||||
case 3:
|
||||
view->SetCurrentCursor(STD_CURSOR_SCALE);
|
||||
break;
|
||||
}
|
||||
bHit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event == eMouseLUp)
|
||||
{
|
||||
if (m_bDragging)
|
||||
{
|
||||
view->AcceptUndo("Manipulator Drag");
|
||||
view->ReleaseMouse();
|
||||
m_bDragging = false;
|
||||
|
||||
if (m_bAlwaysUseLocal)
|
||||
{
|
||||
GetIEditor()->SetReferenceCoordSys(m_coordSysBackUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_AXISGIZMO_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_AXISGIZMO_H
|
||||
#pragma once
|
||||
|
||||
#include "BaseObject.h"
|
||||
#include "Gizmo.h"
|
||||
#include "Include/ITransformManipulator.h"
|
||||
|
||||
// forward declarations.
|
||||
struct DisplayContext;
|
||||
class CAxisHelper;
|
||||
|
||||
/** Gizmo of Objects animation track.
|
||||
*/
|
||||
class SANDBOX_API CAxisGizmo
|
||||
: public CGizmo
|
||||
, public ITransformManipulator
|
||||
, public CBaseObject::EventListener
|
||||
{
|
||||
public:
|
||||
CAxisGizmo();
|
||||
// Creates axis gizmo linked to an object.
|
||||
CAxisGizmo(CBaseObject* object);
|
||||
~CAxisGizmo();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Ovverides from CGizmo
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void GetWorldBounds(AABB& bbox);
|
||||
virtual void Display(DisplayContext& dc);
|
||||
virtual bool HitTest(HitContext& hc);
|
||||
virtual const Matrix34& GetMatrix() const;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ITransformManipulator implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual Matrix34 GetTransformation(RefCoordSys coordSys, IDisplayViewport* view = nullptr) const;
|
||||
virtual void SetTransformation(RefCoordSys coordSys, const Matrix34& tm);
|
||||
virtual bool HitTestManipulator(HitContext& hc);
|
||||
virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int nFlags);
|
||||
virtual void SetAlwaysUseLocal(bool on)
|
||||
{ m_bAlwaysUseLocal = on; }
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SetWorldBounds(const AABB& bbox);
|
||||
|
||||
void DrawAxis(DisplayContext& dc);
|
||||
|
||||
static int GetGlobalAxisGizmoCount() { return m_axisGizmoCount; }
|
||||
|
||||
CBaseObjectPtr GetBaseObject() const override { return m_object; }
|
||||
|
||||
private:
|
||||
void OnObjectEvent(CBaseObject* object, int event) override;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
CBaseObjectPtr m_object;
|
||||
AABB m_bbox;
|
||||
std::unique_ptr<CAxisHelper> m_pAxisHelper;
|
||||
|
||||
bool m_bDragging;
|
||||
QPoint m_cMouseDownPos;
|
||||
Vec3 m_initPos;
|
||||
|
||||
int m_highlightAxis;
|
||||
|
||||
Matrix34 m_localTM;
|
||||
Matrix34 m_parentTM;
|
||||
Matrix34 m_userTM;
|
||||
|
||||
bool m_bAlwaysUseLocal;
|
||||
RefCoordSys m_coordSysBackUp;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
static int m_axisGizmoCount;
|
||||
};
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_AXISGIZMO_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,852 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : Definition of basic Editor object.
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_BASEOBJECT_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_BASEOBJECT_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "Include/HitContext.h"
|
||||
#include "ClassDesc.h"
|
||||
#include "DisplayContext.h"
|
||||
#include "ObjectLoader.h"
|
||||
#include "Util/Variable.h"
|
||||
|
||||
#include "AzCore/Math/Guid.h"
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// forward declarations.
|
||||
class CUndoBaseObject;
|
||||
class CObjectManager;
|
||||
class CGizmo;
|
||||
class CObjectArchive;
|
||||
struct SSubObjSelectionModifyContext;
|
||||
struct SRayHitInfo;
|
||||
class ISubObjectSelectionReferenceFrameCalculator;
|
||||
class CPopupMenuItem;
|
||||
class QMenu;
|
||||
struct IRenderNode;
|
||||
struct IStatObj;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef _smart_ptr<CBaseObject> CBaseObjectPtr;
|
||||
typedef std::vector<CBaseObjectPtr> TBaseObjects;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/*!
|
||||
This class used for object references remapping during cloning operation.
|
||||
*/
|
||||
class CObjectCloneContext
|
||||
{
|
||||
public:
|
||||
//! Add cloned object.
|
||||
SANDBOX_API void AddClone(CBaseObject* pFromObject, CBaseObject* pToObject);
|
||||
|
||||
//! Find cloned object for given object.
|
||||
SANDBOX_API CBaseObject* FindClone(CBaseObject* pFromObject);
|
||||
|
||||
// Find id of the cloned object.
|
||||
GUID ResolveClonedID(REFGUID guid);
|
||||
|
||||
private:
|
||||
typedef std::map<CBaseObject*, CBaseObject*> ObjectsMap;
|
||||
ObjectsMap m_objectsMap;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum EObjectChangedOpType
|
||||
{
|
||||
eOCOT_Empty = 0,
|
||||
eOCOT_Modify,
|
||||
eOCOT_ModifyTransform,
|
||||
eOCOT_ModifyTransformInLibOnly,
|
||||
eOCOT_Add,
|
||||
eOCOT_Delete,
|
||||
eOCOT_Count
|
||||
};
|
||||
|
||||
struct SObjectChangedContext
|
||||
{
|
||||
GUID m_modifiedObjectGlobalId; //! The object id globaly unique and used in ObjectManager
|
||||
EObjectChangedOpType m_operation; //! What was the operation on the modified object
|
||||
Matrix34 m_localTM; //! If we are in modify transform case this is the local TM info
|
||||
|
||||
SObjectChangedContext(EObjectChangedOpType optype)
|
||||
: m_modifiedObjectGlobalId(GUID_NULL)
|
||||
, m_operation(optype) { m_localTM.SetIdentity(); }
|
||||
SObjectChangedContext()
|
||||
: m_modifiedObjectGlobalId(GUID_NULL)
|
||||
, m_operation(eOCOT_Empty) { m_localTM.SetIdentity(); }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum ObjectFlags
|
||||
{
|
||||
OBJFLAG_SELECTED = 0x0001, //!< Object is selected. (Do not set this flag explicitly).
|
||||
OBJFLAG_HIDDEN = 0x0002, //!< Object is hidden.
|
||||
OBJFLAG_FROZEN = 0x0004, //!< Object is frozen (Visible but cannot be selected)
|
||||
OBJFLAG_FLATTEN = 0x0008, //!< Flatten area around object.
|
||||
OBJFLAG_SHARED = 0x0010, //!< This object is shared between missions.
|
||||
|
||||
OBJFLAG_KEEP_HEIGHT = 0x0040, //!< This object should try to preserve height when snapping to flat objects.
|
||||
|
||||
OBJFLAG_NO_HITTEST = 0x0080, //!< This object will be not a target of ray hit test for deep selection mode.
|
||||
OBJFLAG_IS_PARTICLE = 0x0100,
|
||||
// object is in editing mode.
|
||||
OBJFLAG_EDITING = 0x01000,
|
||||
OBJFLAG_ATTACHING = 0x02000, //!< Object in attaching to group mode.
|
||||
OBJFLAG_DELETED = 0x04000, //!< This object is deleted.
|
||||
OBJFLAG_HIGHLIGHT = 0x08000, //!< Object is highlighted (When mouse over).
|
||||
OBJFLAG_INVISIBLE = 0x10000, //!< This object is invisible.
|
||||
OBJFLAG_SUBOBJ_EDITING = 0x20000, //!< This object is in the sub object editing mode.
|
||||
|
||||
OBJFLAG_SHOW_ICONONTOP = 0x100000, //!< Icon will be drawn on top of the object.
|
||||
OBJFLAG_HIDE_HELPERS = 0x200000, //!< Helpers will be hidden.
|
||||
OBJFLAG_DONT_SAVE = 0x400000, //!< Object will not be saved with editor xml data.
|
||||
|
||||
OBJFLAG_PERSISTMASK = OBJFLAG_HIDDEN | OBJFLAG_FROZEN | OBJFLAG_FLATTEN,
|
||||
};
|
||||
|
||||
#define ERF_GET_WRITABLE(flags) (flags)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! This flags passed to CBaseObject::BeginEditParams method.
|
||||
enum ObjectEditFlags
|
||||
{
|
||||
OBJECT_CREATE = 0x001,
|
||||
OBJECT_EDIT = 0x002,
|
||||
OBJECT_COLLAPSE_OBJECTPANEL = 0x004
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Return values from CBaseObject::MouseCreateCallback method.
|
||||
enum MouseCreateResult
|
||||
{
|
||||
MOUSECREATE_CONTINUE = 0, //!< Continue placing this object.
|
||||
MOUSECREATE_ABORT, //!< Abort creation of this object.
|
||||
MOUSECREATE_OK, //!< Accept this object.
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Interface to the object create with the mouse callback.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct IMouseCreateCallback
|
||||
{
|
||||
virtual void Release() = 0;
|
||||
virtual MouseCreateResult OnMouseEvent(CViewport* view, EMouseEvent event, QPoint& point, int flags) = 0;
|
||||
// Some process of creation need to be able to be displayed such as creation for custom solid.
|
||||
virtual void Display([[maybe_unused]] DisplayContext& dc){}
|
||||
// Called after accepting an object to see if new object creation mode should be continued.
|
||||
virtual bool ContinueCreation() = 0;
|
||||
};
|
||||
|
||||
// Flags used for object interaction
|
||||
enum EObjectUpdateFlags
|
||||
{
|
||||
eObjectUpdateFlags_UserInput = 0x00001,
|
||||
eObjectUpdateFlags_PositionChanged = 0x00002,
|
||||
eObjectUpdateFlags_RotationChanged = 0x00004,
|
||||
eObjectUpdateFlags_ScaleChanged = 0x00008,
|
||||
eObjectUpdateFlags_DoNotInvalidate = 0x00100, // Do not cause InvalidateTM call.
|
||||
eObjectUpdateFlags_ParentChanged = 0x00200, // When parent transformation change.
|
||||
eObjectUpdateFlags_Undo = 0x00400, // When doing undo operation.
|
||||
eObjectUpdateFlags_RestoreUndo = 0x00800, // When doing RestoreUndo operation (This is different from normal undo).
|
||||
eObjectUpdateFlags_Animated = 0x01000, // When doing animation.
|
||||
eObjectUpdateFlags_MoveTool = 0x02000, // Transformation changed by the move tool
|
||||
eObjectUpdateFlags_ScaleTool = 0x04000, // Transformation changed by the scale tool
|
||||
eObjectUpdateFlags_UserInputUndo = 0x20000, // Undo operation related to user input rather than actual Undo
|
||||
};
|
||||
|
||||
#define OBJECT_TEXTURE_ICON_SIZEX 32
|
||||
#define OBJECT_TEXTURE_ICON_SIZEY 32
|
||||
#define OBJECT_TEXTURE_ICON_SCALE 10.0f
|
||||
|
||||
enum EScaleWarningLevel
|
||||
{
|
||||
eScaleWarningLevel_None,
|
||||
eScaleWarningLevel_Rescaled,
|
||||
eScaleWarningLevel_RescaledNonUniform,
|
||||
};
|
||||
|
||||
enum ERotationWarningLevel
|
||||
{
|
||||
eRotationWarningLevel_None = 0,
|
||||
eRotationWarningLevel_Rotated,
|
||||
eRotationWarningLevel_RotatedNonRectangular,
|
||||
};
|
||||
|
||||
// Used for external control of object position without changing the object's real position (e.g. TrackView)
|
||||
class ITransformDelegate
|
||||
{
|
||||
public:
|
||||
// Called when matrix got invalidatd
|
||||
virtual void MatrixInvalidated() = 0;
|
||||
|
||||
// Returns current delegated transforms, base transform is passed for delegates
|
||||
// that need it, e.g. for overriding only X
|
||||
virtual Vec3 GetTransformDelegatePos(const Vec3& basePos) const = 0;
|
||||
virtual Quat GetTransformDelegateRotation(const Quat& baseRotation) const = 0;
|
||||
virtual Vec3 GetTransformDelegateScale(const Vec3& baseScale) const = 0;
|
||||
|
||||
// Sets the delegate transform.
|
||||
virtual void SetTransformDelegatePos(const Vec3& position) = 0;
|
||||
virtual void SetTransformDelegateRotation(const Quat& rotation) = 0;
|
||||
virtual void SetTransformDelegateScale(const Vec3& scale) = 0;
|
||||
|
||||
// If those return true the base object uses its own transform instead
|
||||
virtual bool IsPositionDelegated() const = 0;
|
||||
virtual bool IsRotationDelegated() const = 0;
|
||||
virtual bool IsScaleDelegated() const = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
* CBaseObject is the base class for all objects which can be placed in map.
|
||||
* Every object belongs to class specified by ClassDesc.
|
||||
* Specific object classes must override this class, to provide specific functionality.
|
||||
* Objects are reference counted and only destroyed when last reference to object
|
||||
* is destroyed.
|
||||
*
|
||||
*/
|
||||
class SANDBOX_API CBaseObject
|
||||
: public CVarObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
//! Events sent by object to EventListeners
|
||||
enum EObjectListenerEvent
|
||||
{
|
||||
ON_DELETE = 0,// Sent after object was deleted from object manager.
|
||||
ON_ADD, // Sent after object was added to object manager.
|
||||
ON_SELECT, // Sent when objects becomes selected.
|
||||
ON_UNSELECT, // Sent when objects unselected.
|
||||
ON_TRANSFORM, // Sent when object transformed.
|
||||
ON_VISIBILITY, // Sent when object visibility changes.
|
||||
ON_RENAME, // Sent when object changes name.
|
||||
ON_CHILDATTACHED, // Sent when object gets a child attached.
|
||||
ON_PREDELETE, // Sent before an object is processed to be deleted from the object manager.
|
||||
ON_CHILDDETACHED, // Sent when the object gets a child detached.
|
||||
ON_DETACHFROMPARENT, // Sent when the object detaches from a parent.
|
||||
ON_PREATTACHED, // Sent when this object is about to get attached and is already in relative space
|
||||
ON_PREATTACHEDKEEPXFORM, // Sent when this object is about to get attached and needs to stay in place
|
||||
ON_ATTACHED, // Sent when this object got attached
|
||||
ON_PREDETACHED, // Sent when this object is about to get detached and is already in relative space
|
||||
ON_PREDETACHEDKEEPXFORM, // Sent when this object is about to get detached and needs to stay in place
|
||||
ON_DETACHED, // Sent when this object got detached
|
||||
ON_PREFAB_CHANGED, // Sent when prefab representation has been changed
|
||||
};
|
||||
|
||||
//! This callback will be called if object is deleted.
|
||||
struct EventListener
|
||||
{
|
||||
virtual void OnObjectEvent(CBaseObject*, int) = 0;
|
||||
};
|
||||
|
||||
//! Childs structure.
|
||||
typedef std::vector<_smart_ptr<CBaseObject> > Childs;
|
||||
|
||||
//! Retrieve class description of this object.
|
||||
CObjectClassDesc* GetClassDesc() const { return m_classDesc; };
|
||||
|
||||
static bool IsEnabled() { return true; }
|
||||
|
||||
/** Check if both object are of same class.
|
||||
*/
|
||||
virtual bool IsSameClass(CBaseObject* obj);
|
||||
virtual void SetDefaultType() { m_objType = OBJTYPE_DUMMY; };
|
||||
virtual ObjectType GetType() const
|
||||
{
|
||||
if (m_objType == OBJTYPE_DUMMY)
|
||||
{
|
||||
return m_objType;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_classDesc->GetObjectType();
|
||||
}
|
||||
};
|
||||
// const char* GetTypeName() const { return m_classDesc->ClassName(); };
|
||||
QString GetTypeName() const;
|
||||
virtual QString GetTypeDescription() const { return m_classDesc->ClassName(); };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Flags.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SetFlags(int flags) { m_flags |= flags; };
|
||||
void ClearFlags(int flags) { m_flags &= ~flags; };
|
||||
bool CheckFlags(int flags) const { return (m_flags & flags) != 0; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Hidden ID
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static const uint64 s_invalidHiddenID = 0;
|
||||
uint64 GetHideOrder() const { return m_hideOrder; }
|
||||
void SetHideOrder(uint64 newID) { m_hideOrder = newID; }
|
||||
|
||||
//! Returns true if object hidden.
|
||||
bool IsHidden() const;
|
||||
//! Check against min spec.
|
||||
bool IsHiddenBySpec() const;
|
||||
//! Returns true if object frozen.
|
||||
virtual bool IsFrozen() const;
|
||||
//! Returns true if object is shared between missions.
|
||||
bool IsShared() const { return CheckFlags(OBJFLAG_SHARED); }
|
||||
|
||||
//! Returns true if object is selected.
|
||||
virtual bool IsSelected() const { return CheckFlags(OBJFLAG_SELECTED); }
|
||||
//! Returns true if object can be selected.
|
||||
virtual bool IsSelectable() const;
|
||||
|
||||
// Return texture icon.
|
||||
bool HaveTextureIcon() const { return m_nTextureIcon != 0; };
|
||||
int GetTextureIcon() const { return m_nTextureIcon; }
|
||||
void SetTextureIcon(int nTexIcon) { m_nTextureIcon = nTexIcon; }
|
||||
|
||||
//! Set shared between missions flag.
|
||||
virtual void SetShared(bool bShared);
|
||||
//! Set object hidden status.
|
||||
virtual void SetHidden(bool bHidden, uint64 hiddenId = CBaseObject::s_invalidHiddenID, bool bAnimated = false);
|
||||
//! Set object frozen status.
|
||||
virtual void SetFrozen(bool bFrozen);
|
||||
//! Set object selected status.
|
||||
virtual void SetSelected(bool bSelect);
|
||||
//! Return associated 3DEngine render node
|
||||
virtual IRenderNode* GetEngineNode() const { return NULL; };
|
||||
//! Set object highlighted (Note: not selected)
|
||||
virtual void SetHighlight(bool bHighlight);
|
||||
//! Check if object is highlighted.
|
||||
bool IsHighlighted() const { return CheckFlags(OBJFLAG_HIGHLIGHT); }
|
||||
//! Check if object can have measurement axises.
|
||||
virtual bool HasMeasurementAxis() const { return true; }
|
||||
//! Check if the object is isolated when the editor is in Isolation Mode
|
||||
virtual bool IsIsolated() const { return false; }
|
||||
|
||||
// Tooltip is rendered in CObjectMode, when you hover the object
|
||||
virtual QString GetTooltip() const { return QString(); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Object Id.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Get unique object id.
|
||||
//! Every object will have its own unique id assigned.
|
||||
REFGUID GetId() const { return m_guid; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Get name of object.
|
||||
const QString& GetName() const;
|
||||
virtual QString GetComment() const { return QString(); }
|
||||
virtual QString GetWarningsText() const;
|
||||
|
||||
//! Change name of object.
|
||||
virtual void SetName(const QString& name);
|
||||
//! Set object name and make sure it is unique.
|
||||
void SetUniqueName(const QString& name);
|
||||
//! Generate unique object name based on a base name (e.g. class name)
|
||||
virtual void GenerateUniqueName();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Geometry.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Set object position.
|
||||
virtual bool SetPos(const Vec3& pos, int flags = 0);
|
||||
|
||||
//! Set object rotation angles.
|
||||
virtual bool SetRotation(const Quat& rotate, int flags = 0);
|
||||
|
||||
//! Set object scale.
|
||||
virtual bool SetScale(const Vec3& scale, int flags = 0);
|
||||
|
||||
//! Get object position.
|
||||
const Vec3 GetPos() const;
|
||||
|
||||
//! Get object local rotation quaternion.
|
||||
const Quat GetRotation() const;
|
||||
|
||||
//! Get object scale.
|
||||
const Vec3 GetScale() const;
|
||||
|
||||
virtual bool StartScaling() { return false; }
|
||||
virtual bool GetUntransformedScale([[maybe_unused]] Vec3& scale) const { return false; }
|
||||
virtual bool TransformScale([[maybe_unused]] const Vec3& scale) { return false; }
|
||||
|
||||
//! Set flatten area.
|
||||
void SetArea(float area);
|
||||
float GetArea() const { return m_flattenArea; };
|
||||
|
||||
//! Assign display color to the object.
|
||||
virtual void ChangeColor(const QColor& color);
|
||||
//! Get object color.
|
||||
QColor GetColor() const { return m_color; };
|
||||
|
||||
// Set current transform delegate. Pass nullptr to unset.
|
||||
virtual void SetTransformDelegate(ITransformDelegate* pTransformDelegate);
|
||||
ITransformDelegate* GetTransformDelegate() const { return m_pTransformDelegate; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CHILDS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Return true if node have childs.
|
||||
bool HaveChilds() const { return !m_childs.empty(); }
|
||||
//! Return true if have attached childs.
|
||||
size_t GetChildCount() const { return m_childs.size(); }
|
||||
|
||||
//! Get child by index.
|
||||
CBaseObject* GetChild(size_t const i) const;
|
||||
//! Return parent node if exist.
|
||||
CBaseObject* GetParent() const { return m_parent; };
|
||||
//! Scans hierarchy up to determine if we child of specified node.
|
||||
virtual bool IsChildOf(CBaseObject* node);
|
||||
//! Get all child objects
|
||||
void GetAllChildren(TBaseObjects& outAllChildren, CBaseObject* pObj = NULL) const;
|
||||
void GetAllChildren(DynArray< _smart_ptr<CBaseObject> >& outAllChildren, CBaseObject* pObj = NULL) const;
|
||||
void GetAllChildren(CSelectionGroup& outAllChildren, CBaseObject* pObj = NULL) const;
|
||||
//! Clone Children
|
||||
void CloneChildren(CBaseObject* pFromObject);
|
||||
//! Attach new child node.
|
||||
//! @param bKeepPos if true Child node will keep its world space position.
|
||||
virtual void AttachChild(CBaseObject* child, bool bKeepPos = true);
|
||||
//! Attach new child node when the object is not a sort of a group object like AttachChild()
|
||||
//! but if the object is a group object, the group object should be set to all children objects recursively.
|
||||
//! and if the object is a prefab object, the prefab object should be loaded from the prefabitem.
|
||||
//! @param bKeepPos if true Child node will keep its world space position.
|
||||
virtual void AddMember(CBaseObject* pMember, bool bKeepPos = true);
|
||||
//! Detach all childs of this node.
|
||||
virtual void DetachAll(bool bKeepPos = true);
|
||||
// Detach this node from parent.
|
||||
virtual void DetachThis(bool bKeepPos = true);
|
||||
// Returns the link parent.
|
||||
virtual CBaseObject* GetLinkParent() const { return GetParent(); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MATRIX
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Get objects' local transformation matrix.
|
||||
Matrix34 GetLocalTM() const { Matrix34 tm; CalcLocalTM(tm); return tm; };
|
||||
|
||||
//! Get objects' world-space transformation matrix.
|
||||
const Matrix34& GetWorldTM() const;
|
||||
|
||||
// Gets matrix of parent attachment point
|
||||
virtual Matrix34 GetParentAttachPointWorldTM() const;
|
||||
|
||||
// Checks if the attachment point is valid
|
||||
virtual bool IsParentAttachmentValid() const;
|
||||
|
||||
//! Set position in world space.
|
||||
virtual void SetWorldPos(const Vec3& pos, int flags = 0);
|
||||
|
||||
//! Get position in world space.
|
||||
Vec3 GetWorldPos() const { return GetWorldTM().GetTranslation(); };
|
||||
Ang3 GetWorldAngles() const;
|
||||
|
||||
//! Set xform of object given in world space.
|
||||
virtual void SetWorldTM(const Matrix34& tm, int flags = 0);
|
||||
|
||||
//! Set object xform.
|
||||
virtual void SetLocalTM(const Matrix34& tm, int flags = 0);
|
||||
|
||||
// Set object xform.
|
||||
virtual void SetLocalTM(const Vec3& pos, const Quat& rotate, const Vec3& scale, int flags = 0);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Interface to be implemented in plugins.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! Called when object is being created (use GetMouseCreateCallback for more advanced mouse creation callback).
|
||||
virtual int MouseCreateCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags);
|
||||
// Return pointer to the callback object used when creating object by the mouse.
|
||||
// If this function return NULL MouseCreateCallback method will be used instead.
|
||||
virtual IMouseCreateCallback* GetMouseCreateCallback() { return 0; };
|
||||
|
||||
//! Draw object to specified viewport.
|
||||
virtual void Display([[maybe_unused]] DisplayContext& disp) {}
|
||||
|
||||
//! Perform intersection testing of this object.
|
||||
//! Return true if was hit.
|
||||
virtual bool HitTest([[maybe_unused]] HitContext& hc) { return false; };
|
||||
|
||||
//! Perform intersection testing of this object with rectangle.
|
||||
//! Return true if was hit.
|
||||
virtual bool HitTestRect(HitContext& hc);
|
||||
|
||||
//! Perform intersection testing of this object based on its icon helper.
|
||||
//! Return true if was hit.
|
||||
virtual bool HitHelperTest(HitContext& hc);
|
||||
|
||||
//! Get bounding box of object in world coordinate space.
|
||||
virtual void GetBoundBox(AABB& box);
|
||||
|
||||
//! Get bounding box of object in local object space.
|
||||
virtual void GetLocalBounds(AABB& box);
|
||||
|
||||
//! Called after some parameter been modified.
|
||||
virtual void SetModified(bool boModifiedTransformOnly);
|
||||
|
||||
//! Called when visibility of this object changes.
|
||||
//! Derived class may override this to respond to new visibility setting.
|
||||
virtual void UpdateVisibility(bool bVisible);
|
||||
|
||||
//! Serialize object to/from xml.
|
||||
//! @param xmlNode XML node to load/save serialized data to.
|
||||
//! @param bLoading true if loading data from xml.
|
||||
//! @param bUndo true if loading or saving data for Undo/Redo purposes.
|
||||
virtual void Serialize(CObjectArchive& ar);
|
||||
|
||||
//// Pre load called before serialize after all objects where completly loaded.
|
||||
//virtual void PreLoad( CObjectArchive &ar ) {};
|
||||
// Post load called after all objects where completely loaded.
|
||||
virtual void PostLoad([[maybe_unused]] CObjectArchive& ar) {};
|
||||
|
||||
//! Export object to xml.
|
||||
//! Return created object node in xml.
|
||||
virtual XmlNodeRef Export(const QString& levelPath, XmlNodeRef& xmlNode);
|
||||
|
||||
//! Handle events received by object.
|
||||
//! Override in derived classes, to handle specific events.
|
||||
virtual void OnEvent(ObjectEvent event);
|
||||
|
||||
//! Generate dynamic context menu for the object
|
||||
virtual void OnContextMenu(QMenu* menu);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// LookAt Target.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void SetLookAt(CBaseObject* target);
|
||||
CBaseObject* GetLookAt() const { return m_lookat; };
|
||||
//! Returns true if this object is a look-at target.
|
||||
bool IsLookAtTarget() const;
|
||||
CBaseObject* GetLookAtSource() const { return m_lookatSource; };
|
||||
|
||||
|
||||
IObjectManager* GetObjectManager() const;
|
||||
|
||||
//! Store undo information for this object.
|
||||
void StoreUndo(const char* undoDescription, bool minimal = false, int flags = 0);
|
||||
|
||||
//! Add event listener callback.
|
||||
void AddEventListener(EventListener* listener);
|
||||
//! Remove event listener callback.
|
||||
void RemoveEventListener(EventListener* listener);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Analyze errors for this object.
|
||||
virtual void Validate(IErrorReport* report);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Gather resources of this object.
|
||||
virtual void GatherUsedResources(CUsedResources& resources);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Check if specified object is very similar to this one.
|
||||
virtual bool IsSimilarObject(CBaseObject* pObject);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Material Layers Mask.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void SetMaterialLayersMask(uint32 nLayersMask) { m_nMaterialLayersMask = nLayersMask; }
|
||||
uint32 GetMaterialLayersMask() const { return m_nMaterialLayersMask; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Object minimal usage spec (All/Low/Medium/High)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint32 GetMinSpec() const { return m_nMinSpec; }
|
||||
virtual void SetMinSpec(uint32 nSpec, bool bSetChildren = true);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SubObj selection.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Return true if object support selecting of this sub object element type.
|
||||
virtual bool StartSubObjSelection([[maybe_unused]] int elemType) { return false; };
|
||||
virtual void EndSubObjectSelection() {};
|
||||
virtual void CalculateSubObjectSelectionReferenceFrame([[maybe_unused]] ISubObjectSelectionReferenceFrameCalculator* pCalculator) { };
|
||||
virtual void ModifySubObjSelection([[maybe_unused]] SSubObjSelectionModifyContext& modCtx) {};
|
||||
virtual void AcceptSubObjectModify() {};
|
||||
|
||||
//! In This function variables of the object must be initialized.
|
||||
virtual void InitVariables() {};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Procedural Floor Management.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int GetFloorNumber() const { return m_floorNumber; };
|
||||
void SetFloorNumber(int floorNumber) { m_floorNumber = floorNumber; };
|
||||
|
||||
virtual void OnPropertyChanged(IVariable*);
|
||||
virtual void OnMultiSelPropertyChanged(IVariable*);
|
||||
|
||||
//! Draw a reddish highlight indicating its budget usage.
|
||||
virtual void DrawBudgetUsage(DisplayContext& dc, const QColor& color);
|
||||
|
||||
bool IntersectRayMesh(const Vec3& raySrc, const Vec3& rayDir, SRayHitInfo& outHitInfo) const;
|
||||
|
||||
virtual void EditTags([[maybe_unused]] bool alwaysTag) {}
|
||||
virtual bool SupportsEditTags() const { return false; }
|
||||
|
||||
bool CanBeHightlighted() const;
|
||||
bool IsSkipSelectionHelper() const;
|
||||
|
||||
virtual IStatObj* GetIStatObj() { return NULL; }
|
||||
|
||||
// Invalidates cached transformation matrix.
|
||||
// nWhyFlags - Flags that indicate the reason for matrix invalidation.
|
||||
virtual void InvalidateTM(int nWhyFlags);
|
||||
|
||||
protected:
|
||||
friend class CObjectManager;
|
||||
|
||||
//! Ctor is protected to restrict direct usage.
|
||||
CBaseObject();
|
||||
//! Dtor is protected to restrict direct usage.
|
||||
virtual ~CBaseObject();
|
||||
|
||||
//! Initialize Object.
|
||||
//! If previous object specified it must be of exactly same class as this object.
|
||||
//! All data is copied from previous object.
|
||||
//! Optional file parameter specify initial object or script for this object.
|
||||
virtual bool Init(IEditor* ie, CBaseObject* prev, const QString& file);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Must be called after cloning the object on clone of object.
|
||||
//! This will make sure object references are cloned correctly.
|
||||
virtual void PostClone(CBaseObject* pFromObject, CObjectCloneContext& ctx);
|
||||
|
||||
//! Must be implemented by derived class to create game related objects.
|
||||
virtual bool CreateGameObject() { return true; };
|
||||
|
||||
//! If true, all attached chilren will be cloned when the parent object is cloned.
|
||||
virtual bool ShouldCloneChildren() const { return true; }
|
||||
|
||||
/** Called when object is about to be deleted.
|
||||
All Game resources should be freed in this function.
|
||||
*/
|
||||
virtual void Done();
|
||||
|
||||
/** Change current id of object.
|
||||
*/
|
||||
//virtual void SetId( uint32 objectId ) { m_id = objectId; };
|
||||
|
||||
//! Call this to delete an object.
|
||||
virtual void DeleteThis() = 0;
|
||||
|
||||
//! Called when object need to be converted from different object.
|
||||
virtual bool ConvertFromObject(CBaseObject* object);
|
||||
|
||||
//! Called when local transformation matrix is calculated.
|
||||
void CalcLocalTM(Matrix34& tm) const;
|
||||
|
||||
//! Called when child position changed.
|
||||
virtual void OnChildModified() {};
|
||||
|
||||
//! Remove child from our childs list.
|
||||
virtual void RemoveChild(CBaseObject* node);
|
||||
|
||||
//! Resolve parent from callback.
|
||||
void ResolveParent(CBaseObject* object);
|
||||
void SetColor(const QColor& color);
|
||||
|
||||
//! Draw default object items.
|
||||
virtual void DrawDefault(DisplayContext& dc, const QColor& labelColor = QColor(255, 255, 255));
|
||||
//! Draw object label.
|
||||
void DrawLabel(DisplayContext& dc, const Vec3& pos, const QColor& labelColor = QColor(255, 255, 255), float alpha = 1.0f, float size = 1.f);
|
||||
//! Draw 3D Axis at object position.
|
||||
void DrawAxis(DisplayContext& dc, const Vec3& pos, float size);
|
||||
//! Draw area around object.
|
||||
void DrawArea(DisplayContext& dc);
|
||||
//! Draw selection helper.
|
||||
void DrawSelectionHelper(DisplayContext& dc, const Vec3& pos, const QColor& labelColor = QColor(255, 255, 255), float alpha = 1.0f);
|
||||
//! Draw helper icon.
|
||||
virtual void DrawTextureIcon(DisplayContext& dc, const Vec3& pos, float alpha = 1.0f);
|
||||
//! Draw warning icons
|
||||
virtual void DrawWarningIcons(DisplayContext& dc, const Vec3& pos);
|
||||
//! Check if dimension's figures can be displayed before draw them.
|
||||
virtual void DrawDimensions(DisplayContext& dc, AABB* pMergedBoundBox = NULL);
|
||||
|
||||
//! Draw highlight.
|
||||
virtual void DrawHighlight(DisplayContext& dc);
|
||||
|
||||
//! Returns if the object can be drawn, and if its selection helper should also be drawn.
|
||||
bool CanBeDrawn(const DisplayContext& dc, bool& outDisplaySelectionHelper) const;
|
||||
|
||||
//! Returns if object is in the camera view.
|
||||
virtual bool IsInCameraView(const CCamera& camera);
|
||||
//! Returns vis ratio of object in camera
|
||||
virtual float GetCameraVisRatio(const CCamera& camera);
|
||||
|
||||
// Do basic intersection tests
|
||||
virtual bool IntersectRectBounds(const AABB& bbox);
|
||||
virtual bool IntersectRayBounds(const Ray& ray);
|
||||
|
||||
// Do hit testing on specified bounding box.
|
||||
// Function can be used by derived classes.
|
||||
bool HitTestRectBounds(HitContext& hc, const AABB& box);
|
||||
|
||||
// Do helper hit testing as specific location.
|
||||
bool HitHelperAtTest(HitContext& hc, const Vec3& pos);
|
||||
|
||||
// Do helper hit testing taking child objects into account (e.g. opened prefab)
|
||||
virtual bool HitHelperTestForChildObjects([[maybe_unused]] HitContext& hc) { return false; }
|
||||
|
||||
CBaseObject* FindObject(REFGUID id) const;
|
||||
|
||||
// Returns true if game objects should be created.
|
||||
bool IsCreateGameObjects() const;
|
||||
|
||||
// Helper gizmo functions.
|
||||
void AddGizmo(CGizmo* gizmo);
|
||||
void RemoveGizmo(CGizmo* gizmo);
|
||||
|
||||
//! Notify all listeners about event.
|
||||
void NotifyListeners(EObjectListenerEvent event);
|
||||
|
||||
//! Only used by ObjectManager.
|
||||
bool IsPotentiallyVisible() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// May be overridden in derived classes to handle helpers scaling.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void SetHelperScale([[maybe_unused]] float scale) {};
|
||||
virtual float GetHelperScale() { return 1; };
|
||||
|
||||
void SetNameInternal(const QString& name) { m_name = name; }
|
||||
|
||||
void SetDrawTextureIconProperties(DisplayContext& dc, const Vec3& pos, float alpha = 1.0f, int texIconFlags = 0);
|
||||
const Vec3& GetTextureIconDrawPos(){ return m_vDrawIconPos; };
|
||||
int GetTextureIconFlags(){ return m_nIconFlags; };
|
||||
|
||||
Matrix33 GetWorldRotTM() const;
|
||||
Matrix33 GetWorldScaleTM() const;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
//! World space object's position.
|
||||
Vec3 m_pos;
|
||||
//! Object's Rotation angles.
|
||||
Quat m_rotate;
|
||||
//! Object's scale value.
|
||||
Vec3 m_scale;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
private:
|
||||
friend class CUndoBaseObject;
|
||||
friend class CObjectArchive;
|
||||
friend class CSelectionGroup;
|
||||
|
||||
void OnMenuShowInAssetBrowser();
|
||||
|
||||
//! Set class description for this object,
|
||||
//! Only called once after creation by ObjectManager.
|
||||
void SetClassDesc(CObjectClassDesc* classDesc);
|
||||
|
||||
// From CObject, (not implemented)
|
||||
virtual void Serialize([[maybe_unused]] CArchive& ar) {};
|
||||
|
||||
EScaleWarningLevel GetScaleWarningLevel() const;
|
||||
ERotationWarningLevel GetRotationWarningLevel() const;
|
||||
|
||||
// auto resolving
|
||||
void OnMtlResolved(uint32 id, bool success, const char* orgName, const char* newName);
|
||||
|
||||
bool IsInSelectionBox() const { return m_bInSelectionBox; }
|
||||
|
||||
void SetId(REFGUID guid) { m_guid = guid; }
|
||||
|
||||
// Before translating, rotating or scaling, we ask our subclasses for whether
|
||||
// they want us to notify CGameEngine of the upcoming change of our AABB.
|
||||
virtual bool ShouldNotifyOfUpcomingAABBChanges() const { return false; }
|
||||
|
||||
// Notifies the CGameEngine about an upcoming change of our AABB.
|
||||
void OnBeforeAreaChange();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FIELDS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
//Default ObjType
|
||||
ObjectType m_objType;
|
||||
|
||||
//! Unique object Id.
|
||||
GUID m_guid;
|
||||
|
||||
// floor number of object if procedural object flag is set
|
||||
int m_floorNumber;
|
||||
|
||||
//! Flags of this object.
|
||||
int m_flags;
|
||||
|
||||
// Id of the texture icon for this object.
|
||||
int m_nTextureIcon;
|
||||
|
||||
//! Display color.
|
||||
QColor m_color;
|
||||
|
||||
//! World transformation matrix of this object.
|
||||
mutable Matrix34 m_worldTM;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Look At target entity.
|
||||
_smart_ptr<CBaseObject> m_lookat;
|
||||
//! If we are lookat target. this is pointer to source.
|
||||
CBaseObject* m_lookatSource;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Area radius around object, where terrain is flatten and static objects removed.
|
||||
float m_flattenArea;
|
||||
//! Every object keeps for itself height above terrain.
|
||||
float m_height;
|
||||
//! Object's name.
|
||||
QString m_name;
|
||||
//! Class description for this object.
|
||||
CObjectClassDesc* m_classDesc;
|
||||
|
||||
//! Number of reference to this object.
|
||||
//! When reference count reach zero, object will delete itself.
|
||||
int m_numRefs;
|
||||
|
||||
int m_nIconFlags;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Child animation nodes.
|
||||
Childs m_childs;
|
||||
//! Pointer to parent node.
|
||||
mutable CBaseObject* m_parent;
|
||||
|
||||
AABB m_worldBounds;
|
||||
|
||||
// The transform delegate
|
||||
ITransformDelegate* m_pTransformDelegate;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Listeners.
|
||||
std::vector<EventListener*> m_eventListeners;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Flags and bit masks.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
mutable uint32 m_bMatrixInWorldSpace : 1;
|
||||
mutable uint32 m_bMatrixValid : 1;
|
||||
mutable uint32 m_bWorldBoxValid : 1;
|
||||
uint32 m_bInSelectionBox : 1;
|
||||
uint32 m_nMaterialLayersMask : 8;
|
||||
uint32 m_nMinSpec : 8;
|
||||
|
||||
Vec3 m_vDrawIconPos;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
uint64 m_hideOrder;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(CBaseObject*)
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_BASEOBJECT_H
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ClassDesc.h"
|
||||
|
||||
// Editor
|
||||
#include "IconManager.h"
|
||||
|
||||
int CObjectClassDesc::GetTextureIconId()
|
||||
{
|
||||
if (!m_nTextureIcon)
|
||||
{
|
||||
QString pTexName = GetTextureIcon();
|
||||
|
||||
if (!pTexName.isEmpty())
|
||||
{
|
||||
m_nTextureIcon = GetIEditor()->GetIconManager()->GetIconTexture(pTexName.toUtf8().data());
|
||||
}
|
||||
}
|
||||
|
||||
return m_nTextureIcon;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : Class description of CBaseObject
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_CLASSDESC_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_CLASSDESC_H
|
||||
#pragma once
|
||||
|
||||
#include "Plugin.h"
|
||||
#include "Include/ObjectEvent.h"
|
||||
#include <QString>
|
||||
|
||||
class CXmlArchive;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
//! Virtual base class description of CBaseObject.
|
||||
//! Override this class to create specific Class descriptions for every base object class.
|
||||
//! Type name is specified like this:
|
||||
//! Category\Type ex: "TagPoint\Respawn"
|
||||
class SANDBOX_API CObjectClassDesc
|
||||
: public IClassDesc
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
public:
|
||||
CObjectClassDesc()
|
||||
{
|
||||
m_nTextureIcon = 0;
|
||||
}
|
||||
|
||||
//! Release class description.
|
||||
virtual ObjectType GetObjectType() = 0;
|
||||
virtual QObject* CreateQObject() const { return nullptr; }
|
||||
//! If this function return not empty string,object of this class must be created with file.
|
||||
//! Return root path where to look for files this object supports.
|
||||
//! Also wild card for files can be specified, ex: Objects\*.cgf
|
||||
virtual QString GetFileSpec()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual ESystemClassID SystemClassID() { return ESYSTEM_CLASS_OBJECT; };
|
||||
virtual void ShowAbout() {};
|
||||
virtual bool CanExitNow() { return true; }
|
||||
virtual void Serialize([[maybe_unused]] CXmlArchive& ar) {};
|
||||
//! Ex. Object with creation order 200 will be created after any object with order 100.
|
||||
virtual int GameCreationOrder() { return 100; };
|
||||
virtual QString GetTextureIcon() { return QString(); };
|
||||
int GetTextureIconId();
|
||||
virtual bool RenderTextureOnTop() const { return false; }
|
||||
|
||||
virtual QString GetToolClassName() { return "EditTool.ObjectCreate"; }
|
||||
|
||||
QString MenuSuggestion() { return{}; }
|
||||
QString Tooltip() { return{}; }
|
||||
QString Description() { return{}; }
|
||||
|
||||
private:
|
||||
int m_nTextureIcon;
|
||||
};
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_CLASSDESC_H
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "DisplayContextShared.inl"
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : DisplayContext definition.
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_DISPLAYCONTEXT_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_DISPLAYCONTEXT_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "SandboxAPI.h"
|
||||
#include <Cry_Color.h>
|
||||
#include <Cry_Geo.h>
|
||||
|
||||
#include <QColor>
|
||||
|
||||
#define DC_DEFAULT_DOTLINE_STEPS 10
|
||||
#define DC_UNIT_DEGREE 1
|
||||
|
||||
// forward declarations.
|
||||
struct IDisplayViewport;
|
||||
struct IRenderer;
|
||||
struct IRenderAuxGeom;
|
||||
struct IIconManager;
|
||||
class CDisplaySettings;
|
||||
class CCamera;
|
||||
|
||||
enum DisplayFlags
|
||||
{
|
||||
DISPLAY_2D = 0x01,
|
||||
DISPLAY_HIDENAMES = 0x02,
|
||||
DISPLAY_BBOX = 0x04,
|
||||
DISPLAY_TRACKS = 0x08,
|
||||
DISPLAY_TRACKTICKS = 0x010,
|
||||
DISPLAY_WORLDSPACEAXIS = 0x020, //!< Set if axis must be displayed in world space.
|
||||
DISPLAY_LINKS = 0x040,
|
||||
DISPLAY_DEGRADATED = 0x080, //!< Display Objects in degradated quality (When moving/modifying).
|
||||
DISPLAY_SELECTION_HELPERS = 0x100, //!< Display advanced selection helpers.
|
||||
};
|
||||
|
||||
/*!
|
||||
* DisplayContex is a structure passed to BaseObject Display method.
|
||||
* It contains everything the object should know to display itself in a view.
|
||||
* All fields must be filled before passing that structure to Display call.
|
||||
*/
|
||||
struct SANDBOX_API DisplayContext
|
||||
{
|
||||
enum ETextureIconFlags
|
||||
{
|
||||
TEXICON_ADDITIVE = 0x0001,
|
||||
TEXICON_ALIGN_BOTTOM = 0x0002,
|
||||
TEXICON_ALIGN_TOP = 0x0004,
|
||||
TEXICON_ON_TOP = 0x0008,
|
||||
};
|
||||
|
||||
CDisplaySettings* settings;
|
||||
IDisplayViewport* view;
|
||||
IRenderer* renderer;
|
||||
IRenderAuxGeom* pRenderAuxGeom;
|
||||
IIconManager* pIconManager;
|
||||
CCamera* camera;
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
AABB box; // Bounding box of volume that need to be repainted.
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
int flags;
|
||||
|
||||
//! Ctor.
|
||||
DisplayContext();
|
||||
// Helper methods.
|
||||
void SetView(IDisplayViewport* pView);
|
||||
IDisplayViewport* GetView() const { return view; }
|
||||
void Flush2D();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Draw functions
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Set current materialc color.
|
||||
void SetColor(float r, float g, float b, float a = 1) { m_color4b = ColorB(int(r * 255.0f), int(g * 255.0f), int(b * 255.0f), int(a * 255.0f)); };
|
||||
void SetColor(const Vec3& color, float a = 1) { m_color4b = ColorB(int(color.x * 255.0f), int(color.y * 255.0f), int(color.z * 255.0f), int(a * 255.0f)); };
|
||||
void SetColor(const QColor& rgb, float a) { m_color4b = ColorB(rgb.red(), rgb.green(), rgb.blue(), int(a * 255.0f)); };
|
||||
void SetColor(const QColor& color) { m_color4b = ColorB(color.red(), color.green(), color.blue(), color.alpha()); };
|
||||
void SetColor(const ColorB& color) { m_color4b = color; };
|
||||
void SetAlpha(float a = 1) { m_color4b.a = int(a * 255.0f); };
|
||||
ColorB GetColor() const { return m_color4b; }
|
||||
|
||||
void SetSelectedColor(float fAlpha = 1);
|
||||
void SetFreezeColor();
|
||||
|
||||
//! Get color to draw selectin of object.
|
||||
QColor GetSelectedColor();
|
||||
QColor GetFreezeColor();
|
||||
|
||||
// Draw 3D quad.
|
||||
void DrawQuad(const Vec3& p1, const Vec3& p2, const Vec3& p3, const Vec3& p4);
|
||||
void DrawQuad(float width, float height);
|
||||
void DrawQuadGradient(const Vec3& p1, const Vec3& p2, const Vec3& p3, const Vec3& p4, ColorB firstColor, ColorB secondColor);
|
||||
void DrawWireQuad(const Vec3& p1, const Vec3& p2, const Vec3& p3, const Vec3& p4);
|
||||
void DrawWireQuad(float width, float height);
|
||||
// Draw 3D Triangle.
|
||||
void DrawTri(const Vec3& p1, const Vec3& p2, const Vec3& p3);
|
||||
void DrawTriangles(const AZStd::vector<Vec3>& vertices, const ColorB& color);
|
||||
void DrawTrianglesIndexed(const AZStd::vector<Vec3>& vertices, const AZStd::vector<vtx_idx>& indices, const ColorB& color);
|
||||
// Draw wireframe box.
|
||||
void DrawWireBox(const Vec3& min, const Vec3& max);
|
||||
// Draw filled box
|
||||
void DrawSolidBox(const Vec3& min, const Vec3& max);
|
||||
void DrawSolidOBB(const Vec3& center, const Vec3& axisX, const Vec3& axisY, const Vec3& axisZ, const Vec3& halfExtents);
|
||||
void DrawPoint(const Vec3& p, int nSize = 1);
|
||||
void DrawLine(const Vec3& p1, const Vec3& p2);
|
||||
void DrawLine(const Vec3& p1, const Vec3& p2, const ColorF& col1, const ColorF& col2);
|
||||
void DrawLine(const Vec3& p1, const Vec3& p2, const QColor& rgb1, const QColor& rgb2);
|
||||
void DrawLines(const AZStd::vector<Vec3>& vertices, const ColorF& color);
|
||||
void DrawPolyLine(const Vec3* pnts, int numPoints, bool cycled = true);
|
||||
|
||||
// Vera, Confetti
|
||||
void DrawDottedLine(const Vec3& p1, const Vec3& p2, const ColorF& col1, const ColorF& col2, const float numOfSteps = DC_DEFAULT_DOTLINE_STEPS);
|
||||
void DrawWireQuad2d(const QPoint& p1, const QPoint& p2, float z);
|
||||
void DrawLine2d(const QPoint& p1, const QPoint& p2, float z);
|
||||
void DrawLine2dGradient(const QPoint& p1, const QPoint& p2, float z, ColorB firstColor, ColorB secondColor);
|
||||
void DrawWireCircle2d(const QPoint& center, float radius, float z);
|
||||
|
||||
// Draw circle from lines on terrain, position is in world space.
|
||||
void DrawTerrainCircle(const Vec3& worldPos, float radius, float height);
|
||||
void DrawTerrainCircle(const Vec3& center, float radius, float angle1, float angle2, float height);
|
||||
|
||||
/// DrawArc
|
||||
/// Draws an arc around the specified position from a given angle across the angular length given by sweepAngleDegrees
|
||||
/// it orients the arc around the index of the given basis axis.
|
||||
/// \param pos World space position on which to center the arc.
|
||||
/// \param radius Radius that defines the size of the arc.
|
||||
/// \param startAngleDegrees Angle in degrees measured clockwise from the basis axis to the starting point of the arc.
|
||||
/// \param sweepAngleDegreees Angle in degrees measured clockwise from the startAngle parameter to ending point of the arc.
|
||||
/// \param angularStepDegrees Defines the distance between vertices, a small value will result in a greater number of vertices.
|
||||
/// \param referenceAxis Axis on which to align the arc (0 for X, 1 for Y, 2 for Z)
|
||||
void DrawArc(const Vec3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, int referenceAxis = 2);
|
||||
|
||||
|
||||
/// DrawArc
|
||||
/// Draws an arc around the specified position from a given angle across the angular length given by sweepAngleDegrees
|
||||
/// oriented around the specified axis.
|
||||
/// \param pos World space position on which to center the arc.
|
||||
/// \param radius Radius that defines the size of the arc.
|
||||
/// \param startAngleDegrees Angle in degrees measured clockwise from the basis axis to the starting point of the arc.
|
||||
/// \param sweepAngleDegreees Angle in degrees measured clockwise from the startAngle parameter to ending point of the arc.
|
||||
/// \param angularStepDegrees Defines the distance between vertices, a small value will result in a greater number of vertices.
|
||||
/// \param fixedAxis Normal axis on which to align the arc.
|
||||
void DrawArc(const Vec3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, const Vec3& fixedAxis);
|
||||
|
||||
//Vera, Confetti:
|
||||
//Draw an arc and an arrow at the end of the arc
|
||||
void DrawArcWithArrow(const Vec3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, const Vec3& fixedAxis);
|
||||
|
||||
// Draw circle.
|
||||
void DrawCircle(const Vec3& pos, float radius, int nUnchangedAxis = 2 /*z axis*/);
|
||||
|
||||
void DrawHalfDottedCircle(const Vec3& pos, float radius, const Vec3& viewPos, int nUnchangedAxis = 2 /*z axis*/);
|
||||
|
||||
// Vera, Confetti :
|
||||
// Draw a dotted circle.
|
||||
void DrawDottedCircle(const Vec3& pos, float radius, const Vec3& nUnchangedAxis, int numberOfArrows = 0, float stepDegree = DC_UNIT_DEGREE);
|
||||
|
||||
// Draw cylinder.
|
||||
void DrawCylinder(const Vec3& p1, const Vec3& p2, float radius, float height);
|
||||
|
||||
void DrawCone(const Vec3& pos, const Vec3& dir, float radius, float height, bool drawShaded = true);
|
||||
|
||||
/// DrawWireCylinder
|
||||
/// \param center Center of cylinder.
|
||||
/// \param axis Axis along which cylinder is tall.
|
||||
/// \param radius Radius of cylinder.
|
||||
/// \param height Total height of cylinder.
|
||||
void DrawWireCylinder(const Vec3& center, const Vec3& axis, float radius, float height);
|
||||
|
||||
/// DrawSolidCylinder
|
||||
/// \param center Center of cylinder.
|
||||
/// \param axis Axis along which cylinder is tall.
|
||||
/// \param radius Radius of cylinder.
|
||||
/// \param height Total height of cylinder.
|
||||
void DrawSolidCylinder(const Vec3& center, const Vec3& axis, float radius, float height, bool drawShaded = true);
|
||||
|
||||
/// DrawWireCapsule
|
||||
/// \param pos Center of capsule.
|
||||
/// \param axis Axis along which capsule is tall.
|
||||
/// \param radius Radius of capsule.
|
||||
/// \param heightStraightSection Height of capsule's straight section (does not include caps).
|
||||
void DrawWireCapsule(const Vec3& center, const Vec3& axis, float radius, float heightStraightSection);
|
||||
|
||||
//! Draw rectangle on top of terrain.
|
||||
//! Coordinates are in world space.
|
||||
void DrawTerrainRect(float x1, float y1, float x2, float y2, float height);
|
||||
|
||||
void DrawTerrainLine (Vec3 worldPos1, Vec3 worldPos2);
|
||||
|
||||
void DrawWireSphere(const Vec3& pos, float radius);
|
||||
void DrawWireSphere(const Vec3& pos, const Vec3 radius);
|
||||
|
||||
void DrawWireDisk(const Vec3& pos, const Vec3& dir, float radius);
|
||||
|
||||
void PushMatrix(const Matrix34& tm);
|
||||
void PopMatrix();
|
||||
const Matrix34& GetMatrix();
|
||||
|
||||
// Draw special 3D objects.
|
||||
void DrawBall(const Vec3& pos, float radius, bool drawShaded = true);
|
||||
void DrawDisk(const Vec3& pos, const Vec3& dir, float radius);
|
||||
|
||||
//! Draws 3d arrow.
|
||||
void DrawArrow(const Vec3& src, const Vec3& trg, float fHeadScale = 1, bool b2SidedArrow = false);
|
||||
|
||||
// Draw texture label in 2d view coordinates.
|
||||
// w,h in pixels.
|
||||
void DrawTextureLabel(const Vec3& pos, int nWidth, int nHeight, int nTexId, int nTexIconFlags = 0, int srcOffsetX = 0, int scrOffsetY = 0, bool bDistanceScaleIcons = false, float fDistanceScale = 1.0f);
|
||||
|
||||
void RenderObject(int objectType, const Vec3& pos, float scale);
|
||||
void RenderObject(int objectType, const Matrix34& tm);
|
||||
|
||||
void DrawTextLabel(const Vec3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int scrOffsetY = 0);
|
||||
void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false);
|
||||
void SetLineWidth(float width);
|
||||
|
||||
//! Is given bbox visible in this display context.
|
||||
bool IsVisible(const AABB& bounds);
|
||||
|
||||
//! Gets current render state.
|
||||
uint32 GetState() const;
|
||||
//! Set a new render state.
|
||||
//! \param returns previous render state.
|
||||
uint32 SetState(uint32 state);
|
||||
//! Set a new render state flags.
|
||||
//! \param returns previous render state.
|
||||
uint32 SetStateFlag(uint32 state);
|
||||
//! Clear specified flags in render state.
|
||||
//! \param returns previous render state.
|
||||
uint32 ClearStateFlag(uint32 state);
|
||||
|
||||
void DepthTestOff();
|
||||
void DepthTestOn();
|
||||
|
||||
void DepthWriteOff();
|
||||
void DepthWriteOn();
|
||||
|
||||
void CullOff();
|
||||
void CullOn();
|
||||
|
||||
// Enables drawing helper lines in front of usual geometry, adds a small z offset to all drawn lines.
|
||||
bool SetDrawInFrontMode(bool bOn);
|
||||
|
||||
// Description:
|
||||
// Changes fill mode.
|
||||
// Arguments:
|
||||
// nFillMode is one of the values from EAuxGeomPublicRenderflags_FillMode
|
||||
int SetFillMode(int nFillMode);
|
||||
|
||||
//! Convert position to world space.
|
||||
Vec3 ToWorldSpacePosition(const Vec3& v) { return m_matrixStack[m_currentMatrix].TransformPoint(v); }
|
||||
|
||||
//! Convert direction to world space (translation is not considered)
|
||||
Vec3 ToWorldSpaceVector(const Vec3& v) { return m_matrixStack[m_currentMatrix].TransformVector(v); }
|
||||
|
||||
float ToWorldSpaceMaxScale(float value);
|
||||
|
||||
float GetLineWidth() const { return m_thickness; }
|
||||
|
||||
private:
|
||||
|
||||
void InternalDrawLine(const Vec3& v0, const ColorB& colV0, const Vec3& v1, const ColorB& colV1);
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
ColorB m_color4b;
|
||||
uint32 m_renderState;
|
||||
float m_thickness;
|
||||
float m_width;
|
||||
float m_height;
|
||||
|
||||
int m_currentMatrix;
|
||||
//! Matrix stack.
|
||||
Matrix34 m_matrixStack[32];
|
||||
|
||||
struct STextureLabel
|
||||
{
|
||||
float x, y, z; // 2D position (z in world space).
|
||||
float w, h; // Width height.
|
||||
int nTexId; // Texture id.
|
||||
int flags; // ETextureIconFlags
|
||||
float color[4];
|
||||
};
|
||||
std::vector<STextureLabel> m_textureLabels;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_DISPLAYCONTEXT_H
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_ENTITYOBJECT_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_ENTITYOBJECT_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "BaseObject.h"
|
||||
|
||||
#include "IMovieSystem.h"
|
||||
#include "IEntityObjectListener.h"
|
||||
#include "Gizmo.h"
|
||||
#include "CryListenerSet.h"
|
||||
#include "StatObjBus.h"
|
||||
|
||||
#include <QObject>
|
||||
#endif
|
||||
|
||||
#define CLASS_LIGHT "Light"
|
||||
#define CLASS_DESTROYABLE_LIGHT "DestroyableLight"
|
||||
#define CLASS_RIGIDBODY_LIGHT "RigidBodyLight"
|
||||
#define CLASS_ENVIRONMENT_LIGHT "EnvironmentLight"
|
||||
|
||||
class CEntityObject;
|
||||
class QMenu;
|
||||
|
||||
/*!
|
||||
* CEntityEventTarget is an Entity event target and type.
|
||||
*/
|
||||
struct CEntityEventTarget
|
||||
{
|
||||
CBaseObject* target; //! Target object.
|
||||
_smart_ptr<CGizmo> pLineGizmo;
|
||||
QString event;
|
||||
QString sourceEvent;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Named link from entity to entity.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct CEntityLink
|
||||
{
|
||||
GUID targetId; // Target entity id.
|
||||
CEntityObject* target; // Target entity.
|
||||
QString name; // Name of the link.
|
||||
_smart_ptr<CGizmo> pLineGizmo;
|
||||
};
|
||||
|
||||
struct IPickEntitesOwner
|
||||
{
|
||||
virtual void AddEntity(CBaseObject* pEntity) = 0;
|
||||
virtual CBaseObject* GetEntity(int nIdx) = 0;
|
||||
virtual int GetEntityCount() = 0;
|
||||
virtual void RemoveEntity(int nIdx) = 0;
|
||||
};
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
/*!
|
||||
* CEntity is an static object on terrain.
|
||||
*
|
||||
*/
|
||||
class CRYEDIT_API CEntityObject
|
||||
: public CBaseObject
|
||||
, public CBaseObject::EventListener
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
Q_OBJECT
|
||||
public:
|
||||
~CEntityObject();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Overrides from CBaseObject.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Return type name of Entity.
|
||||
QString GetTypeDescription() const { return GetEntityClass(); };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool IsSameClass(CBaseObject* obj);
|
||||
|
||||
virtual bool Init(IEditor* ie, CBaseObject* prev, const QString& file);
|
||||
virtual void InitVariables();
|
||||
virtual void Done();
|
||||
|
||||
void DrawExtraLightInfo (DisplayContext& disp);
|
||||
|
||||
bool GetEntityPropertyBool(const char* name) const;
|
||||
int GetEntityPropertyInteger(const char* name) const;
|
||||
float GetEntityPropertyFloat(const char* name) const;
|
||||
QString GetEntityPropertyString(const char* name) const;
|
||||
void SetEntityPropertyBool(const char* name, bool value);
|
||||
void SetEntityPropertyInteger(const char* name, int value);
|
||||
void SetEntityPropertyFloat(const char* name, float value);
|
||||
void SetEntityPropertyString(const char* name, const QString& value);
|
||||
|
||||
virtual int MouseCreateCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags);
|
||||
virtual void OnContextMenu(QMenu* menu);
|
||||
|
||||
void SetName(const QString& name);
|
||||
void SetSelected(bool bSelect);
|
||||
|
||||
virtual void GetLocalBounds(AABB& box);
|
||||
|
||||
virtual bool HitTest(HitContext& hc);
|
||||
virtual bool HitHelperTest(HitContext& hc);
|
||||
virtual bool HitTestRect(HitContext& hc);
|
||||
void UpdateVisibility(bool bVisible);
|
||||
bool ConvertFromObject(CBaseObject* object);
|
||||
|
||||
virtual void Serialize(CObjectArchive& ar);
|
||||
virtual void PostLoad(CObjectArchive& ar);
|
||||
|
||||
XmlNodeRef Export(const QString& levelPath, XmlNodeRef& xmlNode);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void OnEvent(ObjectEvent event);
|
||||
|
||||
virtual void SetTransformDelegate(ITransformDelegate* pTransformDelegate) override;
|
||||
|
||||
// Set attach flags and target
|
||||
enum EAttachmentType
|
||||
{
|
||||
eAT_Pivot,
|
||||
eAT_GeomCacheNode,
|
||||
eAT_CharacterBone,
|
||||
};
|
||||
|
||||
void SetAttachType(const EAttachmentType attachmentType) { m_attachmentType = attachmentType; }
|
||||
void SetAttachTarget(const char* target) { m_attachmentTarget = target; }
|
||||
EAttachmentType GetAttachType() const { return m_attachmentType; }
|
||||
QString GetAttachTarget() const { return m_attachmentTarget; }
|
||||
|
||||
virtual void SetHelperScale(float scale);
|
||||
virtual float GetHelperScale();
|
||||
|
||||
virtual void GatherUsedResources(CUsedResources& resources);
|
||||
virtual bool IsSimilarObject(CBaseObject* pObject);
|
||||
|
||||
virtual bool HasMeasurementAxis() const { return false; }
|
||||
|
||||
virtual bool IsIsolated() const { return false; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// END CBaseObject
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CEntity interface.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void DeleteEntity() {}
|
||||
|
||||
QString GetEntityClass() const { return m_entityClass; };
|
||||
int GetEntityId() const { return m_entityId; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Return number of event targets of Script.
|
||||
int GetEventTargetCount() const { return m_eventTargets.size(); };
|
||||
CEntityEventTarget& GetEventTarget(int index) { return m_eventTargets[index]; };
|
||||
//! Add new event target, returns index of created event target.
|
||||
//! Event targets are Always entities.
|
||||
int AddEventTarget(CBaseObject* target, const QString& event, const QString& sourceEvent, bool bUpdateScript = true);
|
||||
//! Remove existing event target by index.
|
||||
void RemoveEventTarget(int index, bool bUpdateScript = true);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Entity Links.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Return number of event targets of Script.
|
||||
int GetEntityLinkCount() const { return m_links.size(); };
|
||||
CEntityLink& GetEntityLink(int index) { return m_links[index]; };
|
||||
virtual int AddEntityLink(const QString& name, GUID targetEntityId);
|
||||
virtual bool EntityLinkExists(const QString& name, GUID targetEntityId);
|
||||
void RenameEntityLink(int index, const QString& newName);
|
||||
void RemoveEntityLink(int index);
|
||||
void RemoveAllEntityLinks();
|
||||
virtual void EntityLinked([[maybe_unused]] const QString& name, [[maybe_unused]] GUID targetEntityId){}
|
||||
virtual void EntityUnlinked([[maybe_unused]] const QString& name, [[maybe_unused]] GUID targetEntityId) {}
|
||||
void LoadLink(XmlNodeRef xmlNode, CObjectArchive* pArchive = NULL);
|
||||
void SaveLink(XmlNodeRef xmlNode);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int GetCastShadowMinSpec() const { return mv_castShadowMinSpec; }
|
||||
|
||||
float GetRatioLod() const { return static_cast<float>(mv_ratioLOD); };
|
||||
float GetViewDistanceMultiplier() const { return mv_viewDistanceMultiplier; }
|
||||
|
||||
CVarBlock* GetProperties() const { return m_pProperties; };
|
||||
CVarBlock* GetProperties2() const { return m_pProperties2; };
|
||||
|
||||
bool IsLight() const { return m_bLight; }
|
||||
|
||||
void Validate(IErrorReport* report) override;
|
||||
|
||||
// Find CEntity from AZ::EntityId, which can also handle legacy game Ids stored as AZ::EntityIds
|
||||
static CEntityObject* FindFromEntityId(const AZ::EntityId& id);
|
||||
|
||||
// Get the name of the light animation node assigned to this, if any.
|
||||
QString GetLightAnimation() const;
|
||||
|
||||
IVariable* GetLightVariable(const char* name) const;
|
||||
|
||||
void PreInitLightProperty();
|
||||
void UpdateLightProperty();
|
||||
|
||||
void EnableReload(bool bEnable)
|
||||
{
|
||||
m_bEnableReload = bEnable;
|
||||
}
|
||||
|
||||
static void StoreUndoEntityLink(CSelectionGroup* pGroup);
|
||||
|
||||
void RegisterListener(IEntityObjectListener* pListener);
|
||||
void UnregisterListener(IEntityObjectListener* pListener);
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
void SetEntityProperty(const char* name, T value);
|
||||
template <typename T>
|
||||
T GetEntityProperty(const char* name, T defaultvalue) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Must be called after cloning the object on clone of object.
|
||||
//! This will make sure object references are cloned correctly.
|
||||
virtual void PostClone(CBaseObject* pFromObject, CObjectCloneContext& ctx);
|
||||
|
||||
//! Draw default object items.
|
||||
void DrawProjectorPyramid(DisplayContext& dc, float dist);
|
||||
void DrawProjectorFrustum(DisplayContext& dc, Vec2 size, float dist);
|
||||
|
||||
void OnLoadFailed();
|
||||
|
||||
CVarBlock* CloneProperties(CVarBlock* srcProperties);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Callback called when one of entity properties have been modified.
|
||||
void OnPropertyChange(IVariable* var);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void OnObjectEvent(CBaseObject* target, int event) override;
|
||||
void ResolveEventTarget(CBaseObject* object, unsigned int index);
|
||||
void ReleaseEventTargets();
|
||||
|
||||
public:
|
||||
CEntityObject();
|
||||
|
||||
static const GUID& GetClassID()
|
||||
{
|
||||
// {C80F8AEA-90EF-471f-82C7-D14FA80B9203}
|
||||
static const GUID guid = {
|
||||
0xc80f8aea, 0x90ef, 0x471f, { 0x82, 0xc7, 0xd1, 0x4f, 0xa8, 0xb, 0x92, 0x3 }
|
||||
};
|
||||
return guid;
|
||||
}
|
||||
|
||||
protected:
|
||||
void DeleteThis() { delete this; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Radius callbacks.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void OnRadiusChange(IVariable* var);
|
||||
void OnInnerRadiusChange(IVariable* var);
|
||||
void OnOuterRadiusChange(IVariable* var);
|
||||
void OnBoxSizeXChange(IVariable* var);
|
||||
void OnBoxSizeYChange(IVariable* var);
|
||||
void OnBoxSizeZChange(IVariable* var);
|
||||
void OnProjectorFOVChange(IVariable* var);
|
||||
void OnProjectorTextureChange(IVariable* var);
|
||||
void OnProjectInAllDirsChange(IVariable* var);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Area light callbacks.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void OnAreaLightChange(IVariable* var);
|
||||
void OnAreaWidthChange(IVariable* var);
|
||||
void OnAreaHeightChange(IVariable* var);
|
||||
void OnAreaFOVChange(IVariable* var);
|
||||
void OnAreaLightSizeChange(IVariable* var);
|
||||
void OnColorChange(IVariable* var);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Box projection callbacks.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void OnBoxProjectionChange(IVariable* var);
|
||||
void OnBoxWidthChange(IVariable* var);
|
||||
void OnBoxHeightChange(IVariable* var);
|
||||
void OnBoxLengthChange(IVariable* var);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FreeGameData();
|
||||
|
||||
void AdjustLightProperties(CVarBlockPtr& properties, const char* pSubBlock);
|
||||
IVariable* FindVariableInSubBlock(CVarBlockPtr& properties, IVariable* pSubBlockVar, const char* pVarName);
|
||||
|
||||
unsigned int m_bLoadFailed : 1;
|
||||
unsigned int m_bCalcPhysics : 1;
|
||||
unsigned int m_bDisplayBBox : 1;
|
||||
unsigned int m_bDisplaySolidBBox : 1;
|
||||
unsigned int m_bDisplayAbsoluteRadius : 1;
|
||||
unsigned int m_bDisplayArrow : 1;
|
||||
unsigned int m_bIconOnTop : 1;
|
||||
unsigned int m_bVisible : 1;
|
||||
unsigned int m_bLight : 1;
|
||||
unsigned int m_bAreaLight : 1;
|
||||
unsigned int m_bProjectorHasTexture : 1;
|
||||
unsigned int m_bProjectInAllDirs : 1;
|
||||
unsigned int m_bBoxProjectedCM : 1;
|
||||
unsigned int m_bBBoxSelection : 1;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
Vec3 m_lightColor;
|
||||
|
||||
//! Entity class.
|
||||
QString m_entityClass;
|
||||
//! Id of spawned entity.
|
||||
int m_entityId;
|
||||
|
||||
// Used for light entities
|
||||
float m_projectorFOV;
|
||||
|
||||
IStatObj* m_visualObject;
|
||||
AABB m_box;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Main entity parameters.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CVariable<bool> mv_outdoor;
|
||||
CVariable<bool> mv_castShadow; // Legacy, required for backwards compatibility
|
||||
CSmartVariableEnum<int> mv_castShadowMinSpec;
|
||||
CVariable<int> mv_ratioLOD;
|
||||
CVariable<float> mv_viewDistanceMultiplier;
|
||||
CVariable<bool> mv_hiddenInGame; // Entity is hidden in game (on start).
|
||||
CVariable<bool> mv_recvWind;
|
||||
CVariable<bool> mv_renderNearest;
|
||||
CVariable<bool> mv_noDecals;
|
||||
CVariable<bool> mv_createdThroughPool;
|
||||
CVariable<float> mv_obstructionMultiplier;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Temp variables (Not serializable) just to display radii from properties.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Used for proximity entities.
|
||||
float m_proximityRadius;
|
||||
float m_innerRadius;
|
||||
float m_outerRadius;
|
||||
// Used for probes
|
||||
float m_boxSizeX;
|
||||
float m_boxSizeY;
|
||||
float m_boxSizeZ;
|
||||
// Used for area lights
|
||||
float m_fAreaWidth;
|
||||
float m_fAreaHeight;
|
||||
float m_fAreaLightSize;
|
||||
// Used for box projected cubemaps
|
||||
float m_fBoxWidth;
|
||||
float m_fBoxHeight;
|
||||
float m_fBoxLength;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Event Targets.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Array of event targets of this Entity.
|
||||
typedef std::vector<CEntityEventTarget> EventTargets;
|
||||
EventTargets m_eventTargets;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Links
|
||||
typedef std::vector<CEntityLink> Links;
|
||||
Links m_links;
|
||||
|
||||
//! Entity properties variables.
|
||||
CVarBlockPtr m_pProperties;
|
||||
|
||||
//! Per instance entity properties variables
|
||||
CVarBlockPtr m_pProperties2;
|
||||
|
||||
// Physics state, as a string.
|
||||
XmlNodeRef m_physicsState;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
static float m_helperScale;
|
||||
|
||||
EAttachmentType m_attachmentType;
|
||||
|
||||
bool m_bEnableReload;
|
||||
|
||||
QString m_attachmentTarget;
|
||||
|
||||
private:
|
||||
struct VariableCallbackIndex
|
||||
{
|
||||
enum : unsigned char
|
||||
{
|
||||
OnAreaHeightChange = 0,
|
||||
OnAreaLightChange,
|
||||
OnAreaLightSizeChange,
|
||||
OnAreaWidthChange,
|
||||
OnBoxHeightChange,
|
||||
OnBoxLengthChange,
|
||||
OnBoxProjectionChange,
|
||||
OnBoxSizeXChange,
|
||||
OnBoxSizeYChange,
|
||||
OnBoxSizeZChange,
|
||||
OnBoxWidthChange,
|
||||
OnColorChange,
|
||||
OnInnerRadiusChange,
|
||||
OnOuterRadiusChange,
|
||||
OnProjectInAllDirsChange,
|
||||
OnProjectorFOVChange,
|
||||
OnProjectorTextureChange,
|
||||
OnPropertyChange,
|
||||
OnRadiusChange,
|
||||
|
||||
// must be at the end
|
||||
Count,
|
||||
};
|
||||
};
|
||||
|
||||
void ResetCallbacks();
|
||||
void SetVariableCallback(IVariable* pVar, IVariable::OnSetCallback* func);
|
||||
void ClearCallbacks();
|
||||
|
||||
void ForceVariableUpdate();
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
CListenerSet<IEntityObjectListener*> m_listeners;
|
||||
std::vector< std::pair<IVariable*, IVariable::OnSetCallback*> > m_callbacks;
|
||||
AZStd::fixed_vector< IVariable::OnSetCallback, VariableCallbackIndex::Count > m_onSetCallbacksCache;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_ENTITYOBJECT_H
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "Gizmo.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CGizmo implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CGizmo::CGizmo()
|
||||
{
|
||||
m_bDelete = false;
|
||||
m_matrix.SetIdentity();
|
||||
m_flags = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CGizmo::~CGizmo()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGizmo::SetMatrix(const Matrix34& tm)
|
||||
{
|
||||
m_matrix = tm;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGizmo::DeleteThis()
|
||||
{
|
||||
m_bDelete = true;
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "BaseObject.h"
|
||||
|
||||
// forward declarations.
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_GIZMO_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_GIZMO_H
|
||||
#pragma once
|
||||
struct DisplayContext;
|
||||
struct HitContext;
|
||||
|
||||
enum EGizmoFlags
|
||||
{
|
||||
EGIZMO_SELECTABLE = 0x0001, //! If set gizmo can be selected by clicking.
|
||||
EGIZMO_HIDDEN = 0x0002, //! If set gizmo hidden and should not be displayed.
|
||||
EGIZMO_TRANSFORM_MANIPULATOR = 0x0004, //! This gizmo is a transform manipulator.
|
||||
};
|
||||
|
||||
/** Any helper object that BaseObjects can use to display some usefull information like tracks.
|
||||
Gizmo's life time should be controlled by thier owning BaseObjects.
|
||||
*/
|
||||
class SANDBOX_API CGizmo
|
||||
: public CRefCountBase
|
||||
{
|
||||
public:
|
||||
CGizmo();
|
||||
virtual ~CGizmo();
|
||||
|
||||
virtual void SetName([[maybe_unused]] const char* sName) {};
|
||||
virtual const char* GetName([[maybe_unused]] const char* sName) { return ""; };
|
||||
|
||||
//! Set gizmo object flags.
|
||||
void SetFlags(uint32 flags) { m_flags = flags; }
|
||||
//! Get gizmo object flags.
|
||||
uint32 GetFlags() const { return m_flags; }
|
||||
|
||||
/** Get bounding box of Gizmo in world space.
|
||||
@param bbox Returns bounding box.
|
||||
*/
|
||||
virtual void GetWorldBounds(AABB& bbox) = 0;
|
||||
|
||||
/** Set transformation matrix of this gizmo.
|
||||
*/
|
||||
virtual void SetMatrix(const Matrix34& tm);
|
||||
|
||||
/** Get transformation matrix of this gizmo.
|
||||
*/
|
||||
virtual const Matrix34& GetMatrix() const { return m_matrix; }
|
||||
|
||||
/** Display Gizmo in the viewport.
|
||||
*/
|
||||
virtual void Display(DisplayContext& dc) = 0;
|
||||
|
||||
/** Performs hit testing on gizmo object.
|
||||
*/
|
||||
virtual bool HitTest([[maybe_unused]] HitContext& hc) { return false; };
|
||||
|
||||
//! Is this gizmo need to be deleted?.
|
||||
bool IsDelete() const { return m_bDelete; }
|
||||
//! Set this gizmo to be deleted.
|
||||
void DeleteThis();
|
||||
|
||||
virtual CBaseObjectPtr GetBaseObject() const { return NULL; }
|
||||
|
||||
|
||||
protected:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
mutable Matrix34 m_matrix;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
bool m_bDelete; // This gizmo is marked for deletion.
|
||||
uint32 m_flags;
|
||||
};
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_GIZMO_H
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "GizmoManager.h"
|
||||
|
||||
// Editor
|
||||
#include "Gizmo.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGizmoManager::Display(DisplayContext& dc)
|
||||
{
|
||||
FUNCTION_PROFILER(GetIEditor()->GetSystem(), PROFILE_EDITOR);
|
||||
|
||||
AABB bbox;
|
||||
std::vector<CGizmo*> todelete;
|
||||
for (Gizmos::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
CGizmo* gizmo = *it;
|
||||
if (gizmo->GetFlags() & EGIZMO_HIDDEN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
gizmo->GetWorldBounds(bbox);
|
||||
if (dc.IsVisible(bbox))
|
||||
{
|
||||
gizmo->Display(dc);
|
||||
}
|
||||
|
||||
if (gizmo->IsDelete())
|
||||
{
|
||||
todelete.push_back(gizmo);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete gizmos that needs deletion.
|
||||
for (int i = 0; i < todelete.size(); i++)
|
||||
{
|
||||
RemoveGizmo(todelete[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGizmoManager::AddGizmo(CGizmo* gizmo)
|
||||
{
|
||||
m_gizmos.insert(gizmo);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGizmoManager::RemoveGizmo(CGizmo* gizmo)
|
||||
{
|
||||
m_gizmos.erase(gizmo);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CGizmoManager::GetGizmoCount() const
|
||||
{
|
||||
return (int)m_gizmos.size();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CGizmo* CGizmoManager::GetGizmoByIndex(int nIndex) const
|
||||
{
|
||||
int nCount = 0;
|
||||
Gizmos::iterator ii = m_gizmos.begin();
|
||||
for (; ii != m_gizmos.end(); ++ii)
|
||||
{
|
||||
if ((nCount++) == nIndex)
|
||||
{
|
||||
return *ii;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CGizmoManager::HitTest(HitContext& hc)
|
||||
{
|
||||
float mindist = FLT_MAX;
|
||||
|
||||
HitContext ghc = hc;
|
||||
bool bGizmoHit = false;
|
||||
|
||||
AABB bbox;
|
||||
for (Gizmos::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
CGizmo* gizmo = *it;
|
||||
|
||||
if (gizmo->GetFlags() & EGIZMO_SELECTABLE)
|
||||
{
|
||||
if (gizmo->HitTest(ghc))
|
||||
{
|
||||
bGizmoHit = true;
|
||||
if (ghc.dist < mindist)
|
||||
{
|
||||
mindist = ghc.dist;
|
||||
hc = ghc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bGizmoHit;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CGizmoManager::DeleteAllTransformManipulators()
|
||||
{
|
||||
std::vector<CGizmo*> todelete;
|
||||
for (Gizmos::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
|
||||
{
|
||||
CGizmo* gizmo = *it;
|
||||
if (gizmo->GetFlags() & EGIZMO_TRANSFORM_MANIPULATOR)
|
||||
{
|
||||
todelete.push_back(gizmo);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete gizmos that needs deletion.
|
||||
for (int i = 0; i < todelete.size(); i++)
|
||||
{
|
||||
RemoveGizmo(todelete[i]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_GIZMOMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_GIZMOMANAGER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "IGizmoManager.h"
|
||||
|
||||
|
||||
typedef _smart_ptr<CGizmo> CGizmoPtr;
|
||||
|
||||
/** GizmoManager manages set of currently active Gizmo objects.
|
||||
*/
|
||||
class CGizmoManager
|
||||
: public IGizmoManager
|
||||
{
|
||||
public:
|
||||
void AddGizmo(CGizmo* gizmo);
|
||||
void RemoveGizmo(CGizmo* gizmo);
|
||||
|
||||
int GetGizmoCount() const override;
|
||||
CGizmo* GetGizmoByIndex(int nIndex) const override;
|
||||
|
||||
void Display(DisplayContext& dc);
|
||||
bool HitTest(HitContext& hc);
|
||||
|
||||
void DeleteAllTransformManipulators();
|
||||
|
||||
private:
|
||||
typedef std::set<CGizmoPtr> Gizmos;
|
||||
Gizmos m_gizmos;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_GIZMOMANAGER_H
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class IEntityObjectListener
|
||||
{
|
||||
public:
|
||||
virtual ~IEntityObjectListener() = default;
|
||||
|
||||
virtual void OnNameChanged(const char* pName) = 0;
|
||||
virtual void OnSelectionChanged(const bool bSelected) = 0;
|
||||
virtual void OnDone() = 0;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "LineGizmo.h"
|
||||
|
||||
// Editor
|
||||
#include "Include/IObjectManager.h"
|
||||
#include "DisplayContext.h"
|
||||
#include "DisplaySettings.h"
|
||||
#include "Objects/EntityObject.h"
|
||||
#include "GizmoManager.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CLineGizmo::CLineGizmo()
|
||||
{
|
||||
m_color[0] = ColorF(0, 1, 1, 1);
|
||||
m_color[1] = ColorF(0, 1, 1, 1);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CLineGizmo::~CLineGizmo()
|
||||
{
|
||||
if (m_object[0])
|
||||
{
|
||||
m_object[0]->RemoveEventListener(this);
|
||||
}
|
||||
if (m_object[1])
|
||||
{
|
||||
m_object[1]->RemoveEventListener(this);
|
||||
}
|
||||
m_object[0] = 0;
|
||||
m_object[1] = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CLineGizmo::SetObjects(CBaseObject* pObject1, CBaseObject* pObject2, const QString& boneName)
|
||||
{
|
||||
assert(pObject1);
|
||||
assert(pObject2);
|
||||
m_object[0] = pObject1;
|
||||
m_object[1] = pObject2;
|
||||
m_boneName = boneName;
|
||||
|
||||
m_object[0]->AddEventListener(this);
|
||||
m_object[1]->AddEventListener(this);
|
||||
CalcBounds();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CLineGizmo::OnObjectEvent([[maybe_unused]] CBaseObject* object, int event)
|
||||
{
|
||||
if (event == CBaseObject::ON_TRANSFORM)
|
||||
{
|
||||
// One of objects transformed, recalc gizmo bounds.
|
||||
CalcBounds();
|
||||
return;
|
||||
}
|
||||
if (event == CBaseObject::ON_DELETE)
|
||||
{
|
||||
// This gizmo must be deleted as well if one of the objects is deleted.
|
||||
GetIEditor()->GetObjectManager()->GetGizmoManager()->RemoveGizmo(this);
|
||||
return;
|
||||
}
|
||||
if (event == CBaseObject::ON_VISIBILITY)
|
||||
{
|
||||
// Check visibility of gizmo.
|
||||
bool bVisible = !m_object[0]->CheckFlags(OBJFLAG_INVISIBLE) && !m_object[1]->CheckFlags(OBJFLAG_INVISIBLE);
|
||||
if (bVisible)
|
||||
{
|
||||
SetFlags(GetFlags() & (~EGIZMO_HIDDEN));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFlags(GetFlags() | EGIZMO_HIDDEN);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CLineGizmo::Display(DisplayContext& dc)
|
||||
{
|
||||
if (dc.flags & DISPLAY_LINKS)
|
||||
{
|
||||
dc.DrawLine(m_point[0], m_point[1], m_color[0], m_color[1]);
|
||||
|
||||
//if (!(dc.flags & DISPLAY_HIDENAMES))
|
||||
{
|
||||
Vec3 pos = 0.5f * (m_point[0] + m_point[1]);
|
||||
//dc.renderer->DrawLabelEx( p3+Vec3(0,0,0.3f),1.2f,col,true,true,m_name );
|
||||
|
||||
float camDist = dc.camera->GetPosition().GetDistance(pos);
|
||||
float maxDist = dc.settings->GetLabelsDistance();
|
||||
if (camDist < dc.settings->GetLabelsDistance())
|
||||
{
|
||||
float range = maxDist / 2.0f;
|
||||
float col[4] = { m_color[0].r, m_color[0].g, m_color[0].b, m_color[0].a };
|
||||
if (camDist > range)
|
||||
{
|
||||
col[3] = col[3] * (1.0f - (camDist - range) / range);
|
||||
}
|
||||
dc.SetColor(col[0], col[1], col[2], col[3]);
|
||||
dc.DrawTextLabel(pos + Vec3(0, 0, 0.2f), 1.2f, m_name.toUtf8().data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CLineGizmo::CalcBounds()
|
||||
{
|
||||
m_bbox.Reset();
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
bool IsObjectLight = false;
|
||||
if (qobject_cast<CEntityObject*>(m_object[i]))
|
||||
{
|
||||
CEntityObject* entityobject = static_cast<CEntityObject*>(m_object[i].get());
|
||||
if (entityobject->IsLight())
|
||||
{
|
||||
m_point[i] = entityobject->GetWorldPos();
|
||||
IsObjectLight = true;
|
||||
}
|
||||
}
|
||||
if (IsObjectLight == false)
|
||||
{
|
||||
AABB box;
|
||||
m_object[i]->GetBoundBox(box);
|
||||
m_point[i] = 0.5f * Vec3(box.max + box.min);
|
||||
}
|
||||
m_bbox.Add(m_point[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CLineGizmo::GetWorldBounds(AABB& bbox)
|
||||
{
|
||||
bbox = m_bbox;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CLineGizmo::SetColor(const Vec3& color1, const Vec3& color2, float alpha1, float alpha2)
|
||||
{
|
||||
m_color[0] = ColorF(color1.x, color1.y, color1.z, alpha1);
|
||||
m_color[1] = ColorF(color2.x, color2.y, color2.z, alpha2);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CLineGizmo::SetName(const char* sName)
|
||||
{
|
||||
m_name = sName;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CLineGizmo::HitTest([[maybe_unused]] HitContext& hc)
|
||||
{
|
||||
return 0;
|
||||
/*
|
||||
if (hc.distanceTollerance != 0)
|
||||
return 0;
|
||||
|
||||
Vec3 org = m_object->GetWorldPos();
|
||||
|
||||
float fScreenScale = hc.view->GetScreenScaleFactor(org);
|
||||
float size = gSettings.gizmo.axisGizmoSize * fScreenScale;
|
||||
|
||||
Vec3 x(size,0,0);
|
||||
Vec3 y(0,size,0);
|
||||
Vec3 z(0,0,size);
|
||||
|
||||
float hitDist = 0.01f * fScreenScale;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Calculate ray in local space of axis.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Matrix34 tm;
|
||||
RefCoordSys refCoordSys = GetIEditor()->GetReferenceCoordSys();
|
||||
if (refCoordSys == COORDS_LOCAL)
|
||||
{
|
||||
tm = m_object->GetWorldTM();
|
||||
tm.NoScale();
|
||||
}
|
||||
else
|
||||
{
|
||||
tm.SetIdentity();
|
||||
tm.SetTranslation( m_object->GetWorldPos() );
|
||||
}
|
||||
tm.Invert44();
|
||||
Vec3 raySrc = tm.TransformPoint( hc.raySrc );
|
||||
//CHANGED_BY_IVO
|
||||
//Vec3 rayDir = tm.TransformVector( hc.rayDir );
|
||||
Vec3 rayDir = GetTransposed44(tm) * ( hc.rayDir );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Vec3 pnt;
|
||||
BBox box;
|
||||
box.min = - Vec3(hitDist*2,hitDist*2,hitDist*2);
|
||||
box.max = Vec3(size+hitDist*2,size+hitDist*2,size+hitDist*2);
|
||||
if (!box.IsIntersectRay( raySrc,rayDir,pnt ))
|
||||
{
|
||||
m_highlightAxis = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
float axisdist[10];
|
||||
Vec3 np[10];
|
||||
|
||||
Vec3 rayTrg = raySrc + rayDir*10000.0f;
|
||||
|
||||
size *= 0.3f;
|
||||
Vec3 p1(size,size,0);
|
||||
Vec3 p2(size,0,size);
|
||||
Vec3 p3(0,size,size);
|
||||
|
||||
axisdist[AXIS_X] = RayToLineDistance( raySrc,rayTrg,Vec3(0,0,0),x,np[AXIS_X] );
|
||||
axisdist[AXIS_Y] = RayToLineDistance( raySrc,rayTrg,Vec3(0,0,0),y,np[AXIS_Y] );
|
||||
axisdist[AXIS_Z] = RayToLineDistance( raySrc,rayTrg,Vec3(0,0,0),z,np[AXIS_Z] );
|
||||
axisdist[AXIS_XY] = RayToLineDistance( raySrc,rayTrg,p1,p1-x*0.3f,np[AXIS_XY] );
|
||||
axisdist[AXIS_XZ] = RayToLineDistance( raySrc,rayTrg,p2,p2-x*0.3f,np[AXIS_XZ] );
|
||||
axisdist[AXIS_YZ] = RayToLineDistance( raySrc,rayTrg,p3,p3-y*0.3f,np[AXIS_YZ] );
|
||||
|
||||
float mindist = hitDist;
|
||||
int axis = 0;
|
||||
for (int i = AXIS_X; i <= AXIS_XZ; i++)
|
||||
{
|
||||
if (axisdist[i] < mindist)
|
||||
{
|
||||
mindist = axisdist[i];
|
||||
axis = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (axis != 0)
|
||||
{
|
||||
hc.axis = axis;
|
||||
hc.object = m_object;
|
||||
hc.dist = GetDistance(raySrc,np[axis]);
|
||||
}
|
||||
|
||||
m_highlightAxis = axis;
|
||||
|
||||
return axis != 0;
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_LINEGIZMO_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_LINEGIZMO_H
|
||||
#pragma once
|
||||
|
||||
#include "BaseObject.h"
|
||||
#include "Gizmo.h"
|
||||
|
||||
// forward declarations.
|
||||
struct DisplayContext;
|
||||
|
||||
/** Gizmo of link line connecting two Objects.
|
||||
*/
|
||||
class CLineGizmo
|
||||
: public CGizmo
|
||||
, public CBaseObject::EventListener
|
||||
{
|
||||
public:
|
||||
CLineGizmo();
|
||||
~CLineGizmo();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Ovverides from CGizmo
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void SetName(const char* sName);
|
||||
virtual void GetWorldBounds(AABB& bbox);
|
||||
virtual void Display(DisplayContext& dc);
|
||||
virtual bool HitTest(HitContext& hc);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SetObjects(CBaseObject* pObject1, CBaseObject* pObject2, const QString& boneName = "");
|
||||
void SetColor(const Vec3& color1, const Vec3& color2, float alpha1 = 1.0f, float alpha2 = 1.0f);
|
||||
|
||||
private:
|
||||
void OnObjectEvent(CBaseObject* object, int event) override;
|
||||
void CalcBounds();
|
||||
|
||||
CBaseObjectPtr m_object[2];
|
||||
Vec3 m_point[2];
|
||||
AABB m_bbox;
|
||||
ColorF m_color[2];
|
||||
QString m_name;
|
||||
QString m_boneName;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_LINEGIZMO_H
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ObjectLoader.h"
|
||||
|
||||
// Editor
|
||||
#include "Util/PakFile.h"
|
||||
#include "WaitProgress.h"
|
||||
#include "Include/IObjectManager.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CObjectArchive Implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CObjectArchive::CObjectArchive(IObjectManager* objMan, XmlNodeRef xmlRoot, bool loading)
|
||||
{
|
||||
m_objectManager = objMan;
|
||||
bLoading = loading;
|
||||
bUndo = false;
|
||||
m_nFlags = 0;
|
||||
node = xmlRoot;
|
||||
m_pCurrentErrorReport = GetIEditor()->GetErrorReport();
|
||||
m_pGeometryPak = NULL;
|
||||
m_pCurrentObject = NULL;
|
||||
m_bNeedResolveObjects = false;
|
||||
m_bProgressBarEnabled = true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CObjectArchive::~CObjectArchive()
|
||||
{
|
||||
if (m_pGeometryPak)
|
||||
{
|
||||
delete m_pGeometryPak;
|
||||
}
|
||||
// Always make sure objects are resolved when loading from archive.
|
||||
if (bLoading && m_bNeedResolveObjects)
|
||||
{
|
||||
ResolveObjects();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::SetResolveCallback(CBaseObject* fromObject, REFGUID objectId, ResolveObjRefFunctor1 func)
|
||||
{
|
||||
if (objectId == GUID_NULL)
|
||||
{
|
||||
func(0);
|
||||
return;
|
||||
}
|
||||
|
||||
GUID guid(objectId);
|
||||
|
||||
CBaseObject* pObject = m_objectManager->FindObject(guid);
|
||||
if (pObject && !(m_nFlags & eObjectLoader_MakeNewIDs))
|
||||
{
|
||||
// Object is already resolved. immediately call callback.
|
||||
func(pObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
Callback cb;
|
||||
cb.fromObject = fromObject;
|
||||
cb.func1 = func;
|
||||
m_resolveCallbacks.insert(Callbacks::value_type(guid, cb));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::SetResolveCallback(CBaseObject* fromObject, REFGUID objectId, ResolveObjRefFunctor2 func, uint32 userData)
|
||||
{
|
||||
if (objectId == GUID_NULL)
|
||||
{
|
||||
func(0, userData);
|
||||
return;
|
||||
}
|
||||
|
||||
CBaseObject* object = m_objectManager->FindObject(objectId);
|
||||
if (object && !(m_nFlags & eObjectLoader_MakeNewIDs))
|
||||
{
|
||||
// Object is already resolved. immidiatly call callback.
|
||||
func(object, userData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Callback cb;
|
||||
cb.fromObject = fromObject;
|
||||
cb.func2 = func;
|
||||
cb.userData = userData;
|
||||
m_resolveCallbacks.insert(Callbacks::value_type(objectId, cb));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
GUID CObjectArchive::ResolveID(REFGUID id)
|
||||
{
|
||||
return stl::find_in_map(m_IdRemap, id, id);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::ResolveObjects()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!bLoading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
CWaitProgress wait("Loading Objects", false);
|
||||
if (m_bProgressBarEnabled)
|
||||
{
|
||||
wait.Start();
|
||||
}
|
||||
|
||||
GetIEditor()->SuspendUndo();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Serialize All Objects from XML.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int numObj = m_loadedObjects.size();
|
||||
for (i = 0; i < numObj; i++)
|
||||
{
|
||||
if (m_bProgressBarEnabled)
|
||||
{
|
||||
wait.Step((i * 100) / numObj);
|
||||
}
|
||||
|
||||
SLoadedObjectInfo& obj = m_loadedObjects[i];
|
||||
m_pCurrentErrorReport->SetCurrentValidatorObject(obj.pObject);
|
||||
node = obj.xmlNode;
|
||||
|
||||
obj.pObject->Serialize(*this);
|
||||
|
||||
m_pCurrentErrorReport->SetCurrentValidatorObject(nullptr);
|
||||
|
||||
// Objects can be added to the list here (from Groups).
|
||||
numObj = m_loadedObjects.size();
|
||||
}
|
||||
m_pCurrentErrorReport->SetCurrentValidatorObject(NULL);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
GetIEditor()->ResumeUndo();
|
||||
}
|
||||
|
||||
// Sort objects by sort order.
|
||||
std::sort(m_loadedObjects.begin(), m_loadedObjects.end());
|
||||
|
||||
// Then rearrange to parent-first, if same sort order.
|
||||
for (i = 0; i < m_loadedObjects.size(); i++)
|
||||
{
|
||||
if (m_loadedObjects[i].pObject->GetParent())
|
||||
{
|
||||
// Find later in array.
|
||||
for (int j = i + 1; j < m_loadedObjects.size() && m_loadedObjects[j].nSortOrder == m_loadedObjects[i].nSortOrder; j++)
|
||||
{
|
||||
if (m_loadedObjects[j].pObject == m_loadedObjects[i].pObject->GetParent())
|
||||
{
|
||||
// Swap the objects.
|
||||
std::swap(m_loadedObjects[i], m_loadedObjects[j]);
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Resolve objects GUIDs
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
for (Callbacks::iterator it = m_resolveCallbacks.begin(); it != m_resolveCallbacks.end(); it++)
|
||||
{
|
||||
Callback& cb = it->second;
|
||||
GUID objectId = ResolveID(it->first);
|
||||
CBaseObject* object = m_objectManager->FindObject(objectId);
|
||||
if (!object)
|
||||
{
|
||||
QString from;
|
||||
if (cb.fromObject)
|
||||
{
|
||||
from = cb.fromObject->GetName();
|
||||
}
|
||||
// Cannot resolve this object id.
|
||||
CErrorRecord err;
|
||||
err.error = QObject::tr("Unresolved ObjectID: %1, Referenced from Object %1").arg(GuidUtil::ToString(objectId)).arg(from);
|
||||
err.severity = CErrorRecord::ESEVERITY_ERROR;
|
||||
err.flags = CErrorRecord::FLAG_OBJECTID;
|
||||
err.pObject = cb.fromObject;
|
||||
GetIEditor()->GetErrorReport()->ReportError(err);
|
||||
|
||||
//Warning( "Cannot resolve ObjectID: %s\r\nObject with this ID was not present in loaded file.\r\nFor instance Trigger referencing another object which is not loaded in Level.",GuidUtil::ToString(objectId) );
|
||||
continue;
|
||||
}
|
||||
m_pCurrentErrorReport->SetCurrentValidatorObject(object);
|
||||
// Call callback with this object.
|
||||
if (cb.func1)
|
||||
{
|
||||
(cb.func1)(object);
|
||||
}
|
||||
if (cb.func2)
|
||||
{
|
||||
(cb.func2)(object, cb.userData);
|
||||
}
|
||||
}
|
||||
m_resolveCallbacks.clear();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
{
|
||||
CWaitProgress wait("Creating Objects", false);
|
||||
if (m_bProgressBarEnabled)
|
||||
{
|
||||
wait.Start();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Serialize All Objects from XML.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int numObj = m_loadedObjects.size();
|
||||
for (i = 0; i < numObj; i++)
|
||||
{
|
||||
if (m_bProgressBarEnabled)
|
||||
{
|
||||
wait.Step((i * 100) / numObj);
|
||||
}
|
||||
|
||||
SLoadedObjectInfo& obj = m_loadedObjects[i];
|
||||
m_pCurrentErrorReport->SetCurrentValidatorObject(obj.pObject);
|
||||
|
||||
obj.pObject->CreateGameObject();
|
||||
|
||||
// unset the current validator object because the wait Step
|
||||
// might generate unrelated errors
|
||||
m_pCurrentErrorReport->SetCurrentValidatorObject(nullptr);
|
||||
}
|
||||
m_pCurrentErrorReport->SetCurrentValidatorObject(NULL);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Call PostLoad on all these objects.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
int numObj = m_loadedObjects.size();
|
||||
for (i = 0; i < numObj; i++)
|
||||
{
|
||||
SLoadedObjectInfo& obj = m_loadedObjects[i];
|
||||
m_pCurrentErrorReport->SetCurrentValidatorObject(obj.pObject);
|
||||
node = obj.xmlNode;
|
||||
obj.pObject->PostLoad(*this);
|
||||
}
|
||||
}
|
||||
|
||||
m_bNeedResolveObjects = false;
|
||||
m_pCurrentErrorReport->SetCurrentValidatorObject(NULL);
|
||||
m_sequenceIdRemap.clear();
|
||||
m_pendingIds.clear();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::SaveObject(CBaseObject* pObject)
|
||||
{
|
||||
if (pObject->CheckFlags(OBJFLAG_DONT_SAVE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_savedObjects.find(pObject) == m_savedObjects.end())
|
||||
{
|
||||
m_pCurrentObject = pObject;
|
||||
m_savedObjects.insert(pObject);
|
||||
// If this object was not saved before.
|
||||
XmlNodeRef objNode = node->newChild("Object");
|
||||
XmlNodeRef prevRoot = node;
|
||||
node = objNode;
|
||||
|
||||
pObject->Serialize(*this);
|
||||
node = prevRoot;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CBaseObject* CObjectArchive::LoadObject(const XmlNodeRef& objNode, CBaseObject* pPrevObject)
|
||||
{
|
||||
XmlNodeRef prevNode = node;
|
||||
node = objNode;
|
||||
CBaseObject* pObject;
|
||||
bool bMakeNewID = (m_nFlags & eObjectLoader_MakeNewIDs) ? true : false;
|
||||
|
||||
pObject = m_objectManager->NewObject(*this, pPrevObject, bMakeNewID);
|
||||
if (pObject)
|
||||
{
|
||||
SLoadedObjectInfo obj;
|
||||
obj.nSortOrder = pObject->GetClassDesc()->GameCreationOrder();
|
||||
obj.pObject = pObject;
|
||||
obj.newGuid = pObject->GetId();
|
||||
obj.xmlNode = node;
|
||||
m_loadedObjects.push_back(obj);
|
||||
m_bNeedResolveObjects = true;
|
||||
}
|
||||
node = prevNode;
|
||||
return pObject;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::LoadObjects(XmlNodeRef& rootObjectsNode)
|
||||
{
|
||||
int numObjects = rootObjectsNode->getChildCount();
|
||||
for (int i = 0; i < numObjects; i++)
|
||||
{
|
||||
XmlNodeRef objNode = rootObjectsNode->getChild(i);
|
||||
LoadObject(objNode, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::ReportError(CErrorRecord& err)
|
||||
{
|
||||
if (m_pCurrentErrorReport)
|
||||
{
|
||||
m_pCurrentErrorReport->ReportError(err);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::SetErrorReport(CErrorReport* errReport)
|
||||
{
|
||||
if (errReport)
|
||||
{
|
||||
m_pCurrentErrorReport = errReport;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pCurrentErrorReport = GetIEditor()->GetErrorReport();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::ShowErrors()
|
||||
{
|
||||
GetIEditor()->GetErrorReport()->Display();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::MakeNewIds(bool bEnable)
|
||||
{
|
||||
if (bEnable)
|
||||
{
|
||||
m_nFlags |= eObjectLoader_MakeNewIDs;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nFlags &= ~(eObjectLoader_MakeNewIDs);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::SetShouldResetInternalMembers(bool reset)
|
||||
{
|
||||
if (reset)
|
||||
{
|
||||
m_nFlags |= eObjectLoader_ResetInternalMembers;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nFlags &= ~(eObjectLoader_ResetInternalMembers);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::RemapID(REFGUID oldId, REFGUID newId)
|
||||
{
|
||||
m_IdRemap[oldId] = newId;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CPakFile* CObjectArchive::GetGeometryPak(const char* sFilename)
|
||||
{
|
||||
if (m_pGeometryPak)
|
||||
{
|
||||
return m_pGeometryPak;
|
||||
}
|
||||
m_pGeometryPak = new CPakFile;
|
||||
m_pGeometryPak->Open(sFilename);
|
||||
return m_pGeometryPak;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CBaseObject* CObjectArchive::GetCurrentObject()
|
||||
{
|
||||
return m_pCurrentObject;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectArchive::AddSequenceIdMapping(uint32 oldId, uint32 newId)
|
||||
{
|
||||
assert(oldId != newId);
|
||||
assert(GetIEditor()->GetMovieSystem()->FindSequenceById(oldId) || stl::find(m_pendingIds, oldId));
|
||||
assert(GetIEditor()->GetMovieSystem()->FindSequenceById(newId) == NULL);
|
||||
assert(stl::find(m_pendingIds, newId) == false);
|
||||
m_sequenceIdRemap[oldId] = newId;
|
||||
m_pendingIds.push_back(newId);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint32 CObjectArchive::RemapSequenceId(uint32 id) const
|
||||
{
|
||||
std::map<uint32, uint32>::const_iterator itr = m_sequenceIdRemap.find(id);
|
||||
if (itr == m_sequenceIdRemap.end())
|
||||
{
|
||||
return id;
|
||||
}
|
||||
else
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CObjectArchive::IsAmongPendingIds(uint32 id) const
|
||||
{
|
||||
return stl::find(m_pendingIds, id);
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_OBJECTLOADER_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_OBJECTLOADER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "Util/GuidUtil.h"
|
||||
#include "ErrorReport.h"
|
||||
|
||||
class CPakFile;
|
||||
class CErrorRecord;
|
||||
struct IObjectManager;
|
||||
|
||||
typedef std::map<GUID, GUID, guid_less_predicate> TGUIDRemap;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
/** CObjectLoader used to load Bas Object and resolve ObjectId references while loading.
|
||||
*/
|
||||
class SANDBOX_API CObjectArchive
|
||||
{
|
||||
public:
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
XmlNodeRef node; //!< Current archive node.
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
bool bLoading;
|
||||
bool bUndo;
|
||||
|
||||
CObjectArchive(IObjectManager* objMan, XmlNodeRef xmlRoot, bool loading);
|
||||
~CObjectArchive();
|
||||
|
||||
//! Resolve callback with only one parameter of CBaseObject.
|
||||
typedef AZStd::function<void(CBaseObject*)> ResolveObjRefFunctor1;
|
||||
//! Resolve callback with two parameters one is pointer to CBaseObject and second use data integer.
|
||||
typedef AZStd::function<void(CBaseObject*, unsigned int)> ResolveObjRefFunctor2;
|
||||
|
||||
/** Register Object id.
|
||||
@param objectId Original object id from the file.
|
||||
@param realObjectId Changed object id.
|
||||
*/
|
||||
//void RegisterObjectId( int objectId,int realObjectId );
|
||||
|
||||
// Return object ID remapped after loading.
|
||||
GUID ResolveID(REFGUID id);
|
||||
|
||||
//! Set object resolve callback, it will be called once object with specified Id is loaded.
|
||||
void SetResolveCallback(CBaseObject* fromObject, REFGUID objectId, ResolveObjRefFunctor1 func);
|
||||
//! Set object resolve callback, it will be called once object with specified Id is loaded.
|
||||
void SetResolveCallback(CBaseObject* fromObject, REFGUID objectId, ResolveObjRefFunctor2 func, uint32 userData);
|
||||
//! Resolve all object ids and call callbacks on resolved objects.
|
||||
void ResolveObjects();
|
||||
|
||||
// Save object to archive.
|
||||
void SaveObject(CBaseObject* pObject);
|
||||
|
||||
//! Load multiple objects from archive.
|
||||
void LoadObjects(XmlNodeRef& rootObjectsNode);
|
||||
|
||||
//! Load one object from archive.
|
||||
CBaseObject* LoadObject(const XmlNodeRef& objNode, CBaseObject* pPrevObject = NULL);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int GetLoadedObjectsCount() { return m_loadedObjects.size(); }
|
||||
CBaseObject* GetLoadedObject(int nIndex) const { return m_loadedObjects[nIndex].pObject; }
|
||||
|
||||
//! If true new loaded objects will be assigned new GUIDs.
|
||||
void MakeNewIds(bool bEnable);
|
||||
|
||||
//! Remap object ids.
|
||||
void RemapID(REFGUID oldId, REFGUID newId);
|
||||
|
||||
//! Report error during loading.
|
||||
void ReportError(CErrorRecord& err);
|
||||
//! Assigner different error report class.
|
||||
void SetErrorReport(CErrorReport* errReport);
|
||||
//! Display collected error reports.
|
||||
void ShowErrors();
|
||||
|
||||
void EnableProgressBar(bool bEnable) { m_bProgressBarEnabled = bEnable; };
|
||||
|
||||
CPakFile* GetGeometryPak(const char* sFilename);
|
||||
CBaseObject* GetCurrentObject();
|
||||
|
||||
void AddSequenceIdMapping(uint32 oldId, uint32 newId);
|
||||
uint32 RemapSequenceId(uint32 id) const;
|
||||
bool IsAmongPendingIds(uint32 id) const;
|
||||
|
||||
void SetShouldResetInternalMembers(bool reset);
|
||||
bool ShouldResetInternalMembers() const { return m_nFlags & eObjectLoader_ResetInternalMembers; }
|
||||
|
||||
private:
|
||||
struct SLoadedObjectInfo
|
||||
{
|
||||
int nSortOrder;
|
||||
_smart_ptr<CBaseObject> pObject;
|
||||
XmlNodeRef xmlNode;
|
||||
GUID newGuid;
|
||||
bool operator <(const SLoadedObjectInfo& oi) const { return nSortOrder < oi.nSortOrder; }
|
||||
};
|
||||
|
||||
|
||||
IObjectManager* m_objectManager;
|
||||
struct Callback
|
||||
{
|
||||
ResolveObjRefFunctor1 func1;
|
||||
ResolveObjRefFunctor2 func2;
|
||||
uint32 userData;
|
||||
_smart_ptr<CBaseObject> fromObject;
|
||||
Callback() { func1 = 0; func2 = 0; userData = 0; };
|
||||
};
|
||||
typedef std::multimap<GUID, Callback, guid_less_predicate> Callbacks;
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
Callbacks m_resolveCallbacks;
|
||||
|
||||
// Set of all saved objects to this archive.
|
||||
typedef std::set<_smart_ptr<CBaseObject> > ObjectsSet;
|
||||
ObjectsSet m_savedObjects;
|
||||
|
||||
//typedef std::multimap<int,_smart_ptr<CBaseObject> > OrderedObjects;
|
||||
//OrderedObjects m_orderedObjects;
|
||||
std::vector<SLoadedObjectInfo> m_loadedObjects;
|
||||
|
||||
// Loaded objects IDs, used for remapping of GUIDs.
|
||||
TGUIDRemap m_IdRemap;
|
||||
|
||||
enum EObjectLoaderFlags
|
||||
{
|
||||
eObjectLoader_MakeNewIDs = 0x0001, // If true new loaded objects will be assigned new GUIDs.
|
||||
eObjectLoader_ResetInternalMembers = 0x0004, // In case we are deserializing and we would like to wipe all previous state
|
||||
};
|
||||
int m_nFlags;
|
||||
IErrorReport* m_pCurrentErrorReport;
|
||||
CPakFile* m_pGeometryPak;
|
||||
CBaseObject* m_pCurrentObject;
|
||||
|
||||
bool m_bNeedResolveObjects;
|
||||
bool m_bProgressBarEnabled;
|
||||
|
||||
// This table is used when there is any collision of ids while importing TrackView sequences.
|
||||
std::map<uint32, uint32> m_sequenceIdRemap;
|
||||
std::vector<uint32> m_pendingIds;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_OBJECTLOADER_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : ObjectManager definition.
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_OBJECTMANAGER_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_OBJECTMANAGER_H
|
||||
#pragma once
|
||||
|
||||
#include "IObjectManager.h"
|
||||
#include "BaseObject.h"
|
||||
#include "SelectionGroup.h"
|
||||
#include "ObjectManagerEventBus.h"
|
||||
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <Include/SandboxAPI.h>
|
||||
|
||||
// forward declarations.
|
||||
class CGizmoManager;
|
||||
class CEntityObject;
|
||||
class CObjectArchive;
|
||||
class CObjectClassDesc;
|
||||
class CWaitProgress;
|
||||
|
||||
enum class ImageRotationDegrees;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helper class to signal when we are exporting a level to game
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CObjectManagerLevelIsExporting
|
||||
{
|
||||
public:
|
||||
CObjectManagerLevelIsExporting()
|
||||
{
|
||||
AZ::ObjectManagerEventBus::Broadcast(&AZ::ObjectManagerEventBus::Events::OnExportingStarting);
|
||||
GetIEditor()->GetObjectManager()->SetExportingLevel(true);
|
||||
}
|
||||
|
||||
~CObjectManagerLevelIsExporting()
|
||||
{
|
||||
GetIEditor()->GetObjectManager()->SetExportingLevel(false);
|
||||
AZ::ObjectManagerEventBus::Broadcast(&AZ::ObjectManagerEventBus::Events::OnExportingFinished);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Array of editor objects.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CBaseObjectsCache
|
||||
{
|
||||
public:
|
||||
int GetObjectCount() const { return m_objects.size(); }
|
||||
CBaseObject* GetObject(int nIndex) const { return m_objects[nIndex]; }
|
||||
void AddObject(CBaseObject* object);
|
||||
|
||||
void ClearObjects()
|
||||
{
|
||||
m_objects.clear();
|
||||
m_entityIds.clear();
|
||||
}
|
||||
|
||||
void Reserve(int nCount)
|
||||
{
|
||||
m_objects.reserve(nCount);
|
||||
m_entityIds.reserve(nCount);
|
||||
}
|
||||
|
||||
const AZStd::vector<AZ::EntityId>& GetEntityIdCache() const { return m_entityIds; }
|
||||
|
||||
/// Checksum is used as a dirty flag.
|
||||
unsigned int GetSerialNumber() { return m_serialNumber; }
|
||||
void SetSerialNumber(unsigned int serialNumber) { m_serialNumber = serialNumber; }
|
||||
private:
|
||||
//! List of objects that was displayed at last frame.
|
||||
std::vector<_smart_ptr<CBaseObject> > m_objects;
|
||||
AZStd::vector<AZ::EntityId> m_entityIds;
|
||||
unsigned int m_serialNumber = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
* CObjectManager is a singleton object that
|
||||
* manages global set of objects in level.
|
||||
*/
|
||||
class CObjectManager
|
||||
: public IObjectManager
|
||||
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
//! Selection functor callback.
|
||||
//! Callback function must return a boolean value.
|
||||
//! Return true if selection should proceed, or false to abort object selection.
|
||||
CObjectManager();
|
||||
~CObjectManager();
|
||||
|
||||
void RegisterObjectClasses();
|
||||
|
||||
CBaseObject* NewObject(CObjectClassDesc* cls, CBaseObject* prev = 0, const QString& file = "", const char* newObjectName = nullptr);
|
||||
CBaseObject* NewObject(const QString& typeName, CBaseObject* prev = 0, const QString& file = "", const char* newEntityName = nullptr);
|
||||
|
||||
void DeleteObject(CBaseObject* obj);
|
||||
void DeleteSelection(CSelectionGroup* pSelection);
|
||||
void DeleteAllObjects();
|
||||
CBaseObject* CloneObject(CBaseObject* obj);
|
||||
|
||||
void BeginEditParams(CBaseObject* obj, int flags);
|
||||
void EndEditParams(int flags = 0);
|
||||
// Hides all transform manipulators.
|
||||
void HideTransformManipulators();
|
||||
|
||||
//! Get number of objects manager by ObjectManager (not contain sub objects of groups).
|
||||
int GetObjectCount() const;
|
||||
|
||||
//! Get array of objects, managed by manager (not contain sub objects of groups).
|
||||
//! @param layer if 0 get objects for all layers, or layer to get objects from.
|
||||
void GetObjects(CBaseObjectsArray& objects) const;
|
||||
void GetObjects(DynArray<CBaseObject*>& objects) const;
|
||||
|
||||
//! Get array of objects that pass the filter.
|
||||
//! @param filter The filter functor, return true if you want to get the certain obj, return false if want to skip it.
|
||||
void GetObjects(CBaseObjectsArray& objects, BaseObjectFilterFunctor const& filter) const;
|
||||
|
||||
//! Update objects.
|
||||
void Update();
|
||||
|
||||
//! Display objects on display context.
|
||||
void Display(DisplayContext& dc);
|
||||
|
||||
//! Called when selecting without selection helpers - this is needed since
|
||||
//! the visible object cache is normally not updated when not displaying helpers.
|
||||
void ForceUpdateVisibleObjectCache(DisplayContext& dc);
|
||||
|
||||
//! Check intersection with objects.
|
||||
//! Find intersection with nearest to ray origin object hit by ray.
|
||||
//! If distance tollerance is specified certain relaxation applied on collision test.
|
||||
//! @return true if hit any object, and fills hitInfo structure.
|
||||
bool HitTest(HitContext& hitInfo);
|
||||
|
||||
//! Check intersection with an object.
|
||||
//! @return true if hit, and fills hitInfo structure.
|
||||
bool HitTestObject(CBaseObject* obj, HitContext& hc);
|
||||
|
||||
//! Send event to all objects.
|
||||
//! Will cause OnEvent handler to be called on all objects.
|
||||
void SendEvent(ObjectEvent event);
|
||||
|
||||
//! Send event to all objects within given bounding box.
|
||||
//! Will cause OnEvent handler to be called on objects within bounding box.
|
||||
void SendEvent(ObjectEvent event, const AABB& bounds);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Find object by ID.
|
||||
CBaseObject* FindObject(REFGUID guid) const;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Find object by name.
|
||||
CBaseObject* FindObject(const QString& sName) const;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Find objects of given type.
|
||||
void FindObjectsOfType(const QMetaObject* pClass, std::vector<CBaseObject*>& result) override;
|
||||
void FindObjectsOfType(ObjectType type, std::vector<CBaseObject*>& result) override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Find objects which intersect with a given AABB.
|
||||
virtual void FindObjectsInAABB(const AABB& aabb, std::vector<CBaseObject*>& result) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Operations on objects.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Makes object visible or invisible.
|
||||
void HideObject(CBaseObject* obj, bool hide);
|
||||
//! Shows the last hidden object based on hidden ID
|
||||
void ShowLastHiddenObject();
|
||||
//! Freeze object, making it unselectable.
|
||||
void FreezeObject(CBaseObject* obj, bool freeze);
|
||||
//! Unhide all hidden objects.
|
||||
void UnhideAll();
|
||||
//! Unfreeze all frozen objects.
|
||||
void UnfreezeAll();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Object Selection.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool SelectObject(CBaseObject* obj, bool bUseMask = true);
|
||||
void UnselectObject(CBaseObject* obj);
|
||||
|
||||
//! Select objects within specified distance from given position.
|
||||
//! Return number of selected objects.
|
||||
int SelectObjects(const AABB& box, bool bUnselect = false);
|
||||
|
||||
virtual void SelectEntities(std::set<CEntityObject*>& s);
|
||||
|
||||
int MoveObjects(const AABB& box, const Vec3& offset, ImageRotationDegrees rotation, bool bIsCopy = false);
|
||||
|
||||
//! Selects/Unselects all objects within 2d rectangle in given viewport.
|
||||
void SelectObjectsInRect(CViewport* view, const QRect& rect, bool bSelect);
|
||||
void FindObjectsInRect(CViewport* view, const QRect& rect, std::vector<GUID>& guids);
|
||||
|
||||
//! Clear default selection set.
|
||||
//! @Return number of objects removed from selection.
|
||||
int ClearSelection();
|
||||
|
||||
//! Deselect all current selected objects and selects object that were unselected.
|
||||
//! @Return number of selected objects.
|
||||
int InvertSelection();
|
||||
|
||||
//! Get current selection.
|
||||
CSelectionGroup* GetSelection() const { return m_currSelection; };
|
||||
//! Get named selection.
|
||||
CSelectionGroup* GetSelection(const QString& name) const;
|
||||
// Get selection group names
|
||||
void GetNameSelectionStrings(QStringList& names);
|
||||
//! Change name of current selection group.
|
||||
//! And store it in list.
|
||||
void NameSelection(const QString& name);
|
||||
//! Set one of name selections as current selection.
|
||||
void SetSelection(const QString& name);
|
||||
void RemoveSelection(const QString& name);
|
||||
|
||||
bool IsObjectDeletionAllowed(CBaseObject* pObject);
|
||||
|
||||
//! Delete all objects in selection group.
|
||||
void DeleteSelection();
|
||||
|
||||
uint32 ForceID() const{return m_ForceID; }
|
||||
void ForceID(uint32 FID){m_ForceID = FID; }
|
||||
|
||||
//! Generates uniq name base on type name of object.
|
||||
QString GenerateUniqueObjectName(const QString& typeName);
|
||||
//! Register object name in object manager, needed for generating uniq names.
|
||||
void RegisterObjectName(const QString& name);
|
||||
//! Decrease name number and remove if it was last in object manager, needed for generating uniq names.
|
||||
void UpdateRegisterObjectName(const QString& name);
|
||||
//! Enable/Disable generating of unique object names (Enabled by default).
|
||||
//! Return previous value.
|
||||
bool EnableUniqObjectNames(bool bEnable);
|
||||
|
||||
//! Register XML template of runtime class.
|
||||
void RegisterClassTemplate(const XmlNodeRef& templ);
|
||||
//! Load class templates for specified directory,
|
||||
void LoadClassTemplates(const QString& path);
|
||||
|
||||
//! Registers the ObjectManager's console variables.
|
||||
void RegisterCVars();
|
||||
|
||||
//! Find object class by name.
|
||||
CObjectClassDesc* FindClass(const QString& className);
|
||||
void GetClassCategories(QStringList& categories);
|
||||
void GetClassCategoryToolClassNamePairs(std::vector< std::pair<QString, QString> >& categoryToolClassNamePairs) override;
|
||||
void GetClassTypes(const QString& category, QStringList& types);
|
||||
|
||||
//! Export objects to xml.
|
||||
//! When onlyShared is true ony objects with shared flags exported, overwise only not shared object exported.
|
||||
void Export(const QString& levelPath, XmlNodeRef& rootNode, bool onlyShared);
|
||||
void ExportEntities(XmlNodeRef& rootNode);
|
||||
|
||||
//! Serialize Objects in manager to specified XML Node.
|
||||
//! @param flags Can be one of SerializeFlags.
|
||||
void Serialize(XmlNodeRef& rootNode, bool bLoading, int flags = SERIALIZE_ALL);
|
||||
|
||||
void SerializeNameSelection(XmlNodeRef& rootNode, bool bLoading);
|
||||
|
||||
//! Load objects from object archive.
|
||||
//! @param bSelect if set newly loaded object will be selected.
|
||||
void LoadObjects(CObjectArchive& ar, bool bSelect);
|
||||
|
||||
//! Delete from Object manager all objects without SHARED flag.
|
||||
void DeleteNotSharedObjects();
|
||||
//! Delete from Object manager all objects with SHARED flag.
|
||||
void DeleteSharedObjects();
|
||||
|
||||
bool AddObject(CBaseObject* obj);
|
||||
void RemoveObject(CBaseObject* obj);
|
||||
void ChangeObjectId(REFGUID oldId, REFGUID newId);
|
||||
bool IsDuplicateObjectName(const QString& newName) const
|
||||
{
|
||||
return FindObject(newName) ? true : false;
|
||||
}
|
||||
void ShowDuplicationMsgWarning(CBaseObject* obj, const QString& newName, bool bShowMsgBox) const;
|
||||
void ChangeObjectName(CBaseObject* obj, const QString& newName);
|
||||
|
||||
//! Convert object of one type to object of another type.
|
||||
//! Original object is deleted.
|
||||
bool ConvertToType(CBaseObject* pObject, const QString& typeName);
|
||||
|
||||
//! Set new selection callback.
|
||||
//! @return previous selection callback.
|
||||
IObjectSelectCallback* SetSelectCallback(IObjectSelectCallback* callback);
|
||||
|
||||
// Enables/Disables creating of game objects.
|
||||
void SetCreateGameObject(bool enable) { m_createGameObjects = enable; };
|
||||
//! Return true if objects loaded from xml should immidiatly create game objects associated with them.
|
||||
bool IsCreateGameObjects() const { return m_createGameObjects; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Get access to gizmo manager.
|
||||
IGizmoManager* GetGizmoManager();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Invalidate visibily settings of objects.
|
||||
void InvalidateVisibleList();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ObjectManager notification Callbacks.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void AddObjectEventListener(EventListener* listener);
|
||||
void RemoveObjectEventListener(EventListener* listener);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Used to indicate starting and ending of objects loading.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void StartObjectsLoading(int numObjects);
|
||||
void EndObjectsLoading();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Gathers all resources used by all objects.
|
||||
void GatherUsedResources(CUsedResources& resources);
|
||||
|
||||
virtual bool IsLightClass(CBaseObject* pObject);
|
||||
|
||||
virtual void FindAndRenameProperty2(const char* property2Name, const QString& oldValue, const QString& newValue);
|
||||
virtual void FindAndRenameProperty2If(const char* property2Name, const QString& oldValue, const QString& newValue, const char* otherProperty2Name, const QString& otherValue);
|
||||
|
||||
bool IsReloading() const { return m_bInReloading; }
|
||||
void SetSkipUpdate(bool bSkipUpdate) override { m_bSkipObjectUpdate = bSkipUpdate; }
|
||||
|
||||
void SetExportingLevel(bool bExporting) override { m_bLevelExporting = bExporting; }
|
||||
bool IsExportingLevelInprogress() const override { return m_bLevelExporting; }
|
||||
|
||||
int GetAxisHelperHitRadius() const override { return m_axisHelperHitRadius; }
|
||||
|
||||
private:
|
||||
friend CObjectArchive;
|
||||
friend class CBaseObject;
|
||||
/** Creates and serialize object from xml node.
|
||||
@param objectNode Xml node to serialize object info from.
|
||||
@param pUndoObject Pointer to deleted object for undo.
|
||||
*/
|
||||
CBaseObject* NewObject(CObjectArchive& archive, CBaseObject* pUndoObject, bool bMakeNewId);
|
||||
|
||||
//! Update visibility of all objects.
|
||||
void UpdateVisibilityList();
|
||||
//! Get array of all objects in manager.
|
||||
void GetAllObjects(TBaseObjects& objects) const;
|
||||
|
||||
void UnselectCurrent();
|
||||
void SelectCurrent();
|
||||
void SetObjectSelected(CBaseObject* pObject, bool bSelect);
|
||||
|
||||
// Recursive functions potentially taking into child objects into account
|
||||
void SelectObjectInRect(CBaseObject* pObj, CViewport* view, HitContext hc, bool bSelect);
|
||||
void HitTestObjectAgainstRect(CBaseObject* pObj, CViewport* view, HitContext hc, std::vector<GUID>& guids);
|
||||
|
||||
void SaveRegistry();
|
||||
void LoadRegistry();
|
||||
|
||||
void NotifyObjectListeners(CBaseObject* pObject, CBaseObject::EObjectListenerEvent event);
|
||||
|
||||
void FindDisplayableObjects(DisplayContext& dc, bool bDisplay);
|
||||
|
||||
// EditorComponentModeNotificationBus
|
||||
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
|
||||
private:
|
||||
typedef std::map<GUID, CBaseObjectPtr, guid_less_predicate> Objects;
|
||||
Objects m_objects;
|
||||
typedef std::unordered_map<AZ::u32, CBaseObjectPtr> ObjectsByNameCrc;
|
||||
ObjectsByNameCrc m_objectsByName;
|
||||
|
||||
typedef std::map<QString, CSelectionGroup*> TNameSelectionMap;
|
||||
TNameSelectionMap m_selections;
|
||||
|
||||
//! Used for forcing IDs of "GetEditorObjectID" of PreFabs, as they used to have random IDs on each load
|
||||
uint32 m_ForceID;
|
||||
|
||||
//! Array of currently visible objects.
|
||||
TBaseObjects m_visibleObjects;
|
||||
|
||||
// this number changes whenever visibility is invalidated. Viewports can use it to keep track of whether they need to recompute object
|
||||
// visibility.
|
||||
unsigned int m_visibilitySerialNumber = 1;
|
||||
unsigned int m_lastComputedVisibility = 0; // when the object manager itself last updated visibility (since it also has a cache)
|
||||
int m_lastHideMask = 0;
|
||||
|
||||
float m_maxObjectViewDistRatio;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Selection.
|
||||
//! Current selection group.
|
||||
CSelectionGroup* m_currSelection;
|
||||
int m_nLastSelCount;
|
||||
bool m_bSelectionChanged;
|
||||
IObjectSelectCallback* m_selectCallback;
|
||||
bool m_bLoadingObjects;
|
||||
|
||||
// True while performing a select or deselect operation on more than one object.
|
||||
// Prevents individual undo/redo commands for every object, allowing bulk undo/redo
|
||||
bool m_processingBulkSelect = false;
|
||||
|
||||
//! Default selection.
|
||||
CSelectionGroup m_defaultSelection;
|
||||
|
||||
CBaseObjectPtr m_currEditObject;
|
||||
bool m_bSingleSelection;
|
||||
|
||||
bool m_createGameObjects;
|
||||
bool m_bGenUniqObjectNames;
|
||||
|
||||
// Object manager also handles Gizmo manager.
|
||||
CGizmoManager* m_gizmoManager;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Loading progress.
|
||||
CWaitProgress* m_pLoadProgress;
|
||||
int m_loadedObjects;
|
||||
int m_totalObjectsToLoad;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Numbering for names.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
typedef std::map<QString, std::set<uint16>, stl::less_stricmp<QString> > NameNumbersMap;
|
||||
NameNumbersMap m_nameNumbersMap;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Listeners.
|
||||
std::list<EventListener*> m_objectEventListeners;
|
||||
|
||||
bool m_bExiting;
|
||||
|
||||
std::unordered_set<CEntityObject*> m_animatedAttachedEntities;
|
||||
|
||||
bool m_isUpdateVisibilityList;
|
||||
|
||||
uint64 m_currentHideCount;
|
||||
|
||||
bool m_bInReloading;
|
||||
bool m_bSkipObjectUpdate;
|
||||
bool m_bLevelExporting;
|
||||
|
||||
int m_axisHelperHitRadius = 20;
|
||||
};
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
//! A component to reflect scriptable commands for the Editor
|
||||
class ObjectManagerFuncsHandler
|
||||
: public AZ::Component
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(ObjectManagerFuncsHandler, "{D79B69EE-A2CC-43C0-AA5C-47DCFCCBC955}")
|
||||
|
||||
SANDBOX_API static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
// AZ::Component ...
|
||||
void Activate() override {}
|
||||
void Deactivate() override {}
|
||||
};
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_OBJECTMANAGER_H
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_OBJECTMANAGER_BUS_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_OBJECTMANAGER_BUS_H
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBus to handle object manager events
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
namespace AZ
|
||||
{
|
||||
class ObjectManagerEvents
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
|
||||
virtual ~ObjectManagerEvents() = default;
|
||||
|
||||
virtual void OnExportingStarting() {}
|
||||
virtual void OnExportingFinished() {}
|
||||
};
|
||||
|
||||
using ObjectManagerEventBus = AZ::EBus<ObjectManagerEvents>;
|
||||
}
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_OBJECTMANAGER_BUS_H
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ObjectManagerLegacyUndo.h"
|
||||
|
||||
// AzToolsFramework
|
||||
#include <AzToolsFramework/API/ComponentEntityObjectBus.h>
|
||||
|
||||
// Editor
|
||||
#include "Include/IObjectManager.h"
|
||||
#include "Objects/BaseObject.h"
|
||||
#include "Objects/ObjectLoader.h"
|
||||
#include "Objects/SelectionGroup.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CUndoBaseObjectNew implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CUndoBaseObjectNew::CUndoBaseObjectNew(CBaseObject* object)
|
||||
{
|
||||
m_object = object;
|
||||
}
|
||||
|
||||
void CUndoBaseObjectNew::Undo(bool bUndo)
|
||||
{
|
||||
if (bUndo)
|
||||
{
|
||||
m_redo = XmlHelpers::CreateXmlNode("Redo");
|
||||
// Save current object state.
|
||||
CObjectArchive ar(GetIEditor()->GetObjectManager(), m_redo, false);
|
||||
ar.bUndo = true;
|
||||
m_object->Serialize(ar);
|
||||
}
|
||||
|
||||
// Delete this object.
|
||||
GetIEditor()->DeleteObject(m_object);
|
||||
}
|
||||
|
||||
void CUndoBaseObjectNew::Redo()
|
||||
{
|
||||
if (!m_redo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IObjectManager* objectManager = GetIEditor()->GetObjectManager();
|
||||
{
|
||||
CObjectArchive ar(objectManager, m_redo, true);
|
||||
ar.bUndo = true;
|
||||
ar.MakeNewIds(false);
|
||||
ar.LoadObject(m_redo, m_object);
|
||||
}
|
||||
|
||||
objectManager->ClearSelection();
|
||||
objectManager->SelectObject(m_object);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CUndoBaseObjectDelete implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CUndoBaseObjectDelete::CUndoBaseObjectDelete(CBaseObject* object)
|
||||
{
|
||||
AZ_Assert(object, "Object does not exist");
|
||||
object->SetTransformDelegate(nullptr);
|
||||
m_object = object;
|
||||
|
||||
// Save current object state.
|
||||
m_undo = XmlHelpers::CreateXmlNode("Undo");
|
||||
CObjectArchive ar(GetIEditor()->GetObjectManager(), m_undo, false);
|
||||
ar.bUndo = true;
|
||||
m_bSelected = m_object->IsSelected();
|
||||
m_object->Serialize(ar);
|
||||
}
|
||||
|
||||
void CUndoBaseObjectDelete::Undo([[maybe_unused]] bool bUndo)
|
||||
{
|
||||
IObjectManager* objectManager = GetIEditor()->GetObjectManager();
|
||||
{
|
||||
CObjectArchive ar(objectManager, m_undo, true);
|
||||
ar.bUndo = true;
|
||||
ar.MakeNewIds(false);
|
||||
ar.LoadObject(m_undo, m_object);
|
||||
m_object->ClearFlags(OBJFLAG_SELECTED);
|
||||
}
|
||||
|
||||
if (m_bSelected)
|
||||
{
|
||||
objectManager->ClearSelection();
|
||||
objectManager->SelectObject(m_object);
|
||||
}
|
||||
}
|
||||
|
||||
void CUndoBaseObjectDelete::Redo()
|
||||
{
|
||||
// Delete this object.
|
||||
GetIEditor()->DeleteObject(m_object);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CUndoBaseObjectSelect implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CUndoBaseObjectSelect::CUndoBaseObjectSelect(CBaseObject* object)
|
||||
{
|
||||
AZ_Assert(object, "Object does not exist");
|
||||
m_guid = object->GetId();
|
||||
m_bUndoSelect = object->IsSelected();
|
||||
}
|
||||
|
||||
CUndoBaseObjectSelect::CUndoBaseObjectSelect(CBaseObject* object, bool isSelect)
|
||||
{
|
||||
AZ_Assert(object, "Object does not exist");
|
||||
m_guid = object->GetId();
|
||||
m_bUndoSelect = !isSelect;
|
||||
}
|
||||
|
||||
QString CUndoBaseObjectSelect::GetObjectName()
|
||||
{
|
||||
CBaseObject* object = GetIEditor()->GetObjectManager()->FindObject(m_guid);
|
||||
if (!object)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return object->GetName();
|
||||
}
|
||||
|
||||
void CUndoBaseObjectSelect::Undo(bool bUndo)
|
||||
{
|
||||
CBaseObject* object = GetIEditor()->GetObjectManager()->FindObject(m_guid);
|
||||
if (!object)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (bUndo)
|
||||
{
|
||||
m_bRedoSelect = object->IsSelected();
|
||||
}
|
||||
|
||||
if (m_bUndoSelect)
|
||||
{
|
||||
GetIEditor()->GetObjectManager()->SelectObject(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetIEditor()->GetObjectManager()->UnselectObject(object);
|
||||
}
|
||||
}
|
||||
|
||||
void CUndoBaseObjectSelect::Redo()
|
||||
{
|
||||
if (CBaseObject* object = GetIEditor()->GetObjectManager()->FindObject(m_guid))
|
||||
{
|
||||
if (m_bRedoSelect)
|
||||
{
|
||||
GetIEditor()->GetObjectManager()->SelectObject(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetIEditor()->GetObjectManager()->UnselectObject(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CUndoBaseObjectBulkSelect implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CUndoBaseObjectBulkSelect::CUndoBaseObjectBulkSelect(const AZStd::unordered_set<const CBaseObject*>& previousSelection, const CSelectionGroup& selectionGroup)
|
||||
{
|
||||
int numSelectedObjects = selectionGroup.GetCount();
|
||||
m_entityIdList.reserve(numSelectedObjects);
|
||||
|
||||
// Populate list of entities to restore selection to
|
||||
for (int objectIndex = 0; objectIndex < numSelectedObjects; ++objectIndex)
|
||||
{
|
||||
CBaseObject* object = selectionGroup.GetObject(objectIndex);
|
||||
|
||||
// Don't track Undo/Redo for Legacy Objects or entities that were not selected in this step
|
||||
if (object->GetType() != OBJTYPE_AZENTITY || previousSelection.find(object) != previousSelection.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AZ::EntityId id;
|
||||
AzToolsFramework::ComponentEntityObjectRequestBus::EventResult(
|
||||
id,
|
||||
object,
|
||||
&AzToolsFramework::ComponentEntityObjectRequestBus::Events::GetAssociatedEntityId);
|
||||
|
||||
m_entityIdList.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
void CUndoBaseObjectBulkSelect::Undo(bool bUndo)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor);
|
||||
if (!bUndo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
|
||||
&AzToolsFramework::ToolsApplicationRequests::MarkEntitiesDeselected,
|
||||
m_entityIdList);
|
||||
}
|
||||
|
||||
void CUndoBaseObjectBulkSelect::Redo()
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor);
|
||||
|
||||
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
|
||||
&AzToolsFramework::ToolsApplicationRequests::MarkEntitiesSelected,
|
||||
m_entityIdList);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CUndoBaseObjectClearSelection implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CUndoBaseObjectClearSelection::CUndoBaseObjectClearSelection(const CSelectionGroup& selectionGroup)
|
||||
{
|
||||
int numSelectedObjects = selectionGroup.GetCount();
|
||||
m_entityIdList.reserve(numSelectedObjects);
|
||||
|
||||
// Populate list of entities to restore selection to
|
||||
for (int objectIndex = 0; objectIndex < numSelectedObjects; ++objectIndex)
|
||||
{
|
||||
CBaseObject* object = selectionGroup.GetObject(objectIndex);
|
||||
|
||||
// Don't track Undo/Redo for Legacy Objects
|
||||
if (object->GetType() != OBJTYPE_AZENTITY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AZ::EntityId id;
|
||||
AzToolsFramework::ComponentEntityObjectRequestBus::EventResult(
|
||||
id,
|
||||
object,
|
||||
&AzToolsFramework::ComponentEntityObjectRequestBus::Events::GetAssociatedEntityId);
|
||||
|
||||
m_entityIdList.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
void CUndoBaseObjectClearSelection::Undo(bool bUndo)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor);
|
||||
|
||||
if (!bUndo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
|
||||
&AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities,
|
||||
m_entityIdList);
|
||||
}
|
||||
|
||||
void CUndoBaseObjectClearSelection::Redo()
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor);
|
||||
|
||||
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
|
||||
&AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities,
|
||||
AzToolsFramework::EntityIdList());
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Undo/IUndoObject.h"
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
#include "Objects/BaseObject.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Undo New Object
|
||||
class CUndoBaseObjectNew
|
||||
: public IUndoObject
|
||||
{
|
||||
public:
|
||||
CUndoBaseObjectNew(CBaseObject* object);
|
||||
|
||||
protected:
|
||||
virtual int GetSize() override { return sizeof(*this); }; // Return size of xml state.
|
||||
virtual QString GetDescription() override { return "New BaseObject"; };
|
||||
virtual QString GetObjectName() override { return m_object->GetName(); };
|
||||
|
||||
virtual void Undo(bool bUndo) override;
|
||||
virtual void Redo() override;
|
||||
|
||||
private:
|
||||
CBaseObjectPtr m_object;
|
||||
TGUIDRemap m_remapping;
|
||||
XmlNodeRef m_redo;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Undo Delete Object
|
||||
class CUndoBaseObjectDelete
|
||||
: public IUndoObject
|
||||
{
|
||||
public:
|
||||
CUndoBaseObjectDelete(CBaseObject* object);
|
||||
|
||||
protected:
|
||||
virtual int GetSize() override { return sizeof(*this); }; // Return size of xml state.
|
||||
virtual QString GetDescription() override { return "Delete BaseObject"; };
|
||||
virtual QString GetObjectName() override { return m_object->GetName(); };
|
||||
|
||||
virtual void Undo(bool bUndo) override;
|
||||
virtual void Redo() override;
|
||||
|
||||
private:
|
||||
CBaseObjectPtr m_object;
|
||||
XmlNodeRef m_undo;
|
||||
TGUIDRemap m_remapping;
|
||||
bool m_bSelected;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Undo Select Object
|
||||
class CUndoBaseObjectSelect
|
||||
: public IUndoObject
|
||||
{
|
||||
public:
|
||||
CUndoBaseObjectSelect(CBaseObject* object);
|
||||
|
||||
/**
|
||||
* This Undo command can be used for either Legacy or Component Entities, though for
|
||||
* performance reasons Component Entities are typically undone using CUndoBaseObjectBulkSelect
|
||||
*
|
||||
* @param pObj The object to perform the undo/redo operation on.
|
||||
* @param isSelect This is true if you are trying to undo a select operation, and false if
|
||||
* trying to undo a deselect operation
|
||||
*/
|
||||
CUndoBaseObjectSelect(CBaseObject* object, bool isSelect);
|
||||
|
||||
protected:
|
||||
virtual void Release() override { delete this; };
|
||||
virtual int GetSize() override { return sizeof(*this); }; // Return size of xml state.
|
||||
virtual QString GetDescription() override { return "Select Object"; };
|
||||
virtual QString GetObjectName() override;
|
||||
|
||||
virtual void Undo(bool bUndo) override;
|
||||
virtual void Redo() override;
|
||||
|
||||
private:
|
||||
GUID m_guid;
|
||||
bool m_bUndoSelect;
|
||||
bool m_bRedoSelect;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Undo Select for many Objects
|
||||
class CUndoBaseObjectBulkSelect
|
||||
: public IUndoObject
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This Undo/Redo command is designed to improve performance of the standard CUndoBaseObjectSelect
|
||||
* command by passing all Select/Deselect commands through the proper Ebuses in one bulk operation instead
|
||||
* of individually.
|
||||
*
|
||||
* This only works with Component Entities. Legacy objects must still use the standard CUndoBaseObjectSelect.
|
||||
*
|
||||
* @param previousSelection the set of objects already selected. This is useful to ensure proper Undo/Redo
|
||||
* when a user makes a second rectangular selection by holding ctrl
|
||||
* @param selectionGroup The items that will have their selection restored by either an Undo
|
||||
* or Redo step
|
||||
*/
|
||||
CUndoBaseObjectBulkSelect(const AZStd::unordered_set<const CBaseObject*>& previousSelection, const CSelectionGroup& selectionGroup);
|
||||
|
||||
protected:
|
||||
int GetSize() override { return sizeof(*this); } // Return size of xml state.
|
||||
QString GetDescription() override { return QObject::tr("Select Objects"); }
|
||||
|
||||
/*
|
||||
* Deselects the objects
|
||||
*/
|
||||
void Undo(bool bUndo) override;
|
||||
|
||||
/*
|
||||
* Selects the objects
|
||||
*/
|
||||
void Redo() override;
|
||||
|
||||
private:
|
||||
// The list of Entity Ids involved in the selection change
|
||||
AzToolsFramework::EntityIdList m_entityIdList;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Undo Clear Selection
|
||||
class CUndoBaseObjectClearSelection
|
||||
: public IUndoObject
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This Undo/Redo command is designed to improve performance of the standard CUndoBaseObjectSelect
|
||||
* command by passing all Select/Deselect commands through the proper Ebuses.
|
||||
*
|
||||
* This only works with Component Entities. Legacy objects must still use the standard CUndoBaseObjectSelect.
|
||||
*
|
||||
* @param selectionGroup The items that will have their selection restored by either an Undo
|
||||
* or Redo step
|
||||
*/
|
||||
CUndoBaseObjectClearSelection(const CSelectionGroup& selectionGroup);
|
||||
|
||||
protected:
|
||||
int GetSize() override { return sizeof(*this); } // Return size of xml state.
|
||||
QString GetDescription() override { return QObject::tr("Select Objects"); }
|
||||
|
||||
void Undo(bool bUndo) override;
|
||||
|
||||
void Redo() override;
|
||||
|
||||
private:
|
||||
// The list of Entity Ids involved in the selection change
|
||||
AzToolsFramework::EntityIdList m_entityIdList;
|
||||
};
|
||||
@@ -0,0 +1,643 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : CSelectionGroup implementation.
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "SelectionGroup.h"
|
||||
|
||||
// Editor
|
||||
#include "ViewManager.h"
|
||||
#include "Include/IObjectManager.h"
|
||||
|
||||
#include <IStatObj.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CSelectionGroup::CSelectionGroup()
|
||||
: m_ref(1)
|
||||
, m_bVertexSnapped(false)
|
||||
{
|
||||
m_LastestMoveSelectionFlag = eMS_None;
|
||||
m_LastestMovedObjectRot.SetIdentity();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::AddObject(CBaseObject* obj)
|
||||
{
|
||||
if (!IsContainObject(obj))
|
||||
{
|
||||
m_objects.push_back(obj);
|
||||
m_objectsSet.insert(obj);
|
||||
m_filtered.clear();
|
||||
|
||||
if (obj->GetType() != OBJTYPE_AZENTITY)
|
||||
{
|
||||
m_legacyObjectsSet.insert(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::RemoveObject(CBaseObject* obj)
|
||||
{
|
||||
for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
|
||||
{
|
||||
if (*it == obj)
|
||||
{
|
||||
m_objects.erase(it);
|
||||
m_objectsSet.erase(obj);
|
||||
m_legacyObjectsSet.erase(obj);
|
||||
m_filtered.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::RemoveAll()
|
||||
{
|
||||
m_objects.clear();
|
||||
m_objectsSet.clear();
|
||||
m_filtered.clear();
|
||||
m_legacyObjectsSet.clear();
|
||||
}
|
||||
|
||||
void CSelectionGroup::RemoveAllExceptLegacySet()
|
||||
{
|
||||
m_objects.clear();
|
||||
m_objectsSet.clear();
|
||||
m_filtered.clear();
|
||||
}
|
||||
|
||||
bool CSelectionGroup::IsContainObject(CBaseObject* obj)
|
||||
{
|
||||
return (m_objectsSet.find(obj) != m_objectsSet.end());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSelectionGroup::IsEmpty() const
|
||||
{
|
||||
return m_objects.empty();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSelectionGroup::SameObjectType()
|
||||
{
|
||||
if (IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CBaseObjectPtr pFirst = (*(m_objects.begin()));
|
||||
for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
|
||||
{
|
||||
if ((*it)->metaObject() != pFirst->metaObject())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CSelectionGroup::GetCount() const
|
||||
{
|
||||
return m_objects.size();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CBaseObject* CSelectionGroup::GetObject(int index) const
|
||||
{
|
||||
assert(index >= 0 && index < m_objects.size());
|
||||
return m_objects[index];
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CBaseObject* CSelectionGroup::GetObjectByGuid(REFGUID guid) const
|
||||
{
|
||||
for (size_t i = 0, count(m_objects.size()); i < count; ++i)
|
||||
{
|
||||
if (m_objects[i]->GetId() == guid)
|
||||
{
|
||||
return m_objects[i];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
std::set<CBaseObjectPtr>& CSelectionGroup::GetLegacyObjects()
|
||||
{
|
||||
return m_legacyObjectsSet;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::Copy(const CSelectionGroup& from)
|
||||
{
|
||||
m_name = from.m_name;
|
||||
m_objects = from.m_objects;
|
||||
m_objectsSet = from.m_objectsSet;
|
||||
m_filtered = from.m_filtered;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 CSelectionGroup::GetCenter() const
|
||||
{
|
||||
Vec3 c(0, 0, 0);
|
||||
for (int i = 0; i < GetCount(); i++)
|
||||
{
|
||||
c += GetObject(i)->GetWorldPos();
|
||||
}
|
||||
if (GetCount() > 0)
|
||||
{
|
||||
c /= GetCount();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AABB CSelectionGroup::GetBounds() const
|
||||
{
|
||||
AABB b;
|
||||
AABB box;
|
||||
box.Reset();
|
||||
for (int i = 0; i < GetCount(); i++)
|
||||
{
|
||||
GetObject(i)->GetBoundBox(b);
|
||||
box.Add(b.min);
|
||||
box.Add(b.max);
|
||||
}
|
||||
return box;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::FilterParents()
|
||||
{
|
||||
if (!m_filtered.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_filtered.reserve(m_objects.size());
|
||||
for (int i = 0; i < m_objects.size(); i++)
|
||||
{
|
||||
CBaseObject* obj = m_objects[i];
|
||||
CBaseObject* parent = obj->GetParent();
|
||||
bool bParentInSet = false;
|
||||
while (parent)
|
||||
{
|
||||
if (m_objectsSet.find(parent) != m_objectsSet.end())
|
||||
{
|
||||
bParentInSet = true;
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
if (!bParentInSet)
|
||||
{
|
||||
m_filtered.push_back(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::Move(const Vec3& offset, EMoveSelectionFlag moveFlag, [[maybe_unused]] int referenceCoordSys, const QPoint& point)
|
||||
{
|
||||
// [MichaelS - 17/3/2005] Removed this code from the three edit functions (move,
|
||||
// rotate and scale). This was causing a bug where the render node of objects
|
||||
// was not being updated when objects were dragged away from their position
|
||||
// and then back again, since movement is re-calculated from the initial position
|
||||
// each mouse message (ie first the previous movement is undone and then the
|
||||
// movement is applied). This meant that when moving back to the start position
|
||||
// it appeared like no movement was applied, although it was still necessary to
|
||||
// update the graphics resources. The object transform is explicitly reset
|
||||
// below.
|
||||
|
||||
//if (offset.x == 0 && offset.y == 0 && offset.z == 0)
|
||||
// return;
|
||||
|
||||
m_bVertexSnapped = false;
|
||||
FilterParents();
|
||||
Vec3 newPos;
|
||||
|
||||
bool bValidFollowGeometryMode(true);
|
||||
if (point.x() == -1 || point.y() == -1)
|
||||
{
|
||||
bValidFollowGeometryMode = false;
|
||||
}
|
||||
|
||||
SRayHitInfo pickedInfo;
|
||||
|
||||
if (moveFlag == eMS_FollowGeometryPosNorm)
|
||||
{
|
||||
if (m_LastestMoveSelectionFlag != eMS_FollowGeometryPosNorm)
|
||||
{
|
||||
if (GetFilteredCount() > 0)
|
||||
{
|
||||
CBaseObject* pObj = GetFilteredObject(0);
|
||||
m_LastestMovedObjectRot = pObj->GetRotation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_LastestMoveSelectionFlag = moveFlag;
|
||||
|
||||
for (int i = 0; i < GetFilteredCount(); i++)
|
||||
{
|
||||
CBaseObject* obj = GetFilteredObject(i);
|
||||
|
||||
if(obj->IsFrozen())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == 0 && moveFlag == eMS_FollowGeometryPosNorm && bValidFollowGeometryMode)
|
||||
{
|
||||
Vec3 zaxis = m_LastestMovedObjectRot * Vec3(0, 0, 1);
|
||||
zaxis.Normalize();
|
||||
Quat nq;
|
||||
nq.SetRotationV0V1(zaxis, pickedInfo.vHitNormal);
|
||||
obj->SetPos(pickedInfo.vHitPos);
|
||||
obj->SetRotation(nq * m_LastestMovedObjectRot);
|
||||
continue;
|
||||
}
|
||||
|
||||
Matrix34 wtm = obj->GetWorldTM();
|
||||
Vec3 wp = wtm.GetTranslation();
|
||||
|
||||
newPos = wp + offset;
|
||||
if (moveFlag == eMS_FollowTerrain)
|
||||
{
|
||||
// Make sure object keeps it height.
|
||||
float height = wp.z - GetIEditor()->GetTerrainElevation(wp.x, wp.y);
|
||||
newPos.z = GetIEditor()->GetTerrainElevation(newPos.x, newPos.y) + height;
|
||||
}
|
||||
|
||||
obj->SetWorldPos(newPos, eObjectUpdateFlags_UserInput | eObjectUpdateFlags_PositionChanged | eObjectUpdateFlags_MoveTool);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::MoveTo(const Vec3& pos, EMoveSelectionFlag moveFlag, int referenceCoordSys, const QPoint& point)
|
||||
{
|
||||
FilterParents();
|
||||
if (GetFilteredCount() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CBaseObject* refObj = GetFilteredObject(0);
|
||||
CSelectionGroup::Move(pos - refObj->GetWorldTM().GetTranslation(), moveFlag, referenceCoordSys, point);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::Rotate(const Quat& qRot, int referenceCoordSys)
|
||||
{
|
||||
Matrix34 rotateTM;
|
||||
rotateTM.SetIdentity();
|
||||
rotateTM = Matrix33(qRot) * rotateTM;
|
||||
|
||||
Rotate(rotateTM, referenceCoordSys);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::Rotate(const Ang3& angles, int referenceCoordSys)
|
||||
{
|
||||
//if (angles.x == 0 && angles.y == 0 && angles.z == 0)
|
||||
// return;
|
||||
|
||||
// Rotate selection about selection center.
|
||||
Vec3 center = GetCenter();
|
||||
|
||||
Matrix34 rotateTM = Matrix34::CreateRotationXYZ(DEG2RAD(angles));
|
||||
Rotate(rotateTM, referenceCoordSys);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::Rotate(const Matrix34& rotateTM, int referenceCoordSys)
|
||||
{
|
||||
// Rotate selection about selection center.
|
||||
Vec3 center = GetCenter();
|
||||
|
||||
Matrix34 ToOrigin = Matrix34::CreateIdentity();
|
||||
Matrix34 FromOrigin = Matrix34::CreateIdentity();
|
||||
|
||||
if (referenceCoordSys != COORDS_LOCAL)
|
||||
{
|
||||
ToOrigin.SetTranslation(-center);
|
||||
FromOrigin.SetTranslation(center);
|
||||
|
||||
if (referenceCoordSys == COORDS_USERDEFINED)
|
||||
{
|
||||
Matrix34 userTM;
|
||||
userTM.SetIdentity();
|
||||
Matrix34 invUserTM = userTM.GetInvertedFast();
|
||||
|
||||
ToOrigin = invUserTM * ToOrigin;
|
||||
FromOrigin = FromOrigin * userTM;
|
||||
}
|
||||
}
|
||||
|
||||
FilterParents();
|
||||
|
||||
for (int i = 0; i < GetFilteredCount(); i++)
|
||||
{
|
||||
CBaseObject* obj = GetFilteredObject(i);
|
||||
|
||||
Matrix34 objectTransform = obj->GetWorldTM();
|
||||
if (referenceCoordSys != COORDS_LOCAL)
|
||||
{
|
||||
if (referenceCoordSys == COORDS_PARENT && obj->GetParent())
|
||||
{
|
||||
Matrix34 parentTM = obj->GetParent()->GetWorldTM();
|
||||
parentTM.OrthonormalizeFast();
|
||||
parentTM.SetTranslation(Vec3(0, 0, 0));
|
||||
Matrix34 invParentTM = parentTM.GetInvertedFast();
|
||||
|
||||
objectTransform = FromOrigin * parentTM * rotateTM * invParentTM * ToOrigin * objectTransform;
|
||||
}
|
||||
else
|
||||
{
|
||||
objectTransform = FromOrigin * rotateTM * ToOrigin * objectTransform;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decompose the matrix and reconstruct it to ensure no scaling artifacts are introduced
|
||||
AffineParts affineParts;
|
||||
affineParts.SpectralDecompose(objectTransform);
|
||||
|
||||
Matrix33 rotationMatrix(affineParts.rot);
|
||||
Matrix34 translationMatrix = Matrix34::CreateTranslationMat(affineParts.pos);
|
||||
Matrix33 scaleMatrix = Matrix33::CreateScale(affineParts.scale);
|
||||
|
||||
objectTransform = translationMatrix * rotationMatrix * rotateTM * scaleMatrix;
|
||||
}
|
||||
|
||||
obj->SetWorldTM(objectTransform, eObjectUpdateFlags_UserInput);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::Scale(const Vec3& scale, int referenceCoordSys)
|
||||
{
|
||||
//if (scale.x == 1 && scale.y == 1 && scale.z == 1)
|
||||
// return;
|
||||
|
||||
Vec3 scl = scale;
|
||||
if (scl.x == 0)
|
||||
{
|
||||
scl.x = 0.01f;
|
||||
}
|
||||
if (scl.y == 0)
|
||||
{
|
||||
scl.y = 0.01f;
|
||||
}
|
||||
if (scl.z == 0)
|
||||
{
|
||||
scl.z = 0.01f;
|
||||
}
|
||||
|
||||
// Scale selection relative to selection center.
|
||||
Vec3 center = GetCenter();
|
||||
|
||||
Matrix34 scaleTM;
|
||||
scaleTM.SetIdentity();
|
||||
scaleTM = Matrix33::CreateScale(Vec3(scl.x, scl.y, scl.z)) * scaleTM;
|
||||
|
||||
Matrix34 ToOrigin;
|
||||
Matrix34 FromOrigin;
|
||||
|
||||
ToOrigin.SetIdentity();
|
||||
FromOrigin.SetIdentity();
|
||||
|
||||
if (referenceCoordSys != COORDS_LOCAL)
|
||||
{
|
||||
ToOrigin.SetTranslation(-center);
|
||||
FromOrigin.SetTranslation(center);
|
||||
}
|
||||
|
||||
FilterParents();
|
||||
|
||||
for (int i = 0; i < GetFilteredCount(); i++)
|
||||
{
|
||||
CBaseObject* obj = GetFilteredObject(i);
|
||||
Matrix34 m = obj->GetWorldTM();
|
||||
|
||||
if (referenceCoordSys != COORDS_LOCAL)
|
||||
{
|
||||
// Apply new scale
|
||||
m = FromOrigin * scaleTM * ToOrigin * m;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply new scale
|
||||
m = m * scaleTM;
|
||||
}
|
||||
|
||||
obj->SetWorldTM(m, eObjectUpdateFlags_UserInput | eObjectUpdateFlags_ScaleTool);
|
||||
obj->InvalidateTM(eObjectUpdateFlags_UserInput | eObjectUpdateFlags_ScaleTool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CSelectionGroup::SetScale(const Vec3& scale, int referenceCoordSys)
|
||||
{
|
||||
Vec3 relScale = scale;
|
||||
|
||||
if (GetCount() > 0 && GetObject(0))
|
||||
{
|
||||
Vec3 objScale = GetObject(0)->GetScale();
|
||||
if (relScale == objScale && (objScale.x == 0.0f || objScale.y == 0.0f || objScale.z == 0.0f))
|
||||
{
|
||||
return;
|
||||
}
|
||||
relScale = relScale / objScale;
|
||||
}
|
||||
|
||||
Scale(relScale, referenceCoordSys);
|
||||
}
|
||||
|
||||
|
||||
void CSelectionGroup::StartScaling()
|
||||
{
|
||||
for (int i = 0; i < GetFilteredCount(); i++)
|
||||
{
|
||||
CBaseObject* obj = GetFilteredObject(i);
|
||||
obj->StartScaling();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::Align()
|
||||
{
|
||||
for (int i = 0; i < GetFilteredCount(); ++i)
|
||||
{
|
||||
bool terrain = false;
|
||||
CBaseObject* obj = GetFilteredObject(i);
|
||||
Vec3 pos = obj->GetPos();
|
||||
Quat rot = obj->GetRotation();
|
||||
QPoint point = GetIEditor()->GetActiveView()->WorldToView(pos);
|
||||
Vec3 normal = GetIEditor()->GetActiveView()->ViewToWorldNormal(point, false, true);
|
||||
pos = GetIEditor()->GetActiveView()->ViewToWorld(point, &terrain, false, false, true);
|
||||
Vec3 zaxis = rot * Vec3(0, 0, 1);
|
||||
normal.Normalize();
|
||||
zaxis.Normalize();
|
||||
Quat nq;
|
||||
nq.SetRotationV0V1(zaxis, normal);
|
||||
obj->SetRotation(nq * rot);
|
||||
obj->SetPos(pos);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::Transform(const Vec3& offset, EMoveSelectionFlag moveFlag, const Ang3& angles, const Vec3& scale, int referenceCoordSys)
|
||||
{
|
||||
if (offset != Vec3(0))
|
||||
{
|
||||
Move(offset, moveFlag, referenceCoordSys);
|
||||
}
|
||||
|
||||
if (!(angles == Ang3(ZERO)))
|
||||
{
|
||||
Rotate(angles, referenceCoordSys);
|
||||
}
|
||||
|
||||
if (scale != Vec3(0))
|
||||
{
|
||||
Scale(scale, referenceCoordSys);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::ResetTransformation()
|
||||
{
|
||||
FilterParents();
|
||||
Quat qIdentity;
|
||||
qIdentity.SetIdentity();
|
||||
Vec3 vScale(1.0f, 1.0f, 1.0f);
|
||||
|
||||
for (int i = 0, n = GetFilteredCount(); i < n; ++i)
|
||||
{
|
||||
CBaseObject* pObj = GetFilteredObject(i);
|
||||
pObj->SetRotation(qIdentity);
|
||||
pObj->SetScale(vScale);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::Clone(CSelectionGroup& newGroup)
|
||||
{
|
||||
IObjectManager* pObjMan = GetIEditor()->GetObjectManager();
|
||||
assert(pObjMan);
|
||||
|
||||
int i;
|
||||
CObjectCloneContext cloneContext;
|
||||
|
||||
FilterParents();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Clone every object.
|
||||
for (i = 0; i < GetFilteredCount(); i++)
|
||||
{
|
||||
CBaseObject* pFromObject = GetFilteredObject(i);
|
||||
CBaseObject* newObj = pObjMan->CloneObject(pFromObject);
|
||||
if (!newObj) // can be null, e.g. sequence can't be cloned
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
cloneContext.AddClone(pFromObject, newObj);
|
||||
newGroup.AddObject(newObj);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Only after everything was cloned, call PostClone on all cloned objects.
|
||||
for (i = 0; i < newGroup.GetCount(); ++i)
|
||||
{
|
||||
CBaseObject* pFromObject = GetFilteredObject(i);
|
||||
CBaseObject* pClonedObject = newGroup.GetObject(i);
|
||||
if (pClonedObject)
|
||||
{
|
||||
pClonedObject->PostClone(pFromObject, cloneContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::SendEvent(ObjectEvent event)
|
||||
{
|
||||
for (int i = 0; i < m_objects.size(); i++)
|
||||
{
|
||||
CBaseObject* obj = m_objects[i];
|
||||
obj->OnEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ULONG STDMETHODCALLTYPE CSelectionGroup::AddRef()
|
||||
{
|
||||
return ++m_ref;
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ULONG STDMETHODCALLTYPE CSelectionGroup::Release()
|
||||
{
|
||||
if ((--m_ref) == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_ref;
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::IndicateSnappingVertex(DisplayContext& dc) const
|
||||
{
|
||||
if (m_bVertexSnapped == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dc.DepthTestOff();
|
||||
|
||||
ColorB green(0, 255, 0, 255);
|
||||
|
||||
dc.SetColor(green);
|
||||
float fScale = dc.view->GetScreenScaleFactor(m_snapVertex) * 0.005f;
|
||||
Vec3 sz(fScale, fScale, fScale);
|
||||
dc.DrawWireBox(m_snapVertex - sz, m_snapVertex + sz);
|
||||
|
||||
dc.DepthTestOn();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSelectionGroup::FinishChanges()
|
||||
{
|
||||
Objects selectedObjects(m_objects);
|
||||
int iObjectSize(selectedObjects.size());
|
||||
for (int i = 0; i < iObjectSize; ++i)
|
||||
{
|
||||
CBaseObject* pObject = selectedObjects[i];
|
||||
if (pObject == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : CSelection group definition.
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_SELECTIONGROUP_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_SELECTIONGROUP_H
|
||||
#pragma once
|
||||
|
||||
|
||||
class CBaseObject;
|
||||
|
||||
#include "ObjectEvent.h"
|
||||
#include "Objects/BaseObject.h"
|
||||
|
||||
/*!
|
||||
* CSelectionGroup is a named selection group of objects.
|
||||
*/
|
||||
class SANDBOX_API CSelectionGroup
|
||||
{
|
||||
public:
|
||||
CSelectionGroup();
|
||||
|
||||
//! Set name of selection.
|
||||
void SetName(const QString& name) { m_name = name; };
|
||||
//! Get name of selection.
|
||||
const QString& GetName() const { return m_name; };
|
||||
|
||||
//! Adds object into selection list.
|
||||
void AddObject(CBaseObject* obj);
|
||||
//! Remove object from selection list.
|
||||
void RemoveObject(CBaseObject* obj);
|
||||
//! Remove all objects from selection.
|
||||
void RemoveAll();
|
||||
//! Remove all objects from selection except for the LegacyObjects list
|
||||
//! This is used in a performance improvement for deselecting legacy objects
|
||||
void RemoveAllExceptLegacySet();
|
||||
//! Check if object contained in selection list.
|
||||
bool IsContainObject(CBaseObject* obj);
|
||||
//! Return true if selection doesnt contain any object.
|
||||
bool IsEmpty() const;
|
||||
//! Check if all selected objects are of same type
|
||||
bool SameObjectType();
|
||||
//! Number of selected object.
|
||||
int GetCount() const;
|
||||
//! Get object at given index.
|
||||
CBaseObject* GetObject(int index) const;
|
||||
//! Get object from a GUID
|
||||
CBaseObject* GetObjectByGuid(REFGUID guid) const;
|
||||
//! Get set of legacy objects
|
||||
std::set<CBaseObjectPtr>& GetLegacyObjects();
|
||||
|
||||
//! Get mass center of selected objects.
|
||||
Vec3 GetCenter() const;
|
||||
|
||||
//! Get Bounding box of selection.
|
||||
AABB GetBounds() const;
|
||||
|
||||
void Copy(const CSelectionGroup& from);
|
||||
|
||||
//! Remove from selection group all objects which have parent also in selection group.
|
||||
//! And save resulting objects to saveTo selection.
|
||||
void FilterParents();
|
||||
//! Get number of child filtered objects.
|
||||
int GetFilteredCount() const { return m_filtered.size(); }
|
||||
CBaseObject* GetFilteredObject(int i) const { return m_filtered[i]; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Operations on selection group.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum EMoveSelectionFlag
|
||||
{
|
||||
eMS_None = 0x00,
|
||||
eMS_FollowTerrain = 0x01,
|
||||
eMS_FollowGeometryPosNorm = 0x02
|
||||
};
|
||||
//! Move objects in selection by offset.
|
||||
void Move(const Vec3& offset, EMoveSelectionFlag moveFlag, int referenceCoordSys, const QPoint& point = QPoint(-1, -1));
|
||||
//! Move objects in selection to specific position.
|
||||
void MoveTo(const Vec3& pos, EMoveSelectionFlag moveFlag, int referenceCoordSys, const QPoint& point = QPoint(-1, -1));
|
||||
//! Rotate objects in selection by given quaternion.
|
||||
void Rotate(const Quat& qRot, int referenceCoordSys);
|
||||
//! Rotate objects in selection by given angle.
|
||||
void Rotate(const Ang3& angles, int referenceCoordSys);
|
||||
//! Rotate objects in selection by given rotation matrix.
|
||||
void Rotate(const Matrix34& matRot, int referenceCoordSys);
|
||||
//! Transforms objects
|
||||
void Transform(const Vec3& offset, EMoveSelectionFlag moveFlag, const Ang3& angles, const Vec3& scale, int referenceCoordSys);
|
||||
//! Resets rotation and scale to identity and (1.0f, 1.0f, 1.0f)
|
||||
void ResetTransformation();
|
||||
//! Scale objects in selection by given scale.
|
||||
void StartScaling();
|
||||
void Scale(const Vec3& scale, int referenceCoordSys);
|
||||
void SetScale(const Vec3& scale, int referenceCoordSys);
|
||||
//! Align objects in selection to surface normal
|
||||
void Align();
|
||||
//! Very special method to move contents of a voxel.
|
||||
void MoveContent(const Vec3& offset);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Clone objects in this group and add cloned objects to new selection group.
|
||||
//! Only topmost parent objects will be added to this selection group.
|
||||
void Clone(CSelectionGroup& newGroup);
|
||||
|
||||
// Send event to all objects in selection group.
|
||||
void SendEvent(ObjectEvent event);
|
||||
|
||||
ULONG STDMETHODCALLTYPE AddRef();
|
||||
ULONG STDMETHODCALLTYPE Release();
|
||||
|
||||
void IndicateSnappingVertex(DisplayContext& dc) const;
|
||||
void FinishChanges();
|
||||
private:
|
||||
QString m_name;
|
||||
typedef std::vector<TSmartPtr<CBaseObject> > Objects;
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
Objects m_objects;
|
||||
// Objects set, for fast searches.
|
||||
std::set<CBaseObject*> m_objectsSet;
|
||||
|
||||
// Legacy objects aren't deselected through Ebuses, so keeping a
|
||||
// separate set for them helps improve performance of deselection
|
||||
std::set<CBaseObjectPtr> m_legacyObjectsSet;
|
||||
|
||||
//! Selection list with child objecs filtered out.
|
||||
std::vector<CBaseObject*> m_filtered;
|
||||
|
||||
bool m_bVertexSnapped;
|
||||
Vec3 m_snapVertex;
|
||||
|
||||
const static int SnappingVertexNumThreshold = 700;
|
||||
|
||||
EMoveSelectionFlag m_LastestMoveSelectionFlag;
|
||||
Quat m_LastestMovedObjectRot;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
protected:
|
||||
ULONG m_ref;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_SELECTIONGROUP_H
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "SubObjSelection.h"
|
||||
|
||||
SSubObjSelOptions g_SubObjSelOptions;
|
||||
|
||||
/*
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSubObjSelContext::IsEmpty() const
|
||||
{
|
||||
if (GetCount() == 0)
|
||||
return false;
|
||||
for (int i = 0; i < GetCount(); i++)
|
||||
{
|
||||
CSubObjectSelection *pSel = GetSelection(i);
|
||||
if (!pSel->IsEmpty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSubObjSelContext::ModifySelection( SSubObjSelectionModifyContext &modCtx )
|
||||
{
|
||||
for (int n = 0; n < GetCount(); n++)
|
||||
{
|
||||
CSubObjectSelection *pSel = GetSelection(n);
|
||||
if (pSel->IsEmpty())
|
||||
continue;
|
||||
modCtx.pSubObjSelection = pSel;
|
||||
pSel->pGeometry->SubObjSelectionModify( modCtx );
|
||||
}
|
||||
if (modCtx.type == SO_MODIFY_MOVE)
|
||||
{
|
||||
OnSelectionChange();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSubObjSelContext::AcceptModifySelection()
|
||||
{
|
||||
for (int n = 0; n < GetCount(); n++)
|
||||
{
|
||||
CSubObjectSelection *pSel = GetSelection(n);
|
||||
if (pSel->IsEmpty())
|
||||
continue;
|
||||
if (pSel->pGeometry)
|
||||
pSel->pGeometry->Update();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_SUBOBJSELECTION_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_SUBOBJSELECTION_H
|
||||
#pragma once
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Sub Object element type.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum ESubObjElementType
|
||||
{
|
||||
SO_ELEM_NONE = 0,
|
||||
SO_ELEM_VERTEX,
|
||||
SO_ELEM_EDGE,
|
||||
SO_ELEM_FACE,
|
||||
SO_ELEM_POLYGON,
|
||||
SO_ELEM_UV,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum ESubObjDisplayType
|
||||
{
|
||||
SO_DISPLAY_WIREFRAME,
|
||||
SO_DISPLAY_FLAT,
|
||||
SO_DISPLAY_GEOMETRY,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Options for sub-object selection.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SSubObjSelOptions
|
||||
{
|
||||
bool bSelectByVertex;
|
||||
bool bIgnoreBackfacing;
|
||||
int nMatID;
|
||||
|
||||
bool bSoftSelection;
|
||||
float fSoftSelFalloff;
|
||||
|
||||
// Display options.
|
||||
bool bDisplayBackfacing;
|
||||
bool bDisplayNormals;
|
||||
float fNormalsLength;
|
||||
ESubObjDisplayType displayType;
|
||||
|
||||
SSubObjSelOptions()
|
||||
{
|
||||
bSelectByVertex = false;
|
||||
bIgnoreBackfacing = false;
|
||||
bSoftSelection = false;
|
||||
nMatID = 0;
|
||||
fSoftSelFalloff = 1;
|
||||
|
||||
bDisplayBackfacing = true;
|
||||
bDisplayNormals = false;
|
||||
displayType = SO_DISPLAY_FLAT;
|
||||
fNormalsLength = 0.4f;
|
||||
}
|
||||
};
|
||||
|
||||
extern SSubObjSelOptions g_SubObjSelOptions;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
enum ESubObjSelectionModifyType
|
||||
{
|
||||
SO_MODIFY_UNSELECT,
|
||||
SO_MODIFY_MOVE,
|
||||
SO_MODIFY_ROTATE,
|
||||
SO_MODIFY_SCALE,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// This structure is passed when user is dragging sub object selection.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SSubObjSelectionModifyContext
|
||||
{
|
||||
CViewport* view;
|
||||
ESubObjSelectionModifyType type;
|
||||
Vec3 vValue;
|
||||
Matrix34 worldRefFrame;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_SUBOBJSELECTION_H
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "TrackGizmo.h"
|
||||
|
||||
// Editor
|
||||
#include "DisplayContext.h"
|
||||
#include "TrackView/TrackViewAnimNode.h"
|
||||
#include "AnimationContext.h"
|
||||
#include "Maestro/Types/AnimParamType.h"
|
||||
#include "Settings.h"
|
||||
#include "Viewport.h"
|
||||
|
||||
|
||||
#define TRACK_DRAW_Z_OFFSET (0.01f)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CTrackGizmo implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#define AXIS_SIZE 0.1f
|
||||
|
||||
namespace {
|
||||
int s_highlightAxis = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CTrackGizmo::CTrackGizmo()
|
||||
{
|
||||
m_pAnimNode = 0;
|
||||
|
||||
m_worldBbox.min = Vec3(-10000, -10000, -10000);
|
||||
m_worldBbox.max = Vec3(10000, 10000, 10000);
|
||||
m_keysSelected = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CTrackGizmo::~CTrackGizmo()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CTrackGizmo::SetMatrix(const Matrix34& tm)
|
||||
{
|
||||
CGizmo::SetMatrix(tm);
|
||||
m_worldBbox.min = Vec3(-10000, -10000, -10000);
|
||||
m_worldBbox.max = Vec3(10000, 10000, 10000);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CTrackGizmo::Display(DisplayContext& dc)
|
||||
{
|
||||
if (!(dc.flags & DISPLAY_TRACKS))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_pAnimNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CAnimationContext* ac = GetIEditor()->GetAnimation();
|
||||
|
||||
// Should have animation sequence.
|
||||
if (!ac->GetSequence())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_keysSelected = false;
|
||||
|
||||
// Must have non empty position track.
|
||||
CTrackViewTrack* pTrack = m_pAnimNode->GetTrackForParameter(AnimParamType::Position);
|
||||
if (!pTrack)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int nkeys = pTrack->GetKeyCount();
|
||||
if (nkeys < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Range range = ac->GetTimeRange();
|
||||
//range.start = __min(range.end,track->GetKeyTime(0));
|
||||
//range.end = __min(range.end,track->GetKeyTime(nkeys-1));
|
||||
//float step = range.Length() / 100.0f;
|
||||
//step = min(step,0.01f);
|
||||
float step = 0.1f;
|
||||
|
||||
bool bTicks = (dc.flags & DISPLAY_TRACKTICKS) == DISPLAY_TRACKTICKS;
|
||||
|
||||
// Get Spline color.
|
||||
ColorF splineCol(0.5f, 0.3f, 1, 1);
|
||||
ColorF timeCol(0, 1, 0, 1);
|
||||
|
||||
m_worldBbox.Reset();
|
||||
|
||||
float zOffset = TRACK_DRAW_Z_OFFSET;
|
||||
Vec3 p0(0, 0, 0), p1(0, 0, 0);
|
||||
Vec3 tick(0, 0, 0.05f);
|
||||
pTrack->GetValue(range.start, p0);
|
||||
p0 = m_matrix * p0;
|
||||
p0.z += zOffset;
|
||||
|
||||
// Update bounding box.
|
||||
m_worldBbox.Add(p0);
|
||||
|
||||
for (float t = range.start + step; t < range.end; t += step)
|
||||
{
|
||||
p1 = Vec3(0, 0, 0);
|
||||
pTrack->GetValue(t, p1);
|
||||
p1 = m_matrix * p1;
|
||||
p1.z += zOffset;
|
||||
|
||||
// Update bounding box.
|
||||
m_worldBbox.Add(p1);
|
||||
|
||||
if (bTicks)
|
||||
{
|
||||
dc.DrawLine(p0 - tick, p0 + tick, timeCol, timeCol);
|
||||
}
|
||||
dc.DrawLine(p0, p1, splineCol, splineCol);
|
||||
p0 = p1;
|
||||
}
|
||||
|
||||
int nSubTracks = pTrack->GetChildCount();
|
||||
if (nSubTracks > 0)
|
||||
{
|
||||
for (int i = 0; i < nSubTracks; i++)
|
||||
{
|
||||
DrawKeys(dc, pTrack, static_cast<CTrackViewTrack*>(pTrack->GetChild(i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawKeys(dc, pTrack, pTrack);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CTrackGizmo::SetAnimNode(CTrackViewAnimNode* pNode)
|
||||
{
|
||||
m_pAnimNode = pNode;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CTrackGizmo::GetWorldBounds(AABB& bbox)
|
||||
{
|
||||
bbox = m_worldBbox;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CTrackGizmo::DrawAxis(DisplayContext& dc, const Vec3& org)
|
||||
{
|
||||
float size = AXIS_SIZE;
|
||||
|
||||
dc.DepthTestOff();
|
||||
|
||||
Vec3 x(size, 0, 0);
|
||||
Vec3 y(0, size, 0);
|
||||
Vec3 z(0, 0, size);
|
||||
|
||||
float fScreenScale = dc.view->GetScreenScaleFactor(org);
|
||||
x = x * fScreenScale;
|
||||
y = y * fScreenScale;
|
||||
z = z * fScreenScale;
|
||||
|
||||
float col[4] = { 1, 1, 1, 1 };
|
||||
float hcol[4] = { 1, 0, 0, 1 };
|
||||
dc.renderer->DrawLabelEx(org + x, 1.2f, col, true, true, "X");
|
||||
dc.renderer->DrawLabelEx(org + y, 1.2f, col, true, true, "Y");
|
||||
dc.renderer->DrawLabelEx(org + z, 1.2f, col, true, true, "Z");
|
||||
|
||||
Vec3 colX(1, 0, 0), colY(0, 1, 0), colZ(0, 0, 1);
|
||||
if (s_highlightAxis)
|
||||
{
|
||||
float col2[4] = { 1, 0, 0, 1 };
|
||||
if (s_highlightAxis == 1)
|
||||
{
|
||||
colX(1, 1, 0);
|
||||
dc.renderer->DrawLabelEx(org + x, 1.2f, col2, true, true, "X");
|
||||
}
|
||||
if (s_highlightAxis == 2)
|
||||
{
|
||||
colY(1, 1, 0);
|
||||
dc.renderer->DrawLabelEx(org + y, 1.2f, col2, true, true, "Y");
|
||||
}
|
||||
if (s_highlightAxis == 3)
|
||||
{
|
||||
colZ(1, 1, 0);
|
||||
dc.renderer->DrawLabelEx(org + z, 1.2f, col2, true, true, "Z");
|
||||
}
|
||||
}
|
||||
|
||||
x = x * 0.8f;
|
||||
y = y * 0.8f;
|
||||
z = z * 0.8f;
|
||||
float fArrowScale = fScreenScale * 0.07f;
|
||||
dc.SetColor(colX);
|
||||
dc.DrawArrow(org, org + x, fArrowScale);
|
||||
dc.SetColor(colY);
|
||||
dc.DrawArrow(org, org + y, fArrowScale);
|
||||
dc.SetColor(colZ);
|
||||
dc.DrawArrow(org, org + z, fArrowScale);
|
||||
|
||||
dc.DepthTestOn();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CTrackGizmo::HitTest([[maybe_unused]] HitContext& hc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CTrackGizmo::DrawKeys(DisplayContext& dc, CTrackViewTrack* pTrack, CTrackViewTrack* pKeysTrack)
|
||||
{
|
||||
// Get Key color.
|
||||
dc.SetColor(1, 0, 0, 1);
|
||||
|
||||
float zOffset = TRACK_DRAW_Z_OFFSET;
|
||||
|
||||
int nkeys = pKeysTrack->GetKeyCount();
|
||||
for (int i = 0; i < nkeys; i++)
|
||||
{
|
||||
const CTrackViewKeyHandle& keyHandle = pKeysTrack->GetKey(i);
|
||||
|
||||
const float t = keyHandle.GetTime();
|
||||
Vec3 p0(0, 0, 0);
|
||||
pTrack->GetValue(t, p0);
|
||||
p0 = m_matrix * p0;
|
||||
p0.z += zOffset;
|
||||
|
||||
//float sz = 0.01f * dc.view->GetScreenScaleFactor(p0);
|
||||
float sz2 = 0.005f * dc.view->GetScreenScaleFactor(p0);
|
||||
|
||||
// Draw quad.
|
||||
//dc.DrawBall( p0,sz );
|
||||
dc.DrawWireBox(p0 - Vec3(sz2, sz2, sz2), p0 + Vec3(sz2, sz2, sz2));
|
||||
|
||||
if (keyHandle.IsSelected())
|
||||
{
|
||||
m_keysSelected = true;
|
||||
DrawAxis(dc, p0);
|
||||
dc.SetColor(1, 0, 0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_OBJECTS_TRACKGIZMO_H
|
||||
#define CRYINCLUDE_EDITOR_OBJECTS_TRACKGIZMO_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "Gizmo.h"
|
||||
|
||||
// forward declarations.
|
||||
struct DisplayContext;
|
||||
class CTrackViewAnimNode;
|
||||
class CTrackViewTrack;
|
||||
|
||||
/** Gizmo of Objects animation track.
|
||||
*/
|
||||
class CTrackGizmo
|
||||
: public CGizmo
|
||||
{
|
||||
public:
|
||||
CTrackGizmo();
|
||||
~CTrackGizmo();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Overrides from CGizmo
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void GetWorldBounds(AABB& bbox);
|
||||
virtual void Display(DisplayContext& dc);
|
||||
virtual bool HitTest(HitContext& hc);
|
||||
virtual void SetMatrix(const Matrix34& tm);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SetAnimNode(CTrackViewAnimNode* pNode);
|
||||
void DrawAxis(DisplayContext& dc, const Vec3& pos);
|
||||
|
||||
void DrawKeys(DisplayContext& dc, CTrackViewTrack* pTrack, CTrackViewTrack* pKeysTrack);
|
||||
|
||||
private:
|
||||
CTrackViewAnimNode* m_pAnimNode;
|
||||
AABB m_worldBbox;
|
||||
bool m_keysSelected;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_OBJECTS_TRACKGIZMO_H
|
||||
Reference in New Issue
Block a user