From 9b17c62b1dff76b7d19554edc41b691f80cf1d6e Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 12 Dec 2022 17:07:18 +0800 Subject: [PATCH 1/2] Added active in hierarchy property to scene nodes --- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 40 +++++++++------- SHADE_Engine/src/Scene/SHSceneGraph.h | 1 + SHADE_Engine/src/Scene/SHSceneNode.cpp | 62 ++++++++++++++++++------- SHADE_Engine/src/Scene/SHSceneNode.h | 18 +++++-- 4 files changed, 82 insertions(+), 39 deletions(-) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 5e9f331d..392cbbeb 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -186,6 +186,27 @@ namespace SHADE return NODE_ITER->second->GetChildren(); } + bool SHSceneGraph::IsActive(EntityID entityID) const noexcept + { + //////////////////////////////////////// + // Error handling + if (!SHEntityManager::IsValidEID(entityID)) + { + SHLOG_ERROR("Entity {} is invalid!", entityID) + return false; + } + + const auto NODE_ITER = entityNodeMap.find(entityID); + if (NODE_ITER == entityNodeMap.end()) + { + SHLOG_ERROR("Entity {} cannot be found in the scene!", entityID) + return false; + } + //////////////////////////////////////// + + return NODE_ITER->second->IsActive(); + } + bool SHSceneGraph::IsActiveInHierarchy(EntityID entityID) const noexcept { //////////////////////////////////////// @@ -204,24 +225,7 @@ namespace SHADE } //////////////////////////////////////// - // Recurse up the tree until the root. If any parent is inactive, this node is inactive in the hierarchy. - const SHSceneNode* PARENT_NODE = NODE_ITER->second->parent; - - while (PARENT_NODE->GetEntityID() != root->GetEntityID()) - { - if (!PARENT_NODE->IsActive()) - return false; - - if (!PARENT_NODE->parent) - { - SHLOGV_ERROR("Entity {}'s node that is not the root has no parent!", PARENT_NODE->GetEntityID()) - return false; - } - - PARENT_NODE = PARENT_NODE->parent; - } - - return true; + return NODE_ITER->second->IsActiveInHierarchy(); } /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 37d0e063..68e13b69 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -58,6 +58,7 @@ namespace SHADE [[nodiscard]] SHSceneNode* GetChild (EntityID entityID, EntityID childEntityID) const noexcept; [[nodiscard]] const std::vector& GetChildren (EntityID entityID) const noexcept; + [[nodiscard]] bool IsActive (EntityID entityID) const noexcept; [[nodiscard]] bool IsActiveInHierarchy (EntityID entityID) const noexcept; /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scene/SHSceneNode.cpp b/SHADE_Engine/src/Scene/SHSceneNode.cpp index 28f47989..42046df4 100644 --- a/SHADE_Engine/src/Scene/SHSceneNode.cpp +++ b/SHADE_Engine/src/Scene/SHSceneNode.cpp @@ -23,24 +23,27 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHSceneNode::SHSceneNode(EntityID eid, SHSceneNode* parent) noexcept - : active { true } - , entityID { eid } - , parent { parent } + : active { true } + , isActiveInHierarchy { true } + , entityID { eid } + , parent { parent } {} SHSceneNode::SHSceneNode(const SHSceneNode& rhs) noexcept - : active { rhs.active } - , entityID { rhs.entityID } - , parent { rhs.parent } + : active { rhs.active } + , isActiveInHierarchy { rhs.isActiveInHierarchy } + , entityID { rhs.entityID } + , parent { rhs.parent } { std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children)); } SHSceneNode::SHSceneNode(SHSceneNode&& rhs) noexcept - : active { rhs.active } - , entityID { rhs.entityID } - , parent { rhs.parent } + : active { rhs.active } + , isActiveInHierarchy { rhs.isActiveInHierarchy } + , entityID { rhs.entityID } + , parent { rhs.parent } { std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children)); } @@ -50,9 +53,10 @@ namespace SHADE if (this == &rhs) return *this; - active = rhs.active; - entityID = rhs.entityID; - parent = rhs.parent; + active = rhs.active; + isActiveInHierarchy = rhs.isActiveInHierarchy; + entityID = rhs.entityID; + parent = rhs.parent; children.clear(); std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children)); @@ -62,9 +66,10 @@ namespace SHADE SHSceneNode& SHSceneNode::operator=(SHSceneNode&& rhs) noexcept { - active = rhs.active; - entityID = rhs.entityID; - parent = rhs.parent; + active = rhs.active; + isActiveInHierarchy = rhs.isActiveInHierarchy; + entityID = rhs.entityID; + parent = rhs.parent; children.clear(); std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children)); @@ -81,6 +86,11 @@ namespace SHADE return active; } + bool SHSceneNode::IsActiveInHierarchy() const noexcept + { + return isActiveInHierarchy; + } + EntityID SHSceneNode::GetEntityID() const noexcept { return entityID; @@ -132,7 +142,27 @@ namespace SHADE void SHSceneNode::SetActive(bool newActiveState) noexcept { - active = newActiveState; + active = newActiveState; + isActiveInHierarchy = newActiveState; + + // Recurse down the children to set the active in hierarchy state + recursiveSetActiveInHierarchy(active, children); + } + + /*-----------------------------------------------------------------------------------*/ + /* Private Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHSceneNode::recursiveSetActiveInHierarchy(bool activeInHierarchy, const std::vector& childrenToSet) noexcept + { + if (childrenToSet.empty()) + return; + + for (auto* child : childrenToSet) + { + child->isActiveInHierarchy = activeInHierarchy; + recursiveSetActiveInHierarchy(activeInHierarchy, child->children); + } } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Scene/SHSceneNode.h b/SHADE_Engine/src/Scene/SHSceneNode.h index 87bd8d0b..62979850 100644 --- a/SHADE_Engine/src/Scene/SHSceneNode.h +++ b/SHADE_Engine/src/Scene/SHSceneNode.h @@ -43,7 +43,7 @@ namespace SHADE /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - ~SHSceneNode () = default; + ~SHSceneNode () noexcept = default; SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept; SHSceneNode (const SHSceneNode& rhs) noexcept; @@ -55,10 +55,11 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool IsActive () const noexcept; - [[nodiscard]] EntityID GetEntityID () const noexcept; - [[nodiscard]] SHSceneNode* GetParent () const noexcept; - [[nodiscard]] const std::vector& GetChildren () const noexcept; + [[nodiscard]] bool IsActive () const noexcept; + [[nodiscard]] bool IsActiveInHierarchy () const noexcept; + [[nodiscard]] EntityID GetEntityID () const noexcept; + [[nodiscard]] SHSceneNode* GetParent () const noexcept; + [[nodiscard]] const std::vector& GetChildren () const noexcept; [[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept; @@ -74,9 +75,16 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool active; + bool isActiveInHierarchy; EntityID entityID; SHSceneNode* parent; std::vector children; + + /*---------------------------------------------------------------------------------*/ + /* Member Functions */ + /*---------------------------------------------------------------------------------*/ + + static void recursiveSetActiveInHierarchy(bool activeInHierarchy, const std::vector& childrenToSet) noexcept; }; } // namespace SHADE From 7820d332b11cf26039d377773ad438bca88dee28 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 12 Dec 2022 17:58:15 +0800 Subject: [PATCH 2/2] Changed managed code's GameObject to synce with the node's active state --- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 21 +++++++++++++++++++++ SHADE_Engine/src/Scene/SHSceneGraph.h | 2 ++ SHADE_Engine/src/Scene/SHSceneNode.cpp | 4 ++++ SHADE_Managed/src/Engine/GameObject.cxx | 13 ++++++++++--- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 392cbbeb..b876f5b0 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -310,6 +310,27 @@ namespace SHADE SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); } + void SHSceneGraph::SetActive(EntityID entityID, bool isActive) noexcept + { + //////////////////////////////////////// + // Error handling + if (!SHEntityManager::IsValidEID(entityID)) + { + SHLOG_ERROR("Entity {} is invalid!", entityID) + return; + } + + const auto NODE_ITER = entityNodeMap.find(entityID); + if (NODE_ITER == entityNodeMap.end()) + { + SHLOG_ERROR("Entity {} cannot be found in the scene!", entityID) + return; + } + //////////////////////////////////////// + + NODE_ITER->second->SetActive(isActive); + } + /*-----------------------------------------------------------------------------------*/ /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 68e13b69..3285fc6f 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -68,6 +68,8 @@ namespace SHADE void SetParent (EntityID entityID, SHSceneNode* newParent) noexcept; void SetParent (EntityID entityID, EntityID newParent) noexcept; + void SetActive (EntityID entityID, bool isActive) noexcept; + /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scene/SHSceneNode.cpp b/SHADE_Engine/src/Scene/SHSceneNode.cpp index 42046df4..2b45b037 100644 --- a/SHADE_Engine/src/Scene/SHSceneNode.cpp +++ b/SHADE_Engine/src/Scene/SHSceneNode.cpp @@ -145,6 +145,10 @@ namespace SHADE active = newActiveState; isActiveInHierarchy = newActiveState; + // Set the entity's active state + // TODO(Daniel / Diren): Sync it based on active in hierarchy or active state. + SHEntityManager::GetEntityByID(entityID)->SetActive(active); + // Recurse down the children to set the active in hierarchy state recursiveSetActiveInHierarchy(active, children); } diff --git a/SHADE_Managed/src/Engine/GameObject.cxx b/SHADE_Managed/src/Engine/GameObject.cxx index 3557e8f1..0e03a643 100644 --- a/SHADE_Managed/src/Engine/GameObject.cxx +++ b/SHADE_Managed/src/Engine/GameObject.cxx @@ -76,7 +76,13 @@ namespace SHADE { if (!valid) throw gcnew System::NullReferenceException(); - return GetNativeEntity().GetActive(); + auto node = SHSceneManager::GetCurrentSceneGraph().GetNode(GetEntity()); + if (!node) + { + Debug::LogWarning("Attempting to access a GameObject's Active state which does not exist. Assuming inactive."); + return false; + } + return node->IsActive(); } bool GameObject::IsActiveInHierarchy::get() { @@ -88,7 +94,7 @@ namespace SHADE Debug::LogWarning("Attempting to access a GameObject's ActiveInHierarchy state which does not exist. Assuming inactive."); return false; } - return node->IsActive(); + return node->IsActiveInHierarchy(); } Entity GameObject::EntityId::get() { @@ -148,7 +154,8 @@ namespace SHADE { if (!valid) throw gcnew System::NullReferenceException(); - GetNativeEntity().SetActive(active); + + SHSceneManager::GetCurrentSceneGraph().SetActive(GetEntity(), active); } /*---------------------------------------------------------------------------------*/