Fully implemented delete, added an easy-to-use ID lookup system for undo commands, fixed a bunch of crashes when undoing/redoing after creating/deleting an object

This commit is contained in:
parax0
2016-03-16 19:09:59 -06:00
parent 63812ae4b2
commit c4e05610f3
66 changed files with 992 additions and 569 deletions

View File

@@ -3,8 +3,8 @@
#include "Core/Render/CGraphics.h"
#include "Core/Render/CRenderer.h"
CCollisionNode::CCollisionNode(CScene *pScene, CSceneNode *pParent, CCollisionMeshGroup *pCollision)
: CSceneNode(pScene, pParent)
CCollisionNode::CCollisionNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CCollisionMeshGroup *pCollision)
: CSceneNode(pScene, NodeID, pParent)
{
SetCollision(pCollision);
SetName("Collision");

View File

@@ -9,7 +9,7 @@ class CCollisionNode : public CSceneNode
TResPtr<CCollisionMeshGroup> mpCollision;
public:
CCollisionNode(CScene *pScene, CSceneNode *pParent = 0, CCollisionMeshGroup *pCollision = 0);
CCollisionNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0, CCollisionMeshGroup *pCollision = 0);
ENodeType NodeType();
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo);

View File

@@ -4,8 +4,8 @@
#include "Core/Render/CRenderer.h"
#include <Math/MathUtil.h>
CLightNode::CLightNode(CScene *pScene, CSceneNode *pParent, CLight *Light)
: CSceneNode(pScene, pParent)
CLightNode::CLightNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CLight *Light)
: CSceneNode(pScene, NodeID, pParent)
{
mpLight = Light;
mLocalAABox = CAABox::skOne;

View File

@@ -8,7 +8,7 @@ class CLightNode : public CSceneNode
{
CLight *mpLight;
public:
CLightNode(CScene *pScene, CSceneNode *pParent = 0, CLight *Light = 0);
CLightNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0, CLight *Light = 0);
ENodeType NodeType();
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo);

View File

@@ -4,7 +4,8 @@
#include "Core/Render/CGraphics.h"
#include <Math/MathUtil.h>
CModelNode::CModelNode(CScene *pScene, CSceneNode *pParent, CModel *pModel) : CSceneNode(pScene, pParent)
CModelNode::CModelNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CModel *pModel)
: CSceneNode(pScene, NodeID, pParent)
{
SetModel(pModel);
mScale = CVector3f(1.f);

View File

@@ -15,7 +15,7 @@ class CModelNode : public CSceneNode
CColor mScanOverlayColor;
public:
explicit CModelNode(CScene *pScene, CSceneNode *pParent = 0, CModel *pModel = 0);
explicit CModelNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0, CModel *pModel = 0);
virtual ENodeType NodeType();
virtual void PostLoad();

View File

@@ -8,7 +8,8 @@
class CRootNode : public CSceneNode
{
public:
explicit CRootNode(CScene *pScene, CSceneNode *pParent = 0) : CSceneNode(pScene, pParent) {}
explicit CRootNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0)
: CSceneNode(pScene, NodeID, pParent) {}
~CRootNode() {}
ENodeType NodeType() {

View File

@@ -17,7 +17,7 @@ CScene::CScene()
: mSplitTerrain(true)
, mRanPostLoad(false)
, mNumNodes(0)
, mpSceneRootNode(new CRootNode(this, nullptr))
, mpSceneRootNode(new CRootNode(this, -1, nullptr))
, mpArea(nullptr)
, mpWorld(nullptr)
, mpAreaRootNode(nullptr)
@@ -29,43 +29,76 @@ CScene::~CScene()
ClearScene();
}
CModelNode* CScene::CreateModelNode(CModel *pModel)
bool CScene::IsNodeIDUsed(u32 ID) const
{
return (mNodeMap.find(ID) != mNodeMap.end());
}
u32 CScene::CreateNodeID(u32 SuggestedID /*= -1*/) const
{
if (SuggestedID != -1)
{
if (IsNodeIDUsed(SuggestedID))
Log::Error("Suggested node ID is already being used! New ID will be created.");
else
return SuggestedID;
}
u32 ID = 0;
while (IsNodeIDUsed(ID))
ID++;
return ID;
}
CModelNode* CScene::CreateModelNode(CModel *pModel, u32 NodeID /*= -1*/)
{
if (pModel == nullptr) return nullptr;
CModelNode *pNode = new CModelNode(this, mpAreaRootNode, pModel);
u32 ID = CreateNodeID(NodeID);
CModelNode *pNode = new CModelNode(this, ID, mpAreaRootNode, pModel);
mNodes[eModelNode].push_back(pNode);
mNodeMap[ID] = pNode;
mNumNodes++;
return pNode;
}
CStaticNode* CScene::CreateStaticNode(CStaticModel *pModel)
CStaticNode* CScene::CreateStaticNode(CStaticModel *pModel, u32 NodeID /*= -1*/)
{
if (pModel == nullptr) return nullptr;
CStaticNode *pNode = new CStaticNode(this, mpAreaRootNode, pModel);
u32 ID = CreateNodeID(NodeID);
CStaticNode *pNode = new CStaticNode(this, ID, mpAreaRootNode, pModel);
mNodes[eStaticNode].push_back(pNode);
mNodeMap[ID] = pNode;
mNumNodes++;
return pNode;
}
CCollisionNode* CScene::CreateCollisionNode(CCollisionMeshGroup *pMesh)
CCollisionNode* CScene::CreateCollisionNode(CCollisionMeshGroup *pMesh, u32 NodeID /*= -1*/)
{
if (pMesh == nullptr) return nullptr;
CCollisionNode *pNode = new CCollisionNode(this, mpAreaRootNode, pMesh);
u32 ID = CreateNodeID(NodeID);
CCollisionNode *pNode = new CCollisionNode(this, ID, mpAreaRootNode, pMesh);
mNodes[eCollisionNode].push_back(pNode);
mNodeMap[ID] = pNode;
mNumNodes++;
return pNode;
}
CScriptNode* CScene::CreateScriptNode(CScriptObject *pObj)
CScriptNode* CScene::CreateScriptNode(CScriptObject *pObj, u32 NodeID /*= -1*/)
{
if (pObj == nullptr) return nullptr;
CScriptNode *pNode = new CScriptNode(this, mpAreaRootNode, pObj);
u32 ID = CreateNodeID(NodeID);
u32 InstanceID = pObj->InstanceID();
CScriptNode *pNode = new CScriptNode(this, ID, mpAreaRootNode, pObj);
mNodes[eScriptNode].push_back(pNode);
mScriptNodeMap[pObj->InstanceID()] = pNode;
mNodeMap[ID] = pNode;
mScriptMap[InstanceID] = pNode;
pNode->BuildLightList(mpArea);
// AreaAttributes check
@@ -81,12 +114,14 @@ CScriptNode* CScene::CreateScriptNode(CScriptObject *pObj)
return pNode;
}
CLightNode* CScene::CreateLightNode(CLight *pLight)
CLightNode* CScene::CreateLightNode(CLight *pLight, u32 NodeID /*= -1*/)
{
if (pLight == nullptr) return nullptr;
CLightNode *pNode = new CLightNode(this, mpAreaRootNode, pLight);
u32 ID = CreateNodeID(NodeID);
CLightNode *pNode = new CLightNode(this, ID, mpAreaRootNode, pLight);
mNodes[eLightNode].push_back(pNode);
mNodeMap[ID] = pNode;
mNumNodes++;
return pNode;
}
@@ -104,13 +139,17 @@ void CScene::DeleteNode(CSceneNode *pNode)
}
}
auto MapIt = mNodeMap.find(pNode->ID());
if (MapIt != mNodeMap.end())
mNodeMap.erase(MapIt);
if (Type == eScriptNode)
{
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
auto ScriptMapIt = mScriptNodeMap.find(pScript->Object()->InstanceID());
if (ScriptMapIt != mScriptNodeMap.end())
mScriptNodeMap.erase(ScriptMapIt);
auto it = mScriptMap.find(pScript->Object()->InstanceID());
if (it != mScriptMap.end())
mScriptMap.erase(it);
switch (pScript->Object()->ObjectTypeID())
{
@@ -140,7 +179,7 @@ void CScene::SetActiveArea(CGameArea *pArea)
// Create nodes for new area
mpArea = pArea;
mpAreaRootNode = new CRootNode(this, mpSceneRootNode);
mpAreaRootNode = new CRootNode(this, -1, mpSceneRootNode);
// Create static nodes
u32 Count = mpArea->GetStaticModelCount();
@@ -190,10 +229,11 @@ void CScene::SetActiveArea(CGameArea *pArea)
}
// Ensure script nodes have valid positions + build light lists
for (auto it = mScriptNodeMap.begin(); it != mScriptNodeMap.end(); it++)
for (CSceneIterator It(this, eScriptNode, true); It; ++It)
{
it->second->GeneratePosition();
it->second->BuildLightList(mpArea);
CScriptNode *pScript = static_cast<CScriptNode*>(*It);
pScript->GeneratePosition();
pScript->BuildLightList(mpArea);
}
u32 NumLightLayers = mpArea->GetLightLayerCount();
@@ -239,7 +279,7 @@ void CScene::ClearScene()
mNodes.clear();
mAreaAttributesObjects.clear();
mScriptNodeMap.clear();
mNodeMap.clear();
mNumNodes = 0;
mpArea = nullptr;
@@ -277,17 +317,25 @@ SRayIntersection CScene::SceneRayCast(const CRay& Ray, const SViewInfo& ViewInfo
return Tester.TestNodes(ViewInfo);
}
CScriptNode* CScene::ScriptNodeByID(u32 InstanceID)
CSceneNode* CScene::NodeByID(u32 NodeID)
{
auto it = mScriptNodeMap.find(InstanceID);
auto it = mNodeMap.find(NodeID);
if (it != mScriptNodeMap.end()) return it->second;
if (it != mNodeMap.end()) return it->second;
else return nullptr;
}
CScriptNode* CScene::NodeForInstanceID(u32 InstanceID)
{
auto it = mScriptMap.find(InstanceID);
if (it != mScriptMap.end()) return it->second;
else return nullptr;
}
CScriptNode* CScene::NodeForObject(CScriptObject *pObj)
{
return ScriptNodeByID(pObj->InstanceID());
return NodeForInstanceID(pObj->InstanceID());
}
CLightNode* CScene::NodeForLight(CLight *pLight)

View File

@@ -38,19 +38,23 @@ class CScene
// Environment
std::vector<CAreaAttributes> mAreaAttributesObjects;
// Objects
std::unordered_map<u32, CScriptNode*> mScriptNodeMap;
// Node Management
std::unordered_map<u32, CSceneNode*> mNodeMap;
std::unordered_map<u32, CScriptNode*> mScriptMap;
public:
CScene();
~CScene();
// Scene Management
CModelNode* CreateModelNode(CModel *pModel);
CStaticNode* CreateStaticNode(CStaticModel *pModel);
CCollisionNode* CreateCollisionNode(CCollisionMeshGroup *pMesh);
CScriptNode* CreateScriptNode(CScriptObject *pObj);
CLightNode* CreateLightNode(CLight *pLight);
bool IsNodeIDUsed(u32 ID) const;
u32 CreateNodeID(u32 SuggestedID = -1) const;
CModelNode* CreateModelNode(CModel *pModel, u32 NodeID = -1);
CStaticNode* CreateStaticNode(CStaticModel *pModel, u32 NodeID = -1);
CCollisionNode* CreateCollisionNode(CCollisionMeshGroup *pMesh, u32 NodeID = -1);
CScriptNode* CreateScriptNode(CScriptObject *pObj, u32 NodeID = -1);
CLightNode* CreateLightNode(CLight *pLight, u32 NodeID = -1);
void DeleteNode(CSceneNode *pNode);
void SetActiveArea(CGameArea *pArea);
void SetActiveWorld(CWorld *pWorld);
@@ -58,7 +62,8 @@ public:
void ClearScene();
void AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo);
SRayIntersection SceneRayCast(const CRay& rkRay, const SViewInfo& rkViewInfo);
CScriptNode* ScriptNodeByID(u32 InstanceID);
CSceneNode* NodeByID(u32 NodeID);
CScriptNode* NodeForInstanceID(u32 InstanceID);
CScriptNode* NodeForObject(CScriptObject *pObj);
CLightNode* NodeForLight(CLight *pLight);

View File

@@ -12,11 +12,12 @@
u32 CSceneNode::smNumNodes = 0;
CColor CSceneNode::skSelectionTint = CColor::Integral(39, 154, 167);
CSceneNode::CSceneNode(CScene *pScene, CSceneNode *pParent)
CSceneNode::CSceneNode(CScene *pScene, u32 NodeID, CSceneNode *pParent)
{
smNumNodes++;
mpScene = pScene;
mpParent = pParent;
_mID = NodeID;
mPosition = CVector3f::skZero;
mRotation = CQuaternion::skIdentity;
@@ -341,6 +342,11 @@ CScene* CSceneNode::Scene() const
return mpScene;
}
u32 CSceneNode::ID() const
{
return _mID;
}
CVector3f CSceneNode::LocalPosition() const
{
return mPosition;

View File

@@ -29,6 +29,8 @@ private:
bool _mInheritsRotation;
bool _mInheritsScale;
u32 _mID;
protected:
static u32 smNumNodes;
TString mName;
@@ -51,7 +53,7 @@ protected:
CColor mAmbientColor;
public:
explicit CSceneNode(CScene *pScene, CSceneNode *pParent = 0);
explicit CSceneNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0);
virtual ~CSceneNode();
virtual ENodeType NodeType() = 0;
virtual void PostLoad() {}
@@ -94,6 +96,7 @@ public:
TString Name() const;
CSceneNode* Parent() const;
CScene* Scene() const;
u32 ID() const;
CVector3f LocalPosition() const;
CVector3f AbsolutePosition() const;
CQuaternion LocalRotation() const;

View File

@@ -10,8 +10,8 @@
#include <Common/AnimUtil.h>
#include <Math/MathUtil.h>
CScriptNode::CScriptNode(CScene *pScene, CSceneNode *pParent, CScriptObject *pObject)
: CSceneNode(pScene, pParent)
CScriptNode::CScriptNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CScriptObject *pObject)
: CSceneNode(pScene, NodeID, pParent)
, mGameModeVisibility(eUntested)
{
mpVolumePreviewNode = nullptr;
@@ -21,7 +21,7 @@ CScriptNode::CScriptNode(CScene *pScene, CSceneNode *pParent, CScriptObject *pOb
mpInstance = pObject;
SetActiveModel(nullptr);
mpBillboard = nullptr;
mpCollisionNode = new CCollisionNode(pScene, this);
mpCollisionNode = new CCollisionNode(pScene, -1, this);
mpCollisionNode->SetInheritance(true, true, false);
if (mpInstance)
@@ -43,7 +43,7 @@ CScriptNode::CScriptNode(CScene *pScene, CSceneNode *pParent, CScriptObject *pOb
mpCollisionNode->SetCollision(mpInstance->GetCollision());
// Create preview volume node
mpVolumePreviewNode = new CModelNode(pScene, this, nullptr);
mpVolumePreviewNode = new CModelNode(pScene, -1, this, nullptr);
if (pTemp->ScaleType() == CScriptTemplate::eScaleVolume)
{
@@ -259,14 +259,14 @@ void CScriptNode::DrawSelection()
{
// Don't draw in links if the other object is selected.
CLink *pLink = mpInstance->Link(eIncoming, iIn);
CScriptNode *pLinkNode = mpScene->ScriptNodeByID(pLink->SenderID());
CScriptNode *pLinkNode = mpScene->NodeForInstanceID(pLink->SenderID());
if (pLinkNode && !pLinkNode->IsSelected()) CDrawUtil::DrawLine(CenterPoint(), pLinkNode->CenterPoint(), CColor::skTransparentRed);
}
for (u32 iOut = 0; iOut < mpInstance->NumLinks(eOutgoing); iOut++)
{
CLink *pLink = mpInstance->Link(eOutgoing, iOut);
CScriptNode *pLinkNode = mpScene->ScriptNodeByID(pLink->ReceiverID());
CScriptNode *pLinkNode = mpScene->NodeForInstanceID(pLink->ReceiverID());
if (pLinkNode) CDrawUtil::DrawLine(CenterPoint(), pLinkNode->CenterPoint(), CColor::skTransparentGreen);
}
}
@@ -549,7 +549,7 @@ void CScriptNode::GeneratePosition()
if (NumLinks == 1)
{
u32 LinkedID = (mpInstance->NumLinks(eIncoming) > 0 ? mpInstance->Link(eIncoming, 0)->SenderID() : mpInstance->Link(eOutgoing, 0)->ReceiverID());
CScriptNode *pNode = mpScene->ScriptNodeByID(LinkedID);
CScriptNode *pNode = mpScene->NodeForInstanceID(LinkedID);
pNode->GeneratePosition();
mPosition = pNode->AbsolutePosition();
mPosition.z += (pNode->AABox().Size().z / 2.f);
@@ -564,7 +564,7 @@ void CScriptNode::GeneratePosition()
for (u32 iIn = 0; iIn < mpInstance->NumLinks(eIncoming); iIn++)
{
CScriptNode *pNode = mpScene->ScriptNodeByID(mpInstance->Link(eIncoming, iIn)->SenderID());
CScriptNode *pNode = mpScene->NodeForInstanceID(mpInstance->Link(eIncoming, iIn)->SenderID());
if (pNode)
{
@@ -575,7 +575,7 @@ void CScriptNode::GeneratePosition()
for (u32 iOut = 0; iOut < mpInstance->NumLinks(eOutgoing); iOut++)
{
CScriptNode *pNode = mpScene->ScriptNodeByID(mpInstance->Link(eOutgoing, iOut)->ReceiverID());
CScriptNode *pNode = mpScene->NodeForInstanceID(mpInstance->Link(eOutgoing, iOut)->ReceiverID());
if (pNode)
{

View File

@@ -30,7 +30,7 @@ class CScriptNode : public CSceneNode
} mGameModeVisibility;
public:
CScriptNode(CScene *pScene, CSceneNode *pParent = 0, CScriptObject *pObject = 0);
CScriptNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0, CScriptObject *pObject = 0);
ENodeType NodeType();
void PostLoad();
void OnTransformed();

View File

@@ -5,8 +5,8 @@
#include <Common/AnimUtil.h>
#include <Math/MathUtil.h>
CStaticNode::CStaticNode(CScene *pScene, CSceneNode *pParent, CStaticModel *pModel)
: CSceneNode(pScene, pParent)
CStaticNode::CStaticNode(CScene *pScene, u32 NodeID, CSceneNode *pParent, CStaticModel *pModel)
: CSceneNode(pScene, NodeID, pParent)
{
mpModel = pModel;
mLocalAABox = mpModel->AABox();

View File

@@ -9,7 +9,7 @@ class CStaticNode : public CSceneNode
CStaticModel *mpModel;
public:
CStaticNode(CScene *pScene, CSceneNode *pParent = 0, CStaticModel *pModel = 0);
CStaticNode(CScene *pScene, u32 NodeID, CSceneNode *pParent = 0, CStaticModel *pModel = 0);
ENodeType NodeType();
void PostLoad();
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);