From 6d01bd0b78f3d9f5513474f5b0ef8d53a22035bb Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 7 Mar 2023 19:00:10 +0800 Subject: [PATCH 1/6] Added ability to set starting node --- .../Animation/SHAnimationControllerEditor.cpp | 20 ++++++++++++++++++- .../Animation/SHAnimationControllerEditor.h | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp index 33372760..4be0c7b0 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp @@ -305,7 +305,10 @@ namespace SHADE ImGui::BeginDisabled(ImNodes::NumSelectedNodes() != 1); if (ImGui::Button(std::format("{} Set Starting Node", ICON_MD_HOME).data())) { - + // Get id of selected node + int selectedNode = 0; + ImNodes::GetSelectedNodes(&selectedNode); + controllerData->StartingNode = selectedNode; // We can do this as the ImNodes node index is the same } ImGui::EndDisabled(); } @@ -325,6 +328,15 @@ namespace SHADE // Title ImNodes::BeginNodeTitleBar(); { + // Starting node marker + if (node.Index == controllerData->StartingNode) + { + const float INDENT = NODE_WIDTH * 0.6f; + ImGui::Indent(INDENT); + ImGui::Text(ICON_MD_HOME); + ImGui::Unindent(INDENT); + } + if (node.EditingName) { if (ImGui::Button(ICON_MD_DONE)) @@ -749,6 +761,12 @@ namespace SHADE } } + // Mark starting node + if (nodeMap.contains(controller.GetStartingNode())) + { + data.StartingNode = nodeMap[controller.GetStartingNode()]->Index; + } + return data; } SHAnimationController SHAnimationControllerEditor::serialise(const AnimControllerData& data) diff --git a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h index bafbe4a9..60e939c7 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h +++ b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h @@ -100,7 +100,7 @@ namespace SHADE struct AnimControllerData { - + NodeIndex StartingNode = 0; std::list Nodes; std::unordered_map Params; LinkMap Links; -- 2.40.1 From ff27925f2d644ff442206fdc7f603f19a9766254 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 7 Mar 2023 20:05:37 +0800 Subject: [PATCH 2/6] Added ability to reset state, delete links and nodes --- .../Animation/SHAnimationControllerEditor.cpp | 109 ++++++++++++++++-- .../Animation/SHAnimationControllerEditor.h | 11 +- 2 files changed, 111 insertions(+), 9 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp index 4be0c7b0..9659f036 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp @@ -23,7 +23,8 @@ of DigiPen Institute of Technology is prohibited. #include "Animation/SHAnimationController.h" #include "Editor/SHEditorUI.h" #include "Editor/SHEditorWidgets.hpp" -#include "../../Command/SHCommand.hpp" +#include "Editor/Command/SHCommand.hpp" +#include "Input/SHInputManager.h" namespace SHADE { @@ -144,8 +145,9 @@ namespace SHADE SHEditorWindow::Exit(); } - void SHAnimationControllerEditor::Open(const SHAnimationController& controller) + void SHAnimationControllerEditor::Open(SHAnimationController& controllerHandle) { + controller = controllerHandle; controllerData = deserialise(controller); } /*-----------------------------------------------------------------------------------*/ @@ -158,12 +160,12 @@ namespace SHADE // Save Button if (ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data())) { - // TODO + // TODO: Actually save the resource } // Discard Button if (ImGui::Button(std::format("{} Discard Changes", ICON_MD_CANCEL).data())) { - // TODO + Open(controller); // TODO: Actually load the resource } ImGui::EndMenuBar(); @@ -211,7 +213,6 @@ namespace SHADE // Put into the new controllerData->Params[val] = TYPE; - // TODO: This needs to be handled in a custom command // Update all links for (auto& link : controllerData->Links) { @@ -293,10 +294,11 @@ namespace SHADE ImGui::SameLine(); // Delete Node Button - ImGui::BeginDisabled(ImNodes::NumSelectedNodes() < 1); - if (ImGui::Button(std::format("{} Delete Nodes", ICON_MD_ADD).data())) + ImGui::BeginDisabled((ImNodes::NumSelectedNodes() + ImNodes::NumSelectedLinks()) < 1); + if (ImGui::Button(std::format("{} Delete Objects", ICON_MD_DELETE).data())) { - + deleteSelectedLinks(); + deleteSelectedNodes(); } ImGui::EndDisabled(); ImGui::SameLine(); @@ -423,6 +425,13 @@ namespace SHADE ); } } + + // Delete + if (SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::DEL)) + { + deleteSelectedLinks(); + deleteSelectedNodes(); + } } void SHAnimationControllerEditor::drawPropertiesMenuBar() @@ -674,6 +683,34 @@ namespace SHADE ImGui::Text(TITLE); ImNodes::EndOutputAttribute(); } + void SHAnimationControllerEditor::deleteSelectedNodes() + { + const int NUM_SELECTED_NODES= ImNodes::NumSelectedNodes(); + if (NUM_SELECTED_NODES > 0) + { + std::vector selectedNodes(NUM_SELECTED_NODES); + ImNodes::GetSelectedNodes(selectedNodes.data()); + + for (auto nodeId : selectedNodes) + { + deleteNode(controllerData.value(), nodeId); + } + } + } + void SHAnimationControllerEditor::deleteSelectedLinks() + { + const int NUM_SELECTED_LINKS = ImNodes::NumSelectedLinks(); + if (NUM_SELECTED_LINKS > 0) + { + std::vector selectedLinks(NUM_SELECTED_LINKS); + ImNodes::GetSelectedLinks(selectedLinks.data()); + + for (auto linkId : selectedLinks) + { + deleteLink(controllerData.value(), linkId); + } + } + } std::list::iterator SHAnimationControllerEditor::createNode(AnimControllerData& data) { const NodeIndex NEW_NODE_IDX = data.NextNodeIndex++; @@ -716,6 +753,62 @@ namespace SHADE return EMPLACE_DATA.first; } + void SHAnimationControllerEditor::deleteLink(AnimControllerData& data, LinkIndex link) + { + const NodeLinkIndex LINK_IDX { link }; + + // Error check, don't do anything if they don't exist + if (!data.IndexToNodeMap.contains(LINK_IDX.SourceAttribute.OwnerNodeIndex) || + !data.IndexToNodeMap.contains(LINK_IDX.DestinationAttribute.OwnerNodeIndex)) + return; + + // Get source node and attributes + auto& sourceNode = *data.IndexToNodeMap[LINK_IDX.SourceAttribute.OwnerNodeIndex]; + auto& destNode = *data.IndexToNodeMap[LINK_IDX.DestinationAttribute.OwnerNodeIndex]; + + // Remove attributes + std::erase(sourceNode.OutputAttribs, LINK_IDX.SourceAttribute); + std::erase(destNode.InputAttribs, LINK_IDX.DestinationAttribute); + + // Remove link + std::erase(sourceNode.Transitions, LINK_IDX); + data.Links.erase(link); + } + void SHAnimationControllerEditor::deleteNode(AnimControllerData& data, NodeIndex nodeIndex) + { + // Get node to delete + if (!data.IndexToNodeMap.contains(nodeIndex)) + return; + auto nodeToDeleteIter = data.IndexToNodeMap[nodeIndex]; + + // Remove all links to other nodes + for (auto link : nodeToDeleteIter->Transitions) + { + deleteLink(data, link.Raw); + } + + // Remove all links from other nodes + for (auto node : data.Nodes) + { + for (NodeLinkIndex link : node.Transitions) + { + if (link.DestinationAttribute.OwnerNodeIndex == nodeIndex) + { + deleteLink(data, link.Raw); + } + } + } + + // Then finally, delete this node + data.IndexToNodeMap.erase(nodeIndex); + data.Nodes.erase(nodeToDeleteIter); + + // If the starting node was this node, we need to reassign + if (data.StartingNode == nodeIndex) + { + data.StartingNode = data.Nodes.empty() ? data.NextNodeIndex : data.Nodes.front().Index; + } + } /*-----------------------------------------------------------------------------------*/ /* Static Helper Functions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h index 60e939c7..1066fc7b 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h +++ b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.h @@ -45,7 +45,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Usage Functions */ /*---------------------------------------------------------------------------------*/ - void Open(const SHAnimationController& controller); + void Open(SHAnimationController& controller); private: /*---------------------------------------------------------------------------------*/ @@ -61,6 +61,8 @@ namespace SHADE NodeIndex OwnerNodeIndex; int8_t AttributeIndex; // Negative is input, positive is output }; + + bool operator==(NodeAttributeIndex rhs) const noexcept { return Raw == rhs.Raw; } }; union NodeLinkIndex { @@ -70,6 +72,8 @@ namespace SHADE NodeAttributeIndex SourceAttribute; NodeAttributeIndex DestinationAttribute; }; + + bool operator==(NodeLinkIndex rhs) const noexcept { return Raw != rhs.Raw; } }; struct Node @@ -111,6 +115,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ + SHAnimationController controller; std::optional controllerData; // Persistent Cached Data std::vector conditionsList; @@ -130,12 +135,16 @@ namespace SHADE NodeAttributeIndex getExtraOutputAttrib(uint32_t nodeIndex); void drawInputNode(int id, ImNodesPinShape_ pinShape); void drawOutputNode(int id, int parentNodeId, ImNodesPinShape_ pinShape); + void deleteSelectedNodes(); + void deleteSelectedLinks(); /*---------------------------------------------------------------------------------*/ /* Static Helper Functions */ /*---------------------------------------------------------------------------------*/ static std::list::iterator createNode(AnimControllerData& data); static LinkMap::iterator createLink(AnimControllerData& data, std::list::iterator sourceNode, std::list::iterator destNode); + static void deleteLink(AnimControllerData& data, LinkIndex link); + static void deleteNode(AnimControllerData& data, NodeIndex nodeIndex); static AnimControllerData deserialise(const SHAnimationController& controller); static SHAnimationController serialise(const AnimControllerData& data); }; -- 2.40.1 From dc32c5c9aafe437c846c6a0d670901c4ace8dc02 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 7 Mar 2023 20:29:57 +0800 Subject: [PATCH 3/6] Implemented saving of animation controller from editor --- .../src/Animation/SHAnimationController.cpp | 8 +-- .../src/Animation/SHAnimationController.h | 8 ++- .../src/Animation/SHAnimatorComponent.cpp | 2 +- .../Animation/SHAnimationControllerEditor.cpp | 67 +++++++++++++++++-- 4 files changed, 73 insertions(+), 12 deletions(-) diff --git a/SHADE_Engine/src/Animation/SHAnimationController.cpp b/SHADE_Engine/src/Animation/SHAnimationController.cpp index 9da907bf..ef15f223 100644 --- a/SHADE_Engine/src/Animation/SHAnimationController.cpp +++ b/SHADE_Engine/src/Animation/SHAnimationController.cpp @@ -118,8 +118,8 @@ namespace SHADE nodes.emplace_back(node); // If there is no start node, this is the first node so make it the starting node - if (!startNode) - startNode = node; + if (!StartingNode) + StartingNode = node; return node; } @@ -132,8 +132,8 @@ namespace SHADE throw std::invalid_argument("[SHAnimationController] Attempted to delete a node that doesn't belong."); // Remove if it is a start node - if (startNode == node) - startNode = {}; + if (StartingNode == node) + StartingNode = {}; // Remove from nodes nodes.erase(iter); diff --git a/SHADE_Engine/src/Animation/SHAnimationController.h b/SHADE_Engine/src/Animation/SHAnimationController.h index 64210481..7708d0c9 100644 --- a/SHADE_Engine/src/Animation/SHAnimationController.h +++ b/SHADE_Engine/src/Animation/SHAnimationController.h @@ -145,6 +145,11 @@ namespace SHADE std::unordered_map Params; float ClipPlaybackTime; }; + + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + Handle StartingNode; /*---------------------------------------------------------------------------------*/ /* Lifecycle Functions */ @@ -186,11 +191,11 @@ namespace SHADE /// /// Name of the parameter. void RemoveParameter(const std::string& name); + void SetStartingNode(Handle node); /*---------------------------------------------------------------------------------*/ /* Getters */ /*---------------------------------------------------------------------------------*/ - Handle GetStartingNode() const noexcept { return startNode; } const std::unordered_map& GetParams() const noexcept { return parameters; } const std::vector>& GetNodes() const noexcept { return nodes; } @@ -199,7 +204,6 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ // State machine - Handle startNode; std::vector> nodes; std::unordered_map parameters; diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp index 1ab5c894..0059d721 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp @@ -169,7 +169,7 @@ namespace SHADE animInstanceData.Params.emplace(param.first, SHAnimationController::AnimParam(param.second)); } // First Node - animInstanceData.CurrentNode = animController->GetStartingNode(); + animInstanceData.CurrentNode = animController->StartingNode; // Playback Time animInstanceData.ClipPlaybackTime = 0.0f; diff --git a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp index 9659f036..a67c6a67 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Animation/SHAnimationControllerEditor.cpp @@ -3,7 +3,7 @@ \author Tng Kah Wei, kahwei.tng, 390009620 \par email: kahwei.tng\@digipen.edu \date Mar 1, 2023 -\brief Contains the definition of SHAnimationControllerEditor's functions. +\brief Contains the definition of SHAnimationControllerEditor's functions. Copyright (C) 2023 DigiPen Institute of Technology. @@ -160,7 +160,7 @@ namespace SHADE // Save Button if (ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data())) { - // TODO: Actually save the resource + controller = serialise(controllerData.value()); // TODO: Actually save the resource } // Discard Button if (ImGui::Button(std::format("{} Discard Changes", ICON_MD_CANCEL).data())) @@ -855,15 +855,72 @@ namespace SHADE } // Mark starting node - if (nodeMap.contains(controller.GetStartingNode())) + if (nodeMap.contains(controller.StartingNode)) { - data.StartingNode = nodeMap[controller.GetStartingNode()]->Index; + data.StartingNode = nodeMap[controller.StartingNode]->Index; } return data; } SHAnimationController SHAnimationControllerEditor::serialise(const AnimControllerData& data) { - return {}; + SHAnimationController controller; + + // Maps data nodes to controller nodes + std::unordered_map> nodeMap; + + // Create all nodes first + for (const auto& node : data.Nodes) + { + auto newNode = controller.CreateNode(); + newNode->Name = node.Name; + newNode->Clip = node.Clip; + + nodeMap[node.Index] = newNode; + } + + // Create links + for (const auto& node : data.Nodes) + { + // Get controller node + auto controllerNode = nodeMap[node.Index]; + + for (auto link : node.Transitions) + { + // Ignore invalid link + if (!nodeMap.contains(link.SourceAttribute.OwnerNodeIndex) || !nodeMap.contains(link.DestinationAttribute.OwnerNodeIndex)) + continue; + + // Get link data + const LinkData& LINK_DATA = data.Links.at(link.Raw); + + SHAnimationController::Transition transition; + transition.Target = nodeMap[link.DestinationAttribute.OwnerNodeIndex]; + + if (data.Params.contains(LINK_DATA.ParamName)) + { + transition.Condition = LINK_DATA.Condition; + transition.ParamName = LINK_DATA.ParamName; + transition.Param.ParamType = data.Params.at(LINK_DATA.ParamName); + transition.Param.Value = LINK_DATA.ParamThresholdValue; + } + + controllerNode->Transitions.emplace_back(std::move(transition)); + } + } + + // Starting Node + if (nodeMap.contains(data.StartingNode)) + { + controller.StartingNode = nodeMap[data.StartingNode]; + } + + // Parameters + for (auto param : data.Params) + { + controller.AddParameter(param.first, param.second); + } + + return controller; } } \ No newline at end of file -- 2.40.1 From eae6f6399b1a392cdc7006ecf2d115b7709275b0 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Tue, 7 Mar 2023 22:05:33 +0800 Subject: [PATCH 4/6] Changed implementation of binary loader to load animation clip containers instead of individual animation clips --- .../Libraries/Loaders/SHBinaryLoader.cpp | 93 ++++++++++++++++--- .../Assets/Libraries/Loaders/SHBinaryLoader.h | 5 + 2 files changed, 83 insertions(+), 15 deletions(-) diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp index 8ea85811..ad2a7f2c 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.cpp @@ -1,7 +1,7 @@ #include "SHpch.h" #include "SHBinaryLoader.h" -#include "Assets/Asset Types/SHAnimClipAsset.h" +#include "Assets/Asset Types/SHAnimClipContainerAsset.h" #include @@ -19,15 +19,9 @@ namespace SHADE auto const extension = path.extension().string(); SHAssetData* result{nullptr}; - if (extension == ANIM_CLIP_EXTENSION) + if (extension == ANIM_CONTAINER_EXTENSION) { - const auto data = new SHAnimClipAsset(); - file.read( - reinterpret_cast(&data->animRawDataAssetId), - sizeof(uint32_t) * 3 - ); - data->name = path.stem().string(); - result = data; + LoadAnimClipContainer(file, result, path); } file.close(); @@ -47,15 +41,84 @@ namespace SHADE auto const extension = path.extension().string(); - if (extension == ANIM_CLIP_EXTENSION) + if (extension == ANIM_CONTAINER_EXTENSION) { - auto animClip = dynamic_cast(data); - file.write( - reinterpret_cast(&animClip->animRawDataAssetId), - sizeof(uint32_t) * 3 - ); + WriteAnimClipContainer(file, data, path); } file.close(); } + + void SHBinaryLoader::WriteAnimClipContainer(std::ofstream& file, SHAssetData const* data, AssetPath path) + { + auto const& anim = *dynamic_cast(data); + file.write( + reinterpret_cast(&anim.animRawDataAssetId), + sizeof(uint32_t) + ); + + uint32_t const size {static_cast(anim.clips.size())}; + + file.write( + reinterpret_cast(&size), + sizeof(uint32_t) + ); + + for (auto const& clip : anim.clips) + { + uint32_t charCount {static_cast(clip.name.size())}; + file.write( + reinterpret_cast(&charCount), + sizeof(uint32_t) + ); + + file.write( + clip.name.data(), + charCount + ); + + file.write( + reinterpret_cast(&clip.firstIndex), + sizeof(uint32_t) * 2 + ); + } + } + + void SHBinaryLoader::LoadAnimClipContainer(std::ifstream& file, SHAssetData* result, AssetPath path) + { + auto const data = new SHAnimClipContainerAsset(); + + file.read( + reinterpret_cast(&data->animRawDataAssetId), + sizeof(uint32_t) + ); + + uint32_t size; + + file.read( + reinterpret_cast(&size), + sizeof(uint32_t) + ); + + for (auto i{0}; i < size; ++i) + { + auto& clip {data->clips.emplace_back()}; + uint32_t charCount; + file.read( + reinterpret_cast(&charCount), + sizeof(uint32_t) + ); + + clip.name.resize(charCount); + file.read( + clip.name.data(), + charCount + ); + + file.read( + reinterpret_cast(&clip.firstIndex), + sizeof(uint32_t) * 2 + ); + } + } } diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h index db2316e8..7cf50d51 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHBinaryLoader.h @@ -8,5 +8,10 @@ namespace SHADE { SHAssetData* Load(AssetPath path) override; void Write(SHAssetData const* data, AssetPath path) override; + + private: + //Individual functions to write files + void WriteAnimClipContainer(std::ofstream& file,SHAssetData const* data, AssetPath path); + void LoadAnimClipContainer(std::ifstream& file,SHAssetData* result, AssetPath path); }; } \ No newline at end of file -- 2.40.1 From 07100de9508b2b53d1658998711d962629571777 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Tue, 7 Mar 2023 22:06:42 +0800 Subject: [PATCH 5/6] Added recognition for animation clip container as a file Added functions to create new sub asset for animation clips Added recognition for animation clip containers when creating new assets --- SHADE_Engine/src/Assets/SHAssetMacros.h | 13 +-- SHADE_Engine/src/Assets/SHAssetManager.cpp | 95 +++++++++++++++++++--- SHADE_Engine/src/Assets/SHAssetManager.h | 1 + 3 files changed, 91 insertions(+), 18 deletions(-) diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h index 510bc35a..f9e21f15 100644 --- a/SHADE_Engine/src/Assets/SHAssetMacros.h +++ b/SHADE_Engine/src/Assets/SHAssetMacros.h @@ -57,6 +57,7 @@ enum class AssetType : AssetTypeMeta MESH, SCRIPT, FONT, + ANIM_CONTAINER, ANIM_CLIP, MAX_COUNT }; @@ -79,7 +80,7 @@ constexpr std::string_view FONT_COMPILER_EXE{ "FontCompiler.exe" }; constexpr std::string_view SCENE_FOLDER{ "/Scenes/" }; constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" }; constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" }; -constexpr std::string_view ANIM_CLIP_FOLDER{ "/Animation Clips/" }; +constexpr std::string_view ANIM_CLIP_FOLDER{ "/Animations/" }; // ASSET EXTENSIONS @@ -95,7 +96,8 @@ constexpr std::string_view PREFAB_EXTENSION {".shprefab"}; constexpr std::string_view MATERIAL_EXTENSION {".shmat"}; constexpr std::string_view TEXTURE_EXTENSION {".shtex"}; constexpr std::string_view MODEL_EXTENSION{ ".shmodel" }; -constexpr std::string_view ANIM_CLIP_EXTENSION{ ".shanimclip" }; +constexpr std::string_view ANIM_CONTAINER_EXTENSION{ ".shanimcontainer" }; +constexpr std::string_view FILLER_EXTENSION{"dummy"}; constexpr std::string_view EXTENSIONS[] = { AUDIO_EXTENSION, @@ -106,14 +108,15 @@ constexpr std::string_view EXTENSIONS[] = { SCENE_EXTENSION, PREFAB_EXTENSION, MATERIAL_EXTENSION, - "dummy", + FILLER_EXTENSION, SCRIPT_EXTENSION, FONT_EXTENSION, AUDIO_WAV_EXTENSION, - ANIM_CLIP_EXTENSION + ANIM_CONTAINER_EXTENSION, + FILLER_EXTENSION }; -constexpr size_t EXTENSIONS_COUNT{ 11 }; +constexpr size_t EXTENSIONS_COUNT{ static_cast(AssetType::MAX_COUNT) }; // EXTERNAL EXTENSIONS constexpr std::string_view GLSL_EXTENSION{ ".glsl" }; diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index 503f9082..5ad2bbd4 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -26,7 +26,7 @@ #include "Asset Types/SHPrefabAsset.h" #include "Asset Types/SHMaterialAsset.h" #include "Asset Types/SHSceneAsset.h" -#include "Asset Types/SHAnimClipAsset.h" +#include "Asset Types/SHAnimClipContainerAsset.h" #include "Libraries/Compilers/SHTextureCompiler.h" #include "Libraries/Compilers/SHShaderSourceCompiler.h" @@ -238,10 +238,10 @@ namespace SHADE } break; - case AssetType::ANIM_CLIP: + case AssetType::ANIM_CONTAINER: newPath += ANIM_CLIP_FOLDER; newPath += name; - newPath += ANIM_CLIP_EXTENSION; + newPath += ANIM_CONTAINER_EXTENSION; { auto animClip = new SHAnimClipAsset(); @@ -252,7 +252,7 @@ namespace SHADE default: - SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal asset type, cannot be created", name); + SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal parent asset type, cannot be created", name); return 0; } @@ -267,13 +267,13 @@ namespace SHADE auto result = assetCollection.emplace( id, - SHAsset( - name, - id, - type, - newPath, - false - ) + SHAsset( + name, + id, + type, + newPath, + false + ) ); assetData.emplace(id, data); @@ -284,6 +284,40 @@ namespace SHADE return id; } + AssetID SHAssetManager::CreateNewSubAsset(AssetType type, AssetName name, AssetID parent) + { + if (!assetData.contains(parent)) + { + SHLOG_ERROR("[Asset Manager] Failed to create new sub asset, parent does not exist: {}", name); + return 0; + } + + switch(type) + { + case AssetType::ANIM_CLIP: + { + auto const animContainer {dynamic_cast(assetData[parent])}; + auto id = GenerateAssetID(type); + SHAsset asset{ + .name = name, + .id = id, + .type = type, + .isSubAsset = true, + .parent = parent + }; + auto& newClip {animContainer->clips.emplace_back()}; + newClip.name = name; + assetCollection.emplace(id, asset); + assetData.emplace(id, &newClip); + return id; + } + + default: + SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal sub asset type, cannot be created", name); + return 0; + } + } + bool SHAssetManager::SaveAsset(AssetID id) noexcept { if (assetCollection.contains(id)) @@ -547,7 +581,8 @@ namespace SHADE loaders[static_cast(AssetType::MESH)] = nullptr; loaders[static_cast(AssetType::SCRIPT)] = nullptr; loaders[static_cast(AssetType::FONT)] = dynamic_cast(new SHFontLoader()); - loaders[static_cast(AssetType::ANIM_CLIP)] = dynamic_cast(new SHBinaryLoader()); + loaders[static_cast(AssetType::ANIM_CONTAINER)] = dynamic_cast(new SHBinaryLoader()); + loaders[static_cast(AssetType::ANIM_CLIP)] = nullptr; } /**************************************************************************** @@ -758,6 +793,38 @@ namespace SHADE return newAsset.id; } + else if(ext==ANIM_CONTAINER_EXTENSION) + { + SHAsset newAsset{ + path.stem().string(), + GenerateAssetID(AssetType::ANIM_CONTAINER), + AssetType::ANIM_CONTAINER, + path, + false + }; + + assetCollection.emplace(newAsset.id, newAsset); + + SHAnimClipContainerAsset* const data = reinterpret_cast(LoadData(newAsset)); + assetData.emplace(newAsset.id, data); + for(auto& clip : data->clips) + { + SHAsset subAsset{ + .name = clip.name, + .id = GenerateAssetID(AssetType::ANIM_CLIP), + .type = AssetType::ANIM_CLIP, + .isSubAsset = true, + .parent = newAsset.id + }; + + assetCollection.emplace(subAsset.id, subAsset); + assetCollection[newAsset.id].subAssets.push_back(&assetCollection[subAsset.id]); + + assetData.emplace(subAsset.id, &clip); + } + + SHAssetMetaHandler::WriteMetaData(assetCollection[newAsset.id]); + } } void SHAssetManager::BuildAssetCollection() noexcept @@ -814,7 +881,9 @@ namespace rttr value("Material", AssetType::MATERIAL), value("Mesh", AssetType::MESH), value("Script", AssetType::SCRIPT), - value("Font", AssetType::FONT) + value("Font", AssetType::FONT), + value("Animation Container", AssetType::ANIM_CONTAINER), + value("Animation Clip", AssetType::ANIM_CLIP) ); } } diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index e5cd0359..6a8f91ef 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -63,6 +63,7 @@ namespace SHADE * \return resource id generated for new asset ****************************************************************************/ static AssetID CreateNewAsset(AssetType type, AssetName name) noexcept; + static AssetID CreateNewSubAsset(AssetType type, AssetName name, AssetID parent); static bool SaveAsset(AssetID id) noexcept; static bool DeleteAsset(AssetID id) noexcept; -- 2.40.1 From 3cc949bb7eafc67ab474ac6be1ee8b15df0cbbb4 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Tue, 7 Mar 2023 22:07:38 +0800 Subject: [PATCH 6/6] Animation container redefinition --- .../Assets/Asset Types/Models/SHAnimationAsset.h | 2 -- ...AnimClipAsset.h => SHAnimClipContainerAsset.h} | 15 +++++++++++---- SHADE_Engine/src/Resource/SHResourceManager.h | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) rename SHADE_Engine/src/Assets/Asset Types/{SHAnimClipAsset.h => SHAnimClipContainerAsset.h} (81%) diff --git a/SHADE_Engine/src/Assets/Asset Types/Models/SHAnimationAsset.h b/SHADE_Engine/src/Assets/Asset Types/Models/SHAnimationAsset.h index d7128977..6e98c661 100644 --- a/SHADE_Engine/src/Assets/Asset Types/Models/SHAnimationAsset.h +++ b/SHADE_Engine/src/Assets/Asset Types/Models/SHAnimationAsset.h @@ -82,7 +82,5 @@ namespace SHADE double ticksPerSecond; std::vector nodeChannels; - //std::vector meshChannels; - //std::vector morphMeshChannels; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAnimClipAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHAnimClipContainerAsset.h similarity index 81% rename from SHADE_Engine/src/Assets/Asset Types/SHAnimClipAsset.h rename to SHADE_Engine/src/Assets/Asset Types/SHAnimClipContainerAsset.h index c6887316..bac68579 100644 --- a/SHADE_Engine/src/Assets/Asset Types/SHAnimClipAsset.h +++ b/SHADE_Engine/src/Assets/Asset Types/SHAnimClipContainerAsset.h @@ -12,17 +12,24 @@ of DigiPen Institute of Technology is prohibited. #pragma once #include "SH_API.h" -#include "SHAssetData.h" #include +#include "Assets/SHAssetMacros.h" +#include "SHAssetData.h" + namespace SHADE { - struct SH_API SHAnimClipAsset : SHAssetData + struct SHAnimClipAsset : SHAssetData { std::string name; - AssetID animRawDataAssetId; uint32_t firstIndex; uint32_t lastIndex; }; -} \ No newline at end of file + + struct SH_API SHAnimClipContainerAsset final : SHAssetData + { + AssetID animRawDataAssetId; + std::vector clips; + }; +} diff --git a/SHADE_Engine/src/Resource/SHResourceManager.h b/SHADE_Engine/src/Resource/SHResourceManager.h index 21303982..2dfc7dac 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.h +++ b/SHADE_Engine/src/Resource/SHResourceManager.h @@ -21,7 +21,7 @@ of DigiPen Institute of Technology is prohibited. #include "Assets/Asset Types/Models/SHModelAsset.h" #include "Assets/Asset Types/SHTextureAsset.h" #include "Assets/Asset Types/SHShaderAsset.h" -#include "Assets/Asset Types/SHAnimClipAsset.h" +#include "Assets/Asset Types/SHAnimClipContainerAsset.h" #include "Assets/Asset Types/SHAnimControllerAsset.h" #include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h" -- 2.40.1