From 19f0c0ea7022748a3e22b89ed6128652c02ce0e3 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Sun, 13 Nov 2022 11:43:08 +0800 Subject: [PATCH 01/10] Copy/Paste of entities can now be undone Fixed bug where Shift Select would reset in a duplicate entity selection Moved editor window manager to its own file. --- .../AssetBrowser/SHAssetBrowser.cpp | 1 + .../HierarchyPanel/SHHierarchyPanel.cpp | 74 +++++++----------- .../HierarchyPanel/SHHierarchyPanel.h | 30 -------- .../SHHierarchyPanelCommands.cpp | 63 +++++++++++++++ .../HierarchyPanel/SHHierarchyPanelCommands.h | 55 +++++++++++++ .../EditorWindow/MenuBar/SHEditorMenuBar.cpp | 2 +- .../EditorWindow/SHEditorWindowManager.cpp | 8 ++ .../EditorWindow/SHEditorWindowManager.h | 77 +++++++++++++++++++ .../src/Editor/Gizmos/SHTransformGizmo.cpp | 2 + SHADE_Engine/src/Editor/SHEditor.cpp | 3 +- SHADE_Engine/src/Editor/SHEditor.h | 66 ---------------- .../src/Serialization/SHSerialization.cpp | 72 ++++++++++++----- .../src/Serialization/SHSerialization.h | 14 +++- 13 files changed, 300 insertions(+), 167 deletions(-) create mode 100644 SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.cpp create mode 100644 SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.h create mode 100644 SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.cpp create mode 100644 SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.h diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp index 37521581..889c24cc 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -13,6 +13,7 @@ #include "Editor/SHEditor.h" #include "Editor/DragDrop/SHDragDrop.hpp" #include "Editor/EditorWindow/MaterialInspector/SHMaterialInspector.h" +#include "Editor/EditorWindow/SHEditorWindowManager.h" namespace SHADE { diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index ff65ba58..07446115 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -15,6 +15,7 @@ #include "Editor/DragDrop/SHDragDrop.hpp" #include "Tools/SHException.h" #include "Editor/IconsMaterialDesign.h" +#include "SHHierarchyPanelCommands.h" //#==============================================================# //|| Library Includes || @@ -110,9 +111,12 @@ namespace SHADE } if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) { - ParentSelectedEntities(MAX_EID, draggingEntities); - draggingEntities.clear(); - ImGui::ClearDragDrop(); + if(ImGui::IsDragDropActive()) + { + ParentSelectedEntities(MAX_EID, draggingEntities); + draggingEntities.clear(); + ImGui::ClearDragDrop(); + } } ImGui::End(); } @@ -282,9 +286,12 @@ namespace SHADE } else editor->selectedEntities.clear(); } - else if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) - editor->selectedEntities.clear(); - editor->selectedEntities.push_back(eid); + else + { + if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) + editor->selectedEntities.clear(); + editor->selectedEntities.push_back(eid); + } }//if not selected else { @@ -365,14 +372,16 @@ namespace SHADE if (eid == beginEID || eid == endEID) { startSelecting = true; - editor->selectedEntities.push_back(eid); + if(std::ranges::find(editor->selectedEntities, eid) == editor->selectedEntities.end()) + editor->selectedEntities.push_back(eid); } } else { if (!endSelecting) { - editor->selectedEntities.push_back(eid); + if (std::ranges::find(editor->selectedEntities, eid) == editor->selectedEntities.end()) + editor->selectedEntities.push_back(eid); if (eid == endEID || eid == beginEID) { endSelecting = true; @@ -397,47 +406,20 @@ namespace SHADE void SHHierarchyPanel::CopySelectedEntities() { const auto editor = SHSystemManager::GetSystem(); - SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(editor->selectedEntities)); + auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + std::vector entitiesToCopy{}; + std::ranges::copy_if(editor->selectedEntities, std::back_inserter(entitiesToCopy), [&sceneGraph](EntityID const& eid) + { + if(sceneGraph.GetParent(eid)->GetEntityID() == MAX_EID) + return true; + return false; + }); + SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(entitiesToCopy)); } void SHHierarchyPanel::PasteEntities(EntityID parentEID) { - SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), parentEID)); - } - - void SHCreateEntityCommand::Execute() - { - EntityID newEID = SHEntityManager::CreateEntity(eid); - if (eid == MAX_EID) - eid = newEID; - } - - void SHCreateEntityCommand::Undo() - { - SHEntityManager::DestroyEntity(eid); - } - - void SHEntityParentCommand::Execute() - { - auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); - for (auto const& eid : entities) - { - if (entityParentData[eid].newParentEID == MAX_EID) - sceneGraph.SetParent(eid, nullptr); - else - sceneGraph.SetParent(eid, entityParentData[eid].newParentEID); - } - } - - void SHEntityParentCommand::Undo() - { - auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); - for (auto const& eid : entities) - { - if (entityParentData[eid].oldParentEID == MAX_EID) - sceneGraph.SetParent(eid, nullptr); - else - sceneGraph.SetParent(eid, entityParentData[eid].oldParentEID); - } + //SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), parentEID).front()); + SHCommandManager::PerformCommand(std::make_shared(SHClipboardUtilities::GetDataFromClipboard(), parentEID)); } }//namespace SHADE diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h index 64f841d6..b667bae7 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h @@ -10,7 +10,6 @@ #include "imgui_internal.h" #include "ECS_Base/SHECSMacros.h" #include "Editor/EditorWindow/SHEditorWindow.h" -#include "Editor/Command/SHCommand.hpp" namespace SHADE { class SHSceneNode; @@ -41,33 +40,4 @@ namespace SHADE };//class SHHierarchyPanel - //Might move to a different file - class SHCreateEntityCommand final : public SHBaseCommand - { - public: - void Execute() override; - void Undo() override; - private: - EntityID eid = MAX_EID; - }; - - class SHEntityParentCommand final : public SHBaseCommand - { - public: - struct Data - { - EntityID oldParentEID = MAX_EID; - EntityID newParentEID = MAX_EID; - }; - using EntityParentData = std::unordered_map; - - SHEntityParentCommand(std::vector entityIDs, EntityParentData inEntityParentData):entities(entityIDs),entityParentData(inEntityParentData){} - - void Execute() override; - void Undo() override; - private: - std::vector entities; - std::unordered_map entityParentData; - }; - }//namespace SHADE diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.cpp new file mode 100644 index 00000000..dfae969e --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.cpp @@ -0,0 +1,63 @@ +#include "SHpch.h" +#include "SHHierarchyPanelCommands.h" +#include "ECS_Base/Managers/SHEntityManager.h" +#include "Scene/SHSceneManager.h" +#include "Serialization/SHSerialization.h" +#include "SHHierarchyPanel.h" +#include "Editor/EditorWindow/SHEditorWindowManager.h" + +namespace SHADE +{ + void SHCreateEntityCommand::Execute() + { + EntityID newEID = SHEntityManager::CreateEntity(eid); + if (eid == MAX_EID) + eid = newEID; + } + + void SHCreateEntityCommand::Undo() + { + SHEntityManager::DestroyEntity(eid); + } + + void SHEntityParentCommand::Execute() + { + auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + for (auto const& eid : entities) + { + if (entityParentData[eid].newParentEID == MAX_EID) + sceneGraph.SetParent(eid, nullptr); + else + sceneGraph.SetParent(eid, entityParentData[eid].newParentEID); + } + } + + void SHEntityParentCommand::Undo() + { + auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + for (auto const& eid : entities) + { + if (entityParentData[eid].oldParentEID == MAX_EID) + sceneGraph.SetParent(eid, nullptr); + else + sceneGraph.SetParent(eid, entityParentData[eid].oldParentEID); + } + } + + void SHPasteEntityCommand::Execute() + { + data.createdEntities.clear(); + data.createdEntities = SHSerialization::DeserializeEntitiesFromString(data.entityData, data.parentEID); + data.entityData = SHSerialization::ResolveSerializedEntityIndices(data.entityData, data.createdEntities); + SHEditorWindowManager::GetEditorWindow()->SetScrollTo(data.createdEntities.begin()->second); + } + + void SHPasteEntityCommand::Undo() + { + for (auto const& [oldEID, newEID] : data.createdEntities) + { + SHEntityManager::DestroyEntity(newEID); + } + } + +} diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.h b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.h new file mode 100644 index 00000000..8bad9df2 --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.h @@ -0,0 +1,55 @@ +#pragma once + +#include + +#include "ECS_Base/SHECSMacros.h" +#include "Editor/Command/SHCommand.hpp" +#include "Serialization/SHSerialization.h" +namespace SHADE +{ + class SHCreateEntityCommand final : public SHBaseCommand + { + public: + void Execute() override; + void Undo() override; + private: + EntityID eid = MAX_EID; + }; + + class SHEntityParentCommand final : public SHBaseCommand + { + public: + struct Data + { + EntityID oldParentEID = MAX_EID; + EntityID newParentEID = MAX_EID; + }; + using EntityParentData = std::unordered_map; + + SHEntityParentCommand(std::vector entityIDs, EntityParentData inEntityParentData) :entities(entityIDs), entityParentData(inEntityParentData) {} + + void Execute() override; + void Undo() override; + private: + std::vector entities{}; + std::unordered_map entityParentData{}; + }; + + class SHPasteEntityCommand final : public SHBaseCommand + { + public: + struct Data + { + SHSerialization::CreatedEntitiesList createdEntities{}; + EntityID parentEID{MAX_EID}; + std::string entityData{}; + }; + SHPasteEntityCommand() = delete; + SHPasteEntityCommand(std::string const& serializedEntityData, EntityID parentEid = MAX_EID):data({{}, parentEid, serializedEntityData}){} + + void Execute() override; + void Undo() override; + private: + Data data; + }; +} diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index ce3ca8b5..223f9b83 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -23,7 +23,7 @@ #include "Scene/SHSceneManager.h" #include "Serialization/SHSerialization.h" #include "Serialization/Configurations/SHConfigurationManager.h" - +#include "Editor/EditorWindow/SHEditorWindowManager.h" const std::string LAYOUT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts" }; diff --git a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.cpp b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.cpp new file mode 100644 index 00000000..420b5414 --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.cpp @@ -0,0 +1,8 @@ +#include "SHpch.h" +#include "SHEditorWindowManager.h" + +namespace SHADE +{ + SHEditorWindowManager::EditorWindowMap SHEditorWindowManager::editorWindows{}; + SHEditorWindowManager::EditorWindowID SHEditorWindowManager::windowCount{}; +} diff --git a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.h b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.h new file mode 100644 index 00000000..9e6dd3f4 --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowManager.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include "SHEditorWindow.h" +#include "Tools/SHLog.h" + +namespace SHADE +{ + class SH_API SHEditorWindowManager + { + public: + //#==============================================================# + //|| Type Aliases || + //#==============================================================# + using EditorWindowID = uint8_t; + using EditorWindowPtr = std::unique_ptr; + using EditorWindowMap = std::unordered_map; + /** + * @brief Get ID for the Editor Window Type + * + * @tparam T Type of Editor Window + * @return EditorWindowID ID of Editor Window Type + */ + template , bool> = true> + static EditorWindowID GetEditorWindowID() + { + static EditorWindowID id; + static bool idCreated = false; + if (!idCreated) + { + id = windowCount++; + idCreated = true; + } + return id; + } + + /** + * @brief Create an Editor Window + * + * @tparam T Type of Editor Window to create + */ + template , bool> = true> + static void CreateEditorWindow() + { + static bool isCreated = false; + if (!isCreated) + { + editorWindows[GetEditorWindowID()] = std::make_unique(); + isCreated = true; + } + else + { + SHLog::Warning("Attempt to create duplicate of Editor window type"); + } + } + + /** + * @brief Get pointer to the Editor Window + * + * @tparam T Type of editor window to retrieve + * @return T* Pointer to the editor window + */ + template , bool> = true> + static T* GetEditorWindow() + { + return reinterpret_cast(editorWindows[GetEditorWindowID()].get()); + } + + static EditorWindowMap editorWindows; + private: + // Number of windows; used for Editor Window ID Generation + static EditorWindowID windowCount; + // Map of Editor Windows + friend class SHEditor; + }; +} diff --git a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp index e3bbc809..deea62fc 100644 --- a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp +++ b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp @@ -11,6 +11,8 @@ #include "Camera/SHCameraSystem.h" #include "Editor/Command/SHCommandManager.h" #include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h" +#include "Editor/EditorWindow/SHEditorWindowManager.h" + namespace SHADE { void SHTransformGizmo::Init() diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index 90655a62..077c7025 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -29,6 +29,7 @@ //#==============================================================# //|| Editor Window Includes || //#==============================================================# +#include "EditorWindow/SHEditorWindowManager.h" #include "EditorWindow/SHEditorWindowIncludes.h" //#==============================================================# @@ -77,8 +78,6 @@ namespace SHADE //#==============================================================# //Handle SHEditor::imguiCommandPool; //Handle SHEditor::imguiCommandBuffer; - SHEditorWindowManager::EditorWindowMap SHEditorWindowManager::editorWindows{}; - SHEditorWindowManager::EditorWindowID SHEditorWindowManager::windowCount{}; //std::vector SHEditor::selectedEntities; //#==============================================================# diff --git a/SHADE_Engine/src/Editor/SHEditor.h b/SHADE_Engine/src/Editor/SHEditor.h index 0de7796a..5897c8b7 100644 --- a/SHADE_Engine/src/Editor/SHEditor.h +++ b/SHADE_Engine/src/Editor/SHEditor.h @@ -36,73 +36,7 @@ namespace SHADE class SHVkCommandBuffer; class SHVkCommandPool; - class SHEditorWindowManager - { - public: - //#==============================================================# - //|| Type Aliases || - //#==============================================================# - using EditorWindowID = uint8_t; - using EditorWindowPtr = std::unique_ptr; - using EditorWindowMap = std::unordered_map; - /** - * @brief Get ID for the Editor Window Type - * - * @tparam T Type of Editor Window - * @return EditorWindowID ID of Editor Window Type - */ - template , bool> = true> - static EditorWindowID GetEditorWindowID() - { - static EditorWindowID id; - static bool idCreated = false; - if (!idCreated) - { - id = windowCount++; - idCreated = true; - } - return id; - } - /** - * @brief Create an Editor Window - * - * @tparam T Type of Editor Window to create - */ - template , bool> = true> - static void CreateEditorWindow() - { - static bool isCreated = false; - if (!isCreated) - { - editorWindows[GetEditorWindowID()] = std::make_unique(); - isCreated = true; - } - else - { - SHLog::Warning("Attempt to create duplicate of Editor window type"); - } - } - - /** - * @brief Get pointer to the Editor Window - * - * @tparam T Type of editor window to retrieve - * @return T* Pointer to the editor window - */ - template , bool> = true> - static T* GetEditorWindow() - { - return reinterpret_cast(editorWindows[GetEditorWindowID()].get()); - } - - static EditorWindowMap editorWindows; - private: - // Number of windows; used for Editor Window ID Generation - static EditorWindowID windowCount; - // Map of Editor Windows - friend class SHEditor; - }; /** * @brief SHEditor static class contains editor variables and implementation of editor functions. diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index f2829b95..d2312627 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -61,20 +61,21 @@ namespace SHADE out << YAML::EndSeq; } - static EntityID DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector& createdEntities, EntityID parentEID = MAX_EID) + static EntityID DeserializeEntity(YAML::iterator& it, YAML::Node const& node, SHSerialization::CreatedEntitiesList& createdEntities, EntityID parentEID = MAX_EID) { - EntityID eid = MAX_EID; + EntityID eid{MAX_EID}, oldEID{MAX_EID}; if (!node) return eid; if (node[EIDNode]) - eid = node[EIDNode].as(); - std::string name = "Default"; + oldEID = eid = node[EIDNode].as(); + std::string name = "UnnamedEntitiy"; if (node[EntityNameNode]) name = node[EntityNameNode].as(); //Compile component IDs const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]); eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID); - createdEntities.push_back(eid); + createdEntities[oldEID] = eid; + //createdEntities.push_back(eid); if (node[NumberOfChildrenNode]) { if (const int numOfChildren = node[NumberOfChildrenNode].as(); numOfChildren > 0) @@ -106,7 +107,7 @@ namespace SHADE return NewSceneName.data(); } YAML::Node entities = YAML::Load(assetData->data); - std::vector createdEntities{}; + CreatedEntitiesList createdEntities{}; //Create Entities for (auto it = entities.begin(); it != entities.end(); ++it) @@ -122,14 +123,14 @@ namespace SHADE AssetQueue assetQueue; for (auto it = entities.begin(); it != entities.end(); ++it) { - SHSerializationHelper::FetchAssetsFromComponent((*it)[ComponentsNode], *entityVecIt, assetQueue); + SHSerializationHelper::FetchAssetsFromComponent((*it)[ComponentsNode], createdEntities[(*it)[EIDNode].as()], assetQueue); } LoadAssetsFromAssetQueue(assetQueue); //Initialize Entity entityVecIt = createdEntities.begin(); for (auto it = entities.begin(); it != entities.end(); ++it) { - InitializeEntity(*it, *entityVecIt++); + InitializeEntity(*it, createdEntities[(*it)[EIDNode].as()]); } return assetData->name; @@ -160,9 +161,9 @@ namespace SHADE return std::string(out.c_str()); } - void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path) - { - } + //void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path) + //{ + //} template, bool> = true> static void AddComponentToComponentNode(YAML::Node& componentsNode, EntityID const& eid) @@ -218,13 +219,13 @@ namespace SHADE return node; } - EntityID SHSerialization::DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID) noexcept + SHSerialization::CreatedEntitiesList SHSerialization::DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID) noexcept { if (data.empty()) - return MAX_EID; + return {}; YAML::Node entities = YAML::Load(data.c_str()); EntityID eid{ MAX_EID }; - std::vector createdEntities; + CreatedEntitiesList createdEntities{}; for (auto it = entities.begin(); it != entities.end(); ++it) { eid = DeserializeEntity(it, *it, createdEntities, parentEID); @@ -232,14 +233,14 @@ namespace SHADE if (createdEntities.empty()) { SHLOG_ERROR("Failed to create entities from deserializaiton") - return MAX_EID; + return createdEntities; } - auto entityVecIt = createdEntities.begin(); + //auto entityVecIt = createdEntities.begin(); for (auto it = entities.begin(); it != entities.end(); ++it) { - InitializeEntity(*it, *entityVecIt++); + InitializeEntity(*it, createdEntities[(*it)[EIDNode].as()]); } - return eid; + return createdEntities; } template, bool> = true> @@ -290,6 +291,41 @@ namespace SHADE SHResourceManager::FinaliseChanges(); } + void ResolveSerializedEntityID(YAML::Emitter& out, YAML::iterator& it, YAML::Node const& entityNode, SHSerialization::CreatedEntitiesList const& createdEntities) + { + EntityID eid = entityNode[EIDNode].as(); + YAML::Node resolvedNode = entityNode; + resolvedNode[EIDNode] = createdEntities.at(eid); + out << resolvedNode; + if (entityNode[NumberOfChildrenNode]) + { + if (const int numOfChildren = entityNode[NumberOfChildrenNode].as(); numOfChildren > 0) + { + ++it; + for (int i = 0; i < numOfChildren; ++i) + { + ResolveSerializedEntityID(out, it, (*it), createdEntities); + //DeserializeEntity(it, (*it), createdEntities, eid); + if ((i + 1) < numOfChildren) + ++it; + } + } + } + } + + std::string SHSerialization::ResolveSerializedEntityIndices(std::string serializedEntityData, CreatedEntitiesList const& createdEntities) noexcept + { + YAML::Node entities = YAML::Load(serializedEntityData); + YAML::Emitter out; + out << YAML::BeginSeq; + for (auto it = entities.begin(); it != entities.end(); ++it) + { + ResolveSerializedEntityID(out, it, (*it), createdEntities); + } + out << YAML::EndSeq; + return out.c_str(); + } + void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid) { auto const componentsNode = entityNode[ComponentsNode]; diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h index 3cb268f2..dd487662 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.h +++ b/SHADE_Engine/src/Serialization/SHSerialization.h @@ -2,7 +2,6 @@ #include "SH_API.h" #include -#include #include "ECS_Base/SHECSMacros.h" @@ -26,8 +25,12 @@ namespace SHADE constexpr const char* NumberOfChildrenNode = "NumberOfChildren"; constexpr const char* ScriptsNode = "Scripts"; - struct SH_API SHSerialization + class SH_API SHSerialization { + public: + //Original EID : New EID + using CreatedEntitiesList = std::unordered_map; + static bool SerializeSceneToFile(AssetID const& sceneAssetID); static std::string SerializeSceneToString(); static void SerializeSceneToEmitter(YAML::Emitter& out); @@ -38,15 +41,18 @@ namespace SHADE static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out); static std::string SerializeEntitiesToString(std::vector const& entities) noexcept; - static void SerializeEntityToFile(std::filesystem::path const& path); + //static void SerializeEntityToFile(std::filesystem::path const& path); static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode); - static EntityID DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept; + static CreatedEntitiesList DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept; static std::vector GetComponentIDList(YAML::Node const& componentsNode); static void LoadAssetsFromAssetQueue(std::unordered_map& assetQueue); + + static std::string ResolveSerializedEntityIndices(std::string serializedEntityData, CreatedEntitiesList const& createdEntities) noexcept; private: + //static void ResolveSerializedEntityID(YAML::Emitter& out, YAML::iterator& it, YAML::Node const& entityNode, CreatedEntitiesList const& createdEntities); static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid); static constexpr std::string_view NewSceneName = "New Scene"; From fd7a47b4c01bdff66d9a5bee8ae69bb314f48f69 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sun, 13 Nov 2022 12:44:23 +0800 Subject: [PATCH 02/10] Added changes to hide internal types and constructors that should not be available to SHADE_Scripting --- SHADE_Managed/src/Components/Component.hxx | 3 +-- SHADE_Managed/src/Engine/GenericHandle.hxx | 2 +- SHADE_Managed/src/Scripts/ScriptStore.hxx | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/SHADE_Managed/src/Components/Component.hxx b/SHADE_Managed/src/Components/Component.hxx index e52ab3a7..a1d83eaf 100644 --- a/SHADE_Managed/src/Components/Component.hxx +++ b/SHADE_Managed/src/Components/Component.hxx @@ -110,7 +110,7 @@ namespace SHADE /// Component to check. static operator bool(BaseComponent^ c); - protected: + internal: /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ @@ -193,7 +193,6 @@ namespace SHADE /// NativeComponent* GetNativeComponent(); - protected: /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Engine/GenericHandle.hxx b/SHADE_Managed/src/Engine/GenericHandle.hxx index 3f8e395f..3d77f54d 100644 --- a/SHADE_Managed/src/Engine/GenericHandle.hxx +++ b/SHADE_Managed/src/Engine/GenericHandle.hxx @@ -21,7 +21,7 @@ namespace SHADE /// /// Managed version of the generic Handle. /// - public value struct GenericHandle + private value struct GenericHandle { public: /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Scripts/ScriptStore.hxx b/SHADE_Managed/src/Scripts/ScriptStore.hxx index 23440f3d..2b2540e6 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.hxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.hxx @@ -25,7 +25,7 @@ namespace SHADE /// Responsible for managing all scripts attached to Entities as well as executing /// all lifecycle functions of scripts. /// - public ref class ScriptStore abstract sealed + private ref class ScriptStore abstract sealed { public: /*-----------------------------------------------------------------------------*/ From a83a38eba81a2c44347149cecf9769c8a263de7c Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sun, 13 Nov 2022 13:07:49 +0800 Subject: [PATCH 03/10] Fixed bin and obj folders respawning and causing engine crashes --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index f279bec1..18c2b9e3 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -17,6 +17,7 @@ of DigiPen Institute of Technology is prohibited. #include // std::fstream #include // std::filesystem::canonical, std::filesystem::remove #include // std::shared_ptr +#include // std::this_thread::sleep_for // Project Headers #include "Tools/SHLogger.h" #include "Tools/SHStringUtils.h" @@ -25,7 +26,6 @@ of DigiPen Institute of Technology is prohibited. #include "Events/SHEventReceiver.h" #include "Events/SHEventManager.hpp" #include "Physics/SHPhysicsSystem.h" - #include "Assets/SHAssetMacros.h" namespace SHADE @@ -177,10 +177,10 @@ namespace SHADE } // Prepare directory (delete useless files) - deleteFolder(CSPROJ_DIR + "\\net5.0"); - deleteFolder(CSPROJ_DIR + "\\ref"); - deleteFolder(CSPROJ_DIR + "\\obj"); - deleteFolder(CSPROJ_DIR + "\\bin"); + deleteFolder(CSPROJ_DIR + "/net5.0"); + deleteFolder(CSPROJ_DIR + "/ref"); + deleteFolder(CSPROJ_DIR + "/obj"); + deleteFolder(CSPROJ_DIR + "/bin"); // Attempt to build the assembly std::ostringstream oss; @@ -214,7 +214,10 @@ namespace SHADE // Clean up built files deleteFolder("./tmp"); - deleteFolder(CSPROJ_DIR + "\\obj"); + deleteFolder(CSPROJ_DIR + "/bin"); + using namespace std::chrono_literals; + std::this_thread::sleep_for(50ms); // Not sure why this works but it prevents the folders from respawning + deleteFolder(CSPROJ_DIR + "/obj"); // Read the build log and output to the console dumpBuildLog(BUILD_LOG_PATH); From 635d999c2c47b781686faeb8f232ff2ece8fbaae Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sun, 13 Nov 2022 13:16:36 +0800 Subject: [PATCH 04/10] Fixed redo not working correctly --- SHADE_Managed/src/Editor/UndoRedoStack.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/SHADE_Managed/src/Editor/UndoRedoStack.cxx b/SHADE_Managed/src/Editor/UndoRedoStack.cxx index 789d285d..a83db119 100644 --- a/SHADE_Managed/src/Editor/UndoRedoStack.cxx +++ b/SHADE_Managed/src/Editor/UndoRedoStack.cxx @@ -34,7 +34,8 @@ namespace SHADE bool UndoRedoStack::RedoActionPresent::get() { - return latestActionIndex >= 0 && latestActionIndex < commandStack->Count - 1; + const int REDO_ACTION_INDEX = latestActionIndex + 1; + return REDO_ACTION_INDEX >= 0 && REDO_ACTION_INDEX < commandStack->Count; } /*---------------------------------------------------------------------------------*/ @@ -69,8 +70,9 @@ namespace SHADE { if (!RedoActionPresent) return; - - ICommand^ cmd = commandStack[latestActionIndex]; + + const int REDO_ACTION_INDEX = latestActionIndex + 1; + ICommand^ cmd = commandStack[REDO_ACTION_INDEX]; cmd->Execute(); ++latestActionIndex; } From 276e0806fa8a7e89451a645f592ca73314c7cb7a Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Sun, 13 Nov 2022 13:55:30 +0800 Subject: [PATCH 05/10] Can now undo/redo entity deletion (working afaik) --- .../HierarchyPanel/SHHierarchyPanel.cpp | 30 +++++++++++++++++-- .../HierarchyPanel/SHHierarchyPanel.h | 1 + .../SHHierarchyPanelCommands.cpp | 25 ++++++++++++++-- .../HierarchyPanel/SHHierarchyPanelCommands.h | 25 +++++++++++++--- 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 07446115..6be89a8b 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -106,6 +106,10 @@ namespace SHADE PasteEntities(editor->selectedEntities.back()); } } + if(ImGui::IsKeyReleased(ImGuiKey_Delete)) + { + DeleteSelectedEntities(); + } } } @@ -259,9 +263,10 @@ namespace SHADE PasteEntities(eid); skipFrame = true; } - if (ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data())) + if (ImGui::Selectable(std::format("{} Delete selected", ICON_MD_DELETE).data())) { - SHEntityManager::DestroyEntity(eid); + //SHEntityManager::DestroyEntity(eid); + DeleteSelectedEntities(); } if ((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data())) @@ -420,6 +425,25 @@ namespace SHADE void SHHierarchyPanel::PasteEntities(EntityID parentEID) { //SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), parentEID).front()); - SHCommandManager::PerformCommand(std::make_shared(SHClipboardUtilities::GetDataFromClipboard(), parentEID)); + SHCommandManager::PerformCommand(std::make_shared(SHClipboardUtilities::GetDataFromClipboard(), parentEID)); } + + void SHHierarchyPanel::DeleteSelectedEntities() + { + const auto editor = SHSystemManager::GetSystem(); + auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + + std::vector entitiesToDelete{}; + std::ranges::copy_if(editor->selectedEntities, std::back_inserter(entitiesToDelete), [&sceneGraph, &selectedEntities = editor->selectedEntities](EntityID const& eid) + { + EntityID parentEID = sceneGraph.GetParent(eid)->GetEntityID(); + if (parentEID == MAX_EID) + return true; + else if(std::ranges::find(selectedEntities, parentEID) == selectedEntities.end()) + return true; + return false; + }); + SHCommandManager::PerformCommand(std::make_shared(entitiesToDelete)); + } + }//namespace SHADE diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h index b667bae7..66b9ca2f 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h @@ -32,6 +32,7 @@ namespace SHADE void SelectAllEntities(); void CopySelectedEntities(); void PasteEntities(EntityID parentEID = MAX_EID); + void DeleteSelectedEntities(); bool skipFrame = false; std::string filter; bool isAnyNodeSelected = false; diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.cpp index dfae969e..78545829 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.cpp @@ -44,7 +44,7 @@ namespace SHADE } } - void SHPasteEntityCommand::Execute() + void SHPasteEntitiesCommand::Execute() { data.createdEntities.clear(); data.createdEntities = SHSerialization::DeserializeEntitiesFromString(data.entityData, data.parentEID); @@ -52,7 +52,7 @@ namespace SHADE SHEditorWindowManager::GetEditorWindow()->SetScrollTo(data.createdEntities.begin()->second); } - void SHPasteEntityCommand::Undo() + void SHPasteEntitiesCommand::Undo() { for (auto const& [oldEID, newEID] : data.createdEntities) { @@ -60,4 +60,25 @@ namespace SHADE } } + void SHDeleteEntitiesCommand::Execute() + { + if(!data.createdEntities.empty()) + { + for(auto& eid : data.entitiesToDelete) + { + eid = data.createdEntities[eid]; + } + } + data.entityData = SHSerialization::SerializeEntitiesToString(data.entitiesToDelete); + for (auto const& eid : data.entitiesToDelete) + { + SHEntityManager::DestroyEntity(eid); + } + } + + void SHDeleteEntitiesCommand::Undo() + { + data.createdEntities = SHSerialization::DeserializeEntitiesFromString(data.entityData); + data.entityData = SHSerialization::ResolveSerializedEntityIndices(data.entityData, data.createdEntities); + } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.h b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.h index 8bad9df2..fccd9489 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.h +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanelCommands.h @@ -35,21 +35,38 @@ namespace SHADE std::unordered_map entityParentData{}; }; - class SHPasteEntityCommand final : public SHBaseCommand + class SHPasteEntitiesCommand final : public SHBaseCommand { public: struct Data { - SHSerialization::CreatedEntitiesList createdEntities{}; EntityID parentEID{MAX_EID}; std::string entityData{}; + SHSerialization::CreatedEntitiesList createdEntities{}; }; - SHPasteEntityCommand() = delete; - SHPasteEntityCommand(std::string const& serializedEntityData, EntityID parentEid = MAX_EID):data({{}, parentEid, serializedEntityData}){} + SHPasteEntitiesCommand() = delete; + SHPasteEntitiesCommand(std::string const& serializedEntityData, EntityID parentEid = MAX_EID):data({parentEid, serializedEntityData, {}}){} void Execute() override; void Undo() override; private: Data data; }; + + class SHDeleteEntitiesCommand final : public SHBaseCommand + { + public: + struct Data + { + std::vector entitiesToDelete{}; + SHSerialization::CreatedEntitiesList createdEntities{}; + std::string entityData{}; + }; + SHDeleteEntitiesCommand() = delete; + SHDeleteEntitiesCommand(std::vector entitiesToBeDeleted): data{entitiesToBeDeleted}{} + void Execute() override; + void Undo() override; + private: + Data data; + }; } From 23320863e39de9dd661aea38a73926406fc8904b Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sun, 13 Nov 2022 13:38:09 +0800 Subject: [PATCH 06/10] Added support for undo-redo of adding/removing scripts --- SHADE_Managed/src/Editor/Editor.cxx | 34 +++++++++-- SHADE_Managed/src/Editor/Editor.hxx | 22 +++---- SHADE_Managed/src/Editor/UndoRedoStack.cxx | 60 ++++++++++++++++++- SHADE_Managed/src/Editor/UndoRedoStack.hxx | 30 ++++++++++ SHADE_Managed/src/Scripts/ScriptStore.cxx | 40 +++++++++---- SHADE_Managed/src/Scripts/ScriptStore.hxx | 31 ++++++++-- .../Serialisation/SerialisationUtilities.h++ | 11 ---- 7 files changed, 183 insertions(+), 45 deletions(-) diff --git a/SHADE_Managed/src/Editor/Editor.cxx b/SHADE_Managed/src/Editor/Editor.cxx index 68dddf34..7b2e0982 100644 --- a/SHADE_Managed/src/Editor/Editor.cxx +++ b/SHADE_Managed/src/Editor/Editor.cxx @@ -79,7 +79,10 @@ namespace SHADE if (SHEditorUI::Selectable(Convert::ToNative(type->Name))) { // Add the script - ScriptStore::AddScriptViaName(entity, type->Name); + Script^ script; + ScriptStore::AddScriptViaNameWithRef(entity, type->Name, script); + registerUndoScriptAddAction(entity, script); + break; } } @@ -120,7 +123,7 @@ namespace SHADE SHEditorUI::Indent(); { // Right Click Menu - renderScriptContextMenu(entity, script); + renderScriptContextMenu(entity, script, index); // Go through all fields and output them auto fields = ReflectionUtilities::GetInstanceFields(script); @@ -143,7 +146,7 @@ namespace SHADE } else { - renderScriptContextMenu(entity, script); + renderScriptContextMenu(entity, script, index); } SHEditorUI::PopID(); } @@ -336,7 +339,7 @@ namespace SHADE return false; } - void Editor::renderScriptContextMenu(Entity entity, Script^ script) + void Editor::renderScriptContextMenu(Entity entity, Script^ script, int scriptIndex) { // Right Click Menu if (SHEditorUI::BeginPopupContextItem("scriptContextMenu")) @@ -345,6 +348,7 @@ namespace SHADE { // Mark script for removal ScriptStore::RemoveScript(entity, script); + registerUndoScriptRemoveAction(entity, script, scriptIndex); } SHEditorUI::EndPopup(); } @@ -392,6 +396,28 @@ namespace SHADE SHCommandManager::RegisterCommand(std::reinterpret_pointer_cast(std::make_shared())); } + void Editor::registerUndoScriptAddAction(EntityID id, Script^ script) + { + if (script == nullptr) + return; + + actionStack.Add(gcnew ScriptAddCommand(id, script)); + + // Inform the C++ Undo-Redo stack + SHCommandManager::RegisterCommand(std::reinterpret_pointer_cast(std::make_shared())); + } + + void Editor::registerUndoScriptRemoveAction(EntityID id, Script^ script, int originalIndex) + { + if (script == nullptr) + return; + + actionStack.Add(gcnew ScriptRemoveCommand(id, script, originalIndex)); + + // Inform the C++ Undo-Redo stack + SHCommandManager::RegisterCommand(std::reinterpret_pointer_cast(std::make_shared())); + } + generic Attribute Editor::hasAttribute(System::Reflection::FieldInfo^ field) { diff --git a/SHADE_Managed/src/Editor/Editor.hxx b/SHADE_Managed/src/Editor/Editor.hxx index 64c445e5..79625274 100644 --- a/SHADE_Managed/src/Editor/Editor.hxx +++ b/SHADE_Managed/src/Editor/Editor.hxx @@ -69,7 +69,7 @@ namespace SHADE static UndoRedoStack actionStack; /*-----------------------------------------------------------------------------*/ - /* Helper Functions */ + /* Helper Functions - Inspector Rendering */ /*-----------------------------------------------------------------------------*/ /// /// Renders a single specified Script's inspector. @@ -170,25 +170,25 @@ namespace SHADE /// True if the field is modified. template static bool renderFieldEditorInternal(const std::string& fieldName, interior_ptr managedValPtr, EditorFieldFunc fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib); - /// /// Renders a context menu when right clicked for the scripts /// /// The Entity to render the Scripts of. /// The Script to render the inspector for. - static void renderScriptContextMenu(Entity entity, Script^ script); - /// - /// Adds changes to a variable as an undo-able/redo-able action on the Undo-Redo - /// stack. - /// - /// The object that changes are applied to. - /// The field that was changed. - /// New data to set. - /// Data that was overriden. + /// Index at which the Script is stored. + static void renderScriptContextMenu(Entity entity, Script^ script, int scriptIndex); + /*-----------------------------------------------------------------------------*/ + /* Helper Functions - Undo */ + /*-----------------------------------------------------------------------------*/ static void registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData); static void registerUndoListChangeAction(System::Type^ type, System::Collections::IList^ list, int index, System::Object^ newData, System::Object^ oldData); static void registerUndoListAddAction(System::Type^ type, System::Collections::IList^ list, int index, System::Object^ data); static void registerUndoListRemoveAction(System::Type^ type, System::Collections::IList^ list, int index, System::Object^ data); + static void registerUndoScriptAddAction(EntityID id, Script^ script); + static void registerUndoScriptRemoveAction(EntityID id, Script^ script, int originalIndex); + /*-----------------------------------------------------------------------------*/ + /* Helper Functions - Others */ + /*-----------------------------------------------------------------------------*/ /// /// Checks if a specific field has the specified attribute /// diff --git a/SHADE_Managed/src/Editor/UndoRedoStack.cxx b/SHADE_Managed/src/Editor/UndoRedoStack.cxx index a83db119..3d1f04e9 100644 --- a/SHADE_Managed/src/Editor/UndoRedoStack.cxx +++ b/SHADE_Managed/src/Editor/UndoRedoStack.cxx @@ -21,6 +21,7 @@ of DigiPen Institute of Technology is prohibited. // Project Headers #include "Utility/Debug.hxx" #include "Utility/Convert.hxx" +#include "Scripts/ScriptStore.hxx" namespace SHADE { @@ -182,7 +183,7 @@ namespace SHADE } /*---------------------------------------------------------------------------------*/ - /* ListElementAddCommand - ICommand Functions */ + /* ListElementAddCommand - Constructor */ /*---------------------------------------------------------------------------------*/ ListElementAddCommand::ListElementAddCommand(System::Collections::IList^ list, int addIndex, System::Object^ data) : list { list } @@ -222,7 +223,7 @@ namespace SHADE } /*---------------------------------------------------------------------------------*/ - /* ListElementRemoveCommand - ICommand Functions */ + /* ListElementRemoveCommand - Constructor */ /*---------------------------------------------------------------------------------*/ ListElementRemoveCommand::ListElementRemoveCommand(System::Collections::IList^ list, int removeIndex, System::Object^ data) : list { list } @@ -260,4 +261,59 @@ namespace SHADE // Not allowed return false; } + + /*---------------------------------------------------------------------------------*/ + /* ScriptAddCommand - Constructor */ + /*---------------------------------------------------------------------------------*/ + ScriptAddCommand::ScriptAddCommand(EntityID id, Script^ script) + : entity { id } + , addedScript { script } + {} + + /*---------------------------------------------------------------------------------*/ + /* ScriptAddCommand - ICommand Functions */ + /*---------------------------------------------------------------------------------*/ + bool ScriptAddCommand::Execute() + { + return ScriptStore::AddScript(entity, addedScript) != nullptr; + } + + bool ScriptAddCommand::Unexceute() + { + return ScriptStore::RemoveScript(entity, addedScript); + } + + bool ScriptAddCommand::Merge(ICommand^) + { + // Not allowed + return false; + } + + /*---------------------------------------------------------------------------------*/ + /* ScriptRemoveCommand - Constructor */ + /*---------------------------------------------------------------------------------*/ + ScriptRemoveCommand::ScriptRemoveCommand(EntityID id, Script^ script, int index) + : entity { id } + , removedScript { script } + , originalIndex { index } + {} + + /*---------------------------------------------------------------------------------*/ + /* ScriptRemoveCommand - ICommand Functions */ + /*---------------------------------------------------------------------------------*/ + bool ScriptRemoveCommand::Execute() + { + return ScriptStore::RemoveScript(entity, removedScript); + } + + bool ScriptRemoveCommand::Unexceute() + { + return ScriptStore::AddScript(entity, removedScript, originalIndex) != nullptr; + } + + bool ScriptRemoveCommand::Merge(ICommand^) + { + // Not allowed + return false; + } } diff --git a/SHADE_Managed/src/Editor/UndoRedoStack.hxx b/SHADE_Managed/src/Editor/UndoRedoStack.hxx index dea458bc..c377e2b7 100644 --- a/SHADE_Managed/src/Editor/UndoRedoStack.hxx +++ b/SHADE_Managed/src/Editor/UndoRedoStack.hxx @@ -12,6 +12,7 @@ Reproduction or disclosure of this file or its contents without the prior writte of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ #pragma once +#include "Scripts/Script.hxx" namespace SHADE { @@ -102,6 +103,35 @@ namespace SHADE System::Object^ data; }; + private ref class ScriptAddCommand sealed : public ICommand + { + public: + ScriptAddCommand(EntityID id, Script^ script); + + bool Execute() override; + bool Unexceute() override; + bool Merge(ICommand^ command) override; + + private: + EntityID entity; + Script^ addedScript; + }; + + private ref class ScriptRemoveCommand sealed : public ICommand + { + public: + ScriptRemoveCommand(EntityID id, Script^ script, int index); + + bool Execute() override; + bool Unexceute() override; + bool Merge(ICommand^ command) override; + + private: + EntityID entity; + Script^ removedScript; + int originalIndex; + }; + /// /// Class that is able to store a stack of actions that can be done and redone. /// diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index d11e70c3..b42f7508 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -38,6 +38,20 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ generic T ScriptStore::AddScript(Entity entity) + { + // Create the script and add it in + array^ params = gcnew array{GameObject(entity)}; + Script^ script = safe_cast(System::Activator::CreateInstance(T::typeid, params)); + + return safe_cast(AddScript(entity, script)); + } + + Script^ ScriptStore::AddScript(Entity entity, Script^ script) + { + return AddScript(entity, script, System::Int32::MaxValue); + } + + Script^ ScriptStore::AddScript(Entity entity, Script^ script, int index) { // Check if entity exists if (!EntityUtils::IsValid(entity)) @@ -57,15 +71,13 @@ namespace SHADE entityScriptList = scripts[entity]; } - // Create the script and add it in - array^ params = gcnew array{GameObject(entity)}; - Script^ script = safe_cast(System::Activator::CreateInstance(T::typeid, params)); - entityScriptList->Add(script); + // Add the script in + entityScriptList->Insert(System::Math::Clamp(index, 0, entityScriptList->Count), script); awakeList.Add(script); startList.Add(script); script->OnAttached(); - return safe_cast(script); + return script; } bool ScriptStore::AddScriptViaName(Entity entity, System::String^ scriptName) @@ -364,7 +376,10 @@ namespace SHADE } } startList.Clear(); - startList.AddRange(%inactiveStartList); + for each (Script ^ script in startList) + { + startList.Add(script); + } inactiveStartList.Clear(); SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") @@ -373,9 +388,8 @@ namespace SHADE { SAFE_NATIVE_CALL_BEGIN // Clear the queue - while (disposalQueue.Count > 0) - { - Script^ script = disposalQueue.Dequeue(); + for each (Script^ script in disposalQueue) + {; if (Application::IsPlaying) { script->OnDestroy(); @@ -388,6 +402,7 @@ namespace SHADE scripts.Remove(entity); } } + disposalQueue.Clear(); SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") } void ScriptStore::Exit() @@ -677,9 +692,9 @@ namespace SHADE void ScriptStore::removeScript(Script^ script) { // Prepare for disposal - disposalQueue.Enqueue(script); + disposalQueue.Add(script); - // Also remove it fromm awake and start queues if they were created but not initialised + // Also remove it from awake and start queues if they were created but not initialised awakeList.Remove(script); startList.Remove(script); script->OnDetached(); @@ -749,7 +764,8 @@ namespace SHADE void ScriptStore::getGenericMethods() { - addScriptMethod = ScriptStore::typeid->GetMethod("AddScript"); + array^ paramTypes = gcnew array{ Entity::typeid }; + addScriptMethod = ScriptStore::typeid->GetMethod("AddScript", paramTypes); if (addScriptMethod == nullptr) { Debug::LogError("[ScriptStore] Failed to get MethodInfo of \"AddScript()\". Adding of scripts from native code will fail."); diff --git a/SHADE_Managed/src/Scripts/ScriptStore.hxx b/SHADE_Managed/src/Scripts/ScriptStore.hxx index 2b2540e6..62e3003a 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.hxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.hxx @@ -46,6 +46,27 @@ namespace SHADE generic where T : ref class, Script static T AddScript(Entity entity); /// + /// Adds a specified pre-constructed Script to a specified Entity. + /// + /// The entity to add a script to. + /// The pre-constructed Script to add. + /// Reference to the script added. + /// + /// If the specified Entity is invalid. + /// + static Script^ AddScript(Entity entity, Script^ script); + /// + /// Adds a specified pre-constructed Script to a specified Entity. + /// + /// The entity to add a script to. + /// The pre-constructed Script to add. + /// Location in the script list to add. + /// Reference to the script added. + /// + /// If the specified Entity is invalid. + /// + static Script^ AddScript(Entity entity, Script^ script, int index); + /// /// Adds a Script to a specified Entity. ///
/// This function is meant for consumption from native code. If you are writing @@ -281,16 +302,16 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ using ScriptList = System::Collections::Generic::List; using ScriptDictionary = System::Collections::Generic::Dictionary; - using ScriptQueue = System::Collections::Generic::Queue; + using ScriptSet = System::Collections::Generic::HashSet; /*-----------------------------------------------------------------------------*/ /* Static Data Members */ /*-----------------------------------------------------------------------------*/ static ScriptDictionary scripts; - static ScriptList awakeList; - static ScriptList startList; - static ScriptList inactiveStartList; - static ScriptQueue disposalQueue; + static ScriptSet awakeList; + static ScriptSet startList; + static ScriptSet inactiveStartList; + static ScriptSet disposalQueue; static System::Collections::Generic::IEnumerable^ scriptTypeList; static System::Reflection::MethodInfo^ addScriptMethod; diff --git a/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ index c1728fe6..3e756ce4 100644 --- a/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ +++ b/SHADE_Managed/src/Serialisation/SerialisationUtilities.h++ @@ -28,7 +28,6 @@ namespace SHADE template bool SerialisationUtilities::fieldInsertYaml(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, YAML::Node& fieldNode) { - Debug::Log(FieldType::typeid->Name); return varInsertYamlInternal(fieldInfo->GetValue(object), fieldNode); } template @@ -123,16 +122,6 @@ namespace SHADE return true; } } - else if constexpr (std::is_same_v) - { - if (ReflectionUtilities::FieldIsList(fieldInfo)) - { - System::Collections::IList^ iList = safe_cast(object); - object = gcnew - if (node.IsSequence() ) - - } - } else { if (object->GetType() == FieldType::typeid) From af361062e709ac38fecf6bdcb93233ea8cc3cb92 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sun, 13 Nov 2022 16:07:14 +0800 Subject: [PATCH 07/10] Modified how scripts are added and updated to support runtime adding of scripts --- SHADE_Managed/src/Scripts/ScriptStore.cxx | 38 ++++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index b42f7508..6b33b31b 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -73,8 +73,16 @@ namespace SHADE // Add the script in entityScriptList->Insert(System::Math::Clamp(index, 0, entityScriptList->Count), script); - awakeList.Add(script); - startList.Add(script); + if (Application::IsPlaying) + { + script->Awake(); + script->Start(); + } + else + { + awakeList.Add(script); + startList.Add(script); + } script->OnAttached(); return script; @@ -451,9 +459,10 @@ namespace SHADE continue; // Update each script - for each (Script^ script in entity.Value) + ScriptList^ scripts = entity.Value; + for (int i = 0; i < scripts->Count; ++i) { - script->FixedUpdate(); + scripts[i]->FixedUpdate(); } } SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") @@ -468,9 +477,10 @@ namespace SHADE continue; // Update each script - for each (Script^ script in entity.Value) + ScriptList^ scripts = entity.Value; + for (int i = 0; i < scripts->Count; ++i) { - script->Update(); + scripts[i]->Update(); } } SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") @@ -485,9 +495,10 @@ namespace SHADE continue; // Update each script - for each (Script^ script in entity.Value) + ScriptList^ scripts = entity.Value; + for (int i = 0; i < scripts->Count; ++i) { - script->LateUpdate(); + scripts[i]->LateUpdate(); } } SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") @@ -503,9 +514,10 @@ namespace SHADE continue; // Update each script - for each (Script^ script in entity.Value) + ScriptList^ scripts = entity.Value; + for (int i = 0; i < scripts->Count; ++i) { - script->OnDrawGizmos(); + scripts[i]->OnDrawGizmos(); } } SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") @@ -537,8 +549,9 @@ namespace SHADE auto entityScripts = scripts[entity.first]; if (entityScripts->Count > 0) { - for each (Script ^ script in entityScripts) + for (int i = 0; i < entityScripts->Count; ++i) { + Script^ script = entityScripts[i]; switch (collisionInfo.GetCollisionState()) { case SHCollisionEvent::State::ENTER: @@ -578,8 +591,9 @@ namespace SHADE auto entityScripts = scripts[entity.first]; if (entityScripts->Count > 0) { - for each (Script ^ script in entityScripts) + for (int i = 0; i < entityScripts->Count; ++i) { + Script^ script = entityScripts[i]; switch (triggerInfo.GetCollisionState()) { case SHCollisionEvent::State::ENTER: From 4dc85273956282c542a6116b39060baecf634ded Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sun, 13 Nov 2022 16:29:25 +0800 Subject: [PATCH 08/10] Reworked scripts to no longer need definition of constructors --- Assets/Scenes/M2Scene.shade | 7 ++++++- Assets/Scripts/AIPrototype.cs | 1 - Assets/Scripts/CameraControl.cs | 1 - Assets/Scripts/CameraFix.cs | 1 - Assets/Scripts/Item.cs | 1 - Assets/Scripts/PhysicsTest.cs | 1 - Assets/Scripts/PickAndThrow.cs | 1 - Assets/Scripts/PlayerController.cs | 2 -- Assets/Scripts/PrintWhenActive.cs | 2 -- Assets/Scripts/RaccoonShowcase.cs | 1 - Assets/Scripts/RaccoonSpin.cs | 2 -- Assets/Scripts/ThirdPersonCamera.cs | 1 - SHADE_Managed/src/Scripts/Script.cxx | 10 +++++++--- SHADE_Managed/src/Scripts/Script.hxx | 14 +++++++------- SHADE_Managed/src/Scripts/ScriptStore.cxx | 5 +++-- 15 files changed, 23 insertions(+), 27 deletions(-) diff --git a/Assets/Scenes/M2Scene.shade b/Assets/Scenes/M2Scene.shade index b2a5683f..75b69d27 100644 --- a/Assets/Scenes/M2Scene.shade +++ b/Assets/Scenes/M2Scene.shade @@ -226,4 +226,9 @@ Bounciness: 0 Density: 1 Position Offset: {x: 0, y: 0.5, z: 0} - Scripts: ~ \ No newline at end of file + Scripts: + - Type: Item + currCategory: 0 + - Type: PickAndThrow + throwForce: [100, 200, 100] + item: 51000 \ No newline at end of file diff --git a/Assets/Scripts/AIPrototype.cs b/Assets/Scripts/AIPrototype.cs index d678de78..62255778 100644 --- a/Assets/Scripts/AIPrototype.cs +++ b/Assets/Scripts/AIPrototype.cs @@ -51,7 +51,6 @@ public class AIPrototype : Script private GameObject? player; - public AIPrototype(GameObject gameObj) : base(gameObj) { } protected override void awake() { diff --git a/Assets/Scripts/CameraControl.cs b/Assets/Scripts/CameraControl.cs index fc900f46..b25d65eb 100644 --- a/Assets/Scripts/CameraControl.cs +++ b/Assets/Scripts/CameraControl.cs @@ -7,7 +7,6 @@ namespace SHADE_Scripting { public float turnSpeed = 0.5f; - public CameraControl(GameObject go) : base(go) { } protected override void update() { //Camera diff --git a/Assets/Scripts/CameraFix.cs b/Assets/Scripts/CameraFix.cs index 5347a72f..0ca085ad 100644 --- a/Assets/Scripts/CameraFix.cs +++ b/Assets/Scripts/CameraFix.cs @@ -3,7 +3,6 @@ using System; public class CameraFix : Script { - public CameraFix(GameObject gameObj) : base(gameObj) { } private Transform tranform; public Vector3 pos = Vector3.Zero; diff --git a/Assets/Scripts/Item.cs b/Assets/Scripts/Item.cs index 96ec092d..5047a241 100644 --- a/Assets/Scripts/Item.cs +++ b/Assets/Scripts/Item.cs @@ -10,7 +10,6 @@ public class Item : Script } public ItemCategory currCategory; - public Item(GameObject gameObj) : base(gameObj) { } protected override void awake() { diff --git a/Assets/Scripts/PhysicsTest.cs b/Assets/Scripts/PhysicsTest.cs index cc01615d..9726a51c 100644 --- a/Assets/Scripts/PhysicsTest.cs +++ b/Assets/Scripts/PhysicsTest.cs @@ -8,7 +8,6 @@ public class PhysicsTest : Script private Transform Transform; private RigidBody RigidBody; private Collider Collider; - public PhysicsTest(GameObject gameObj) : base(gameObj) { } protected override void awake() { diff --git a/Assets/Scripts/PickAndThrow.cs b/Assets/Scripts/PickAndThrow.cs index ea814b36..ec8846c5 100644 --- a/Assets/Scripts/PickAndThrow.cs +++ b/Assets/Scripts/PickAndThrow.cs @@ -14,7 +14,6 @@ public class PickAndThrow : Script private float lastXDir; private float lastZDir; private bool inRange = false; - public PickAndThrow(GameObject gameObj) : base(gameObj) { } protected override void awake() { diff --git a/Assets/Scripts/PlayerController.cs b/Assets/Scripts/PlayerController.cs index 86ba7c98..4a02d470 100644 --- a/Assets/Scripts/PlayerController.cs +++ b/Assets/Scripts/PlayerController.cs @@ -73,8 +73,6 @@ public class PlayerController : Script public float mediumMultiper = 0.5f; public float heavyMultiper = 0.25f; - public PlayerController(GameObject gameObj) : base(gameObj) { } - protected override void awake() { //default setup diff --git a/Assets/Scripts/PrintWhenActive.cs b/Assets/Scripts/PrintWhenActive.cs index 41afdd58..11d7f025 100644 --- a/Assets/Scripts/PrintWhenActive.cs +++ b/Assets/Scripts/PrintWhenActive.cs @@ -2,8 +2,6 @@ public class PrintWhenActive : Script { - public PrintWhenActive(GameObject gameObj) : base(gameObj) { } - protected override void update() { Debug.Log("Active!"); diff --git a/Assets/Scripts/RaccoonShowcase.cs b/Assets/Scripts/RaccoonShowcase.cs index dc9d914d..3c767f7f 100644 --- a/Assets/Scripts/RaccoonShowcase.cs +++ b/Assets/Scripts/RaccoonShowcase.cs @@ -23,7 +23,6 @@ public class RaccoonShowcase : Script [Range(-5, 5)] public List intList = new List(new int[] { 2, 8, 2, 6, 8, 0, 1 }); public List enumList = new List(new Light.Type[] { Light.Type.Point, Light.Type.Directional, Light.Type.Ambient }); - public RaccoonShowcase(GameObject gameObj) : base(gameObj) {} protected override void awake() { diff --git a/Assets/Scripts/RaccoonSpin.cs b/Assets/Scripts/RaccoonSpin.cs index efdfadeb..84100a21 100644 --- a/Assets/Scripts/RaccoonSpin.cs +++ b/Assets/Scripts/RaccoonSpin.cs @@ -14,8 +14,6 @@ public class RaccoonSpin : Script [SerializeField] private CallbackEvent testEvent3 = new CallbackEvent(); private Transform Transform; - public RaccoonSpin(GameObject gameObj) : base(gameObj) { } - protected override void awake() { diff --git a/Assets/Scripts/ThirdPersonCamera.cs b/Assets/Scripts/ThirdPersonCamera.cs index 141865e8..fed26ae9 100644 --- a/Assets/Scripts/ThirdPersonCamera.cs +++ b/Assets/Scripts/ThirdPersonCamera.cs @@ -15,7 +15,6 @@ namespace SHADE_Scripting public float turnSpeedPitch = 0.3f; public float turnSpeedYaw = 0.5f; public float pitchClamp = 45.0f; - public ThirdPersonCamera(GameObject go) : base(go) { } protected override void awake() { diff --git a/SHADE_Managed/src/Scripts/Script.cxx b/SHADE_Managed/src/Scripts/Script.cxx index 9d6cadb8..017242d6 100644 --- a/SHADE_Managed/src/Scripts/Script.cxx +++ b/SHADE_Managed/src/Scripts/Script.cxx @@ -93,6 +93,11 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* "All-time" Lifecycle Functions */ /*---------------------------------------------------------------------------------*/ + void Script::Initialize(GameObject newOwner) + { + owner = newOwner; + } + void Script::OnAttached() { SAFE_NATIVE_CALL_BEGIN @@ -198,9 +203,8 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Constructors */ /*---------------------------------------------------------------------------------*/ - Script::Script(GameObject gameObj) - : owner { gameObj } - , OnGizmosDrawOverriden { false } + Script::Script() + : OnGizmosDrawOverriden { false } {} /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Scripts/Script.hxx b/SHADE_Managed/src/Scripts/Script.hxx index bbe36784..fb564d27 100644 --- a/SHADE_Managed/src/Scripts/Script.hxx +++ b/SHADE_Managed/src/Scripts/Script.hxx @@ -165,7 +165,7 @@ namespace SHADE internal: /*-----------------------------------------------------------------------------*/ - /* Properties */ + /* Fields */ /*-----------------------------------------------------------------------------*/ /// /// If true, the OnGizmosDraw function was overridden. @@ -176,6 +176,10 @@ namespace SHADE /* "All-Time" Lifecycle Functions */ /*-----------------------------------------------------------------------------*/ /// + /// Used to initialize a Script with a GameObject. + /// + void Initialize(GameObject newOwner); + /// /// Used to call onAttached(). This is called immediately when this script is /// attached to a GameObject. /// @@ -272,13 +276,9 @@ namespace SHADE /* Constructors */ /*-----------------------------------------------------------------------------*/ /// - /// Constructor for Script to tie it to a specific GameObject. - /// Constructors of derived Scripts should call this Constructor. + /// Default Constructor /// - /// - /// GameObject that this Script will be tied to. - /// - Script(GameObject gameObj); + Script(); /*-----------------------------------------------------------------------------*/ /* Virtual "All-Time" Lifecycle Functions */ diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index 6b33b31b..a6f978a1 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -40,8 +40,7 @@ namespace SHADE T ScriptStore::AddScript(Entity entity) { // Create the script and add it in - array^ params = gcnew array{GameObject(entity)}; - Script^ script = safe_cast(System::Activator::CreateInstance(T::typeid, params)); + Script^ script = safe_cast(System::Activator::CreateInstance(T::typeid)); return safe_cast(AddScript(entity, script)); } @@ -72,6 +71,7 @@ namespace SHADE } // Add the script in + script->Initialize(GameObject(entity)); entityScriptList->Insert(System::Math::Clamp(index, 0, entityScriptList->Count), script); if (Application::IsPlaying) { @@ -130,6 +130,7 @@ namespace SHADE std::ostringstream oss; oss << "[ScriptStore] Failed to add Script named \"" << Convert::ToNative(scriptName) << "\" to Entity #" << entity << "! (" << Convert::ToNative(e->GetType()->Name) << ")"; + oss << Convert::ToNative(e->ToString()); Debug::LogError(oss.str()); return false; } From 895eb56cc01cb7fc17446fecda47020fd3e5e8e6 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Sun, 13 Nov 2022 17:26:21 +0800 Subject: [PATCH 09/10] Integrate cam arm --- SHADE_Engine/src/Camera/SHCameraSystem.cpp | 8 ------ .../ViewportWindow/SHEditorViewport.cpp | 27 ++++++++++++++++--- .../ViewportWindow/SHEditorViewport.h | 2 ++ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/SHADE_Engine/src/Camera/SHCameraSystem.cpp b/SHADE_Engine/src/Camera/SHCameraSystem.cpp index 8f886926..ff942666 100644 --- a/SHADE_Engine/src/Camera/SHCameraSystem.cpp +++ b/SHADE_Engine/src/Camera/SHCameraSystem.cpp @@ -63,14 +63,6 @@ namespace SHADE } UpdateCameraComponent(editorCamera); - - if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::LEFT_ALT)) - { - UpdateEditorArm(dt, true, SHVec3{ 0.0f }); - } - else - UpdateEditorArm(dt, false, SHVec3{ 0.0f }); - } void SHCameraSystem::UpdateEditorArm(double dt,bool active ,SHVec3 const& targetPos) noexcept diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp index 7b3b5411..d0b32ff5 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp @@ -33,14 +33,32 @@ namespace SHADE void SHEditorViewport::Update() { SHEditorWindow::Update(); - if (shouldUpdateCamera) + auto camSystem = SHSystemManager::GetSystem(); + SHEditor* editor = SHSystemManager::GetSystem(); + + if (!editor->selectedEntities.empty()) + { + if (SHTransformComponent* transform = SHComponentManager::GetComponent_s(editor->selectedEntities.front())) + { + targetPos = transform->GetWorldPosition(); + } + else + { + targetPos = {}; + } + } + else + { + targetPos = {}; + } + if (shouldUpdateCamera || shouldUpdateCamArm) { - auto camSystem = SHSystemManager::GetSystem(); camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime()); shouldUpdateCamera = false; } + camSystem->UpdateEditorArm(SHFrameRateController::GetRawDeltaTime(), shouldUpdateCamArm, targetPos); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - SHEditor* editor = SHSystemManager::GetSystem(); if (Begin()) { @@ -64,6 +82,9 @@ namespace SHADE shouldUpdateCamera = true; } + + shouldUpdateCamArm = ImGui::IsWindowHovered() && ImGui::IsKeyDown(ImGuiKey_LeftAlt) && ImGui::IsMouseDown(ImGuiMouseButton_Left); + if (editor->editorState != SHEditor::State::PLAY && ImGui::IsWindowFocused() && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) { if (ImGui::IsKeyReleased(ImGuiKey_W)) diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.h b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.h index 0fae4317..8f49c514 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.h +++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.h @@ -29,5 +29,7 @@ namespace SHADE void DrawMenuBar() noexcept; SHVec2 beginCursorPos; bool shouldUpdateCamera = false; + bool shouldUpdateCamArm = false; + SHVec3 targetPos; };//class SHEditorViewport }//namespace SHADE From b1c004771c790fcbefd169ed1a8f33ce76570c21 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Sun, 13 Nov 2022 17:26:35 +0800 Subject: [PATCH 10/10] Gave the damn entities names cuz i was going crazy --- Assets/Scenes/M2Scene.shade | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Assets/Scenes/M2Scene.shade b/Assets/Scenes/M2Scene.shade index b2a5683f..be4ce4f1 100644 --- a/Assets/Scenes/M2Scene.shade +++ b/Assets/Scenes/M2Scene.shade @@ -1,5 +1,5 @@ - EID: 0 - Name: Default + Name: Camera IsActive: true NumberOfChildren: 0 Components: @@ -22,7 +22,7 @@ Strength: 0 Scripts: ~ - EID: 1 - Name: Default + Name: Floor IsActive: true NumberOfChildren: 0 Components: @@ -92,7 +92,7 @@ Position Offset: {x: 0, y: 0.5, z: 0} Scripts: ~ - EID: 3 - Name: Default + Name: Empty IsActive: true NumberOfChildren: 0 Components: @@ -102,7 +102,7 @@ Scale: {x: 1, y: 1, z: 1} Scripts: ~ - EID: 4 - Name: Default + Name: Empty2 IsActive: true NumberOfChildren: 0 Components: @@ -112,7 +112,7 @@ Scale: {x: 1, y: 1, z: 1} Scripts: ~ - EID: 9 - Name: Default + Name: Bag IsActive: true NumberOfChildren: 0 Components: @@ -160,7 +160,7 @@ Position Offset: {x: 0, y: 0.5, z: 0} Scripts: ~ - EID: 7 - Name: Default + Name: BigBoi IsActive: true NumberOfChildren: 0 Components: @@ -173,7 +173,7 @@ Material: 126974645 Scripts: ~ - EID: 8 - Name: Default + Name: AmbientLight IsActive: true NumberOfChildren: 0 Components: