From 9be58e7e5d961df6c90f60fbc20a4f8ea38a927d Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 8 Nov 2022 18:32:13 +0800 Subject: [PATCH 01/15] Added SceneGraph interaction functions in GameObject --- SHADE_Managed/src/Engine/ChildListCache.cxx | 89 ++++++++++++++ SHADE_Managed/src/Engine/ChildListCache.hxx | 80 +++++++++++++ SHADE_Managed/src/Engine/EngineInterface.hxx | 2 +- SHADE_Managed/src/Engine/GameObject.cxx | 120 +++++++++++++++++-- SHADE_Managed/src/Engine/GameObject.hxx | 102 ++++++++++++++-- 5 files changed, 372 insertions(+), 21 deletions(-) create mode 100644 SHADE_Managed/src/Engine/ChildListCache.cxx create mode 100644 SHADE_Managed/src/Engine/ChildListCache.hxx diff --git a/SHADE_Managed/src/Engine/ChildListCache.cxx b/SHADE_Managed/src/Engine/ChildListCache.cxx new file mode 100644 index 00000000..b183646f --- /dev/null +++ b/SHADE_Managed/src/Engine/ChildListCache.cxx @@ -0,0 +1,89 @@ +/************************************************************************************//*! +\file ChildListCache.cxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Nov 11, 2022 +\brief Contains the definition of the functions for the ChildListCache managed + class. + + Note: This file is written in C++17/CLI. + +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. +*//*************************************************************************************/ +// Precompiled Headers +#include "SHpch.h" +// Primary Header +#include "ChildListCache.hxx" +// External Dependencies +#include "Scene/SHSceneManager.h" +// Project Headers +#include "Utility/Debug.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Static Usage Functions */ + /*---------------------------------------------------------------------------------*/ + ChildListCache::ChildEnumerable^ ChildListCache::GetChildList(Entity entity) + { + // Ignore if invalid + if (entity == MAX_EID) + return nullptr; + + // Check if in cache + if (cachedLists->ContainsKey(entity)) + return cachedLists[entity]; + + // Grab the native child list + auto node = GameObject(entity).GetSceneNode(); + if (!node || node->GetChildren().empty()) + return nullptr; + + // Otherwise + // - Create the list + ChildList^ list = gcnew ChildList(); + updateChildList(list, node); + // - Cache it + cachedLists[entity] = list; + + return list; + } + + void ChildListCache::UpdateChildList(Entity entity) + { + // Ignore if invalid + if (entity == MAX_EID) + return; + + // Check if in cache + if (!cachedLists->ContainsKey(entity)) + return; + + // Update + updateChildList(cachedLists[entity], GameObject(entity).GetSceneNode()); + } + + /*---------------------------------------------------------------------------------*/ + /* Event Handling Functions */ + /*---------------------------------------------------------------------------------*/ + void ChildListCache::OnChildrenChanged(EntityID entity) + { + SAFE_NATIVE_CALL_BEGIN + UpdateChildList(entity); + SAFE_NATIVE_CALL_END_N("SHADE_Managed.ChildListCache") + } + + /*---------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*---------------------------------------------------------------------------------*/ + void ChildListCache::updateChildList(ChildList^ list, const SHSceneNode* sceneNode) + { + list->Clear(); + for (auto node : sceneNode->GetChildren()) + { + list->Add(GameObject(node->GetEntityID())); + } + } +} diff --git a/SHADE_Managed/src/Engine/ChildListCache.hxx b/SHADE_Managed/src/Engine/ChildListCache.hxx new file mode 100644 index 00000000..1a2637d3 --- /dev/null +++ b/SHADE_Managed/src/Engine/ChildListCache.hxx @@ -0,0 +1,80 @@ +/************************************************************************************//*! +\file ChildListCache.hxx +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Nov 11, 2022 +\brief Contains the definition of the ChildListCache managed class. + + Note: This file is written in C++17/CLI. + +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 Includes +#include "GameObject.hxx" + +namespace SHADE { } + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*---------------------------------------------------------------------------------*/ + class SHSceneNode; + + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Static class that caches all the lists of children for GameObjects. + /// + private ref class ChildListCache abstract sealed + { + public: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + using ChildList = System::Collections::Generic::List; + using ChildEnumerable = System::Collections::Generic::IEnumerable; + using ListMap = System::Collections::Generic::Dictionary; + + internal: + /*-----------------------------------------------------------------------------*/ + /* Static Usage Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Retrieves the children list for the specified Entity. + /// + /// + /// Enumerable read only list of an Entity's children. Null if entity is invalid + /// or there are no children. + /// + static ChildEnumerable^ GetChildList(Entity entity); + /// + /// Updates the children list for the specified Entity if it exists. + /// + static void UpdateChildList(Entity entity); + + /*-----------------------------------------------------------------------------*/ + /* Event Handling Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// To be + /// + static void OnChildrenChanged(EntityID entity); + + private: + /*-----------------------------------------------------------------------------*/ + /* Static Data Members */ + /*-----------------------------------------------------------------------------*/ + static ListMap^ cachedLists = gcnew ListMap(); + + /*-----------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------*/ + static void updateChildList(ChildList^ list, const SHSceneNode* sceneNode); + }; +} \ No newline at end of file diff --git a/SHADE_Managed/src/Engine/EngineInterface.hxx b/SHADE_Managed/src/Engine/EngineInterface.hxx index 4fd8f7b3..37ded4eb 100644 --- a/SHADE_Managed/src/Engine/EngineInterface.hxx +++ b/SHADE_Managed/src/Engine/EngineInterface.hxx @@ -20,7 +20,7 @@ namespace SHADE { /// /// Static class that contains the functions for interfacing with the core - /// PlushieEngine written in C++ for managing the lifecycle of managed code. + /// SHADE Engine written in C++ for managing the lifecycle of managed code. /// private ref class EngineInterface abstract sealed { diff --git a/SHADE_Managed/src/Engine/GameObject.cxx b/SHADE_Managed/src/Engine/GameObject.cxx index 9f15c6c9..ece163f9 100644 --- a/SHADE_Managed/src/Engine/GameObject.cxx +++ b/SHADE_Managed/src/Engine/GameObject.cxx @@ -23,6 +23,7 @@ of DigiPen Institute of Technology is prohibited. #include "Utility/Convert.hxx" #include "Scripts/ScriptStore.hxx" #include "Utility/Debug.hxx" +#include "ChildListCache.hxx" namespace SHADE { @@ -87,30 +88,43 @@ namespace SHADE throw gcnew System::NullReferenceException(); return entity; } - GameObject^ GameObject::Parent::get() + GameObject GameObject::Parent::get() { if (!valid) throw gcnew System::NullReferenceException(); + const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); const auto* ROOT = SCENE_GRAPH.GetRoot(); - const auto* NODE = SCENE_GRAPH.GetNode(entity); if (NODE == nullptr) throw gcnew System::InvalidOperationException("Unable to retrieve SceneGraphNode for Entity " + entity.ToString()); const auto* PARENT = NODE->GetParent(); - return PARENT != ROOT ? gcnew GameObject(PARENT->GetEntityID()) : nullptr; + return PARENT != ROOT ? GameObject(PARENT->GetEntityID()) : GameObject(); } - void GameObject::Parent::set(GameObject^ newParent) + void GameObject::Parent::set(GameObject newParent) { if (!valid) throw gcnew System::NullReferenceException(); const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); - if (newParent == nullptr) - SCENE_GRAPH.SetParent(entity, nullptr); + if (newParent) + SCENE_GRAPH.SetParent(entity, newParent.EntityId); else - SCENE_GRAPH.SetParent(entity, newParent->EntityId); + SCENE_GRAPH.SetParent(entity, nullptr); + } + int GameObject::ChildCount::get() + { + if (!valid) + throw gcnew System::NullReferenceException(); + + const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); + const auto* ROOT = SCENE_GRAPH.GetRoot(); + const auto* NODE = SCENE_GRAPH.GetNode(entity); + if (NODE == nullptr) + throw gcnew System::InvalidOperationException("Unable to retrieve SceneGraphNode for Entity " + entity.ToString()); + + return static_cast(NODE->GetChildren().size()); } /*---------------------------------------------------------------------------------*/ @@ -215,6 +229,88 @@ namespace SHADE ScriptStore::RemoveScript(entity); } + /*---------------------------------------------------------------------------------*/ + /* Scene Graph Functions */ + /*---------------------------------------------------------------------------------*/ + void GameObject::DetachChildren() + { + // Validity Checks + if (!valid) + throw gcnew System::NullReferenceException(); + auto node = GetSceneNode(); + if (!node) + throw gcnew System::NullReferenceException(); + + // Unparent all children to the root + for (auto child : node->GetChildren()) + { + child->SetParent(nullptr); + ChildListCache::UpdateChildList(child->GetEntityID()); + } + ChildListCache::UpdateChildList(entity); + } + + GameObject GameObject::GetChild(int index) + { + // Validity Checks + if (!valid) + throw gcnew System::NullReferenceException(); + auto node = GetSceneNode(); + if (!node) + throw gcnew System::NullReferenceException(); + + auto child = node->GetChild(index); + return child ? GameObject(child->GetEntityID()) : GameObject(); + } + + System::Collections::Generic::IEnumerable^ GameObject::GetChildren() + { + return ChildListCache::GetChildList(entity); + } + + int GameObject::GetSiblingIndex() + { + throw gcnew System::NotImplementedException(); + } + + bool GameObject::IsChildOf(GameObject gameObj) + { + // Search parents recursively + auto node = GetSceneNode(); + while (node != nullptr) + { + if (node->GetEntityID() == gameObj.entity) + return true; + + // Go up higher + node = node->GetParent(); + } + return false; + } + + void GameObject::SetAsFirstSibling() + { + throw gcnew System::NotImplementedException(); + } + + void GameObject::SetAsLastSibling() + { + throw gcnew System::NotImplementedException(); + } + + void GameObject::SetSiblingIndex(int index) + { + throw gcnew System::NotImplementedException(); + } + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + GameObject::operator bool(GameObject gameObj) + { + return gameObj.valid; + } + /*---------------------------------------------------------------------------------*/ /* Constructors */ /*---------------------------------------------------------------------------------*/ @@ -245,11 +341,15 @@ namespace SHADE } /*---------------------------------------------------------------------------------*/ - /* Operator Overloads */ + /* Helper Functions */ /*---------------------------------------------------------------------------------*/ - GameObject::operator bool(GameObject gameObj) + SHSceneNode* GameObject::GetSceneNode() { - return gameObj.valid; + const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); + const auto* ROOT = SCENE_GRAPH.GetRoot(); + if (!ROOT) + return nullptr; + return SCENE_GRAPH.GetNode(entity); } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Engine/GameObject.hxx b/SHADE_Managed/src/Engine/GameObject.hxx index 030b917c..ec75f9d9 100644 --- a/SHADE_Managed/src/Engine/GameObject.hxx +++ b/SHADE_Managed/src/Engine/GameObject.hxx @@ -20,7 +20,7 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { /*---------------------------------------------------------------------------------*/ - /* Forward Declarations */ + /* Forward Declarations */ /*---------------------------------------------------------------------------------*/ ref class Script; ref class BaseComponent; @@ -97,10 +97,17 @@ namespace SHADE /// /// The parent entity for this GameObject. /// - property GameObject^ Parent + property GameObject Parent { - GameObject^ get(); - void set(GameObject^); + GameObject get(); + void set(GameObject); + } + /// + /// Number of Children held by this GameObject + /// + property int ChildCount + { + int get(); } /*-----------------------------------------------------------------------------*/ @@ -120,8 +127,7 @@ namespace SHADE /// /// Whether to activate or deactivate this GameObject. /// - void SetActive(bool active); - + void SetActive(bool active); /*-----------------------------------------------------------------------------*/ /* Component Access Functions */ @@ -214,6 +220,82 @@ namespace SHADE generic where T : ref class, Script void RemoveScript(); + /*-----------------------------------------------------------------------------*/ + /* Scene Graph Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Unparents all children. Useful if you want to destroy the root of a hierarchy + /// without destroying the children. + /// + void DetachChildren(); + /// + /// Returns a child by index. + /// + /// Index of the child GameObject to retrieve. + /// + /// Handle to the GameObject if the index is valid. Invalid GameObject otherwise. + /// + GameObject GetChild(int index); + /// + /// Returns a cached enumerable container of child GameObjects of this + /// GameObject. + /// + /// + /// Enumerable container of child GameObjects of this GameObject. Null if + /// ChildCount is 0. + /// + System::Collections::Generic::IEnumerable^ GetChildren(); + /// + /// Gets the sibling index. Use GetSiblingIndex to find out the GameObject’s + /// place in this hierarchy. When the sibling index of a GameObject is changed, + /// its order in the Hierarchy window will also change. + /// + /// + /// Index of this GameObject among the parent GameObject's children. + /// + [System::ObsoleteAttribute("Not yet implemented.", true)] + int GetSiblingIndex(); + /// + /// Checks if this GameObject a direct or indirect child of the specified + /// GameObject. + /// + /// + /// True if this GameObject is a child, deep child (child of a child) or + /// identical to this GameObject, otherwise false. + /// + bool IsChildOf(GameObject gameObj); + /// + /// Move the GameObject to the start of the parent GameObject's children list. + /// + [System::ObsoleteAttribute("Not yet implemented.", true)] + void SetAsFirstSibling(); + /// + /// Move the GameObject to the end of the parent GameObject's children list. + /// + [System::ObsoleteAttribute("Not yet implemented.", true)] + void SetAsLastSibling(); + /// + /// Move the GameObject to the specified position in the parent GameObject's + /// children list. An existing object at that position if any, will be pushed + /// to the next index (existing element will be at index + 1). + /// + /// + /// Position to place this GameObject at in the hierarchy. Clamped to between + /// [0, parent.ChildCount]. + /// + [System::ObsoleteAttribute("Not yet implemented.", true)] + void SetSiblingIndex(int index); + + /*-----------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*-----------------------------------------------------------------------------*/ + /// + /// Implicit conversion operator to enable checking if a GameObject is valid. + /// + /// GameObjects to check. + /// True if the GameObject is valid. + static operator bool(GameObject gameObj); + internal: /*-----------------------------------------------------------------------------*/ /* Constructors */ @@ -249,13 +331,13 @@ namespace SHADE SHEntity& GetNativeEntity(); /*-----------------------------------------------------------------------------*/ - /* Operator Overloads */ + /* Helper Functions */ /*-----------------------------------------------------------------------------*/ /// - /// Implicit conversion operator to enable checking if a GameObject is valid. + /// Retrieves the SceneNode for this GameObject's referenced entity. /// - /// GameObjects to check. - static operator bool(GameObject gameObj); + /// Pointer to the SceneNode for this GameObject.. + SHSceneNode* GetSceneNode(); private: /*-----------------------------------------------------------------------------*/ From 8512c658f9503acc83dca3a5e0ad9c6ba8089732 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 8 Nov 2022 18:32:47 +0800 Subject: [PATCH 02/15] Made GameObject an IEnumerable to follow Unity's Transform interface for iterating through children --- SHADE_Managed/src/Engine/GameObject.cxx | 20 ++++++++++++++++++++ SHADE_Managed/src/Engine/GameObject.hxx | 11 ++++++++++- TempScriptsFolder/RaccoonShowcase.cs | 5 +++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/SHADE_Managed/src/Engine/GameObject.cxx b/SHADE_Managed/src/Engine/GameObject.cxx index ece163f9..e7cc4445 100644 --- a/SHADE_Managed/src/Engine/GameObject.cxx +++ b/SHADE_Managed/src/Engine/GameObject.cxx @@ -265,6 +265,9 @@ namespace SHADE System::Collections::Generic::IEnumerable^ GameObject::GetChildren() { + // Validity Checks + if (!valid) + throw gcnew System::NullReferenceException(); return ChildListCache::GetChildList(entity); } @@ -390,4 +393,21 @@ namespace SHADE { return !(lhs == rhs); } + + /*---------------------------------------------------------------------------------*/ + /* IEnummerable */ + /*---------------------------------------------------------------------------------*/ + System::Collections::Generic::IEnumerator^ GameObject::GetEnumerator() + { + System::Collections::Generic::IEnumerable^ childList = GetChildren(); + if (childList == nullptr) + return System::Linq::Enumerable::Empty()->GetEnumerator(); + else + return childList->GetEnumerator(); + } + + System::Collections::IEnumerator^ GameObject::GetEnumeratorNonGeneric() + { + return GetEnumerator(); + } } diff --git a/SHADE_Managed/src/Engine/GameObject.hxx b/SHADE_Managed/src/Engine/GameObject.hxx index ec75f9d9..ce1dd3eb 100644 --- a/SHADE_Managed/src/Engine/GameObject.hxx +++ b/SHADE_Managed/src/Engine/GameObject.hxx @@ -32,8 +32,9 @@ namespace SHADE /// Lightweight object for an Entity that allows for easy access to Component and /// Script operations. /// Can be set to a invalid/null GameObject by default construction. + /// Can also be iterated to access children. /// - public value class GameObject : public System::IEquatable + public value class GameObject : public System::IEquatable, public System::Collections::Generic::IEnumerable { public: /*-----------------------------------------------------------------------------*/ @@ -386,6 +387,14 @@ namespace SHADE /// Another GameObject to check with. /// True if both Components are different. static bool operator!=(GameObject lhs, GameObject rhs); + + /*-----------------------------------------------------------------------------*/ + /* IEnummerable */ + /*-----------------------------------------------------------------------------*/ + /// + System::Collections::Generic::IEnumerator^ GetEnumerator() override; + /// + System::Collections::IEnumerator^ GetEnumeratorNonGeneric() override = System::Collections::IEnumerable::GetEnumerator; }; } diff --git a/TempScriptsFolder/RaccoonShowcase.cs b/TempScriptsFolder/RaccoonShowcase.cs index da0b89d2..2fc8104d 100644 --- a/TempScriptsFolder/RaccoonShowcase.cs +++ b/TempScriptsFolder/RaccoonShowcase.cs @@ -27,6 +27,11 @@ public class RaccoonShowcase : Script Debug.LogError("Transform is NULL!"); } + foreach (var child in Owner) + { + Debug.Log(child.Name); + } + originalScale = Transform.LocalScale.z; } protected override void update() From 0e5609995fd5f39ec956ec149649b27995f762ed Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Thu, 10 Nov 2022 16:44:16 +0800 Subject: [PATCH 03/15] 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 04/15] 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 05/15] 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 06/15] 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 07/15] 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 09/15] 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; }; } From d93ea8e49bb36ae96c33e71497b1d3697487fe89 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 10 Nov 2022 23:34:53 +0800 Subject: [PATCH 10/15] Child caches are now updated when scene hierarchy changes --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 38 ++++++++++++++++++- SHADE_Engine/src/Scripting/SHScriptEngine.h | 3 ++ SHADE_Managed/src/Engine/GameObject.cxx | 3 +- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 276eeb24..f279bec1 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -318,6 +318,20 @@ namespace SHADE return eventData->handle; } + SHEventHandle SHScriptEngine::onSceneNodeChildrenAdded(SHEventPtr eventPtr) + { + auto eventData = reinterpret_cast*>(eventPtr.get()); + csSceneNodeChildrenChanged(eventData->data->parent->GetEntityID()); + return eventData->handle; + } + + SHEventHandle SHScriptEngine::onSceneNodeChildrenRemoved(SHEventPtr eventPtr) + { + auto eventData = reinterpret_cast*>(eventPtr.get()); + csSceneNodeChildrenChanged(eventData->data->parent->GetEntityID()); + return eventData->handle; + } + /*-----------------------------------------------------------------------------------*/ /* Helper Functions */ /*-----------------------------------------------------------------------------------*/ @@ -442,6 +456,12 @@ namespace SHADE DEFAULT_CSHARP_NAMESPACE + ".Collider", "OnCollisionShapeRemoved" ); + csSceneNodeChildrenChanged = dotNet.GetFunctionPtr + ( + DEFAULT_CSHARP_LIB_NAME, + DEFAULT_CSHARP_NAMESPACE + ".ChildListCache", + "OnChildrenChanged" + ); csEditorRenderScripts = dotNet.GetFunctionPtr ( DEFAULT_CSHARP_LIB_NAME, @@ -464,6 +484,7 @@ namespace SHADE void SHScriptEngine::registerEvents() { + /* Entity */ // Register for entity destroyed event std::shared_ptr> destroyedEventReceiver { @@ -471,26 +492,39 @@ namespace SHADE }; SHEventManager::SubscribeTo(SH_ENTITY_DESTROYED_EVENT, std::dynamic_pointer_cast(destroyedEventReceiver)); + /* Colliders */ // Register for collider added event std::shared_ptr> addedColliderEventReceiver { std::make_shared>(this, &SHScriptEngine::onColliderAdded) }; SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_ADDED_EVENT, std::dynamic_pointer_cast(addedColliderEventReceiver)); - // Register for collider removed event std::shared_ptr> removedColliderEventReceiver { std::make_shared>(this, &SHScriptEngine::onColliderRemoved) }; SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_REMOVED_EVENT, std::dynamic_pointer_cast(removedColliderEventReceiver)); - // Register for collider component removed event std::shared_ptr> removedColliderComponentEventReceiver { std::make_shared>(this, &SHScriptEngine::onColliderComponentRemoved) }; SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, std::dynamic_pointer_cast(removedColliderComponentEventReceiver)); + + /* SceneGraph */ + // Register for SceneNode child added event + std::shared_ptr> addChildEventReceiver + { + std::make_shared>(this, &SHScriptEngine::onSceneNodeChildrenAdded) + }; + SHEventManager::SubscribeTo(SH_SCENEGRAPH_ADD_CHILD_EVENT, std::dynamic_pointer_cast(addChildEventReceiver)); + // Register for SceneNode child removed event + std::shared_ptr> removeChildEventReceiver + { + std::make_shared>(this, &SHScriptEngine::onSceneNodeChildrenRemoved) + }; + SHEventManager::SubscribeTo(SH_SCENEGRAPH_REMOVE_CHILD_EVENT, std::dynamic_pointer_cast(removeChildEventReceiver)); } void SHScriptEngine::dumpBuildLog(const std::string_view& buildLogPath) diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index 7d83606e..ef778627 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -267,6 +267,7 @@ namespace SHADE // - Events CsEventRelayFuncPtr csColliderOnListChanged = nullptr; CsEventRelayFuncPtr csColliderOnRemoved = nullptr; + CsEventRelayFuncPtr csSceneNodeChildrenChanged = nullptr; // - Editor CsScriptEditorFuncPtr csEditorRenderScripts = nullptr; CsFuncPtr csEditorUndo = nullptr; @@ -279,6 +280,8 @@ namespace SHADE SHEventHandle onColliderAdded(SHEventPtr eventPtr); SHEventHandle onColliderRemoved(SHEventPtr eventPtr); SHEventHandle onColliderComponentRemoved(SHEventPtr eventPtr); + SHEventHandle onSceneNodeChildrenAdded(SHEventPtr eventPtr); + SHEventHandle onSceneNodeChildrenRemoved(SHEventPtr eventPtr); /*-----------------------------------------------------------------------------*/ /* Helper Functions */ diff --git a/SHADE_Managed/src/Engine/GameObject.cxx b/SHADE_Managed/src/Engine/GameObject.cxx index 79960ff6..017366fe 100644 --- a/SHADE_Managed/src/Engine/GameObject.cxx +++ b/SHADE_Managed/src/Engine/GameObject.cxx @@ -244,8 +244,7 @@ namespace SHADE // Unparent all children to the root for (auto child : node->GetChildren()) { - child->SetParent(nullptr); - ChildListCache::UpdateChildList(child->GetEntityID()); + SHSceneManager::GetCurrentSceneGraph().SetParent(child->GetEntityID(), nullptr); } ChildListCache::UpdateChildList(entity); } From e824c174056f008cf4fe56f9bc08a29e4fb23c85 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Fri, 11 Nov 2022 10:06:26 +0800 Subject: [PATCH 11/15] Fixed asset type conversion bug when loading from meta files Removed compile all function Set parent id to 0 for non sub assets --- SHADE_Engine/src/Assets/SHAssetMacros.h | 3 +- SHADE_Engine/src/Assets/SHAssetManager.cpp | 45 ------------------- SHADE_Engine/src/Assets/SHAssetManager.h | 2 - .../src/Assets/SHAssetMetaHandler.cpp | 1 + 4 files changed, 3 insertions(+), 48 deletions(-) diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h index e0551262..7ffdb5f1 100644 --- a/SHADE_Engine/src/Assets/SHAssetMacros.h +++ b/SHADE_Engine/src/Assets/SHAssetMacros.h @@ -51,8 +51,8 @@ enum class AssetType : AssetTypeMeta SCENE, PREFAB, MATERIAL, - SCRIPT, MESH, + SCRIPT, MAX_COUNT }; constexpr size_t TYPE_COUNT{ static_cast(AssetType::MAX_COUNT) }; @@ -97,6 +97,7 @@ constexpr std::string_view EXTENSIONS[] = { SCENE_EXTENSION, PREFAB_EXTENSION, MATERIAL_EXTENSION, + "dummy", SCRIPT_EXTENSION, AUDIO_WAV_EXTENSION, }; diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index f4727417..5a1bd5db 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -405,51 +405,6 @@ namespace SHADE return result; } - void SHAssetManager::CompileAll() noexcept - { - std::vector paths; - - for (auto const& dir : std::filesystem::recursive_directory_iterator{ ASSET_ROOT }) - { - if (dir.is_regular_file()) - { - for (auto const& ext : EXTERNALS) - { - if (dir.path().extension().string() == ext.data()) - { - paths.push_back(dir.path()); - } - } - } - } - - for (auto const& path : paths) - { - AssetPath newPath; - auto const ext{ path.extension().string() }; - if (ext == GLSL_EXTENSION.data()) - { - newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value(); - } - else if (ext == DDS_EXTENSION.data()) - { - newPath = SHTextureCompiler::CompileTextureAsset(path).value(); - } - else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data()) - { - std::string command = MODEL_COMPILER_EXE.data(); - command += " " + path.string(); - std::system(command.c_str()); - - std::string modelPath = path.string().substr(0, path.string().find_last_of('.')); - modelPath += MODEL_EXTENSION; - newPath = modelPath; - } - - GenerateNewMeta(newPath); - } - } - bool SHAssetManager::DeleteLocalFile(AssetPath path) noexcept { //TODO Move this to dedicated library diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index a891ec23..5af648e4 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -107,8 +107,6 @@ namespace SHADE static SHAsset CreateAssetFromPath(AssetPath path) noexcept; - static void CompileAll() noexcept; - static bool DeleteLocalFile(AssetPath path) noexcept; //TODO use this function to create asset data internall at all calls to generate id diff --git a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp index 9ae8cde2..b75ee1ad 100644 --- a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp +++ b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp @@ -98,6 +98,7 @@ namespace SHADE meta.type = static_cast(type); meta.isSubAsset = false; + meta.parent = 0; // Burn Line if (std::getline(metaFile, line)) From 6df3f3d4174c7ae4f5e5e4b3c2f50eeb7c46ef5a Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Fri, 11 Nov 2022 10:47:03 +0800 Subject: [PATCH 12/15] Fixed get type from extension bug in asset handler --- SHADE_Engine/src/Assets/SHAssetMacros.h | 2 ++ SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h index 7ffdb5f1..7e5befab 100644 --- a/SHADE_Engine/src/Assets/SHAssetMacros.h +++ b/SHADE_Engine/src/Assets/SHAssetMacros.h @@ -102,6 +102,8 @@ constexpr std::string_view EXTENSIONS[] = { AUDIO_WAV_EXTENSION, }; +constexpr size_t EXTENSIONS_COUNT{ 11 }; + // EXTERNAL EXTENSIONS constexpr std::string_view GLSL_EXTENSION{ ".glsl" }; constexpr std::string_view DDS_EXTENSION{ ".dds" }; diff --git a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp index b75ee1ad..f3b24ed1 100644 --- a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp +++ b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp @@ -38,7 +38,7 @@ namespace SHADE ****************************************************************************/ AssetType SHAssetMetaHandler::GetTypeFromExtension(AssetExtension ext) noexcept { - for (int i{0}; i < EXTENSIONS->size(); ++i) + for (auto i{0}; i < EXTENSIONS_COUNT; ++i) { if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0) { From 9fe5dc385bf6f55b1e91f461cead7743877882b0 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Fri, 11 Nov 2022 10:52:57 +0800 Subject: [PATCH 13/15] Implemented check for raw asset if compiled --- SHADE_Engine/src/Filesystem/SHFileSystem.cpp | 63 +++++++++++++++++++- SHADE_Engine/src/Filesystem/SHFileSystem.h | 1 + SHADE_Engine/src/Filesystem/SHFolder.h | 3 +- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp index c4bcc5dc..9144b0d8 100644 --- a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp +++ b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp @@ -38,6 +38,41 @@ namespace SHADE return false; } + bool SHFileSystem::MatchExtention(FileExt raw, FileExt compiled) noexcept + { + if (raw == GLSL_EXTENSION) + { + if (compiled == SHADER_EXTENSION || + compiled == SHADER_BUILT_IN_EXTENSION) + { + return true; + } + } + else if (raw == DDS_EXTENSION) + { + if (compiled == TEXTURE_EXTENSION) + { + return true; + } + } + else if (raw == FBX_EXTENSION) + { + if (compiled == MODEL_EXTENSION) + { + return true; + } + } + else if (raw == GLTF_EXTENSION) + { + if (compiled == MODEL_EXTENSION) + { + return true; + } + } + + return false; + } + void SHFileSystem::BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map& assetCollection) noexcept { std::stack folderStack; @@ -52,6 +87,7 @@ namespace SHADE std::vector assets; + // Get all subfolders/files in this current folder for (auto& dirEntry : std::filesystem::directory_iterator(folder->path)) { auto path = dirEntry.path(); @@ -60,8 +96,6 @@ namespace SHADE { if (path.extension().string() == META_EXTENSION) { - //auto asset = SHAssetMetaHandler::RetrieveMetaData(path); - //assetCollection.insert({ asset.id, asset }); assets.push_back(SHAssetMetaHandler::RetrieveMetaData(path)); } else @@ -77,6 +111,7 @@ namespace SHADE continue; } + // If item is folder auto newFolder{ folder->CreateSubFolderHere(path.stem().string()) }; folderStack.push(newFolder); } @@ -97,6 +132,30 @@ namespace SHADE } } } + + for (auto i {0}; i < folder->files.size(); ++i) + { + auto& file = folder->files[i]; + if (file.compilable) + { + for (auto j{ 0 }; j < folder->files.size(); ++j) + { + auto& check = folder->files[j]; + if (i == j || check.compilable) + { + continue; + } + + if (file.name == check.name) + { + if (MatchExtention(file.ext, check.ext)) + { + file.compiled = true; + } + } + } + } + } } } diff --git a/SHADE_Engine/src/Filesystem/SHFileSystem.h b/SHADE_Engine/src/Filesystem/SHFileSystem.h index 87d13f42..d30f2164 100644 --- a/SHADE_Engine/src/Filesystem/SHFileSystem.h +++ b/SHADE_Engine/src/Filesystem/SHFileSystem.h @@ -24,5 +24,6 @@ namespace SHADE private: static bool DeleteFolder(FolderPointer location) noexcept; static bool IsCompilable(std::string ext) noexcept; + static bool MatchExtention(FileExt raw, FileExt compiled) noexcept; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Filesystem/SHFolder.h b/SHADE_Engine/src/Filesystem/SHFolder.h index 5c702b51..234e6f19 100644 --- a/SHADE_Engine/src/Filesystem/SHFolder.h +++ b/SHADE_Engine/src/Filesystem/SHFolder.h @@ -33,7 +33,8 @@ namespace SHADE FilePath path; FileExt ext; SHAsset const* assetMeta; - bool compilable; + bool compilable; + bool compiled; }; class SHFolder From 94b64e92dd51ac837aadaa266d696f93dc49a9a8 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Fri, 11 Nov 2022 10:55:19 +0800 Subject: [PATCH 14/15] Initialise files to not compiled --- SHADE_Engine/src/Filesystem/SHFileSystem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp index 9144b0d8..9aaf72a4 100644 --- a/SHADE_Engine/src/Filesystem/SHFileSystem.cpp +++ b/SHADE_Engine/src/Filesystem/SHFileSystem.cpp @@ -105,7 +105,8 @@ namespace SHADE path.string(), path.extension().string(), nullptr, - IsCompilable(path.extension().string()) + IsCompilable(path.extension().string()), + false ); } continue; From 3b22f95e29a04129d025be57ec6b120862219e30 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Fri, 11 Nov 2022 13:21:22 +0800 Subject: [PATCH 15/15] Added font identifiers --- SHADE_Engine/src/Assets/SHAssetMacros.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h index 7e5befab..44dfd5c5 100644 --- a/SHADE_Engine/src/Assets/SHAssetMacros.h +++ b/SHADE_Engine/src/Assets/SHAssetMacros.h @@ -53,6 +53,7 @@ enum class AssetType : AssetTypeMeta MATERIAL, MESH, SCRIPT, + FONT, MAX_COUNT }; constexpr size_t TYPE_COUNT{ static_cast(AssetType::MAX_COUNT) }; @@ -86,7 +87,8 @@ constexpr std::string_view SCENE_EXTENSION {".shade"}; constexpr std::string_view PREFAB_EXTENSION {".shprefab"}; constexpr std::string_view MATERIAL_EXTENSION {".shmat"}; constexpr std::string_view TEXTURE_EXTENSION {".shtex"}; -constexpr std::string_view MODEL_EXTENSION {".shmodel"}; +constexpr std::string_view MODEL_EXTENSION{ ".shmodel" }; +constexpr std::string_view FONT_EXTENSION{ ".shfont" }; constexpr std::string_view EXTENSIONS[] = { AUDIO_EXTENSION, @@ -99,6 +101,7 @@ constexpr std::string_view EXTENSIONS[] = { MATERIAL_EXTENSION, "dummy", SCRIPT_EXTENSION, + FONT_EXTENSION, AUDIO_WAV_EXTENSION, }; @@ -109,12 +112,14 @@ constexpr std::string_view GLSL_EXTENSION{ ".glsl" }; constexpr std::string_view DDS_EXTENSION{ ".dds" }; constexpr std::string_view FBX_EXTENSION{ ".fbx" }; constexpr std::string_view GLTF_EXTENSION{ ".gltf" }; +constexpr std::string_view TTF_EXTENSION{ ".ttf" }; constexpr std::string_view EXTERNALS[] = { GLSL_EXTENSION, DDS_EXTENSION, FBX_EXTENSION, - GLTF_EXTENSION + GLTF_EXTENSION, + TTF_EXTENSION }; // SHADER IDENTIFIERS @@ -129,11 +134,4 @@ constexpr std::pair SHADER_IDENTIFIERS[ }; constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 }; - -// Error flags -constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"}; -constexpr std::string_view META_NOT_FOUND_ERR {"META NOT FOUND"}; -constexpr std::string_view ASSET_NOT_FOUND_ERR {"ASSET NOT FOUND"}; -constexpr std::string_view EXT_DOES_NOT_EXIST {"TYPE DOES NOT HAVE EXTENSION DEFINED"}; - #endif // !SH_ASSET_MACROS_H