From eeab3494ba35bd395646ebee60829203863ee3b8 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 10 Nov 2022 03:30:02 +0800 Subject: [PATCH 01/13] Reworked SceneGraph Interface --- Assets/Scenes/M2Scene.shade | 84 ++--- .../HierarchyPanel/SHHierarchyPanel.cpp | 4 +- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 337 ++++++------------ SHADE_Engine/src/Scene/SHSceneGraph.h | 109 ++---- SHADE_Engine/src/Scene/SHSceneNode.cpp | 143 ++++++++ SHADE_Engine/src/Scene/SHSceneNode.h | 82 +++++ SHADE_Managed/src/Engine/GameObject.cxx | 2 +- 7 files changed, 405 insertions(+), 356 deletions(-) create mode 100644 SHADE_Engine/src/Scene/SHSceneNode.cpp create mode 100644 SHADE_Engine/src/Scene/SHSceneNode.h diff --git a/Assets/Scenes/M2Scene.shade b/Assets/Scenes/M2Scene.shade index 30dea780..b2a5683f 100644 --- a/Assets/Scenes/M2Scene.shade +++ b/Assets/Scenes/M2Scene.shade @@ -124,48 +124,6 @@ Mesh: 144838771 Material: 123745521 Scripts: ~ -- EID: 5 - Name: item - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: 0, y: -2, z: -5} - Rotate: {x: 0, y: 0, z: 0} - Scale: {x: 2, y: 2, z: 2} - Renderable Component: - Mesh: 144838771 - Material: 123745521 - RigidBody Component: - Type: Dynamic - Mass: 1 - Drag: 0 - Angular Drag: 0 - Use Gravity: true - Interpolate: false - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: true - Freeze Rotation Y: true - Freeze Rotation Z: true - Collider Component: - Colliders: - - Is Trigger: false - Type: Box - Half Extents: {x: 1, y: 1, z: 1} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0.5, z: 0} - - Is Trigger: true - Type: Box - Half Extents: {x: 2, y: 2, z: 2} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0.5, z: 0} - Scripts: ~ - EID: 6 Name: AI IsActive: true @@ -226,4 +184,46 @@ Color: {x: 1, y: 1, z: 1, w: 1} Layer: 4294967295 Strength: 0.25 + Scripts: ~ +- EID: 5 + Name: item + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: -2, z: -5} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 2, y: 2, z: 2} + Renderable Component: + Mesh: 144838771 + Material: 123745521 + RigidBody Component: + Type: Dynamic + Mass: 1 + Drag: 0 + Angular Drag: 0 + Use Gravity: true + Interpolate: false + Freeze Position X: false + Freeze Position Y: false + Freeze Position Z: false + Freeze Rotation X: true + Freeze Rotation Y: true + Freeze Rotation Z: true + Collider Component: + Colliders: + - Is Trigger: false + Type: Box + Half Extents: {x: 1, y: 1, z: 1} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0.5, z: 0} + - Is Trigger: true + Type: Box + Half Extents: {x: 2, y: 2, z: 2} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0.5, z: 0} Scripts: ~ \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index e2c39ad8..ff65ba58 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -419,7 +419,7 @@ namespace SHADE void SHEntityParentCommand::Execute() { - auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); for (auto const& eid : entities) { if (entityParentData[eid].newParentEID == MAX_EID) @@ -431,7 +431,7 @@ namespace SHADE void SHEntityParentCommand::Undo() { - auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); for (auto const& eid : entities) { if (entityParentData[eid].oldParentEID == MAX_EID) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index df46b3fb..900d482a 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -16,8 +16,6 @@ // Project Headers #include "ECS_Base/Managers/SHEntityManager.h" #include "Events/SHEventManager.hpp" -#include "Tools/SHLogger.h" -#include "Tools/SHException.h" namespace SHADE { @@ -25,56 +23,6 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHSceneNode::SHSceneNode(EntityID eid, SHSceneNode* parent) noexcept - : active { true } - , entityID { eid } - , parent { parent } - {} - - - SHSceneNode::SHSceneNode(const SHSceneNode& rhs) noexcept - : active { rhs.active } - , 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 } - { - std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children)); - } - - SHSceneNode& SHSceneNode::operator=(const SHSceneNode& rhs) noexcept - { - if (this == &rhs) - return *this; - - active = rhs.active; - entityID = rhs.entityID; - parent = rhs.parent; - - children.clear(); - std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children)); - - return *this; - } - - SHSceneNode& SHSceneNode::operator=(SHSceneNode&& rhs) noexcept - { - active = rhs.active; - entityID = rhs.entityID; - parent = rhs.parent; - - children.clear(); - std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children)); - - return *this; - } - SHSceneGraph::SHSceneGraph() noexcept : root { nullptr } { @@ -110,56 +58,6 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - bool SHSceneNode::IsActive() const noexcept - { - return active; - } - - EntityID SHSceneNode::GetEntityID() const noexcept - { - return entityID; - } - - SHSceneNode* SHSceneNode::GetParent() const noexcept - { - return parent; - } - - const std::vector& SHSceneNode::GetChildren() const noexcept - { - return children; - } - - SHSceneNode* SHSceneNode::GetChild(EntityID childID) const noexcept - { - //////////////////////////////////////// - // Error handling - if (!SHEntityManager::IsValidEID(childID)) - { - SHLOG_ERROR("Child Entity {} is invalid! Unable to get child from Entity {}", childID, entityID) - return nullptr; - } - - if (children.empty()) - { - SHLOG_WARNING("Entity {} has no children!", entityID) - return nullptr; - } - //////////////////////////////////////// - - // Find child - const auto ENTITY_MATCH = [&](const SHSceneNode* node) { return node->GetEntityID() == childID; }; - - const auto CHILD_ITER = std::ranges::find_if(children.begin(), children.end(),ENTITY_MATCH); - if (CHILD_ITER == children.end()) - { - SHLOG_WARNING("Entity {} is not a child of Entity {}! Unable to retrieve child node!", childID, entityID) - return nullptr; - } - - return *CHILD_ITER; - } - const SHSceneNode* SHSceneGraph::GetRoot() const noexcept { if (root != nullptr) @@ -313,41 +211,7 @@ namespace SHADE /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHSceneNode::SetParent(SHSceneNode* parentNode) noexcept - { - if (parentNode == nullptr) - { - SHLOG_WARNING("Removing Entity {}'s parent", entityID) - - if (parent) - parent->RemoveChild(this); - - return; - } - - // Handle self assignment - if (parent && parentNode->entityID == parent->entityID) - return; - - if (parent) - parent->RemoveChild(this); - - parent = parentNode; - // Update parent's children - parent->AddChild(this); - } - - void SHSceneNode::SetActive(bool newActiveState) noexcept - { - active = newActiveState; - - for (auto* child : children) - { - SetActive(newActiveState); - } - } - - void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* parent) const noexcept + void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* newParent) noexcept { //////////////////////////////////////// // Error Handling @@ -369,18 +233,33 @@ namespace SHADE { .node = NODE_ITER->second , .oldParent = NODE_ITER->second->GetParent() - , .newParent = parent ? parent : root + , .newParent = newParent ? newParent : root }; - if (parent == nullptr) - parent = root; + if (newParent == nullptr) + newParent = root; - NODE_ITER->second->SetParent(parent); + ChangeParent(NODE_ITER->second, newParent); SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); } - void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept + void SHSceneGraph::SetParent(SHSceneNode* node, SHSceneNode* newParent) noexcept + { + const SHSceneGraphChangeParentEvent EVENT_DATA + { + .node = node + , .oldParent = node->parent + , .newParent = newParent ? newParent : root + }; + + if (newParent == nullptr) + newParent = root; + + ChangeParent(node, newParent); + } + + void SHSceneGraph::SetParent(EntityID entityID, EntityID newParent) noexcept { //////////////////////////////////////// // Error Handling @@ -390,9 +269,9 @@ namespace SHADE return; } - if (!SHEntityManager::IsValidEID(parent)) + if (!SHEntityManager::IsValidEID(newParent)) { - SHLOG_ERROR("Parent Entity {} is invalid! Unable to set Entity {}'s parent!", parent, entityID) + SHLOG_ERROR("Parent Entity {} is invalid! Unable to set Entity {}'s parent!", newParent, entityID) return; } @@ -403,10 +282,10 @@ namespace SHADE return; } - auto PARENT_ITER = entityNodeMap.find(parent); + auto PARENT_ITER = entityNodeMap.find(newParent); if (PARENT_ITER == entityNodeMap.end()) { - SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to parent to Entity {}", parent, entityID) + SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to parent to Entity {}", newParent, entityID) return; } //////////////////////////////////////// @@ -419,92 +298,46 @@ namespace SHADE }; SHSceneNode* currentNode = NODE_ITER->second; - currentNode->SetParent(PARENT_ITER->second); + ChangeParent(currentNode, PARENT_ITER->second); SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); } - /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHSceneNode::AddChild(SHSceneNode* newChild) noexcept + void SHSceneGraph::SetParent(SHSceneNode* node, EntityID newParent) noexcept { //////////////////////////////////////// // Error Handling - if (newChild == nullptr) + + if (!SHEntityManager::IsValidEID(newParent)) { - SHLOG_WARNING("Attempting to add a non-existent child to an entity!") + SHLOG_ERROR("Parent Entity {} is invalid! Unable to set Entity {}'s parent!", newParent, node->entityID) + return; + } + + auto PARENT_ITER = entityNodeMap.find(newParent); + if (PARENT_ITER == entityNodeMap.end()) + { + SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to parent to Entity {}", newParent, node->entityID) return; } //////////////////////////////////////// - if (newChild->parent) - newChild->parent->RemoveChild(newChild); - - newChild->parent = this; - children.emplace_back(newChild); + const SHSceneGraphChangeParentEvent EVENT_DATA + { + .node = node + , .oldParent = node->parent + , .newParent = PARENT_ITER->second + }; + + ChangeParent(node, PARENT_ITER->second); + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); } - bool SHSceneNode::RemoveChild(EntityID childID) noexcept - { - //////////////////////////////////////// - // Error Handling - if (!SHEntityManager::IsValidEID(childID)) - { - SHLOG_ERROR("Entity {} is invalid!", childID) - return false; - } - //////////////////////////////////////// - auto childIter = std::find_if(children.begin(), children.end(), [&](SHSceneNode* node) - { - return node->GetEntityID() == childID; - }); - - if (childIter == children.end()) - { - SHLOG_WARNING("Unable to remove Entity {} from Entity {} since it is not it's child!", childID, entityID) - return false; - } - - (*childIter)->parent = nullptr; - childIter = children.erase(childIter); - - return true; - } - - bool SHSceneNode::RemoveChild(SHSceneNode* childToRemove) noexcept - { - //////////////////////////////////////// - // Error Handling - if (childToRemove == nullptr) - { - SHLOG_WARNING("Attempting to remove non-existent child from Entity {}", entityID) - return false; - } - //////////////////////////////////////// - - auto childIter = std::find(children.begin(), children.end(), childToRemove); - if (childIter == children.end()) - { - SHLOG_WARNING("Unable to remove Entity {} from Entity {} since it is not it's child!", childToRemove->entityID, entityID) - return false; - } - - childIter = children.erase(childIter); - childToRemove->parent = nullptr; - - return true; - } - - void SHSceneNode::RemoveAllChildren() noexcept - { - for (const auto child : children) - child->parent = nullptr; - - children.clear(); - } + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ SHSceneNode* SHSceneGraph::AddNode(EntityID entityID, SHSceneNode* parent) { @@ -528,13 +361,12 @@ namespace SHADE if (parent == nullptr) { // Specific handling for root to avoid a warning when removing a non-existent child - parent = root; newNode->parent = root; root->children.emplace_back(newNode); } else { - newNode->SetParent(parent); + ChangeParent(newNode, parent); } return newNode; @@ -557,9 +389,8 @@ namespace SHADE // Remove reference of current node from parent SHSceneNode* currentNode = NODE_ITER->second; - SHSceneNode* parent = currentNode->GetParent(); - if (parent != nullptr) - parent->RemoveChild(currentNode); + if (currentNode->parent != nullptr) + RemoveChild(currentNode->parent, currentNode); ReleaseNode(currentNode); return true; @@ -568,9 +399,8 @@ namespace SHADE bool SHSceneGraph::RemoveNode(SHSceneNode* nodeToRemove) noexcept { // Remove reference of current node from parent - SHSceneNode* parent = nodeToRemove->GetParent(); - if (parent != nullptr) - parent->RemoveChild(nodeToRemove); + if (nodeToRemove->parent != nullptr) + RemoveChild(nodeToRemove->parent, nodeToRemove); ReleaseNode(nodeToRemove); return true; @@ -594,11 +424,6 @@ namespace SHADE SHSceneNode* SHSceneGraph::AllocateNode(EntityID entityID) { SHSceneNode* newNode = new SHSceneNode{entityID}; - - //#ifdef _DEBUG - // SHLOG_INFO("Allocated a new Scene Node for Entity {}!", entityID) - //#endif - entityNodeMap.emplace(entityID, newNode); return newNode; } @@ -608,19 +433,65 @@ namespace SHADE SHASSERT(node != nullptr, "Attempting to release Invalid Node!") // Remove parent's reference to this node if there is a parent - if (node->GetParent() != nullptr) - node->GetParent()->RemoveChild(node); + if (node->parent != nullptr) + RemoveChild(node->parent, node); // Remove child's references to this node. Children end up as floating nodes. for (auto* child : node->GetChildren()) { - child->SetParent(nullptr); + ChangeParent(child, nullptr); } entityNodeMap.erase(node->GetEntityID()); delete node; } + void SHSceneGraph::ChangeParent(SHSceneNode* node, SHSceneNode* newParent) + { + // Handle self assignment + if (node->parent != nullptr && newParent != nullptr && node->parent->entityID == newParent->entityID) + return; + + // Remove child + if (node->parent) + RemoveChild(node->parent, node); + + if (newParent == nullptr) + { + SHLOG_WARNING("Removing Entity {}'s parent", node->entityID) + return; + } + + node->parent = newParent; + // Update parent's children + AddChild(newParent, node); + } + + void SHSceneGraph::AddChild(SHSceneNode* node, SHSceneNode* newChild) + { + SHASSERT(node != nullptr, "Attempting to modify a non-existent scene node!") + SHASSERT(newChild != nullptr, "Attempting to add a non-existent child to a SceneNode!") + + if (newChild->parent) + RemoveChild(newChild->parent, newChild); + + newChild->parent = node; + node->children.emplace_back(newChild); + } + + void SHSceneGraph::RemoveChild(SHSceneNode* node, SHSceneNode* childToRemove) + { + SHASSERT(node != nullptr, "Attempting to modify a non-existent scene node!") + SHASSERT(childToRemove != nullptr, "Attempting to remove a non-existent child from a SceneNode!") + + auto childIter = std::find(node->children.begin(), node->children.end(), childToRemove); + if (childIter == node->children.end()) + return; + + childIter = node->children.erase(childIter); + childToRemove->parent = nullptr; + } + void SHSceneGraph::TraverseAndInvokeFunction(const SHSceneNode* node, const UnaryFunction& function) { for (auto* child : node->children) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 45ab48e5..99de9c44 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -1,7 +1,7 @@ /**************************************************************************************** * \file SHSceneGraph.h * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for a Scene Graph & Scene Nodes. + * \brief Interface for a Scene Graph. * * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * disclosure of this file or its contents without the prior written consent @@ -15,81 +15,14 @@ // Project Headers #include "ECS_Base/Entity/SHEntity.h" #include "SH_API.h" +#include "SHSceneNode.h" namespace SHADE { - /*-----------------------------------------------------------------------------------*/ - /* Forward Declarations */ - /*-----------------------------------------------------------------------------------*/ - - class SHSceneGraph; - /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHSceneNode - { - private: - /*---------------------------------------------------------------------------------*/ - /* Friends */ - /*---------------------------------------------------------------------------------*/ - - friend class SHSceneGraph; - - public: - /*---------------------------------------------------------------------------------*/ - /* Constructors & Destructor */ - /*---------------------------------------------------------------------------------*/ - - ~SHSceneNode () = default; - - SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept; - SHSceneNode (const SHSceneNode& rhs) noexcept; - SHSceneNode (SHSceneNode&& rhs) noexcept; - SHSceneNode& operator= (const SHSceneNode& rhs) noexcept; - SHSceneNode& operator= (SHSceneNode&& rhs) noexcept; - - /*---------------------------------------------------------------------------------*/ - /* 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]] SHSceneNode* GetChild (EntityID childID) const noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Setter Functions */ - /*---------------------------------------------------------------------------------*/ - - void SetParent (SHSceneNode* parentNode) noexcept; - void SetActive (bool newActiveState) noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - void AddChild (SHSceneNode* newChild) noexcept; - - bool RemoveChild (EntityID childID) noexcept; - bool RemoveChild (SHSceneNode* childToRemove) noexcept; - - void RemoveAllChildren () noexcept; - - private: - /*---------------------------------------------------------------------------------*/ - /* Data Members */ - /*---------------------------------------------------------------------------------*/ - - bool active; - EntityID entityID; - SHSceneNode* parent; - std::vector children; - }; - class SH_API SHSceneGraph { public: @@ -130,19 +63,22 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetParent (EntityID entityID, SHSceneNode* parent) const noexcept; - void SetParent (EntityID entityID, EntityID parent) const noexcept; + void SetParent (EntityID entityID, SHSceneNode* newParent) noexcept; + void SetParent (SHSceneNode* node, SHSceneNode* newParent) noexcept; + + void SetParent (EntityID entityID, EntityID newParent) noexcept; + void SetParent (SHSceneNode* node, EntityID newParent) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr); - bool RemoveNode (EntityID entityID) noexcept; - bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; - void Reset () noexcept; + bool RemoveNode (EntityID entityID) noexcept; + bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; + void Reset () noexcept; - void Traverse (const UnaryFunction& function) const; + void Traverse (const UnaryFunction& function) const; private: /*---------------------------------------------------------------------------------*/ @@ -156,9 +92,14 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - SHSceneNode* AllocateNode (EntityID entityID); - void ReleaseNode (SHSceneNode* node) noexcept; - static void TraverseAndInvokeFunction (const SHSceneNode* node, const UnaryFunction& function); + SHSceneNode* AllocateNode (EntityID entityID); + void ReleaseNode (SHSceneNode* node) noexcept; + + void ChangeParent (SHSceneNode* node, SHSceneNode* newParent); + void AddChild (SHSceneNode* node, SHSceneNode* newChild); + void RemoveChild (SHSceneNode* node, SHSceneNode* childToRemove); + + static void TraverseAndInvokeFunction (const SHSceneNode* node, const UnaryFunction& function); }; /*-----------------------------------------------------------------------------------*/ @@ -172,4 +113,16 @@ namespace SHADE SHSceneNode* newParent; }; + struct SHSceneGraphAddChildEvent + { + SHSceneNode* parent; + SHSceneNode* addedChild; + }; + + struct SHSceneGraphRemoveChildEvent + { + SHSceneNode* parent; + SHSceneNode* removedChild; + }; + } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Scene/SHSceneNode.cpp b/SHADE_Engine/src/Scene/SHSceneNode.cpp new file mode 100644 index 00000000..b619d464 --- /dev/null +++ b/SHADE_Engine/src/Scene/SHSceneNode.cpp @@ -0,0 +1,143 @@ +/**************************************************************************************** + * \file SHSceneNode.c[[ + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Scene Node. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#include + +// Primary Header +#include "SHSceneNode.h" + +// Project Headers +#include "ECS_Base/Managers/SHEntityManager.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHSceneNode::SHSceneNode(EntityID eid, SHSceneNode* parent) noexcept + : active { true } + , entityID { eid } + , parent { parent } + {} + + + SHSceneNode::SHSceneNode(const SHSceneNode& rhs) noexcept + : active { rhs.active } + , 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 } + { + std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children)); + } + + SHSceneNode& SHSceneNode::operator=(const SHSceneNode& rhs) noexcept + { + if (this == &rhs) + return *this; + + active = rhs.active; + entityID = rhs.entityID; + parent = rhs.parent; + + children.clear(); + std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children)); + + return *this; + } + + SHSceneNode& SHSceneNode::operator=(SHSceneNode&& rhs) noexcept + { + active = rhs.active; + entityID = rhs.entityID; + parent = rhs.parent; + + children.clear(); + std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children)); + + return *this; + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + bool SHSceneNode::IsActive() const noexcept + { + return active; + } + + EntityID SHSceneNode::GetEntityID() const noexcept + { + return entityID; + } + + SHSceneNode* SHSceneNode::GetParent() const noexcept + { + return parent; + } + + const std::vector& SHSceneNode::GetChildren() const noexcept + { + return children; + } + + SHSceneNode* SHSceneNode::GetChild(EntityID childID) const noexcept + { + //////////////////////////////////////// + // Error handling + if (!SHEntityManager::IsValidEID(childID)) + { + SHLOG_ERROR("Child Entity {} is invalid! Unable to get child from Entity {}", childID, entityID) + return nullptr; + } + + if (children.empty()) + { + SHLOG_WARNING("Entity {} has no children!", entityID) + return nullptr; + } + //////////////////////////////////////// + + // Find child + const auto ENTITY_MATCH = [&](const SHSceneNode* node) { return node->GetEntityID() == childID; }; + + const auto CHILD_ITER = std::ranges::find_if(children.begin(), children.end(),ENTITY_MATCH); + if (CHILD_ITER == children.end()) + { + SHLOG_WARNING("Entity {} is not a child of Entity {}! Unable to retrieve child node!", childID, entityID) + return nullptr; + } + + return *CHILD_ITER; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHSceneNode::SetActive(bool newActiveState) noexcept + { + active = newActiveState; + + for (auto* child : children) + { + SetActive(newActiveState); + } + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Scene/SHSceneNode.h b/SHADE_Engine/src/Scene/SHSceneNode.h new file mode 100644 index 00000000..87bd8d0b --- /dev/null +++ b/SHADE_Engine/src/Scene/SHSceneNode.h @@ -0,0 +1,82 @@ +/**************************************************************************************** + * \file SHSceneNode.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Scene Node. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +#include + +// Project Headers +#include "ECS_Base/Entity/SHEntity.h" +#include "SH_API.h" +#include "SHSceneGraph.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + + class SHSceneGraph; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + class SH_API SHSceneNode + { + private: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHSceneGraph; + + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + ~SHSceneNode () = default; + + SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept; + SHSceneNode (const SHSceneNode& rhs) noexcept; + SHSceneNode (SHSceneNode&& rhs) noexcept; + SHSceneNode& operator= (const SHSceneNode& rhs) noexcept; + SHSceneNode& operator= (SHSceneNode&& rhs) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* 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]] SHSceneNode* GetChild (EntityID childID) const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetActive (bool newActiveState) noexcept; + + private: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + bool active; + EntityID entityID; + SHSceneNode* parent; + std::vector children; + }; +} // namespace SHADE + diff --git a/SHADE_Managed/src/Engine/GameObject.cxx b/SHADE_Managed/src/Engine/GameObject.cxx index 9f15c6c9..bc17be8b 100644 --- a/SHADE_Managed/src/Engine/GameObject.cxx +++ b/SHADE_Managed/src/Engine/GameObject.cxx @@ -105,7 +105,7 @@ namespace SHADE { if (!valid) throw gcnew System::NullReferenceException(); - const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); + auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); if (newParent == nullptr) SCENE_GRAPH.SetParent(entity, nullptr); From ac217ffe973910baba4bf958bc87406030b834b3 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 10 Nov 2022 09:06:38 +0800 Subject: [PATCH 02/13] Added Add and Remove Child Events to SceneGraph --- SHADE_Engine/src/Events/SHEventDefines.h | 12 +++--- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 18 ++++++++- SHADE_Engine/src/Scene/SHSceneGraph.h | 24 +----------- SHADE_Engine/src/Scene/SHSceneGraphEvents.h | 41 +++++++++++++++++++++ 4 files changed, 66 insertions(+), 29 deletions(-) create mode 100644 SHADE_Engine/src/Scene/SHSceneGraphEvents.h diff --git a/SHADE_Engine/src/Events/SHEventDefines.h b/SHADE_Engine/src/Events/SHEventDefines.h index d649fabf..d7bbf5f0 100644 --- a/SHADE_Engine/src/Events/SHEventDefines.h +++ b/SHADE_Engine/src/Events/SHEventDefines.h @@ -11,9 +11,11 @@ constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 }; constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 }; constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 }; constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 }; -constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 6 }; -constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 7 }; -constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 8 }; -constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 9 }; -constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 10 }; +constexpr SHEventIdentifier SH_SCENEGRAPH_ADD_CHILD_EVENT { 6 }; +constexpr SHEventIdentifier SH_SCENEGRAPH_REMOVE_CHILD_EVENT { 7 }; +constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 8 }; +constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 9 }; +constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 10 }; +constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 11 }; +constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 12 }; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 900d482a..ff479eec 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -1,7 +1,7 @@ /**************************************************************************************** * \file SHSceneGraph.cpp * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for a Scene Graph & Scene Nodes. + * \brief Implementation for a Scene Graph. * * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * disclosure of this file or its contents without the prior written consent @@ -477,6 +477,14 @@ namespace SHADE newChild->parent = node; node->children.emplace_back(newChild); + + const SHSceneGraphAddChildEvent EVENT_DATA + { + .parent = node + , .childAdded = newChild + }; + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_ADD_CHILD_EVENT); } void SHSceneGraph::RemoveChild(SHSceneNode* node, SHSceneNode* childToRemove) @@ -490,6 +498,14 @@ namespace SHADE childIter = node->children.erase(childIter); childToRemove->parent = nullptr; + + const SHSceneGraphRemoveChildEvent EVENT_DATA + { + .parent = node + , .childRemoved = childToRemove + }; + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_REMOVE_CHILD_EVENT); } void SHSceneGraph::TraverseAndInvokeFunction(const SHSceneNode* node, const UnaryFunction& function) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 99de9c44..1d448b37 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -16,6 +16,7 @@ #include "ECS_Base/Entity/SHEntity.h" #include "SH_API.h" #include "SHSceneNode.h" +#include "SHSceneGraphEvents.h" namespace SHADE { @@ -102,27 +103,4 @@ namespace SHADE static void TraverseAndInvokeFunction (const SHSceneNode* node, const UnaryFunction& function); }; - /*-----------------------------------------------------------------------------------*/ - /* Event Data Definitions */ - /*-----------------------------------------------------------------------------------*/ - - struct SHSceneGraphChangeParentEvent - { - SHSceneNode* node; - SHSceneNode* oldParent; - SHSceneNode* newParent; - }; - - struct SHSceneGraphAddChildEvent - { - SHSceneNode* parent; - SHSceneNode* addedChild; - }; - - struct SHSceneGraphRemoveChildEvent - { - SHSceneNode* parent; - SHSceneNode* removedChild; - }; - } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Scene/SHSceneGraphEvents.h b/SHADE_Engine/src/Scene/SHSceneGraphEvents.h new file mode 100644 index 00000000..ccdf06be --- /dev/null +++ b/SHADE_Engine/src/Scene/SHSceneGraphEvents.h @@ -0,0 +1,41 @@ +/**************************************************************************************** + * \file SHSceneGraphEvents.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for Scene Graph Events. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +// Project Headers +#include "SHSceneNode.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Event Data Definitions */ + /*-----------------------------------------------------------------------------------*/ + + struct SHSceneGraphChangeParentEvent + { + SHSceneNode* node; + SHSceneNode* oldParent; + SHSceneNode* newParent; + }; + + struct SHSceneGraphAddChildEvent + { + SHSceneNode* parent; + SHSceneNode* childAdded; + }; + + struct SHSceneGraphRemoveChildEvent + { + SHSceneNode* parent; + SHSceneNode* childRemoved; + }; + +} // namespace SHADE \ No newline at end of file From 08b3cbafcd4e2a08fd5701179fce20c700b89704 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 10 Nov 2022 10:20:54 +0800 Subject: [PATCH 03/13] Added IsChildOf method to SceneGraph --- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 147 ++++++++++++++++++++++++ SHADE_Engine/src/Scene/SHSceneGraph.h | 14 ++- 2 files changed, 156 insertions(+), 5 deletions(-) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index ff479eec..e2bd58e2 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -263,6 +263,7 @@ namespace SHADE { //////////////////////////////////////// // Error Handling + if (!SHEntityManager::IsValidEID(entityID)) { SHLOG_ERROR("Entity {} is invalid! Unable to set parent of an invalid entity!", entityID) @@ -374,6 +375,8 @@ namespace SHADE bool SHSceneGraph::RemoveNode(EntityID entityID) noexcept { + //////////////////////////////////////// + // Error Handling if (!SHEntityManager::IsValidEID(entityID)) { SHLOG_ERROR("Entity {} is invalid!", entityID) @@ -386,6 +389,7 @@ namespace SHADE SHLOG_ERROR("Entity {} does not exist in the scene!", entityID) return false; } + //////////////////////////////////////// // Remove reference of current node from parent SHSceneNode* currentNode = NODE_ITER->second; @@ -412,6 +416,149 @@ namespace SHADE ReleaseNode(node); } + bool SHSceneGraph::IsChildOf(EntityID entityID, SHSceneNode* targetNode) noexcept + { + //////////////////////////////////////// + // Error Handling + + if (!SHEntityManager::IsValidEID(entityID)) + { + SHLOG_ERROR("Entity {} is invalid!", entityID) + return false; + } + + auto NODE_ITER = entityNodeMap.find(entityID); + if (NODE_ITER == entityNodeMap.end()) + { + SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", entityID) + return false; + } + + //////////////////////////////////////// + + // Handle self-checks + if (NODE_ITER->second == targetNode) + { + SHLOG_WARNING("Entity {} cannot be a child of itself!", entityID) + return false; + } + + // Search for a matching target until the root + const SHSceneNode* CURRENT_TARGET = NODE_ITER->second->parent; + while (CURRENT_TARGET != root) + { + if (CURRENT_TARGET == targetNode) + return true; + + CURRENT_TARGET = CURRENT_TARGET->parent; + } + + return false; + } + + bool SHSceneGraph::IsChildOf(SHSceneNode* node, SHSceneNode* targetNode) noexcept + { + if (!node || !targetNode) + { + SHLOG_ERROR("Attempting to check for invalid scene nodes!") + return false; + } + + if (node == targetNode) + { + SHLOG_WARNING("Entity {} cannot be a child of itself!", node->entityID) + return false; + } + + const SHSceneNode* CURRENT_TARGET = node->parent; + while (CURRENT_TARGET != root) + { + if (CURRENT_TARGET == targetNode) + return true; + + CURRENT_TARGET = CURRENT_TARGET->parent; + } + + return false; + } + + bool SHSceneGraph::IsChildOf(EntityID entityID, EntityID targetID) noexcept + { + //////////////////////////////////////// + // Error Handling + + if (!SHEntityManager::IsValidEID(entityID)) + { + SHLOG_ERROR("Entity {} is invalid!", entityID) + return false; + } + + if (!SHEntityManager::IsValidEID(targetID)) + { + SHLOG_ERROR("Entity {} is invalid!", targetID) + return false; + } + + auto NODE_ITER = entityNodeMap.find(entityID); + if (NODE_ITER == entityNodeMap.end()) + { + SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", entityID) + return false; + } + + auto TARGET_ITER = entityNodeMap.find(targetID); + if (TARGET_ITER == entityNodeMap.end()) + { + SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", targetID) + return false; + } + + //////////////////////////////////////// + + const SHSceneNode* CURRENT_TARGET = NODE_ITER->second->parent; + while (CURRENT_TARGET != root) + { + if (CURRENT_TARGET == TARGET_ITER->second) + return true; + + CURRENT_TARGET = CURRENT_TARGET->parent; + } + + return false; + } + + bool SHSceneGraph::IsChildOf(SHSceneNode* node, EntityID targetID) noexcept + { + //////////////////////////////////////// + // Error Handling + + if (!SHEntityManager::IsValidEID(targetID)) + { + SHLOG_ERROR("Entity {} is invalid!", targetID) + return false; + } + + auto TARGET_ITER = entityNodeMap.find(targetID); + if (TARGET_ITER == entityNodeMap.end()) + { + SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", targetID) + return false; + } + + //////////////////////////////////////// + + const SHSceneNode* CURRENT_TARGET = node->parent; + while (CURRENT_TARGET != root) + { + if (CURRENT_TARGET == TARGET_ITER->second) + return true; + + CURRENT_TARGET = CURRENT_TARGET->parent; + } + + return false; + } + void SHSceneGraph::Traverse (const UnaryFunction& function) const { TraverseAndInvokeFunction(root, function); diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 1d448b37..494f480e 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -66,7 +66,6 @@ namespace SHADE void SetParent (EntityID entityID, SHSceneNode* newParent) noexcept; void SetParent (SHSceneNode* node, SHSceneNode* newParent) noexcept; - void SetParent (EntityID entityID, EntityID newParent) noexcept; void SetParent (SHSceneNode* node, EntityID newParent) noexcept; @@ -75,11 +74,16 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr); - bool RemoveNode (EntityID entityID) noexcept; - bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; - void Reset () noexcept; + bool RemoveNode (EntityID entityID) noexcept; + bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; + void Reset () noexcept; - void Traverse (const UnaryFunction& function) const; + bool IsChildOf (EntityID entityID, SHSceneNode* targetNode) noexcept; + bool IsChildOf (SHSceneNode* node, SHSceneNode* targetNode) noexcept; + bool IsChildOf (EntityID entityID, EntityID targetID) noexcept; + bool IsChildOf (SHSceneNode* node, EntityID targetID) noexcept; + + void Traverse (const UnaryFunction& function) const; private: /*---------------------------------------------------------------------------------*/ From 578f384808fe1f5fe26fed136cb033e2104e8490 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 10 Nov 2022 10:24:09 +0800 Subject: [PATCH 04/13] Removed redundant overloads to restrict potential bad function calls --- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 105 ------------------------ SHADE_Engine/src/Scene/SHSceneGraph.h | 6 +- 2 files changed, 1 insertion(+), 110 deletions(-) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index e2bd58e2..6240b7bf 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -244,21 +244,6 @@ namespace SHADE SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); } - void SHSceneGraph::SetParent(SHSceneNode* node, SHSceneNode* newParent) noexcept - { - const SHSceneGraphChangeParentEvent EVENT_DATA - { - .node = node - , .oldParent = node->parent - , .newParent = newParent ? newParent : root - }; - - if (newParent == nullptr) - newParent = root; - - ChangeParent(node, newParent); - } - void SHSceneGraph::SetParent(EntityID entityID, EntityID newParent) noexcept { //////////////////////////////////////// @@ -304,38 +289,6 @@ namespace SHADE SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); } - void SHSceneGraph::SetParent(SHSceneNode* node, EntityID newParent) noexcept - { - //////////////////////////////////////// - // Error Handling - - if (!SHEntityManager::IsValidEID(newParent)) - { - SHLOG_ERROR("Parent Entity {} is invalid! Unable to set Entity {}'s parent!", newParent, node->entityID) - return; - } - - auto PARENT_ITER = entityNodeMap.find(newParent); - if (PARENT_ITER == entityNodeMap.end()) - { - SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to parent to Entity {}", newParent, node->entityID) - return; - } - //////////////////////////////////////// - - const SHSceneGraphChangeParentEvent EVENT_DATA - { - .node = node - , .oldParent = node->parent - , .newParent = PARENT_ITER->second - }; - - ChangeParent(node, PARENT_ITER->second); - - SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); - } - - /*-----------------------------------------------------------------------------------*/ /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -456,32 +409,6 @@ namespace SHADE return false; } - bool SHSceneGraph::IsChildOf(SHSceneNode* node, SHSceneNode* targetNode) noexcept - { - if (!node || !targetNode) - { - SHLOG_ERROR("Attempting to check for invalid scene nodes!") - return false; - } - - if (node == targetNode) - { - SHLOG_WARNING("Entity {} cannot be a child of itself!", node->entityID) - return false; - } - - const SHSceneNode* CURRENT_TARGET = node->parent; - while (CURRENT_TARGET != root) - { - if (CURRENT_TARGET == targetNode) - return true; - - CURRENT_TARGET = CURRENT_TARGET->parent; - } - - return false; - } - bool SHSceneGraph::IsChildOf(EntityID entityID, EntityID targetID) noexcept { //////////////////////////////////////// @@ -527,38 +454,6 @@ namespace SHADE return false; } - bool SHSceneGraph::IsChildOf(SHSceneNode* node, EntityID targetID) noexcept - { - //////////////////////////////////////// - // Error Handling - - if (!SHEntityManager::IsValidEID(targetID)) - { - SHLOG_ERROR("Entity {} is invalid!", targetID) - return false; - } - - auto TARGET_ITER = entityNodeMap.find(targetID); - if (TARGET_ITER == entityNodeMap.end()) - { - SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", targetID) - return false; - } - - //////////////////////////////////////// - - const SHSceneNode* CURRENT_TARGET = node->parent; - while (CURRENT_TARGET != root) - { - if (CURRENT_TARGET == TARGET_ITER->second) - return true; - - CURRENT_TARGET = CURRENT_TARGET->parent; - } - - return false; - } - void SHSceneGraph::Traverse (const UnaryFunction& function) const { TraverseAndInvokeFunction(root, function); diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 494f480e..5747be7b 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -65,9 +65,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ void SetParent (EntityID entityID, SHSceneNode* newParent) noexcept; - void SetParent (SHSceneNode* node, SHSceneNode* newParent) noexcept; void SetParent (EntityID entityID, EntityID newParent) noexcept; - void SetParent (SHSceneNode* node, EntityID newParent) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ @@ -79,9 +77,7 @@ namespace SHADE void Reset () noexcept; bool IsChildOf (EntityID entityID, SHSceneNode* targetNode) noexcept; - bool IsChildOf (SHSceneNode* node, SHSceneNode* targetNode) noexcept; - bool IsChildOf (EntityID entityID, EntityID targetID) noexcept; - bool IsChildOf (SHSceneNode* node, EntityID targetID) noexcept; + bool IsChildOf (EntityID entityID, EntityID targetID) noexcept; void Traverse (const UnaryFunction& function) const; From fa0787d349900ee3fb097baf7901c08b1168bbb7 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Thu, 10 Nov 2022 10:33:21 +0800 Subject: [PATCH 05/13] Changed hardcoded paths to use defined asset root folder Shifted scripts and project into folder in assets --- .../Scripts}/AIPrototype.cs | 0 .../Scripts}/CameraControl.cs | 0 {TempScriptsFolder => Assets/Scripts}/CameraFix.cs | 0 {TempScriptsFolder => Assets/Scripts}/Item.cs | 0 .../Scripts}/PhysicsTest.cs | 0 .../Scripts}/PickAndThrow.cs | 0 .../Scripts}/PlayerController.cs | 0 .../Scripts}/PrintWhenActive.cs | 0 .../Scripts}/RaccoonShowcase.cs | 0 .../Scripts}/RaccoonSpin.cs | 0 .../Scripts}/ThirdPersonCamera.cs | 0 SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp | 10 ++++++---- .../EditorWindow/MenuBar/SHEditorMenuBar.cpp | 6 ++++-- SHADE_Engine/src/Editor/SHEditor.cpp | 14 +++++++++----- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 4 +++- 15 files changed, 22 insertions(+), 12 deletions(-) rename {TempScriptsFolder => Assets/Scripts}/AIPrototype.cs (100%) rename {TempScriptsFolder => Assets/Scripts}/CameraControl.cs (100%) rename {TempScriptsFolder => Assets/Scripts}/CameraFix.cs (100%) rename {TempScriptsFolder => Assets/Scripts}/Item.cs (100%) rename {TempScriptsFolder => Assets/Scripts}/PhysicsTest.cs (100%) rename {TempScriptsFolder => Assets/Scripts}/PickAndThrow.cs (100%) rename {TempScriptsFolder => Assets/Scripts}/PlayerController.cs (100%) rename {TempScriptsFolder => Assets/Scripts}/PrintWhenActive.cs (100%) rename {TempScriptsFolder => Assets/Scripts}/RaccoonShowcase.cs (100%) rename {TempScriptsFolder => Assets/Scripts}/RaccoonSpin.cs (100%) rename {TempScriptsFolder => Assets/Scripts}/ThirdPersonCamera.cs (100%) diff --git a/TempScriptsFolder/AIPrototype.cs b/Assets/Scripts/AIPrototype.cs similarity index 100% rename from TempScriptsFolder/AIPrototype.cs rename to Assets/Scripts/AIPrototype.cs diff --git a/TempScriptsFolder/CameraControl.cs b/Assets/Scripts/CameraControl.cs similarity index 100% rename from TempScriptsFolder/CameraControl.cs rename to Assets/Scripts/CameraControl.cs diff --git a/TempScriptsFolder/CameraFix.cs b/Assets/Scripts/CameraFix.cs similarity index 100% rename from TempScriptsFolder/CameraFix.cs rename to Assets/Scripts/CameraFix.cs diff --git a/TempScriptsFolder/Item.cs b/Assets/Scripts/Item.cs similarity index 100% rename from TempScriptsFolder/Item.cs rename to Assets/Scripts/Item.cs diff --git a/TempScriptsFolder/PhysicsTest.cs b/Assets/Scripts/PhysicsTest.cs similarity index 100% rename from TempScriptsFolder/PhysicsTest.cs rename to Assets/Scripts/PhysicsTest.cs diff --git a/TempScriptsFolder/PickAndThrow.cs b/Assets/Scripts/PickAndThrow.cs similarity index 100% rename from TempScriptsFolder/PickAndThrow.cs rename to Assets/Scripts/PickAndThrow.cs diff --git a/TempScriptsFolder/PlayerController.cs b/Assets/Scripts/PlayerController.cs similarity index 100% rename from TempScriptsFolder/PlayerController.cs rename to Assets/Scripts/PlayerController.cs diff --git a/TempScriptsFolder/PrintWhenActive.cs b/Assets/Scripts/PrintWhenActive.cs similarity index 100% rename from TempScriptsFolder/PrintWhenActive.cs rename to Assets/Scripts/PrintWhenActive.cs diff --git a/TempScriptsFolder/RaccoonShowcase.cs b/Assets/Scripts/RaccoonShowcase.cs similarity index 100% rename from TempScriptsFolder/RaccoonShowcase.cs rename to Assets/Scripts/RaccoonShowcase.cs diff --git a/TempScriptsFolder/RaccoonSpin.cs b/Assets/Scripts/RaccoonSpin.cs similarity index 100% rename from TempScriptsFolder/RaccoonSpin.cs rename to Assets/Scripts/RaccoonSpin.cs diff --git a/TempScriptsFolder/ThirdPersonCamera.cs b/Assets/Scripts/ThirdPersonCamera.cs similarity index 100% rename from TempScriptsFolder/ThirdPersonCamera.cs rename to Assets/Scripts/ThirdPersonCamera.cs diff --git a/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp b/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp index c3c7ef03..c913030b 100644 --- a/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp +++ b/SHADE_Engine/src/AudioSystem/SHAudioSystem.cpp @@ -17,6 +17,8 @@ #include #include +const std::string AUDIO_FOLDER_PATH{ std::string(ASSET_ROOT)+ "/Audio/" }; + namespace SHADE { SHAudioSystem::SHAudioSystem() @@ -79,10 +81,10 @@ namespace SHADE //SHResourceManager::LoadAllAudio(system, soundList); - LoadBank("../../Assets/Audio/Master.bank"); - LoadBank("../../Assets/Audio/Master.strings.bank"); - //LoadBank("../../Assets/Audio/Music.bank"); - LoadBank("../../Assets/Audio/footsteps.bank"); + LoadBank((AUDIO_FOLDER_PATH + "Master.bank").data()); + LoadBank((AUDIO_FOLDER_PATH + "Master.strings.bank").data()); + //LoadBank((AUDIO_FOLDER_PATH + "Music.bank").data()); + LoadBank((AUDIO_FOLDER_PATH + "footsteps.bank").data()); //auto clip = CreateAudioClip("event:/Characters/sfx_footsteps_human"); //clip->Play(); diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index c18f0c8c..cfb36cd0 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -24,6 +24,9 @@ #include "Serialization/SHSerialization.h" #include "Serialization/Configurations/SHConfigurationManager.h" + +const std::string LAYOUT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts" }; + namespace SHADE { constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | @@ -43,8 +46,7 @@ namespace SHADE void SHEditorMenuBar::Init() { SHEditorWindow::Init(); - constexpr std::string_view path = "../../Assets/Editor/Layouts"; - for(auto const& entry : std::filesystem::directory_iterator(path)) + for(auto const& entry : std::filesystem::directory_iterator(LAYOUT_FOLDER_PATH)) { layoutPaths.push_back(entry.path()); } diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index 19d147e6..c4ad3459 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -65,6 +65,10 @@ RTTR_REGISTRATION ); } +const std::string USER_LAYOUT_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts/UserLayout.ini" }; +const std::string DEFAULT_LAYOUT_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts/Default.ini" }; +const std::string FONT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Fonts/"}; + namespace SHADE { @@ -106,7 +110,7 @@ namespace SHADE io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking - io->IniFilename = "../../Assets/Editor/Layouts/UserLayout.ini"; + io->IniFilename = USER_LAYOUT_PATH.data(); io->ConfigWindowsMoveFromTitleBarOnly = true; InitLayout(); @@ -236,20 +240,20 @@ namespace SHADE { if(!std::filesystem::exists(io->IniFilename)) { - std::filesystem::copy_file("../../Assets/Editor/Layouts/Default.ini", io->IniFilename); + std::filesystem::copy_file(DEFAULT_LAYOUT_PATH.data(), io->IniFilename); } //eventually load preferred layout here } void SHEditor::InitFonts() noexcept { - ImFont* mainFont = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/Segoe UI.ttf", 20.f);//TODO: Change to config based assets path + ImFont* mainFont = io->Fonts->AddFontFromFileTTF(std::string(FONT_FOLDER_PATH + "Segoe UI.ttf").data(), 20.f);//TODO: Change to config based assets path ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.GlyphOffset.y = 5.f; constexpr ImWchar icon_ranges_fa[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; - ImFont* UIFontFA = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/fa-solid-900.ttf", 20.f, &icons_config, icon_ranges_fa); //TODO: Change to config based assets path + ImFont* UIFontFA = io->Fonts->AddFontFromFileTTF(std::string(FONT_FOLDER_PATH + "fa-solid-900.ttf").data(), 20.f, &icons_config, icon_ranges_fa); //TODO: Change to config based assets path constexpr ImWchar icon_ranges_md[] = { ICON_MIN_MD, ICON_MAX_16_MD, 0 }; - ImFont* UIFontMD = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/MaterialIcons-Regular.ttf", 20.f, &icons_config, icon_ranges_md); //TODO: Change to config based assets path + ImFont* UIFontMD = io->Fonts->AddFontFromFileTTF(std::string(FONT_FOLDER_PATH + "MaterialIcons-Regular.ttf").data(), 20.f, &icons_config, icon_ranges_md); //TODO: Change to config based assets path io->Fonts->Build(); } diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 827f45a2..4f3fbce6 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -26,13 +26,15 @@ of DigiPen Institute of Technology is prohibited. #include "Events/SHEventManager.hpp" #include "Physics/SHPhysicsSystem.h" +#include "Assets/SHAssetMacros.h" + namespace SHADE { /*-----------------------------------------------------------------------------------*/ /* Static Definitions */ /*----------------------------------------------------------------------------------*/ const std::string SHScriptEngine::DEFAULT_CSHARP_NAMESPACE = std::string("SHADE"); - const std::string SHScriptEngine::CSPROJ_DIR = "..\\..\\TempScriptsFolder"; + const std::string SHScriptEngine::CSPROJ_DIR = std::string(ASSET_ROOT) + "/Scripts"; const std::string SHScriptEngine::CSPROJ_PATH = std::string(CSPROJ_DIR) + "\\SHADE_Scripting.csproj"; /*-----------------------------------------------------------------------------------*/ From 35bcdc5239ca3cd86ea697504f98c3355d122a9e Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Thu, 10 Nov 2022 11:14:40 +0800 Subject: [PATCH 06/13] Missed out path for config --- .../src/Serialization/Configurations/SHConfigurationManager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SHADE_Engine/src/Serialization/Configurations/SHConfigurationManager.h b/SHADE_Engine/src/Serialization/Configurations/SHConfigurationManager.h index abf679ca..767b8c2b 100644 --- a/SHADE_Engine/src/Serialization/Configurations/SHConfigurationManager.h +++ b/SHADE_Engine/src/Serialization/Configurations/SHConfigurationManager.h @@ -25,8 +25,8 @@ namespace SHADE class SH_API SHConfigurationManager { public: - static constexpr std::string_view applicationConfigPath{"../../Assets/Application.SHConfig"}; - static constexpr std::string_view editorConfigPath{"../../Assets/Editor/Editor.SHConfig"}; + static inline std::string applicationConfigPath{ std::string(ASSET_ROOT) + "/Application.SHConfig"}; + static inline std::string editorConfigPath{ std::string(ASSET_ROOT) + "/Editor/Editor.SHConfig"}; static void SaveApplicationConfig(); static SHApplicationConfig& LoadApplicationConfig(WindowData* wndData = nullptr); From 0e5609995fd5f39ec956ec149649b27995f762ed Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Thu, 10 Nov 2022 16:44:16 +0800 Subject: [PATCH 07/13] Added data member to signal whether asset file can be compiled Properly linked meta file to file in directory Fixed extension to type conversion bug --- SHADE_Engine/src/Assets/SHAssetMacros.h | 9 +++--- SHADE_Engine/src/Assets/SHAssetManager.cpp | 8 +++-- SHADE_Engine/src/Assets/SHAssetManager.h | 2 +- SHADE_Engine/src/Filesystem/SHFileSystem.cpp | 31 ++++++++++++++++---- SHADE_Engine/src/Filesystem/SHFileSystem.h | 2 +- SHADE_Engine/src/Filesystem/SHFolder.h | 1 + 6 files changed, 38 insertions(+), 15 deletions(-) diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h index 92c4b69e..e0551262 100644 --- a/SHADE_Engine/src/Assets/SHAssetMacros.h +++ b/SHADE_Engine/src/Assets/SHAssetMacros.h @@ -51,6 +51,7 @@ enum class AssetType : AssetTypeMeta SCENE, PREFAB, MATERIAL, + SCRIPT, MESH, MAX_COUNT }; @@ -91,12 +92,12 @@ constexpr std::string_view EXTENSIONS[] = { AUDIO_EXTENSION, SHADER_EXTENSION, SHADER_BUILT_IN_EXTENSION, - MATERIAL_EXTENSION, - TEXTURE_EXTENSION, + TEXTURE_EXTENSION, MODEL_EXTENSION, - SCRIPT_EXTENSION, - SCENE_EXTENSION, + SCENE_EXTENSION, PREFAB_EXTENSION, + MATERIAL_EXTENSION, + SCRIPT_EXTENSION, AUDIO_WAV_EXTENSION, }; diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index 3fd71a8e..dbe9dd27 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -338,7 +338,7 @@ namespace SHADE return result; } - void SHAssetManager::CompileAsset(AssetPath const& path) noexcept + void SHAssetManager::CompileAsset(AssetPath const& path, bool genMeta) noexcept { if (!std::filesystem::exists(path)) { @@ -360,10 +360,12 @@ namespace SHADE std::string modelPath = path.string().substr(0, path.string().find_last_of('.')); modelPath += MODEL_EXTENSION; newPath = modelPath; - - GenerateNewMeta(newPath); } + if (genMeta) + { + GenerateNewMeta(newPath); + } } FolderPointer SHAssetManager::GetRootFolder() noexcept diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index ba10d84f..7fd7d039 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -87,7 +87,7 @@ namespace SHADE static std::vector GetAllDataOfType(AssetType type) noexcept; static std::vector GetAllRecordOfType(AssetType type) noexcept; - static void CompileAsset(AssetPath const& path) noexcept; + static void CompileAsset(AssetPath const& path, bool genMeta) noexcept; static FolderPointer GetRootFolder() noexcept; diff --git a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp index 4c0971e6..fe9b67f5 100644 --- a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp +++ b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp @@ -24,7 +24,20 @@ namespace SHADE return true; } - void SHFileSystem::BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map& assetCollection) noexcept + bool SHFileSystem::IsCompilable(std::string ext) noexcept + { + for (auto const& external : EXTERNALS) + { + if (ext == external) + { + return true; + } + } + + return false; + } + + void SHFileSystem::BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map& assetCollection) noexcept { std::queue folderQueue; root = new SHFolder("root"); @@ -38,9 +51,10 @@ namespace SHADE std::vector assets; - for (auto const& dirEntry : std::filesystem::directory_iterator(folder->path)) + for (auto& dirEntry : std::filesystem::directory_iterator(folder->path)) { - auto const& path = dirEntry.path(); + auto path = dirEntry.path(); + path.make_preferred(); if (!dirEntry.is_directory()) { if (path.extension().string() == META_EXTENSION) @@ -55,7 +69,8 @@ namespace SHADE path.stem().string(), path.string(), path.extension().string(), - nullptr + nullptr, + IsCompilable(path.extension().string()) ); } continue; @@ -72,8 +87,12 @@ namespace SHADE { if (file.name == asset.name) { - file.assetMeta = &assetCollection[asset.id]; - break; + AssetPath path{ file.path }; + if (SHAssetMetaHandler::GetTypeFromExtension(path.extension().string()) == asset.type) + { + file.assetMeta = &assetCollection[asset.id]; + break; + } } } } diff --git a/SHADE_Engine/src/Filesystem/SHFileSystem.h b/SHADE_Engine/src/Filesystem/SHFileSystem.h index 956d3916..3f2e1c5b 100644 --- a/SHADE_Engine/src/Filesystem/SHFileSystem.h +++ b/SHADE_Engine/src/Filesystem/SHFileSystem.h @@ -23,6 +23,6 @@ namespace SHADE private: static bool DeleteFolder(FolderPointer location) noexcept; - + static bool IsCompilable(std::string ext) noexcept; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Filesystem/SHFolder.h b/SHADE_Engine/src/Filesystem/SHFolder.h index 54e95033..5c702b51 100644 --- a/SHADE_Engine/src/Filesystem/SHFolder.h +++ b/SHADE_Engine/src/Filesystem/SHFolder.h @@ -33,6 +33,7 @@ namespace SHADE FilePath path; FileExt ext; SHAsset const* assetMeta; + bool compilable; }; class SHFolder From 03f9c593b6637c807071c0d3b685c9d7891cbbab Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Thu, 10 Nov 2022 17:09:55 +0800 Subject: [PATCH 08/13] Function to call to refresh asset directory --- SHADE_Engine/src/Assets/SHAssetManager.cpp | 7 +++++ SHADE_Engine/src/Assets/SHAssetManager.h | 1 + SHADE_Engine/src/Filesystem/SHFileSystem.cpp | 32 ++++++++++++++++---- SHADE_Engine/src/Filesystem/SHFileSystem.h | 2 +- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index dbe9dd27..f4727417 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -373,6 +373,13 @@ namespace SHADE return folderRoot; } + void SHAssetManager::RefreshDirectory() noexcept + { + SHFileSystem::DestroyDirectory(folderRoot); + assetCollection.clear(); + BuildAssetCollection(); + } + bool SHAssetManager::IsRecognised(char const* ext) noexcept { for (auto const& e : EXTENSIONS) diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index 7fd7d039..a891ec23 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -90,6 +90,7 @@ namespace SHADE static void CompileAsset(AssetPath const& path, bool genMeta) noexcept; static FolderPointer GetRootFolder() noexcept; + static void RefreshDirectory() noexcept; private: diff --git a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp index fe9b67f5..c4bcc5dc 100644 --- a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp +++ b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp @@ -12,6 +12,7 @@ #include "SHFileSystem.h" #include #include +#include #include "Assets/SHAssetMetaHandler.h" @@ -39,15 +40,15 @@ namespace SHADE void SHFileSystem::BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map& assetCollection) noexcept { - std::queue folderQueue; + std::stack folderStack; root = new SHFolder("root"); root->path = path; - folderQueue.push(root); + folderStack.push(root); - while (!folderQueue.empty()) + while (!folderStack.empty()) { - auto const folder = folderQueue.front(); - folderQueue.pop(); + auto const folder = folderStack.top(); + folderStack.pop(); std::vector assets; @@ -77,7 +78,7 @@ namespace SHADE } auto newFolder{ folder->CreateSubFolderHere(path.stem().string()) }; - folderQueue.push(newFolder); + folderStack.push(newFolder); } for (auto const& asset : assets) @@ -98,4 +99,23 @@ namespace SHADE } } } + + void SHFileSystem::DestroyDirectory(FolderPointer root) noexcept + { + std::stack folderStack; + folderStack.push(root); + + while(!folderStack.empty()) + { + auto const folder = folderStack.top(); + folderStack.pop(); + + for (auto const& ptr : folder->subFolders) + { + folderStack.push(ptr); + } + + delete folder; + } + } } diff --git a/SHADE_Engine/src/Filesystem/SHFileSystem.h b/SHADE_Engine/src/Filesystem/SHFileSystem.h index 3f2e1c5b..87d13f42 100644 --- a/SHADE_Engine/src/Filesystem/SHFileSystem.h +++ b/SHADE_Engine/src/Filesystem/SHFileSystem.h @@ -20,7 +20,7 @@ namespace SHADE { public: static void BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map& assetCollection) noexcept; - + static void DestroyDirectory(FolderPointer root) noexcept; private: static bool DeleteFolder(FolderPointer location) noexcept; static bool IsCompilable(std::string ext) noexcept; From ed1bc7c62d31a62980adc029f96c0ecbe605d80d Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Thu, 10 Nov 2022 17:34:33 +0800 Subject: [PATCH 09/13] Changed scripting project relative path to managed and csharp dlls --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 4f3fbce6..dc779334 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -264,12 +264,12 @@ namespace SHADE \n\ \n\ \n\ - ..\\bin\\Debug\\SHADE_Managed.dll\n\ - ..\\bin\\Release\\SHADE_Managed.dll\n\ + ..\\..\\bin\\Debug\\SHADE_Managed.dll\n\ + ..\\..\\bin\\Release\\SHADE_Managed.dll\n\ \n\ \n\ - ..\\bin\\Debug\\SHADE_CSharp.dll\n\ - ..\\bin\\Release\\SHADE_CSharp.dll\n\ + ..\\..\\bin\\Debug\\SHADE_CSharp.dll\n\ + ..\\..\\bin\\Release\\SHADE_CSharp.dll\n\ \n\ \n\ "; From c95a6a2492da4e01555c23ed52441c4c33fc29e5 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Thu, 10 Nov 2022 17:37:59 +0800 Subject: [PATCH 10/13] Added open modes for ofstream when building csharp project --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index dc779334..276eeb24 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -275,7 +275,7 @@ namespace SHADE "; // Attempt to create the file - std::ofstream file(path); + std::ofstream file(path, std::ios::out | std::ios::trunc); if (!file.is_open()) throw std::runtime_error("Unable to create CsProj file!"); From 2fdff77420bade71a1e8bfa3bf03d9af68722ec7 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Thu, 10 Nov 2022 23:01:09 +0800 Subject: [PATCH 11/13] Asset browser is wonky now Refresh asset browser Compile asset --- .../AssetBrowser/SHAssetBrowser.cpp | 73 +++++++++++++++---- .../AssetBrowser/SHAssetBrowser.h | 4 +- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp index 37b8ecd4..9159be7e 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -36,13 +36,27 @@ namespace SHADE DrawCurrentFolder(); } ImGui::End(); + if (queueReset) + { + SHAssetManager::RefreshDirectory(); + rootFolder = SHAssetManager::GetRootFolder(); + queueReset = false; + } + } + + void SHAssetBrowser::Refresh() + { + queueReset = true; } void SHAssetBrowser::DrawMenuBar() { if (ImGui::BeginMenuBar()) { - + if(ImGui::SmallButton("Refresh")) + { + Refresh(); + } ImGui::EndMenuBar(); } } @@ -102,16 +116,14 @@ namespace SHADE } for (auto const& file : files) { - if(file.assetMeta == nullptr) - continue; const float horizontalLineSize = 25.0f; - const ImRect childRect = DrawFile(file.assetMeta); + const ImRect childRect = DrawFile(file); const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f; drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1); vertLineEnd.y = midPoint; } drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1); - if(assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder) + if (assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder) DrawAssetBeingCreated(); ImGui::TreePop(); @@ -148,12 +160,40 @@ namespace SHADE //} } - ImRect SHAssetBrowser::DrawFile(SHAsset const* const asset) noexcept + ImRect SHAssetBrowser::DrawFile(SHFile file) noexcept { - if (asset == nullptr) - return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); - const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end(); - ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf; + + SHAsset const* const asset = file.assetMeta; + if (file.compilable) + { + ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf; + std::string icon{ ICON_MD_FILE_PRESENT }; + + bool const isOpen = ImGui::TreeNodeEx(file.name.data(), flags, "%s %s%s", icon.data(), file.name.data(), file.ext.data()); + const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); + + if (ImGui::BeginPopupContextItem()) + { + if (ImGui::Selectable("Compile")) + { + SHAssetManager::CompileAsset(file.path, true); + Refresh(); + } + ImGui::EndPopup(); + } + + ImGui::TreePop(); + + return nodeRect; + } + if (asset) + DrawAsset(asset); + } + + ImRect SHAssetBrowser::DrawAsset(SHAsset const* const asset) + { + const bool isSelected = asset ? std::ranges::find(selectedAssets, asset->id) != selectedAssets.end() : false; + ImGuiTreeNodeFlags flags = (asset && !asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf; if (isSelected) flags |= ImGuiTreeNodeFlags_Selected; std::string icon{}; @@ -172,9 +212,11 @@ namespace SHADE case AssetType::MAX_COUNT: break; default:; } - + bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s", icon.data(), asset->name.data()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); + + if (SHDragDrop::BeginSource()) { auto id = asset->id; @@ -197,7 +239,7 @@ namespace SHADE case AssetType::TEXTURE: break; case AssetType::MESH: break; case AssetType::SCENE: - if(auto editor = SHSystemManager::GetSystem()) + if (auto editor = SHSystemManager::GetSystem()) { editor->LoadScene(asset->id); } @@ -222,12 +264,12 @@ namespace SHADE ImVec2 vertLineStart = ImGui::GetCursorScreenPos(); vertLineStart.x += horizontalOffset; ImVec2 vertLineEnd = vertLineStart; - if(isOpen) + if (isOpen) { - for(auto const& subAsset : asset->subAssets) + for (auto const& subAsset : asset->subAssets) { const float horizontalLineSize = 25.0f; - const ImRect childRect = DrawFile(subAsset); + const ImRect childRect = DrawAsset(subAsset); const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f; drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1); vertLineEnd.y = midPoint; @@ -253,6 +295,7 @@ namespace SHADE matInspector->OpenMaterial(assetId, true); } assetBeingCreated.reset(); + Refresh(); } } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h index 00023ebe..8258a6c7 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h @@ -21,7 +21,8 @@ namespace SHADE void DrawMenuBar(); ImRect RecursivelyDrawTree(FolderPointer folder); void DrawCurrentFolder(); - ImRect DrawFile(SHAsset const* const asset) noexcept; + ImRect DrawFile(SHFile file) noexcept; + ImRect DrawAsset(SHAsset const* const asset); void DrawAssetBeingCreated() noexcept; FolderPointer rootFolder, prevFolder, currentFolder; @@ -29,5 +30,6 @@ namespace SHADE std::vector selectedFolders; std::vector selectedAssets; static constexpr float tileWidth = 50.0f; + bool queueReset = false; }; } From aad83d9e32508f1900d050b4d7980842510cceca Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Thu, 10 Nov 2022 23:01:09 +0800 Subject: [PATCH 13/13] Revert "Asset browser is wonky now" This reverts commit 2fdff77420bade71a1e8bfa3bf03d9af68722ec7. --- .../AssetBrowser/SHAssetBrowser.cpp | 73 ++++--------------- .../AssetBrowser/SHAssetBrowser.h | 4 +- 2 files changed, 16 insertions(+), 61 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp index 9159be7e..37b8ecd4 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -36,27 +36,13 @@ namespace SHADE DrawCurrentFolder(); } ImGui::End(); - if (queueReset) - { - SHAssetManager::RefreshDirectory(); - rootFolder = SHAssetManager::GetRootFolder(); - queueReset = false; - } - } - - void SHAssetBrowser::Refresh() - { - queueReset = true; } void SHAssetBrowser::DrawMenuBar() { if (ImGui::BeginMenuBar()) { - if(ImGui::SmallButton("Refresh")) - { - Refresh(); - } + ImGui::EndMenuBar(); } } @@ -116,14 +102,16 @@ namespace SHADE } for (auto const& file : files) { + if(file.assetMeta == nullptr) + continue; const float horizontalLineSize = 25.0f; - const ImRect childRect = DrawFile(file); + const ImRect childRect = DrawFile(file.assetMeta); const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f; drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1); vertLineEnd.y = midPoint; } drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1); - if (assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder) + if(assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder) DrawAssetBeingCreated(); ImGui::TreePop(); @@ -160,40 +148,12 @@ namespace SHADE //} } - ImRect SHAssetBrowser::DrawFile(SHFile file) noexcept + ImRect SHAssetBrowser::DrawFile(SHAsset const* const asset) noexcept { - - SHAsset const* const asset = file.assetMeta; - if (file.compilable) - { - ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf; - std::string icon{ ICON_MD_FILE_PRESENT }; - - bool const isOpen = ImGui::TreeNodeEx(file.name.data(), flags, "%s %s%s", icon.data(), file.name.data(), file.ext.data()); - const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); - - if (ImGui::BeginPopupContextItem()) - { - if (ImGui::Selectable("Compile")) - { - SHAssetManager::CompileAsset(file.path, true); - Refresh(); - } - ImGui::EndPopup(); - } - - ImGui::TreePop(); - - return nodeRect; - } - if (asset) - DrawAsset(asset); - } - - ImRect SHAssetBrowser::DrawAsset(SHAsset const* const asset) - { - const bool isSelected = asset ? std::ranges::find(selectedAssets, asset->id) != selectedAssets.end() : false; - ImGuiTreeNodeFlags flags = (asset && !asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf; + if (asset == nullptr) + return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); + const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end(); + ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf; if (isSelected) flags |= ImGuiTreeNodeFlags_Selected; std::string icon{}; @@ -212,11 +172,9 @@ namespace SHADE case AssetType::MAX_COUNT: break; default:; } - + bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s", icon.data(), asset->name.data()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); - - if (SHDragDrop::BeginSource()) { auto id = asset->id; @@ -239,7 +197,7 @@ namespace SHADE case AssetType::TEXTURE: break; case AssetType::MESH: break; case AssetType::SCENE: - if (auto editor = SHSystemManager::GetSystem()) + if(auto editor = SHSystemManager::GetSystem()) { editor->LoadScene(asset->id); } @@ -264,12 +222,12 @@ namespace SHADE ImVec2 vertLineStart = ImGui::GetCursorScreenPos(); vertLineStart.x += horizontalOffset; ImVec2 vertLineEnd = vertLineStart; - if (isOpen) + if(isOpen) { - for (auto const& subAsset : asset->subAssets) + for(auto const& subAsset : asset->subAssets) { const float horizontalLineSize = 25.0f; - const ImRect childRect = DrawAsset(subAsset); + const ImRect childRect = DrawFile(subAsset); const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f; drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1); vertLineEnd.y = midPoint; @@ -295,7 +253,6 @@ namespace SHADE matInspector->OpenMaterial(assetId, true); } assetBeingCreated.reset(); - Refresh(); } } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h index 8258a6c7..00023ebe 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h @@ -21,8 +21,7 @@ namespace SHADE void DrawMenuBar(); ImRect RecursivelyDrawTree(FolderPointer folder); void DrawCurrentFolder(); - ImRect DrawFile(SHFile file) noexcept; - ImRect DrawAsset(SHAsset const* const asset); + ImRect DrawFile(SHAsset const* const asset) noexcept; void DrawAssetBeingCreated() noexcept; FolderPointer rootFolder, prevFolder, currentFolder; @@ -30,6 +29,5 @@ namespace SHADE std::vector selectedFolders; std::vector selectedAssets; static constexpr float tileWidth = 50.0f; - bool queueReset = false; }; }