git mv Code\Sandbox\Editor Code/Editor

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
Esteban Papp
2021-06-29 12:41:59 -07:00
parent 9f0bbf3b74
commit e34e36cb35
1415 changed files with 0 additions and 0 deletions
+366
View File
@@ -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;
}
+89
View File
@@ -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
+852
View File
@@ -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
+29
View File
@@ -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;
}
+67
View File
@@ -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
+11
View File
@@ -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"
+297
View File
@@ -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
+441
View File
@@ -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
+40
View File
@@ -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;
};
+79
View File
@@ -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
+131
View File
@@ -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]);
}
}
+41
View File
@@ -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;
};
+254
View File
@@ -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;
*/
}
+54
View File
@@ -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
+427
View File
@@ -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);
}
+154
View File
@@ -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
+468
View File
@@ -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;
};
+643
View File
@@ -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;
}
}
}
+147
View File
@@ -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
+61
View File
@@ -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();
}
}
*/
+90
View File
@@ -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
+257
View File
@@ -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);
}
}
}
+50
View File
@@ -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