Added CSceneIterator and implemented support for Select All/Invert Selection

This commit is contained in:
parax0
2016-01-09 09:39:43 -07:00
parent 7eeb90b925
commit 38d04bcd25
20 changed files with 459 additions and 48 deletions

View File

@@ -31,7 +31,7 @@ CModelNode* CScene::CreateModelNode(CModel *pModel)
if (pModel == nullptr) return nullptr;
CModelNode *pNode = new CModelNode(this, mpSceneRootNode, pModel);
mNodes[eShowObjects].push_back(pNode);
mNodes[eModelNode].push_back(pNode);
mNumNodes++;
return pNode;
}
@@ -41,7 +41,7 @@ CStaticNode* CScene::CreateStaticNode(CStaticModel *pModel)
if (pModel == nullptr) return nullptr;
CStaticNode *pNode = new CStaticNode(this, mpAreaRootNode, pModel);
mNodes[eShowWorld].push_back(pNode);
mNodes[eStaticNode].push_back(pNode);
mNumNodes++;
return pNode;
}
@@ -51,7 +51,7 @@ CCollisionNode* CScene::CreateCollisionNode(CCollisionMeshGroup *pMesh)
if (pMesh == nullptr) return nullptr;
CCollisionNode *pNode = new CCollisionNode(this, mpAreaRootNode, pMesh);
mNodes[eShowWorldCollision].push_back(pNode);
mNodes[eCollisionNode].push_back(pNode);
mNumNodes++;
return pNode;
}
@@ -61,7 +61,7 @@ CScriptNode* CScene::CreateScriptNode(CScriptObject *pObj)
if (pObj == nullptr) return nullptr;
CScriptNode *pNode = new CScriptNode(this, mpAreaRootNode, pObj);
mNodes[eShowObjects].push_back(pNode);
mNodes[eScriptNode].push_back(pNode);
mNumNodes++;
return pNode;
}
@@ -71,7 +71,7 @@ CLightNode* CScene::CreateLightNode(CLight *pLight)
if (pLight == nullptr) return nullptr;
CLightNode *pNode = new CLightNode(this, mpAreaRootNode, pLight);
mNodes[eShowLights].push_back(pNode);
mNodes[eLightNode].push_back(pNode);
mNumNodes++;
return pNode;
}
@@ -115,7 +115,7 @@ void CScene::SetActiveArea(CGameArea *pArea)
{
CScriptLayer *pLayer = mpArea->GetScriptLayer(iLyr);
u32 NumObjects = pLayer->GetNumObjects();
mNodes[eShowObjects].reserve(mNodes[eShowObjects].size() + NumObjects);
mNodes[eScriptNode].reserve(mNodes[eScriptNode].size() + NumObjects);
for (u32 iObj = 0; iObj < NumObjects; iObj++)
{
@@ -202,10 +202,11 @@ void CScene::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
// Override show flags in game mode
FShowFlags ShowFlags = (ViewInfo.GameMode ? gkGameModeShowFlags : ViewInfo.ShowFlags);
FNodeFlags NodeFlags = NodeFlagsForShowFlags(ShowFlags);
for (auto it = mNodes.begin(); it != mNodes.end(); it++)
{
if (ShowFlags & it->first)
if (NodeFlags & it->first)
{
std::vector<CSceneNode*>& rNodeVec = it->second;
@@ -219,11 +220,12 @@ void CScene::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
SRayIntersection CScene::SceneRayCast(const CRay& Ray, const SViewInfo& ViewInfo)
{
FShowFlags ShowFlags = (ViewInfo.GameMode ? gkGameModeShowFlags : ViewInfo.ShowFlags);
FNodeFlags NodeFlags = NodeFlagsForShowFlags(ShowFlags);
CRayCollisionTester Tester(Ray);
for (auto it = mNodes.begin(); it != mNodes.end(); it++)
{
if (ShowFlags & it->first)
if (NodeFlags & it->first)
{
std::vector<CSceneNode*>& rNodeVec = it->second;
@@ -252,7 +254,7 @@ CScriptNode* CScene::NodeForObject(CScriptObject *pObj)
CLightNode* CScene::NodeForLight(CLight *pLight)
{
// Slow. Is there a better way to do this?
std::vector<CSceneNode*>& rLights = mNodes[eShowLights];
std::vector<CSceneNode*>& rLights = mNodes[eLightNode];
for (auto it = rLights.begin(); it != rLights.end(); it++)
{
@@ -291,3 +293,24 @@ CGameArea* CScene::GetActiveArea()
{
return mpArea;
}
// ************ STATIC ************
FShowFlags CScene::ShowFlagsForNodeFlags(FNodeFlags NodeFlags)
{
FShowFlags Out;
if (NodeFlags & eStaticNode) Out |= eShowWorld;
if (NodeFlags & eScriptNode) Out |= eShowObjects;
if (NodeFlags & eCollisionNode) Out |= eShowWorldCollision;
if (NodeFlags & eLightNode) Out |= eShowLights;
return Out;
}
FNodeFlags CScene::NodeFlagsForShowFlags(FShowFlags ShowFlags)
{
FNodeFlags Out = eRootNode | eModelNode;
if (ShowFlags & eShowWorld) Out |= eStaticNode;
if (ShowFlags & eShowWorldCollision) Out |= eCollisionNode;
if (ShowFlags & eShowObjects) Out |= eScriptNode | eScriptExtraNode;
if (ShowFlags & eShowLights) Out |= eLightNode;
return Out;
}

View File

@@ -22,11 +22,13 @@
class CScene
{
friend class CSceneIterator;
bool mSplitTerrain;
u32 mNumNodes;
CRootNode *mpSceneRootNode;
std::unordered_map<EShowFlag, std::vector<CSceneNode*>> mNodes;
std::unordered_map<ENodeType, std::vector<CSceneNode*>> mNodes;
TResPtr<CGameArea> mpArea;
TResPtr<CWorld> mpWorld;
@@ -60,6 +62,10 @@ public:
// Setters/Getters
CModel* GetActiveSkybox();
CGameArea* GetActiveArea();
// Static
static FShowFlags ShowFlagsForNodeFlags(FNodeFlags NodeFlags);
static FNodeFlags NodeFlagsForShowFlags(FShowFlags ShowFlags);
};
#endif // CSCENE_H

View File

@@ -0,0 +1,72 @@
#include "CSceneIterator.h"
#include "CScene.h"
CSceneIterator::CSceneIterator(CScene *pScene, FNodeFlags AllowedNodeTypes /*= eAllNodeTypes*/, bool AllowHiddenNodes /*= false*/)
: mpScene(pScene)
, mAllowHiddenNodes(AllowHiddenNodes)
, mNodeFlags(AllowedNodeTypes)
, mpCurNode(nullptr)
{
mMapIterator = mpScene->mNodes.begin();
while (mMapIterator != mpScene->mNodes.end())
{
if (mMapIterator->first & AllowedNodeTypes)
break;
mMapIterator++;
}
if (mMapIterator != mpScene->mNodes.end())
{
mVectorIterator = (mMapIterator->second).begin();
Next(); // Find first node
}
}
// ************ PROTECTED ************
void CSceneIterator::InternalFindNext()
{
// This function does most of the heavy lifting. We continue from where we left off last time this function was called.
while (mMapIterator != mpScene->mNodes.end())
{
// Iterate over each node in the vector.
std::vector<CSceneNode*>& rVector = mMapIterator->second;
bool FoundNext = false;
while (mVectorIterator != rVector.end())
{
CSceneNode *pNode = *mVectorIterator;
// Check node visibility
if (mAllowHiddenNodes || pNode->IsVisible())
{
mpCurNode = pNode;
FoundNext = true;
}
mVectorIterator++;
if (FoundNext) return;
}
// We've reached the end of this node vector, so advance the map iterator
while (true)
{
mMapIterator++;
if (mMapIterator == mpScene->mNodes.end())
{
break;
}
if (mNodeFlags & mMapIterator->first)
{
mVectorIterator = mMapIterator->second.begin();
break;
}
}
}
// If we're down here, then it seems we're done iterating the scene.
mpCurNode = nullptr;
}

View File

@@ -0,0 +1,66 @@
#ifndef CSCENEITERATOR_H
#define CSCENEITERATOR_H
#include "ENodeType.h"
#include <unordered_map>
class CScene;
class CSceneNode;
class CSceneIterator
{
CScene *mpScene;
bool mAllowHiddenNodes;
FNodeFlags mNodeFlags;
CSceneNode *mpCurNode;
std::unordered_map<ENodeType, std::vector<CSceneNode*>>::iterator mMapIterator;
std::vector<CSceneNode*>::iterator mVectorIterator;
public:
CSceneIterator(CScene *pScene, FNodeFlags AllowedNodeTypes = eAllNodeTypes, bool AllowHiddenNodes = false);
inline CSceneNode* Next()
{
InternalFindNext();
return mpCurNode;
}
inline bool DoneIterating() const
{
return (mpCurNode == nullptr);
}
inline CSceneNode* GetNode() const
{
return mpCurNode;
}
inline CSceneNode* operator*() const
{
return mpCurNode;
}
inline CSceneNode* operator->() const
{
return mpCurNode;
}
inline CSceneIterator& operator++()
{
Next();
return *this;
}
inline CSceneIterator operator++(int)
{
CSceneIterator Copy = *this;
Next();
return Copy;
}
protected:
void InternalFindNext();
};
#endif // CSCENEITERATOR_H

View File

@@ -1,16 +1,21 @@
#ifndef ENODETYPE_H
#define ENODETYPE_H
#include <Common/Flags.h>
enum ENodeType
{
eRootNode,
eModelNode,
eStaticNode,
eCollisionNode,
eScriptNode,
eScriptExtraNode,
eLightNode
eRootNode = 0x0,
eModelNode = 0x1,
eStaticNode = 0x2,
eCollisionNode = 0x4,
eScriptNode = 0x8,
eScriptExtraNode = 0x10,
eLightNode = 0x20,
eAllNodeTypes = 0x3F
};
DECLARE_FLAGS(ENodeType, FNodeFlags)
#endif // ENODETYPE_H