From e97f5747cba58ab9fcea84102226fef7496eefd0 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Wed, 1 Mar 2023 01:30:34 +0800 Subject: [PATCH] Modified SHAnimatorComponent to support manual and animation controller modes. Fleshed out SHAnimationController. Added SHAnimControllerAsset stub. --- .../src/Animation/SHAnimationClip.cpp | 12 +- SHADE_Engine/src/Animation/SHAnimationClip.h | 2 + .../src/Animation/SHAnimationController.cpp | 44 +++- .../src/Animation/SHAnimationController.h | 50 ++-- .../src/Animation/SHAnimatorComponent.cpp | 231 +++++++++++++----- .../src/Animation/SHAnimatorComponent.h | 71 +++--- .../Asset Types/SHAnimControllerAsset.h | 27 ++ SHADE_Engine/src/Assets/SHAssetMacros.h | 40 +-- .../Inspector/SHEditorComponentView.hpp | 25 -- SHADE_Engine/src/Resource/SHResourceManager.h | 23 +- .../src/Resource/SHResourceManager.hpp | 28 ++- .../src/Serialization/SHYAMLConverters.h | 8 +- 12 files changed, 374 insertions(+), 187 deletions(-) create mode 100644 SHADE_Engine/src/Assets/Asset Types/SHAnimControllerAsset.h diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.cpp b/SHADE_Engine/src/Animation/SHAnimationClip.cpp index 2678b95b..130503af 100644 --- a/SHADE_Engine/src/Animation/SHAnimationClip.cpp +++ b/SHADE_Engine/src/Animation/SHAnimationClip.cpp @@ -13,6 +13,7 @@ of DigiPen Institute of Technology is prohibited. #include "SHpch.h" // Primary Header #include "SHAnimationClip.h" +#include "SHRawAnimation.h" namespace SHADE { @@ -20,8 +21,15 @@ namespace SHADE /* Constructors */ /*-----------------------------------------------------------------------------------*/ SHAnimationClip::SHAnimationClip(Handle rawAnimHandle, int firstFrame, int lastFrame) - : rawAnim { rawAnimHandle } + : rawAnim { rawAnimHandle } , startFrameIndex { firstFrame } , endFrameIndex { lastFrame } - {} + , duration { 0.0f } + { + if (!rawAnim) + return; + + const int ONE_PAST_LAST_FRAME = lastFrame + 1; + duration = (ONE_PAST_LAST_FRAME - firstFrame) / rawAnim->GetTicksPerSecond(); + } } \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.h b/SHADE_Engine/src/Animation/SHAnimationClip.h index 547acf92..9b93a7a3 100644 --- a/SHADE_Engine/src/Animation/SHAnimationClip.h +++ b/SHADE_Engine/src/Animation/SHAnimationClip.h @@ -50,6 +50,7 @@ namespace SHADE inline Handle GetRawAnimation() const noexcept { return rawAnim; } inline int GetStartFrameIndex() const noexcept { return startFrameIndex; } inline int GetEndFrameIndex() const noexcept { return endFrameIndex; } + inline float GetTotalDuration() const noexcept { return duration; } private: /*---------------------------------------------------------------------------------*/ @@ -58,5 +59,6 @@ namespace SHADE Handle rawAnim; int startFrameIndex; // First Frame int endFrameIndex; // Last Frame (inclusive) + float duration; // Total playback time }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimationController.cpp b/SHADE_Engine/src/Animation/SHAnimationController.cpp index 86c665fd..3230b2d9 100644 --- a/SHADE_Engine/src/Animation/SHAnimationController.cpp +++ b/SHADE_Engine/src/Animation/SHAnimationController.cpp @@ -20,22 +20,28 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ /* Lifecycle Functions */ /*-----------------------------------------------------------------------------------*/ - void SHAnimationController::Update() + void SHAnimationController::Update(InstanceData& instData, float dt) { // Is there a valid node - if (!currentNode) + if (!instData.CurrentNode) return; - // Update - for (const auto& transition : currentNode->Transitions) - { + // Update the current playback + instData.ClipPlaybackTime += dt; + // Check if we finished playing + if (instData.ClipPlaybackTime > instData.CurrentNode->Clip->GetTotalDuration()) + { + // Clamp + instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetTotalDuration(); + + // Go to next state + for (const auto& transition : instData.CurrentNode->Transitions) + { + // TODO + } } } - void SHAnimationController::Reset() - { - currentNode = startNode; - } /*-----------------------------------------------------------------------------------*/ /* Usage Functions */ @@ -75,4 +81,24 @@ namespace SHADE // Clear node node.Free(); } + + /*-----------------------------------------------------------------------------------*/ + /* AnimParam Functions */ + /*-----------------------------------------------------------------------------------*/ + SHAnimationController::AnimParam::AnimParam(Type type) + : ParamType { type } + { + switch (ParamType) + { + case Type::Bool: + Value = false; + break; + case Type::Float: + Value = 0.0f; + break; + case Type::Int: + Value = 0; + break; + } + } } diff --git a/SHADE_Engine/src/Animation/SHAnimationController.h b/SHADE_Engine/src/Animation/SHAnimationController.h index c6d353e6..4efb1116 100644 --- a/SHADE_Engine/src/Animation/SHAnimationController.h +++ b/SHADE_Engine/src/Animation/SHAnimationController.h @@ -27,6 +27,7 @@ namespace SHADE /// /// Object that controls the animation that is played by an animator through the use /// of an internal state machine. + /// This should never be modified once it has been attached to a SHAnimatorComponent! /// class SH_API SHAnimationController { @@ -58,12 +59,23 @@ namespace SHADE Float, Int }; + using ValueType = std::variant; + + /*-------------------------------------------------------------------------------*/ + /* Constructor */ + /*-------------------------------------------------------------------------------*/ + /// + /// Constructs an AnimParam with the default value set for the Value field based + /// on the specified type. + /// + /// Type of AnimParam. + explicit AnimParam(Type type); /*-------------------------------------------------------------------------------*/ /* Data Members */ /*-------------------------------------------------------------------------------*/ - Type ParamType; - std::variant Value; + Type ParamType; + ValueType Value; }; /// @@ -91,10 +103,11 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ /* Data Members */ /*-------------------------------------------------------------------------------*/ - ConditionType Condition; - Handle Target; + ConditionType Condition; + AnimParam::ValueType Threshold; + Handle Target; }; - + /// /// Describes a node in the animation controller. /// @@ -103,6 +116,16 @@ namespace SHADE Handle Clip; std::vector Transitions; }; + + /// + /// Describes a node in the animation controller. + /// + struct InstanceData + { + Handle CurrentNode; + std::unordered_map Params; + float ClipPlaybackTime; + }; /*---------------------------------------------------------------------------------*/ /* Lifecycle Functions */ @@ -110,11 +133,7 @@ namespace SHADE /// /// Runs a single update for the animation controller. /// - void Update(); - /// - /// Resets the animation controller to its starting node. - /// - void Reset(); + void Update(InstanceData& instData, float dt); /*---------------------------------------------------------------------------------*/ /* Usage Functions */ @@ -130,20 +149,23 @@ namespace SHADE /// /// Node to destroy. void DestroyNode(Handle node); - + void AddTransition(Handle source, const Transition& transition); + void AddParameter(const std::string& name, AnimParam::Type type); + /*---------------------------------------------------------------------------------*/ /* Getters */ /*---------------------------------------------------------------------------------*/ - Handle GetCurrentNode() const noexcept { return currentNode; } + Handle GetStartingNode() const noexcept { return startNode; } + const std::unordered_map& GetParams() const noexcept { return parameters; } + const std::vector>& GetNodes() const noexcept { return nodes; } private: /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ // State machine - Handle currentNode; Handle startNode; std::vector> nodes; - std::unordered_map parameters; + std::unordered_map parameters; }; } diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp index eee7fd51..1ab5c894 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp @@ -39,9 +39,42 @@ namespace SHADE void SHAnimatorComponent::Play(Handle clip) { + // Ignore if nothing is specified + if (!clip) + { + SHLOG_WARNING("[SHAnimatorComponent] Attempted to play an null SHAnimationClip. Use Stop() if stopping animation instead."); + return; + } + + // Remove animation controller as we switch to manual play mode + animController = {}; + animInstanceData.CurrentNode = {}; + animInstanceData.Params.clear(); + animInstanceData.ClipPlaybackTime = 0.0f; + + // Set accordingly currClip = clip; currPlaybackTime = 0.0f; - Play(); + channelMaps.clear(); + auto RAW_ANIM = clip->GetRawAnimation(); + + // Set up if valid + if (currClip && RAW_ANIM) + { + // Create channel maps + channelMaps.emplace(RAW_ANIM, createChannelMap(RAW_ANIM)); + // Calculate secs for the clip + secsPerTick = 1.0f / RAW_ANIM->GetTicksPerSecond(); + + // Start playback + Play(); + + // Set to initial pose + if (rig && rig->GetRootNode()) + { + updateCurrentAnimatorState(currClip, 0.0f); + } + } } void SHAnimatorComponent::PlayOneShot(Handle clip) @@ -67,6 +100,37 @@ namespace SHADE currPlaybackTime = 0.0f; } + /*-----------------------------------------------------------------------------------*/ + /* Update Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHAnimatorComponent::Update(float dt) + { + // Reset matrices + std::fill(boneMatrices.begin(), boneMatrices.end(), SHMatrix::Identity); + + // Do not do anything if is not playing or there's nothing to animate + if (!isPlaying || !rig || !rig->GetRootNode()) + return; + + // Update the animation controller if any, this will set the currClip + if (animController) + { + updateAnimController(dt); + + // Only update the animation state if there is a clip + if (animInstanceData.CurrentNode && animInstanceData.CurrentNode->Clip) + { + updateCurrentAnimatorState(animInstanceData.CurrentNode->Clip, animInstanceData.ClipPlaybackTime); + } + } + // Otherwise, a single clip was provided, then we'll use it + else if (currClip) + { + updateManualClipState(dt); + updateCurrentAnimatorState(currClip, currPlaybackTime); + } + } + /*-----------------------------------------------------------------------------------*/ /* Setter Functions */ /*-----------------------------------------------------------------------------------*/ @@ -86,104 +150,143 @@ namespace SHADE } } - void SHAnimatorComponent::SetClip(Handle newClip) + void SHAnimatorComponent::SetAnimationController(Handle ac) { // No change - if (currClip == newClip) + if (animController == ac) return; - // Get animation data - auto animData = currClip->GetRawAnimation(); - if (!animData) - return; + // Set the controller + animController = ac; - // Set parameters - currClip = newClip; - secsPerTick = 1.0f / animData->GetTicksPerSecond(); - - // Calculate total time for the clip - if (currClip) + // If valid, we want to initialize it + if (animController) { - const int ONE_PAST_LAST_FRAME = currClip->GetEndFrameIndex() + 1; - currClipTotalTime = (ONE_PAST_LAST_FRAME - currClip->GetStartFrameIndex()) / animData->GetTicksPerSecond(); - } - - // Build channel map and clip-specific data - channelMap.clear(); - if (animData) - { - for (const auto& channel : animData->GetChannels()) + // Parameters + animInstanceData.Params.clear(); + for (auto param : animController->GetParams()) { - channelMap.emplace(channel.Name, &channel); + animInstanceData.Params.emplace(param.first, SHAnimationController::AnimParam(param.second)); + } + // First Node + animInstanceData.CurrentNode = animController->GetStartingNode(); + // Playback Time + animInstanceData.ClipPlaybackTime = 0.0f; + + // Get set of unique SHRawAnimation used by the animController + std::unordered_set> rawAnims; + for (auto node : animController->GetNodes()) + { + // Ensure no null handles + if (!node) + continue; + const Handle CLIP = node->Clip; + if (!CLIP) + continue; + const Handle RAW_ANIM = CLIP->GetRawAnimation(); + if (!RAW_ANIM) + continue; + + // Store + rawAnims.emplace(RAW_ANIM); + } + + // Load channel maps + for (auto anim : rawAnims) + { + channelMaps.emplace(anim, createChannelMap(anim)); } } - - if (rig && rig->GetRootNode() && currClip) + } + + /*-----------------------------------------------------------------------------------*/ + /* Helper Functions - Loading */ + /*-----------------------------------------------------------------------------------*/ + SHAnimatorComponent::ChannelMap SHAnimatorComponent::createChannelMap(Handle rawAnimData) + { + ChannelMap channelMap; + for (const auto& channel : rawAnimData->GetChannels()) { - updatePoseWithClip(0.0f); + channelMap.emplace(channel.Name, &channel); + } + return channelMap; + } + + /*-----------------------------------------------------------------------------------*/ + /* Helper Functions - Update */ + /*-----------------------------------------------------------------------------------*/ + void SHAnimatorComponent::updateAnimController(float dt) + { + // No animation controller + if (!animInstanceData.CurrentNode) + return; + + // Update the animation controller + animController->Update(animInstanceData, dt); + + // Get current clip + currClip = animInstanceData.CurrentNode->Clip; + if (currClip && currClip->GetRawAnimation()) + { + secsPerTick = 1.0f / currClip->GetRawAnimation(); } } - - /*-----------------------------------------------------------------------------------*/ - /* Update Functions */ - /*-----------------------------------------------------------------------------------*/ - void SHAnimatorComponent::Update(float dt) + void SHAnimatorComponent::updateManualClipState(float dt) { - // Reset matrices - std::fill(boneMatrices.begin(), boneMatrices.end(), SHMatrix::Identity); - - // Nothing to animate - if (!currClip || !isPlaying || !rig || !rig->GetRootNode()) - return; - - // Get animation data - auto animData = currClip->GetRawAnimation(); - if (!animData) - return; - - // Update time on the playback currPlaybackTime += dt; - if (currPlaybackTime > currClipTotalTime) + if (currPlaybackTime > currClip->GetTotalDuration()) { if (playOnce) { playOnce = false; isPlaying = false; + currPlaybackTime = currClip->GetTotalDuration(); } else { - currPlaybackTime = currPlaybackTime - currClipTotalTime; + currPlaybackTime = currPlaybackTime - currClip->GetTotalDuration(); } } + } + void SHAnimatorComponent::updateCurrentAnimatorState(Handle clip, float playbackTime) + { + // Nothing to animate + if (!clip || !isPlaying || !rig || !rig->GetRootNode()) + return; + + // Check that we have animation data + if (!clip->GetRawAnimation()) + return; // Play the clip - updatePoseWithClip(currPlaybackTime); + updatePoseWithClip(clip, currPlaybackTime); } - - /*-----------------------------------------------------------------------------------*/ - /* Helper Functions */ - /*-----------------------------------------------------------------------------------*/ - void SHAnimatorComponent::updatePoseWithClip(float poseTime) + void SHAnimatorComponent::updatePoseWithClip(Handle clip, float poseTime) { // Get closest frame index - const int CLOSEST_FRAME_IDX = currClip->GetStartFrameIndex() + static_cast(std::floorf(poseTime * currClip->GetRawAnimation()->GetTicksPerSecond())); - updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, rig->GetRootNode(), SHMatrix::Identity); + const int CLOSEST_FRAME_IDX = clip->GetStartFrameIndex() + static_cast(std::floorf(poseTime / secsPerTick)); + updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, clip->GetRawAnimation(), rig->GetRootNode(), SHMatrix::Identity); } - void SHAnimatorComponent::updatePoseWithClip(int closestFrameIndex, float poseTime, Handle node, const SHMatrix& parentMatrix) + void SHAnimatorComponent::updatePoseWithClip(int closestFrameIndex, float poseTime, Handle rawAnimData, Handle node, const SHMatrix& parentMatrix) { // Check if there is a channel for this node const std::string& BONE_NAME = rig->GetName(node); SHMatrix transformMatrix = node->TransformMatrix; - if (channelMap.contains(BONE_NAME)) + + if (channelMaps.contains(rawAnimData)) { - const auto CHANNEL = channelMap[BONE_NAME]; - transformMatrix = SHMatrix::Transform - ( - getInterpolatedValue(CHANNEL->PositionKeyFrames, closestFrameIndex, poseTime), - getInterpolatedValue(CHANNEL->RotationKeyFrames, closestFrameIndex, poseTime), - getInterpolatedValue(CHANNEL->ScaleKeyFrames, closestFrameIndex, poseTime) - ); + auto channelMap = channelMaps[rawAnimData]; + if (channelMap.contains(BONE_NAME)) + { + const auto CHANNEL = channelMap[BONE_NAME]; + transformMatrix = SHMatrix::Transform + ( + getInterpolatedValue(CHANNEL->PositionKeyFrames, closestFrameIndex, poseTime), + getInterpolatedValue(CHANNEL->RotationKeyFrames, closestFrameIndex, poseTime), + getInterpolatedValue(CHANNEL->ScaleKeyFrames, closestFrameIndex, poseTime) + ); + } } // Apply parent's transformation @@ -200,7 +303,7 @@ namespace SHADE // Apply pose to children for (auto& child : node->Children) { - updatePoseWithClip(closestFrameIndex, poseTime, child, transformMatrix); + updatePoseWithClip(closestFrameIndex, poseTime, rawAnimData, child, transformMatrix); } } } diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.h b/SHADE_Engine/src/Animation/SHAnimatorComponent.h index 12d377fe..d4af2c2b 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.h +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.h @@ -23,6 +23,7 @@ of DigiPen Institute of Technology is prohibited. #include "Math/Vector/SHVec3.h" #include "Math/SHQuaternion.h" #include "SHRawAnimation.h" +#include "SHAnimationController.h" namespace SHADE { @@ -52,12 +53,14 @@ namespace SHADE /// void Play(); /// - /// Plays the specified animation clip from the start. + /// Plays the specified animation clip from the start. This will unset any + /// SHAnimationControllers that have been set. /// /// Animation clip to play. void Play(Handle clip); /// - /// Plays the specified animation clip from the start one time only. + /// Plays the specified animation clip from the start one time only. This will unset + /// any SHAnimationControllers that have been set. /// /// Animation clip to play. void PlayOneShot(Handle clip); @@ -74,6 +77,16 @@ namespace SHADE /// void Stop(); + /*---------------------------------------------------------------------------------*/ + /* Update Functions */ + /*---------------------------------------------------------------------------------*/ + /// + /// Updates the current state of the animation if one is specified based on the + /// current animation clip and frames. This will update the bone matrices. + /// + /// Time passed since the last frame. + void Update(float dt); + /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ @@ -82,13 +95,7 @@ namespace SHADE /// /// Rig to use. void SetRig(Handle newRig); - /// - /// Sets the animation clip of this animator without playing it. - /// This will set the pose of the model to it's initial pose. - /// If the clip is the same as the current clip, nothing happens. - /// - /// Clip to use. - void SetClip(Handle newClip); + void SetAnimationController(Handle ac); /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -104,51 +111,55 @@ namespace SHADE /// Handle to the currently set rig. Handle GetRig() const noexcept { return rig; } /// - /// - /// Retrieve the currently set animation clip. - /// - /// Handle to the currently set animation clip. - Handle GetCurrentClip() const noexcept { return currClip; } - /// /// Checks if an animation is currently playing. /// /// True if an animation clip is currently playing. bool IsPlaying() const { return isPlaying; } - - /*---------------------------------------------------------------------------------*/ - /* Update Functions */ - /*---------------------------------------------------------------------------------*/ /// - /// Updates the current state of the animation if one is specified based on the - /// current animation clip and frames. This will update the bone matrices. + /// Retrieves the current node for the Animation Controller. This returns a null + /// if there is no Animation Controller currently set. /// - /// Time passed since the last frame. - void Update(float dt); + /// Handle to the current Animation Controller node. + Handle GetCurrentNode() const noexcept { return animInstanceData.CurrentNode; } + Handle GetAnimationController() const noexcept { return animController; } private: + /*---------------------------------------------------------------------------------*/ + /* Type Definition */ + /*---------------------------------------------------------------------------------*/ + using ChannelMap = std::unordered_map; + /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ // Resources Handle rig; + // Playback Tracking for Animation Controller Mode + Handle animController; + SHAnimationController::InstanceData animInstanceData; + // Playback Tracking for Manual Mode Handle currClip; - // Playback Tracking float currPlaybackTime = 0.0f; - bool isPlaying = true; bool playOnce = false; - float currClipTotalTime = 0.0f; - // Useful Cached Data + // Shared Tracking + bool isPlaying = true; float secsPerTick = 0.0f; // Buffer std::vector boneMatrices; // Caches - std::unordered_map channelMap; + std::unordered_map, ChannelMap> channelMaps; /*---------------------------------------------------------------------------------*/ /* Helper Functions */ /*---------------------------------------------------------------------------------*/ - void updatePoseWithClip(float poseTime); - void updatePoseWithClip(int closestFrameIndex, float poseTime, Handle node, const SHMatrix& parentMatrix); + // Loading + ChannelMap createChannelMap(Handle rawAnimData); + // Update + void updateAnimController(float dt); + void updateManualClipState(float dt); + void updateCurrentAnimatorState(Handle clip, float playbackTime); + void updatePoseWithClip(Handle clip, float poseTime); + void updatePoseWithClip(int closestFrameIndex, float poseTime, Handle rawAnimData, Handle node, const SHMatrix& parentMatrix); template T getInterpolatedValue(const std::vector>& keyframes, int closestFrameIndex, float poseTime); diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAnimControllerAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHAnimControllerAsset.h new file mode 100644 index 00000000..625e4d5c --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHAnimControllerAsset.h @@ -0,0 +1,27 @@ +/************************************************************************************//*! +\file SHAnimControllerAsset.h +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Mar 1, 2023 +\brief Contains the definition of the SHAnimControllerAsset struct and related + types. + +Copyright (C) 2023 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +#include + +#include "SH_API.h" +#include "SHAssetData.h" + +namespace SHADE +{ + struct SH_API SHAnimControllerAsset : SHAssetData + { + std::string name; + // TODO + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h index 566e34e2..33891d7f 100644 --- a/SHADE_Engine/src/Assets/SHAssetMacros.h +++ b/SHADE_Engine/src/Assets/SHAssetMacros.h @@ -18,10 +18,10 @@ // FMOD Fwd Declare namespace FMOD { - class Sound; - class System; - class ChannelGroup; - class Channel; + class Sound; + class System; + class ChannelGroup; + class Channel; } enum FMOD_RESULT : int; enum FMOD_SPEAKERMODE : int; @@ -45,9 +45,9 @@ constexpr AssetID INVALID_ASSET_ID {0}; // Asset type enum enum class AssetType : AssetTypeMeta { - INVALID, - SHADER, - SHADER_BUILT_IN, + INVALID, + SHADER, + SHADER_BUILT_IN, TEXTURE, MODEL, SCENE, @@ -56,7 +56,7 @@ enum class AssetType : AssetTypeMeta MESH, SCRIPT, FONT, - MAX_COUNT + MAX_COUNT }; constexpr size_t TYPE_COUNT{ static_cast(AssetType::MAX_COUNT) }; @@ -94,18 +94,18 @@ constexpr std::string_view TEXTURE_EXTENSION {".shtex"}; constexpr std::string_view MODEL_EXTENSION{ ".shmodel" }; constexpr std::string_view EXTENSIONS[] = { - AUDIO_EXTENSION, - SHADER_EXTENSION, - SHADER_BUILT_IN_EXTENSION, + AUDIO_EXTENSION, + SHADER_EXTENSION, + SHADER_BUILT_IN_EXTENSION, TEXTURE_EXTENSION, MODEL_EXTENSION, SCENE_EXTENSION, - PREFAB_EXTENSION, + PREFAB_EXTENSION, MATERIAL_EXTENSION, "dummy", SCRIPT_EXTENSION, FONT_EXTENSION, - AUDIO_WAV_EXTENSION, + AUDIO_WAV_EXTENSION, }; constexpr size_t EXTENSIONS_COUNT{ 11 }; @@ -118,10 +118,10 @@ constexpr std::string_view GLTF_EXTENSION{ ".gltf" }; constexpr std::string_view TTF_EXTENSION{ ".ttf" }; constexpr std::string_view EXTERNALS[] = { - GLSL_EXTENSION, - DDS_EXTENSION, - FBX_EXTENSION, - GLTF_EXTENSION, + GLSL_EXTENSION, + DDS_EXTENSION, + FBX_EXTENSION, + GLTF_EXTENSION, TTF_EXTENSION }; @@ -131,9 +131,9 @@ constexpr std::string_view FRAGMENT_SHADER{ "_FS" }; constexpr std::string_view COMPUTER_SHADER{ "_CS" }; constexpr std::pair SHADER_IDENTIFIERS[] = { - std::make_pair(VERTEX_SHADER, SHADE::SH_SHADER_TYPE::VERTEX), - std::make_pair(FRAGMENT_SHADER, SHADE::SH_SHADER_TYPE::FRAGMENT), - std::make_pair(COMPUTER_SHADER, SHADE::SH_SHADER_TYPE::COMPUTE) + std::make_pair(VERTEX_SHADER, SHADE::SH_SHADER_TYPE::VERTEX), + std::make_pair(FRAGMENT_SHADER, SHADE::SH_SHADER_TYPE::FRAGMENT), + std::make_pair(COMPUTER_SHADER, SHADE::SH_SHADER_TYPE::COMPUTE) }; constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 }; diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 3ceb7166..5bb2d29d 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -646,31 +646,6 @@ namespace SHADE SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); } } - Handle const clip = (component->GetCurrentClip() ? component->GetCurrentClip()->GetRawAnimation() : Handle{}); - const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName(clip).value_or("") : ""; - SHEditorWidgets::DragDropReadOnlyField("Clip", CLIP_NAME, - [component]() - { - Handle const clip = (component->GetCurrentClip() ? component->GetCurrentClip()->GetRawAnimation() : Handle{}); - return SHResourceManager::GetAssetID(clip).value_or(0); - }, - [component](AssetID const& id) - { - if (SHAssetManager::GetType(id) != AssetType::MODEL) - { - SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!") - return; - } - component->SetClip(SHResourceManager::LoadOrGet(id)); - }, SHDragDrop::DRAG_RESOURCE); - if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) - { - if (Handle const clip = component->GetCurrentClip()->GetRawAnimation()) - { - AssetID assetID = SHResourceManager::GetAssetID(clip).value_or(0); - SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); - } - } } else { diff --git a/SHADE_Engine/src/Resource/SHResourceManager.h b/SHADE_Engine/src/Resource/SHResourceManager.h index 1f26bf2a..21303982 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.h +++ b/SHADE_Engine/src/Resource/SHResourceManager.h @@ -22,6 +22,7 @@ of DigiPen Institute of Technology is prohibited. #include "Assets/Asset Types/SHTextureAsset.h" #include "Assets/Asset Types/SHShaderAsset.h" #include "Assets/Asset Types/SHAnimClipAsset.h" +#include "Assets/Asset Types/SHAnimControllerAsset.h" #include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h" #include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h" @@ -40,6 +41,7 @@ namespace SHADE class SHMaterial; struct SHRigNode; class SHAnimationClip; + class SHAnimationController; /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -48,16 +50,17 @@ namespace SHADE /// Template structs that maps a resource to their loaded asset representation type. /// template - struct SHResourceLoader { using AssetType = void; }; - template<> struct SHResourceLoader { using AssetType = SHMeshAsset; }; - template<> struct SHResourceLoader { using AssetType = SHTextureAsset; }; - template<> struct SHResourceLoader { using AssetType = SHShaderAsset; }; - template<> struct SHResourceLoader { using AssetType = SHMaterialAsset; }; - template<> struct SHResourceLoader { using AssetType = SHMaterialSpec; }; - template<> struct SHResourceLoader { using AssetType = SHFontAsset; }; - template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; - template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; - template<> struct SHResourceLoader { using AssetType = SHAnimClipAsset; }; + struct SHResourceLoader { using AssetType = void; }; + template<> struct SHResourceLoader { using AssetType = SHMeshAsset; }; + template<> struct SHResourceLoader { using AssetType = SHTextureAsset; }; + template<> struct SHResourceLoader { using AssetType = SHShaderAsset; }; + template<> struct SHResourceLoader { using AssetType = SHMaterialAsset; }; + template<> struct SHResourceLoader { using AssetType = SHMaterialSpec; }; + template<> struct SHResourceLoader { using AssetType = SHFontAsset; }; + template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; + template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; + template<> struct SHResourceLoader { using AssetType = SHAnimClipAsset; }; + template<> struct SHResourceLoader { using AssetType = SHAnimControllerAsset; }; /// /// Static class responsible for loading and caching runtime resources from their diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index da557748..be6cc5e6 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -36,14 +36,16 @@ namespace SHADE Handle SHResourceManager::LoadOrGet(AssetID assetId) { // Check if it is an unsupported type - if (!std::is_same_v && - !std::is_same_v && - !std::is_same_v && - !std::is_same_v && - !std::is_same_v && - !std::is_same_v && - !std::is_same_v && - !std::is_same_v + if (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v ) { static_assert(true, "Unsupported Resource Type specified for SHResourceManager."); @@ -361,7 +363,7 @@ namespace SHADE loadedAssetData.emplace_back(assetId); return resourceHub.Create(*assetData.anims[0]); } - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) { loadedAssetData.emplace_back(assetId); return resourceHub.Create @@ -371,5 +373,13 @@ namespace SHADE assetData->lastIndex ); } + else if constexpr (std::is_same_v) + { + loadedAssetData.emplace_back(assetId); + return resourceHub.Create + ( + // TODO + ); + } } } diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index 9fceb10d..bcc3d792 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -394,13 +394,13 @@ namespace YAML struct convert { static constexpr std::string_view RIG_YAML_TAG = "Rig"; - static constexpr std::string_view CLIP_YAML_TAG = "Clip"; + static constexpr std::string_view AC_YAML_TAG = "AnimationController"; static YAML::Node encode(SHAnimatorComponent const& rhs) { YAML::Node node; node[RIG_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetRig()).value_or(0); - node[CLIP_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetCurrentClip()).value_or(0); + node[AC_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetAnimationController()).value_or(0); return node; } static bool decode(YAML::Node const& node, SHAnimatorComponent& rhs) @@ -409,9 +409,9 @@ namespace YAML { rhs.SetRig(SHResourceManager::LoadOrGet(node[RIG_YAML_TAG.data()].as())); } - if (node[CLIP_YAML_TAG.data()].IsDefined()) + if (node[AC_YAML_TAG.data()].IsDefined()) { - rhs.SetClip(SHResourceManager::LoadOrGet(node[CLIP_YAML_TAG.data()].as())); + rhs.SetAnimationController(SHResourceManager::LoadOrGet(node[AC_YAML_TAG.data()].as())); } return true; }