From b89be05cebf8ee0052c8194c5121a7ae2e33bf18 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Sat, 4 Feb 2023 01:20:01 +0800 Subject: [PATCH 1/6] Shortcuts in hierarchy panel cannot be pressed when any widget is focused --- .../HierarchyPanel/SHHierarchyPanel.cpp | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index a7e85ad4..7aeed173 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -96,30 +96,32 @@ namespace SHADE } ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal); - if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_A)) + if (!ImGui::IsAnyItemFocused()) { - SelectAllEntities(); - } - if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_C)) - { - CopySelectedEntities(); - } - if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && !ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V)) - { - PasteEntities(); - } - if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V)) - { - if (editor->selectedEntities.size() == 1) + if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_A)) { - PasteEntities(editor->selectedEntities.back()); + SelectAllEntities(); + } + if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_C)) + { + CopySelectedEntities(); + } + if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && !ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V)) + { + PasteEntities(); + } + if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V)) + { + if (editor->selectedEntities.size() == 1) + { + PasteEntities(editor->selectedEntities.back()); + } + } + if (ImGui::IsKeyReleased(ImGuiKey_Delete)) + { + DeleteSelectedEntities(); } } - if (ImGui::IsKeyReleased(ImGuiKey_Delete)) - { - DeleteSelectedEntities(); - } - } if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) { From 42f4c1c75ebfa6922a88b5aa5341d3aff84811b3 Mon Sep 17 00:00:00 2001 From: SHAM-DP Date: Fri, 24 Feb 2023 20:21:09 +0800 Subject: [PATCH 2/6] Aspect Ratio WIP --- .../ViewportWindow/SHEditorViewport.cpp | 74 ++++++++++++++++++- .../ViewportWindow/SHEditorViewport.h | 13 +++- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp index 8c32b1c5..7ea4d799 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp @@ -59,7 +59,7 @@ namespace SHADE camSystem->UpdateEditorArm(SHFrameRateController::GetRawDeltaTime(), shouldUpdateCamArm, targetPos); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - + if (Begin()) { ImGuizmo::SetDrawlist(); @@ -121,12 +121,22 @@ namespace SHADE //auto pos = ImGui::GetCursorPos(); //windowCursorPos = {} + if (beginContentRegionAvailable.x == 0 || beginContentRegionAvailable.y == 0) { beginContentRegionAvailable = windowSize; } - gfxSystem->PrepareResize(static_cast(beginContentRegionAvailable.x), static_cast(beginContentRegionAvailable.y)); + + //beginContentRegionAvailable = CalculateWindowSize(beginContentRegionAvailable); + SHVec2 viewportSize = CalculateWindowSize(beginContentRegionAvailable); + gfxSystem->PrepareResize(static_cast(viewportSize.x), static_cast(viewportSize.y)); shouldUpdateCamera = true; + //if (aspectRatio != AspectRatio::FREE && (ImGui::IsMouseDown(ImGuiMouseButton_Left) || ImGui::IsMouseReleased(ImGuiMouseButton_Left))) + //{ + // windowSize = CalculateWindowSize(windowSize); + // beginContentRegionAvailable = CalculateWindowSize(beginContentRegionAvailable); + // ImGui::SetWindowSize(windowName.data(), CalculateWindowSize(windowSize)); + //} } void SHEditorViewport::OnPosChange() @@ -194,13 +204,73 @@ namespace SHADE ImGui::PopStyleColor(); ImGui::EndDisabled(); + //TODO: Shift to constructor + auto arRTTRtype = rttr::type::get(); + auto enumAlign = arRTTRtype.get_enumeration(); + auto names = enumAlign.get_names(); + std::vector arNames; + for (auto const& name : names) + { + arNames.push_back(name.data()); + } + int currentAR = static_cast(aspectRatio); + ImGui::SetNextItemWidth(80.0f); + if (ImGui::Combo("Aspect Ratio", ¤tAR, arNames.data(), arNames.size())) + { + aspectRatio = static_cast(currentAR); + windowSize = CalculateWindowSize(windowSize); + ImGui::SetWindowSize(windowSize); + //beginContentRegionAvailable = CalculateWindowSize(beginContentRegionAvailable); + //OnResize(); + } + auto camSystem = SHSystemManager::GetSystem(); auto editorCamera = camSystem->GetEditorCamera(); //ImGui::SetNextItemWidth(10.0f); SHEditorWidgets::SliderFloat("CamSpeed", 0.0f, 5.0f, [editorCamera] {return editorCamera->movementSpeed; }, [editorCamera](float const& value) {editorCamera->movementSpeed = value; }); SHEditorWidgets::DragVec3("TurnSpeed", { "X", "Y", "Z" }, [editorCamera] {return editorCamera->turnSpeed; }, [editorCamera](SHVec3 const& value) {editorCamera->turnSpeed = value; }); + //if(ImGui::BeginCombo("Aspect Ratio", arNames[(uint8_t)aspectRatio].data())) + //{ + // auto nameIt = names.begin(); + // auto valueIt = values.end(); + // while(nameIt != names.end() && valueIt != values.end()) + // { + // if ImGui::Beg + // } + //} + ImGui::EndMenuBar(); } } + + SHVec2 SHEditorViewport::CalculateWindowSize(SHVec2 const& rhs) noexcept +{ + switch (aspectRatio) + { + case SHADE::SHEditorViewport::AspectRatio::FREE: + return rhs; + case SHADE::SHEditorViewport::AspectRatio::AR16_9: + return SHVec2(rhs.x, rhs.x * 0.5625f); + case SHADE::SHEditorViewport::AspectRatio::AR21_9: + return SHVec2(rhs.x, rhs.x * 0.42857f); + case SHADE::SHEditorViewport::AspectRatio::AR21_10: + return SHVec2(rhs.x, rhs.x * 0.47619f); + default: + return rhs; + } + } + }//namespace SHADE + +RTTR_REGISTRATION +{ + using namespace rttr; + using namespace SHADE; + registration::enumeration("AspectRatio")( + value("FREE", SHEditorViewport::AspectRatio::FREE), + value("16:9", SHEditorViewport::AspectRatio::AR16_9), + value("21:9", SHEditorViewport::AspectRatio::AR21_9), + value("21:10", SHEditorViewport::AspectRatio::AR21_10) + ); +} diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.h b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.h index 8f49c514..d7fb0f39 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.h +++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.h @@ -16,7 +16,15 @@ namespace SHADE { class SHEditorViewport final : public SHEditorWindow { + public: + enum class AspectRatio : uint8_t + { + FREE, + AR16_9, + AR21_9, + AR21_10 + }; SHEditorViewport(); void Init() override; void Update() override; @@ -27,9 +35,12 @@ namespace SHADE void OnPosChange() override; private: void DrawMenuBar() noexcept; - SHVec2 beginCursorPos; + SHVec2 CalculateWindowSize(SHVec2 const& rhs) noexcept; + bool shouldUpdateCamera = false; bool shouldUpdateCamArm = false; + AspectRatio aspectRatio {AspectRatio::FREE}; + SHVec2 beginCursorPos; SHVec3 targetPos; };//class SHEditorViewport }//namespace SHADE From 38c6cb6fed12f0d86f86b053be073a086d3f8679 Mon Sep 17 00:00:00 2001 From: SHAM-DP Date: Fri, 24 Feb 2023 20:34:49 +0800 Subject: [PATCH 3/6] Prefab WIP Added component status --- .../Serialization/Prefab/SHPrefabManager.cpp | 19 +++++++++- .../Serialization/Prefab/SHPrefabManager.h | 20 +++++++++- .../src/Serialization/SHSerialization.cpp | 37 ++++++++++++++----- .../src/Serialization/SHSerialization.h | 7 ++-- 4 files changed, 66 insertions(+), 17 deletions(-) diff --git a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp index 8ab098b8..048298ed 100644 --- a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp +++ b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp @@ -1,5 +1,9 @@ #include "SHpch.h" #include "SHPrefabManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" +#include "Assets/SHAssetManager.h" +#include "Assets/Asset Types/SHPrefabAsset.h" +#include "Serialization/SHSerialization.h" namespace SHADE { @@ -32,7 +36,7 @@ namespace SHADE { if (prefabMap.contains(prefabAssetID)) { - prefabMap[prefabAssetID].insert(eid); + prefabMap[prefabAssetID].push_back(eid); } } @@ -40,10 +44,21 @@ namespace SHADE { if (prefabMap.contains(prefabAssetID)) { - prefabMap[prefabAssetID].erase(eid); + std::ranges::remove(prefabMap[prefabAssetID], eid); } } + void SHPrefabManager::SaveEntityAsPrefab(EntityID const& eid) noexcept + { + SHEntity* const entity = SHEntityManager::GetEntityByID(eid); + AssetID const assetID = SHAssetManager::CreateNewAsset(AssetType::PREFAB, entity->name); + + auto assetData = SHAssetManager::GetData(assetID); + assetData->data = SHSerialization::SerializeEntitiesToString({eid}); + + SHAssetManager::SaveAsset(assetID); + } + void SHPrefabManager::Clear() noexcept { prefabMap.clear(); diff --git a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h index 37c317ed..29d47c5c 100644 --- a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h +++ b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h @@ -2,7 +2,8 @@ #include "Assets/SHAssetMacros.h" #include "ECS_Base/SHECSMacros.h" -#include +#include "ECS_Base/General/SHFamily.h" +#include "ECS_Base/Components/SHComponent.h" #include @@ -11,7 +12,17 @@ namespace SHADE class SHPrefabManager { public: - using PrefabMap = std::unordered_map>; + + enum class PrefabEntityComponentStatus : uint8_t + { + PES_UNCHANGED = 0, + PES_MODIFIED, + PES_ADDED, + PES_REMOVED + }; + + using PrefabMap = std::unordered_map>; + using PrefabEntitiesComponentStatusData = std::unordered_map,PrefabEntityComponentStatus>>; static void AddPrefab(AssetID const& prefabAssetID) noexcept; static void RemovePrefab(AssetID const& prefabAssetID) noexcept; @@ -19,10 +30,15 @@ namespace SHADE static void UpdateAllPrefabEntities(AssetID const& prefabAssetID) noexcept; static void AddEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept; static void RemoveEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept; + static void SaveEntityAsPrefab(EntityID const& eid) noexcept; static void Clear() noexcept; static bool Empty() noexcept; private: static PrefabMap prefabMap; + static PrefabEntitiesComponentStatusData prefabEntitiesComponentStatusData; + + friend class SHSerialization; + friend class SHSerializationHelper; }; } diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index febca024..c291e4ea 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -23,7 +23,7 @@ namespace SHADE auto assetData = SHAssetManager::GetData(sceneAssetID); if(!assetData) { - SHLOG_ERROR("Asset does not exist: {}", sceneAssetID); + SHLOG_ERROR("Serialization: Asset does not exist: {}", sceneAssetID); return false; } YAML::Emitter out; @@ -45,7 +45,7 @@ namespace SHADE auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); auto root = sceneGraph.GetRoot(); - SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node."); + SHASSERT(root != nullptr, "Serialization: Root is null. Failed to serialize scene to node."); auto const& children = root->GetChildren(); out << YAML::BeginSeq; @@ -105,7 +105,7 @@ namespace SHADE auto assetData = SHAssetManager::GetData(sceneAssetID); if(!assetData) { - SHLOG_ERROR("Attempted to load scene that doesn't exist {}", sceneAssetID) + SHLOG_ERROR("Serialization: Attempted to load scene that doesn't exist {}", sceneAssetID) SHSceneManager::SetCurrentSceneAssetID(0); return NewSceneName.data(); } @@ -119,7 +119,7 @@ namespace SHADE } if (createdEntities.empty()) { - SHLOG_ERROR("Failed to create entities from deserializaiton") + SHLOG_ERROR("Serialization: Failed to create entities from deserialization") return NewSceneName.data(); } auto entityVecIt = createdEntities.begin(); @@ -139,26 +139,33 @@ namespace SHADE return assetData->name; } - void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out) + void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out, bool isPrefab /*= false*/, EntityID* entityIndex /*= nullptr*/) { out << SerializeEntityToNode(entityNode); + if(isPrefab) + ++(*entityIndex); + auto const& children = entityNode->GetChildren(); for (auto const& child : children) { - EmitEntity(child, out); + EmitEntity(child, out, isPrefab); } } - std::string SHSerialization::SerializeEntitiesToString(std::vector const& entities) noexcept + std::string SHSerialization::SerializeEntitiesToString(std::vector const& entities, bool isPrefab) noexcept { YAML::Emitter out; YAML::Node node; auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); out << YAML::BeginSeq; + EntityID entityIndex = 0; for (auto const& eid : entities) { auto entityNode = sceneGraph.GetNode(eid); - EmitEntity(entityNode, out); + if(isPrefab) + EmitEntity(entityNode, out, isPrefab); + else + EmitEntity(entityNode, out); } out << YAML::EndSeq; return std::string(out.c_str()); @@ -179,8 +186,11 @@ namespace SHADE } } - YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode) + YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode, bool isPrefab /*= false*/, EntityID* entityIndex /*= nullptr*/) { + if(!sceneNode) + return YAML::Node(); + YAML::Node node; auto eid = sceneNode->GetEntityID(); auto entity = SHEntityManager::GetEntityByID(eid); @@ -190,7 +200,14 @@ namespace SHADE return node; } node.SetStyle(YAML::EmitterStyle::Block); + node[EIDNode] = eid; + + if(isPrefab) //TODO: Set asset id for top level prefab entity only + { + node[PrefabID] = 0; + } + node[EntityNameNode] = entity->name; node[IsActiveNode] = sceneNode->IsActive(); auto const& children = sceneNode->GetChildren(); @@ -236,7 +253,7 @@ namespace SHADE } if (createdEntities.empty()) { - SHLOG_ERROR("Failed to create entities from deserializaiton") + SHLOG_ERROR("Failed to create entities from deserialization") return createdEntities; } //auto entityVecIt = createdEntities.begin(); diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h index dd487662..9d8362ed 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.h +++ b/SHADE_Engine/src/Serialization/SHSerialization.h @@ -24,6 +24,7 @@ namespace SHADE constexpr const char* IsActiveNode = "IsActive"; constexpr const char* NumberOfChildrenNode = "NumberOfChildren"; constexpr const char* ScriptsNode = "Scripts"; + constexpr const char* PrefabID = "PrefabID"; class SH_API SHSerialization { @@ -38,11 +39,11 @@ namespace SHADE static std::string DeserializeSceneFromFile(AssetID const& sceneAssetID) noexcept; - static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out); + static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out, bool isPrefab = false, EntityID* entityIndex = nullptr); - static std::string SerializeEntitiesToString(std::vector const& entities) noexcept; + static std::string SerializeEntitiesToString(std::vector const& entities, bool isPrefab = false) noexcept; //static void SerializeEntityToFile(std::filesystem::path const& path); - static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode); + static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode, bool isPrefab = false, EntityID* entityIndex = nullptr); static CreatedEntitiesList DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept; From ff2b9b4af38d6918beca1fa838191f2d20614ae1 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Sun, 26 Feb 2023 22:44:39 +0800 Subject: [PATCH 4/6] Rudimentary Prefab (no resolution) Warning Fixes --- Assets/Editor/Editor.SHConfig | 4 - Assets/Prefabs/====Raccoon====.shprefab | 147 ++++++++++++++++++ .../Prefabs/====Raccoon====.shprefab.shmeta | 3 + .../AssetBrowser/SHAssetBrowser.cpp | 34 ++++ .../HierarchyPanel/SHHierarchyPanel.cpp | 10 +- .../Serialization/Prefab/SHPrefabManager.cpp | 27 +++- .../Serialization/Prefab/SHPrefabManager.h | 3 +- .../src/Serialization/SHSerialization.cpp | 35 +++-- .../src/Serialization/SHSerialization.h | 5 +- .../Serialization/SHSerializationHelper.hpp | 1 + 10 files changed, 243 insertions(+), 26 deletions(-) delete mode 100644 Assets/Editor/Editor.SHConfig create mode 100644 Assets/Prefabs/====Raccoon====.shprefab create mode 100644 Assets/Prefabs/====Raccoon====.shprefab.shmeta diff --git a/Assets/Editor/Editor.SHConfig b/Assets/Editor/Editor.SHConfig deleted file mode 100644 index 37edf50c..00000000 --- a/Assets/Editor/Editor.SHConfig +++ /dev/null @@ -1,4 +0,0 @@ -Start Maximized: true -Working Scene ID: 97158628 -Window Size: {x: 1920, y: 1013} -Style: 0 \ No newline at end of file diff --git a/Assets/Prefabs/====Raccoon====.shprefab b/Assets/Prefabs/====Raccoon====.shprefab new file mode 100644 index 00000000..59b42ef2 --- /dev/null +++ b/Assets/Prefabs/====Raccoon====.shprefab @@ -0,0 +1,147 @@ +- EID: 0 + PrefabID: 117058283 + Name: ====Raccoon==== + IsActive: true + NumberOfChildren: 2 + Components: ~ + Scripts: ~ +- EID: 1 + Name: Player + IsActive: true + NumberOfChildren: 3 + Components: + Transform Component: + Translate: {x: 2.35245037, y: 0.38365531, z: 7.10571432} + Rotate: {x: -0, y: 0, z: -0} + Scale: {x: 0.999999881, y: 1, z: 0.999999881} + IsActive: true + Renderable Component: + Mesh: 149697411 + Material: 126974645 + IsActive: true + RigidBody Component: + Type: Dynamic + Drag: 0.00999999978 + Angular Drag: 0.100000001 + Use Gravity: false + Interpolate: false + Sleeping Enabled: true + Freeze Position X: false + Freeze Position Y: true + Freeze Position Z: false + Freeze Rotation X: true + Freeze Rotation Y: true + Freeze Rotation Z: true + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 0 + Type: Box + Half Extents: {x: 0.400000006, y: 0.5, z: 0.300000012} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0.25, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true + Scripts: + - Type: PlayerController + Enabled: true + respawnPoint: 239 + currentState: 0 + maxMoveVel: 3 + moveForce: 50 + sprintMultiplier: 1.5 + rotationFactorPerFrame: 5 + maxJumpHeight: 2 + maxJumpTime: 0.75 + fallMultipler: 3 + lightMultiper: 0.899999976 + mediumMultiper: 0.699999988 + heavyMultiper: 0.5 + - Type: PickAndThrow + Enabled: true + throwForce: [10, 8, 10] + cameraArmOffSet: [0.25, 0.600000024, 0.200000003] + delayTimer: 1 + aimingLength: 1 + throwItem: false + rayDistance: 0.75 + rayHeight: 0.100000001 +- EID: 2 + Name: HoldingPoint + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: 0.899999976, z: 0.200000286} + Rotate: {x: 0, y: 0, z: -0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Scripts: ~ +- EID: 3 + Name: PlayerCamera + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: -5.96046448e-08, z: 0} + Rotate: {x: 0, y: 6.28318548, z: 2.23517329e-08} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Camera Component: + Position: {x: 2.12735963, y: 0.362327784, z: 7.98933029} + Pitch: 0 + Yaw: 360 + Roll: 1.28065994e-06 + Width: 2560 + Near: 0.00999999978 + Far: 10000 + Perspective: true + FOV: 45 + IsActive: true + Camera Arm Component: + Arm Pitch: 0 + Arm Yaw: 0 + Arm Length: 3 + Look At Camera Origin: true + Target Offset: {x: 0, y: 0.75, z: 0} + Camera Collision: true + IsActive: true + Scripts: + - Type: SHADE_Scripting.ThirdPersonCamera + Enabled: true + armLength: 3 + turnSpeedPitch: 0.200000003 + turnSpeedYaw: 0.400000006 + pitchClamp: 45 + inverseXControls: false + inverseYControls: false + lowerClamp: 5 +- EID: 4 + Name: PlayerBag + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: -2.98023224e-08, z: 4.76837158e-07} + Rotate: {x: 0, y: 0, z: -0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 144838771 + Material: 123745521 + IsActive: true + Scripts: ~ +- EID: 5 + Name: RespawnPoint + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.5, y: 0.660660267, z: 7} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Scripts: ~ \ No newline at end of file diff --git a/Assets/Prefabs/====Raccoon====.shprefab.shmeta b/Assets/Prefabs/====Raccoon====.shprefab.shmeta new file mode 100644 index 00000000..8fc77e7e --- /dev/null +++ b/Assets/Prefabs/====Raccoon====.shprefab.shmeta @@ -0,0 +1,3 @@ +Name: ====Raccoon==== +ID: 117058283 +Type: 6 diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp index 791396df..dce3ffbd 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -19,6 +19,10 @@ #include "Tools/Utilities/SHStringUtilities.h" #include #include +#include "Assets/Asset Types/SHPrefabAsset.h" +#include "Serialization/SHSerialization.h" +#include +#include "Serialization/Prefab/SHPrefabManager.h" namespace SHADE { @@ -247,6 +251,7 @@ namespace SHADE const ImRect childRect = DrawAsset(file.assetMeta, file.ext); return childRect; } + return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); } ImRect SHAssetBrowser::DrawAsset(SHAsset const* const asset, FileExt const& ext /*= ""*/) noexcept @@ -365,6 +370,35 @@ namespace SHADE } } + if(ImGui::BeginPopupContextItem()) + { + switch (asset->type) + { + case AssetType::INVALID: break; + case AssetType::SHADER: break; + case AssetType::SHADER_BUILT_IN: break; + case AssetType::TEXTURE: break; + case AssetType::MESH: break; + case AssetType::SCENE: + break; + case AssetType::PREFAB: + { + if(ImGui::Selectable("Insert into scene")) + { + auto createdEntitiesList = SHSerialization::DeserializeEntitiesFromString(SHAssetManager::GetData(asset->id)->data); + SHEditorWindowManager::GetEditorWindow()->SetScrollTo(createdEntitiesList.begin()->second); + SHPrefabManager::AddEntity(asset->id, createdEntitiesList.begin()->second); + } + } + break; + case AssetType::MATERIAL: break; + case AssetType::SCRIPT: break; + case AssetType::MAX_COUNT: break; + default:; + } + ImGui::EndPopup(); + } + if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index a7e85ad4..a24d46e2 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -26,6 +26,9 @@ #include "Serialization/SHSerialization.h" #include "Tools/Utilities/SHClipboardUtilities.h" #include "Tools/Utilities/SHStringUtilities.h" +#include "Serialization/Prefab/SHPrefabManager.h" +#include "../SHEditorWindowManager.h" +#include "../AssetBrowser/SHAssetBrowser.h" namespace SHADE @@ -315,7 +318,7 @@ namespace SHADE const ImGuiTreeNodeFlags nodeFlags = ((isSelected) ? ImGuiTreeNodeFlags_Selected : 0) | ((children.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow); //Draw Node - bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast(eid), nodeFlags, "%u: %s", SHEntityManager::GetEntityIndex(eid), entity->name.c_str()); + bool isNodeOpen = ImGui::TreeNodeEx((void*)(eid), nodeFlags, "%u: %s", SHEntityManager::GetEntityIndex(eid), entity->name.c_str()); if(!filter.empty()) { @@ -388,6 +391,11 @@ namespace SHADE //SHEntityManager::DestroyEntity(eid); DeleteSelectedEntities(); } + if(ImGui::Selectable("Save entity as Prefab")) + { + SHPrefabManager::SaveEntityAsPrefab(eid); + SHEditorWindowManager::GetEditorWindow()->QueueRefresh(); + } if ((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data())) { diff --git a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp index 048298ed..b19a20df 100644 --- a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp +++ b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp @@ -9,9 +9,21 @@ namespace SHADE { SHPrefabManager::PrefabMap SHPrefabManager::prefabMap{}; + AssetID SHPrefabManager::GetPrefabAssetID(EntityID eid) noexcept + { + for(auto const& [assetId, entityList] : prefabMap) + { + if(std::ranges::find(entityList, eid) != entityList.end()) + { + return assetId; + } + } + return 0; + } + void SHPrefabManager::AddPrefab(AssetID const& prefabAssetID) noexcept { - prefabMap.insert({ prefabAssetID, {} }); + prefabMap[prefabAssetID] = {}; } void SHPrefabManager::RemovePrefab(AssetID const& prefabAssetID) noexcept @@ -34,17 +46,16 @@ namespace SHADE void SHPrefabManager::AddEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept { - if (prefabMap.contains(prefabAssetID)) - { - prefabMap[prefabAssetID].push_back(eid); - } + + prefabMap[prefabAssetID].push_back(eid); + } void SHPrefabManager::RemoveEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept { if (prefabMap.contains(prefabAssetID)) { - std::ranges::remove(prefabMap[prefabAssetID], eid); + (void)std::ranges::remove(prefabMap[prefabAssetID], eid); } } @@ -52,9 +63,9 @@ namespace SHADE { SHEntity* const entity = SHEntityManager::GetEntityByID(eid); AssetID const assetID = SHAssetManager::CreateNewAsset(AssetType::PREFAB, entity->name); - + AddEntity(assetID, eid); auto assetData = SHAssetManager::GetData(assetID); - assetData->data = SHSerialization::SerializeEntitiesToString({eid}); + assetData->data = SHSerialization::SerializeEntityToString(eid); SHAssetManager::SaveAsset(assetID); } diff --git a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h index 29d47c5c..64e8f24f 100644 --- a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h +++ b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h @@ -24,6 +24,7 @@ namespace SHADE using PrefabMap = std::unordered_map>; using PrefabEntitiesComponentStatusData = std::unordered_map,PrefabEntityComponentStatus>>; + static AssetID GetPrefabAssetID(EntityID eid) noexcept; static void AddPrefab(AssetID const& prefabAssetID) noexcept; static void RemovePrefab(AssetID const& prefabAssetID) noexcept; static void ClearPrefab(AssetID const& prefabAssetID) noexcept; @@ -39,6 +40,6 @@ namespace SHADE static PrefabEntitiesComponentStatusData prefabEntitiesComponentStatusData; friend class SHSerialization; - friend class SHSerializationHelper; + friend struct SHSerializationHelper; }; } diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index c291e4ea..464b1d9d 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -15,6 +15,7 @@ #include "ECS_Base/Managers/SHSystemManager.h" #include "Scripting/SHScriptEngine.h" #include "Tools/FileIO/SHFileIO.h" +#include "Prefab/SHPrefabManager.h" namespace SHADE { @@ -62,6 +63,7 @@ namespace SHADE EntityID eid{MAX_EID}, oldEID{MAX_EID}; if (!node) return eid; + if (node[EIDNode]) oldEID = eid = node[EIDNode].as(); std::string name = "UnnamedEntitiy"; @@ -141,18 +143,18 @@ namespace SHADE void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out, bool isPrefab /*= false*/, EntityID* entityIndex /*= nullptr*/) { - out << SerializeEntityToNode(entityNode); + out << SerializeEntityToNode(entityNode, isPrefab, entityIndex); if(isPrefab) ++(*entityIndex); auto const& children = entityNode->GetChildren(); for (auto const& child : children) { - EmitEntity(child, out, isPrefab); + EmitEntity(child, out, isPrefab, entityIndex); } } - std::string SHSerialization::SerializeEntitiesToString(std::vector const& entities, bool isPrefab) noexcept + std::string SHSerialization::SerializeEntitiesToString(std::vector const& entities) noexcept { YAML::Emitter out; YAML::Node node; @@ -162,15 +164,27 @@ namespace SHADE for (auto const& eid : entities) { auto entityNode = sceneGraph.GetNode(eid); - if(isPrefab) - EmitEntity(entityNode, out, isPrefab); - else - EmitEntity(entityNode, out); + EmitEntity(entityNode, out); } out << YAML::EndSeq; return std::string(out.c_str()); } + std::string SHSerialization::SerializeEntityToString(EntityID eid) noexcept + { + YAML::Emitter out; + YAML::Node node; + auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); + out << YAML::BeginSeq; + EntityID entityIndex = 0; + + auto entityNode = sceneGraph.GetNode(eid); + EmitEntity(entityNode, out, true, &entityIndex); + + out << YAML::EndSeq; + return std::string(out.c_str()); + } + //void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path) //{ //} @@ -201,11 +215,12 @@ namespace SHADE } node.SetStyle(YAML::EmitterStyle::Block); - node[EIDNode] = eid; + node[EIDNode] = (entityIndex) ? *entityIndex : eid; - if(isPrefab) //TODO: Set asset id for top level prefab entity only + AssetID prefabAssetID = SHPrefabManager::GetPrefabAssetID(eid); + if(prefabAssetID != 0) { - node[PrefabID] = 0; + node[PrefabID] = prefabAssetID; } node[EntityNameNode] = entity->name; diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h index 9d8362ed..c8971f84 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.h +++ b/SHADE_Engine/src/Serialization/SHSerialization.h @@ -38,10 +38,11 @@ namespace SHADE static std::string DeserializeSceneFromFile(AssetID const& sceneAssetID) noexcept; - static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out, bool isPrefab = false, EntityID* entityIndex = nullptr); - static std::string SerializeEntitiesToString(std::vector const& entities, bool isPrefab = false) noexcept; + static std::string SerializeEntitiesToString(std::vector const& entities) noexcept; + + static std::string SerializeEntityToString(EntityID eid) noexcept; //static void SerializeEntityToFile(std::filesystem::path const& path); static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode, bool isPrefab = false, EntityID* entityIndex = nullptr); diff --git a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp index 08f1262f..a4936528 100644 --- a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp +++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp @@ -135,6 +135,7 @@ namespace SHADE } } + return YAML::Node(); } template From dabc94a845407c63a33f5684926db9864abb3580 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Sun, 26 Feb 2023 23:26:24 +0800 Subject: [PATCH 5/6] editor cam pos display as requested --- .../EditorWindow/MenuBar/SHEditorMenuBar.cpp | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index e8c943c2..d0c71265 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -26,6 +26,8 @@ #include "Serialization/Configurations/SHConfigurationManager.h" #include "Editor/EditorWindow/SHEditorWindowManager.h" #include "Physics/System/SHPhysicsDebugDrawSystem.h" +#include "Camera/SHCameraSystem.h" +#include "Tools/Utilities/SHClipboardUtilities.h" const std::string LAYOUT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts" }; @@ -154,7 +156,39 @@ namespace SHADE ImGui::PushStyleColor(ImGuiCol_WindowBg, ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg]); if (ImGui::BeginViewportSideBar("MainStatusBar", ImGui::GetMainViewport(), ImGuiDir_Down, menuBarHeight, editorMenuBarFlags)) { - ImGui::Text("Entity count: %zu", SHEntityManager::GetEntityCount()); + auto camSystem = SHSystemManager::GetSystem(); + std::string editorCamPosText{}; + auto editorCam = camSystem->GetEditorCamera(); + if(editorCam) + { + auto editorCamPos = editorCam->GetPosition(); + editorCamPosText = std::format("Editor Cam [X: {:.3f}, Y: {:.3f}, Z: {:.3f}]", editorCamPos.x, editorCamPos.y, editorCamPos.z); + + //ImGui::Text(editorCamPosText.data()); + } + ImGui::Text("Entity count: %zu %s", SHEntityManager::GetEntityCount(), editorCamPosText.data()); + if(ImGui::BeginPopupContextItem("EditorCamPosContext")) + { + if(editorCam) + { + if(ImGui::Selectable("Copy Editor Cam Pos X")) + { + auto editorCamPos = editorCam->GetPosition(); + SHClipboardUtilities::WriteToClipboard(std::format("{:.3f}", editorCamPos.x)); + } + if (ImGui::Selectable("Copy Editor Cam Pos Y")) + { + auto editorCamPos = editorCam->GetPosition(); + SHClipboardUtilities::WriteToClipboard(std::format("{:.3f}", editorCamPos.y)); + } + if (ImGui::Selectable("Copy Editor Cam Pos Z")) + { + auto editorCamPos = editorCam->GetPosition(); + SHClipboardUtilities::WriteToClipboard(std::format("{:.3f}", editorCamPos.z)); + } + } + ImGui::EndPopup(); + } } ImGui::End(); ImGui::PopStyleColor(); From 99c1eebe7007df3b6b0b8c1c5a2625cc6a031e79 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Mon, 27 Feb 2023 12:57:37 +0800 Subject: [PATCH 6/6] Fixed behaviour of script Awake() and Start() not getting called as intended (first frame that object is active) --- SHADE_Managed/src/Scripts/ScriptStore.cxx | 18 ++++++++++++------ SHADE_Managed/src/Scripts/ScriptStore.hxx | 1 + 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index 62bfc383..aba63eb2 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -482,11 +482,20 @@ namespace SHADE { SAFE_NATIVE_CALL_BEGIN // Clear the awake queue - for each (Script^ script in awakeList) + for each (Script ^ script in awakeList) { - script->Awake(); + if (script->Owner.IsActiveInHierarchy) + { + script->Awake(); + } + else + { + inactiveAwakeList.Add(script); + } } awakeList.Clear(); + awakeList.UnionWith(%inactiveAwakeList); + inactiveAwakeList.Clear(); // Clear the start queue for each (Script^ script in startList) @@ -501,10 +510,7 @@ namespace SHADE } } startList.Clear(); - for each (Script ^ script in startList) - { - startList.Add(script); - } + startList.UnionWith(%inactiveStartList); inactiveStartList.Clear(); SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") diff --git a/SHADE_Managed/src/Scripts/ScriptStore.hxx b/SHADE_Managed/src/Scripts/ScriptStore.hxx index e59e3a7f..4734b474 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.hxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.hxx @@ -353,6 +353,7 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ static ScriptDictionary scripts; static ScriptSet awakeList; + static ScriptSet inactiveAwakeList; static ScriptSet startList; static ScriptSet inactiveStartList; static ScriptSet disposalQueue;