Implemented Animation Clip asset and animation controller #410
|
@ -13,6 +13,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
// Primary Header
|
// Primary Header
|
||||||
#include "SHAnimationClip.h"
|
#include "SHAnimationClip.h"
|
||||||
|
#include "SHRawAnimation.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -20,8 +21,15 @@ namespace SHADE
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame)
|
SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame)
|
||||||
: rawAnim { rawAnimHandle }
|
: rawAnim { rawAnimHandle }
|
||||||
, startFrameIndex { firstFrame }
|
, startFrameIndex { firstFrame }
|
||||||
, endFrameIndex { lastFrame }
|
, endFrameIndex { lastFrame }
|
||||||
{}
|
, duration { 0.0f }
|
||||||
|
{
|
||||||
|
if (!rawAnim)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int ONE_PAST_LAST_FRAME = lastFrame + 1;
|
||||||
|
duration = (ONE_PAST_LAST_FRAME - firstFrame) / rawAnim->GetTicksPerSecond();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -50,6 +50,7 @@ namespace SHADE
|
||||||
inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; }
|
inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; }
|
||||||
inline int GetStartFrameIndex() const noexcept { return startFrameIndex; }
|
inline int GetStartFrameIndex() const noexcept { return startFrameIndex; }
|
||||||
inline int GetEndFrameIndex() const noexcept { return endFrameIndex; }
|
inline int GetEndFrameIndex() const noexcept { return endFrameIndex; }
|
||||||
|
inline float GetTotalDuration() const noexcept { return duration; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -58,5 +59,6 @@ namespace SHADE
|
||||||
Handle<SHRawAnimation> rawAnim;
|
Handle<SHRawAnimation> rawAnim;
|
||||||
int startFrameIndex; // First Frame
|
int startFrameIndex; // First Frame
|
||||||
int endFrameIndex; // Last Frame (inclusive)
|
int endFrameIndex; // Last Frame (inclusive)
|
||||||
|
float duration; // Total playback time
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -20,22 +20,28 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Lifecycle Functions */
|
/* Lifecycle Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
void SHAnimationController::Update()
|
void SHAnimationController::Update(InstanceData& instData, float dt)
|
||||||
{
|
{
|
||||||
// Is there a valid node
|
// Is there a valid node
|
||||||
if (!currentNode)
|
if (!instData.CurrentNode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Update
|
// Update the current playback
|
||||||
for (const auto& transition : currentNode->Transitions)
|
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 */
|
/* Usage Functions */
|
||||||
|
@ -75,4 +81,24 @@ namespace SHADE
|
||||||
// Clear node
|
// Clear node
|
||||||
node.Free();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace SHADE
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Object that controls the animation that is played by an animator through the use
|
/// Object that controls the animation that is played by an animator through the use
|
||||||
/// of an internal state machine.
|
/// of an internal state machine.
|
||||||
|
/// This should never be modified once it has been attached to a SHAnimatorComponent!
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class SH_API SHAnimationController
|
class SH_API SHAnimationController
|
||||||
{
|
{
|
||||||
|
@ -58,12 +59,23 @@ namespace SHADE
|
||||||
Float,
|
Float,
|
||||||
Int
|
Int
|
||||||
};
|
};
|
||||||
|
using ValueType = std::variant<bool, float, int>;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructor */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an AnimParam with the default value set for the Value field based
|
||||||
|
/// on the specified type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">Type of AnimParam.</param>
|
||||||
|
explicit AnimParam(Type type);
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
Type ParamType;
|
Type ParamType;
|
||||||
std::variant<bool, float, int> Value;
|
ValueType Value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -91,10 +103,11 @@ namespace SHADE
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
ConditionType Condition;
|
ConditionType Condition;
|
||||||
Handle<Node> Target;
|
AnimParam::ValueType Threshold;
|
||||||
|
Handle<Node> Target;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes a node in the animation controller.
|
/// Describes a node in the animation controller.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -103,6 +116,16 @@ namespace SHADE
|
||||||
Handle<SHAnimationClip> Clip;
|
Handle<SHAnimationClip> Clip;
|
||||||
std::vector<Transition> Transitions;
|
std::vector<Transition> Transitions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes a node in the animation controller.
|
||||||
|
/// </summary>
|
||||||
|
struct InstanceData
|
||||||
|
{
|
||||||
|
Handle<Node> CurrentNode;
|
||||||
|
std::unordered_map<std::string, AnimParam> Params;
|
||||||
|
float ClipPlaybackTime;
|
||||||
|
};
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Lifecycle Functions */
|
/* Lifecycle Functions */
|
||||||
|
@ -110,11 +133,7 @@ namespace SHADE
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs a single update for the animation controller.
|
/// Runs a single update for the animation controller.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Update();
|
void Update(InstanceData& instData, float dt);
|
||||||
/// <summary>
|
|
||||||
/// Resets the animation controller to its starting node.
|
|
||||||
/// </summary>
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Usage Functions */
|
/* Usage Functions */
|
||||||
|
@ -130,20 +149,23 @@ namespace SHADE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node">Node to destroy.</param>
|
/// <param name="node">Node to destroy.</param>
|
||||||
void DestroyNode(Handle<Node> node);
|
void DestroyNode(Handle<Node> node);
|
||||||
|
void AddTransition(Handle<Node> source, const Transition& transition);
|
||||||
|
void AddParameter(const std::string& name, AnimParam::Type type);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Getters */
|
/* Getters */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
Handle<Node> GetCurrentNode() const noexcept { return currentNode; }
|
Handle<Node> GetStartingNode() const noexcept { return startNode; }
|
||||||
|
const std::unordered_map<std::string, AnimParam::Type>& GetParams() const noexcept { return parameters; }
|
||||||
|
const std::vector<Handle<Node>>& GetNodes() const noexcept { return nodes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
// State machine
|
// State machine
|
||||||
Handle<Node> currentNode;
|
|
||||||
Handle<Node> startNode;
|
Handle<Node> startNode;
|
||||||
std::vector<Handle<Node>> nodes;
|
std::vector<Handle<Node>> nodes;
|
||||||
std::unordered_map<std::string, AnimParam> parameters;
|
std::unordered_map<std::string, AnimParam::Type> parameters;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,42 @@ namespace SHADE
|
||||||
|
|
||||||
void SHAnimatorComponent::Play(Handle<SHAnimationClip> clip)
|
void SHAnimatorComponent::Play(Handle<SHAnimationClip> 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;
|
currClip = clip;
|
||||||
currPlaybackTime = 0.0f;
|
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<SHAnimationClip> clip)
|
void SHAnimatorComponent::PlayOneShot(Handle<SHAnimationClip> clip)
|
||||||
|
@ -67,6 +100,37 @@ namespace SHADE
|
||||||
currPlaybackTime = 0.0f;
|
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 */
|
/* Setter Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -86,104 +150,143 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAnimatorComponent::SetClip(Handle<SHAnimationClip> newClip)
|
void SHAnimatorComponent::SetAnimationController(Handle<SHAnimationController> ac)
|
||||||
{
|
{
|
||||||
// No change
|
// No change
|
||||||
if (currClip == newClip)
|
if (animController == ac)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get animation data
|
// Set the controller
|
||||||
auto animData = currClip->GetRawAnimation();
|
animController = ac;
|
||||||
if (!animData)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Set parameters
|
// If valid, we want to initialize it
|
||||||
currClip = newClip;
|
if (animController)
|
||||||
secsPerTick = 1.0f / animData->GetTicksPerSecond();
|
|
||||||
|
|
||||||
// Calculate total time for the clip
|
|
||||||
if (currClip)
|
|
||||||
{
|
{
|
||||||
const int ONE_PAST_LAST_FRAME = currClip->GetEndFrameIndex() + 1;
|
// Parameters
|
||||||
currClipTotalTime = (ONE_PAST_LAST_FRAME - currClip->GetStartFrameIndex()) / animData->GetTicksPerSecond();
|
animInstanceData.Params.clear();
|
||||||
}
|
for (auto param : animController->GetParams())
|
||||||
|
|
||||||
// Build channel map and clip-specific data
|
|
||||||
channelMap.clear();
|
|
||||||
if (animData)
|
|
||||||
{
|
|
||||||
for (const auto& channel : animData->GetChannels())
|
|
||||||
{
|
{
|
||||||
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<Handle<SHRawAnimation>> rawAnims;
|
||||||
|
for (auto node : animController->GetNodes())
|
||||||
|
{
|
||||||
|
// Ensure no null handles
|
||||||
|
if (!node)
|
||||||
|
continue;
|
||||||
|
const Handle<SHAnimationClip> CLIP = node->Clip;
|
||||||
|
if (!CLIP)
|
||||||
|
continue;
|
||||||
|
const Handle<SHRawAnimation> 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<SHRawAnimation> 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void SHAnimatorComponent::updateManualClipState(float dt)
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Update Functions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
void SHAnimatorComponent::Update(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;
|
currPlaybackTime += dt;
|
||||||
if (currPlaybackTime > currClipTotalTime)
|
if (currPlaybackTime > currClip->GetTotalDuration())
|
||||||
{
|
{
|
||||||
if (playOnce)
|
if (playOnce)
|
||||||
{
|
{
|
||||||
playOnce = false;
|
playOnce = false;
|
||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
|
currPlaybackTime = currClip->GetTotalDuration();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currPlaybackTime = currPlaybackTime - currClipTotalTime;
|
currPlaybackTime = currPlaybackTime - currClip->GetTotalDuration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
void SHAnimatorComponent::updateCurrentAnimatorState(Handle<SHAnimationClip> 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
|
// Play the clip
|
||||||
updatePoseWithClip(currPlaybackTime);
|
updatePoseWithClip(clip, currPlaybackTime);
|
||||||
}
|
}
|
||||||
|
void SHAnimatorComponent::updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime)
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Helper Functions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
void SHAnimatorComponent::updatePoseWithClip(float poseTime)
|
|
||||||
{
|
{
|
||||||
// Get closest frame index
|
// Get closest frame index
|
||||||
const int CLOSEST_FRAME_IDX = currClip->GetStartFrameIndex() + static_cast<int>(std::floorf(poseTime * currClip->GetRawAnimation()->GetTicksPerSecond()));
|
const int CLOSEST_FRAME_IDX = clip->GetStartFrameIndex() + static_cast<int>(std::floorf(poseTime / secsPerTick));
|
||||||
updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, rig->GetRootNode(), SHMatrix::Identity);
|
updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, clip->GetRawAnimation(), rig->GetRootNode(), SHMatrix::Identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAnimatorComponent::updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
|
void SHAnimatorComponent::updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
|
||||||
{
|
{
|
||||||
// Check if there is a channel for this node
|
// Check if there is a channel for this node
|
||||||
const std::string& BONE_NAME = rig->GetName(node);
|
const std::string& BONE_NAME = rig->GetName(node);
|
||||||
SHMatrix transformMatrix = node->TransformMatrix;
|
SHMatrix transformMatrix = node->TransformMatrix;
|
||||||
if (channelMap.contains(BONE_NAME))
|
|
||||||
|
if (channelMaps.contains(rawAnimData))
|
||||||
{
|
{
|
||||||
const auto CHANNEL = channelMap[BONE_NAME];
|
auto channelMap = channelMaps[rawAnimData];
|
||||||
transformMatrix = SHMatrix::Transform
|
if (channelMap.contains(BONE_NAME))
|
||||||
(
|
{
|
||||||
getInterpolatedValue(CHANNEL->PositionKeyFrames, closestFrameIndex, poseTime),
|
const auto CHANNEL = channelMap[BONE_NAME];
|
||||||
getInterpolatedValue(CHANNEL->RotationKeyFrames, closestFrameIndex, poseTime),
|
transformMatrix = SHMatrix::Transform
|
||||||
getInterpolatedValue(CHANNEL->ScaleKeyFrames, closestFrameIndex, poseTime)
|
(
|
||||||
);
|
getInterpolatedValue(CHANNEL->PositionKeyFrames, closestFrameIndex, poseTime),
|
||||||
|
getInterpolatedValue(CHANNEL->RotationKeyFrames, closestFrameIndex, poseTime),
|
||||||
|
getInterpolatedValue(CHANNEL->ScaleKeyFrames, closestFrameIndex, poseTime)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply parent's transformation
|
// Apply parent's transformation
|
||||||
|
@ -200,7 +303,7 @@ namespace SHADE
|
||||||
// Apply pose to children
|
// Apply pose to children
|
||||||
for (auto& child : node->Children)
|
for (auto& child : node->Children)
|
||||||
{
|
{
|
||||||
updatePoseWithClip(closestFrameIndex, poseTime, child, transformMatrix);
|
updatePoseWithClip(closestFrameIndex, poseTime, rawAnimData, child, transformMatrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
#include "Math/SHQuaternion.h"
|
#include "Math/SHQuaternion.h"
|
||||||
#include "SHRawAnimation.h"
|
#include "SHRawAnimation.h"
|
||||||
|
#include "SHAnimationController.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -52,12 +53,14 @@ namespace SHADE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Play();
|
void Play();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="clip">Animation clip to play.</param>
|
/// <param name="clip">Animation clip to play.</param>
|
||||||
void Play(Handle<SHAnimationClip> clip);
|
void Play(Handle<SHAnimationClip> clip);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="clip">Animation clip to play.</param>
|
/// <param name="clip">Animation clip to play.</param>
|
||||||
void PlayOneShot(Handle<SHAnimationClip> clip);
|
void PlayOneShot(Handle<SHAnimationClip> clip);
|
||||||
|
@ -74,6 +77,16 @@ namespace SHADE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Update Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dt">Time passed since the last frame.</param>
|
||||||
|
void Update(float dt);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -82,13 +95,7 @@ namespace SHADE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="newRig">Rig to use.</param>
|
/// <param name="newRig">Rig to use.</param>
|
||||||
void SetRig(Handle<SHRig> newRig);
|
void SetRig(Handle<SHRig> newRig);
|
||||||
/// <summary>
|
void SetAnimationController(Handle<SHAnimationController> ac);
|
||||||
/// 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.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newClip">Clip to use.</param>
|
|
||||||
void SetClip(Handle<SHAnimationClip> newClip);
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
|
@ -104,51 +111,55 @@ namespace SHADE
|
||||||
/// <returns>Handle to the currently set rig.</returns>
|
/// <returns>Handle to the currently set rig.</returns>
|
||||||
Handle<SHRig> GetRig() const noexcept { return rig; }
|
Handle<SHRig> GetRig() const noexcept { return rig; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <summary>
|
|
||||||
/// Retrieve the currently set animation clip.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Handle to the currently set animation clip.</returns>
|
|
||||||
Handle<SHAnimationClip> GetCurrentClip() const noexcept { return currClip; }
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if an animation is currently playing.
|
/// Checks if an animation is currently playing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if an animation clip is currently playing.</returns>
|
/// <returns>True if an animation clip is currently playing.</returns>
|
||||||
bool IsPlaying() const { return isPlaying; }
|
bool IsPlaying() const { return isPlaying; }
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Update Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the current state of the animation if one is specified based on the
|
/// Retrieves the current node for the Animation Controller. This returns a null
|
||||||
/// current animation clip and frames. This will update the bone matrices.
|
/// if there is no Animation Controller currently set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dt">Time passed since the last frame.</param>
|
/// <returns>Handle to the current Animation Controller node.</returns>
|
||||||
void Update(float dt);
|
Handle<SHAnimationController::Node> GetCurrentNode() const noexcept { return animInstanceData.CurrentNode; }
|
||||||
|
Handle<SHAnimationController> GetAnimationController() const noexcept { return animController; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definition */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
using ChannelMap = std::unordered_map<std::string, const SHRawAnimation::Channel*>;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
// Resources
|
// Resources
|
||||||
Handle<SHRig> rig;
|
Handle<SHRig> rig;
|
||||||
|
// Playback Tracking for Animation Controller Mode
|
||||||
|
Handle<SHAnimationController> animController;
|
||||||
|
SHAnimationController::InstanceData animInstanceData;
|
||||||
|
// Playback Tracking for Manual Mode
|
||||||
Handle<SHAnimationClip> currClip;
|
Handle<SHAnimationClip> currClip;
|
||||||
// Playback Tracking
|
|
||||||
float currPlaybackTime = 0.0f;
|
float currPlaybackTime = 0.0f;
|
||||||
bool isPlaying = true;
|
|
||||||
bool playOnce = false;
|
bool playOnce = false;
|
||||||
float currClipTotalTime = 0.0f;
|
// Shared Tracking
|
||||||
// Useful Cached Data
|
bool isPlaying = true;
|
||||||
float secsPerTick = 0.0f;
|
float secsPerTick = 0.0f;
|
||||||
// Buffer
|
// Buffer
|
||||||
std::vector<SHMatrix> boneMatrices;
|
std::vector<SHMatrix> boneMatrices;
|
||||||
// Caches
|
// Caches
|
||||||
std::unordered_map<std::string, const SHRawAnimation::Channel*> channelMap;
|
std::unordered_map<Handle<SHRawAnimation>, ChannelMap> channelMaps;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
void updatePoseWithClip(float poseTime);
|
// Loading
|
||||||
void updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
|
ChannelMap createChannelMap(Handle<SHRawAnimation> rawAnimData);
|
||||||
|
// Update
|
||||||
|
void updateAnimController(float dt);
|
||||||
|
void updateManualClipState(float dt);
|
||||||
|
void updateCurrentAnimatorState(Handle<SHAnimationClip> clip, float playbackTime);
|
||||||
|
void updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime);
|
||||||
|
void updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime);
|
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime);
|
||||||
|
|
||||||
|
|
|
@ -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 <string>
|
||||||
|
|
||||||
|
#include "SH_API.h"
|
||||||
|
#include "SHAssetData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SH_API SHAnimControllerAsset : SHAssetData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
// TODO
|
||||||
|
};
|
||||||
|
}
|
|
@ -18,10 +18,10 @@
|
||||||
// FMOD Fwd Declare
|
// FMOD Fwd Declare
|
||||||
namespace FMOD
|
namespace FMOD
|
||||||
{
|
{
|
||||||
class Sound;
|
class Sound;
|
||||||
class System;
|
class System;
|
||||||
class ChannelGroup;
|
class ChannelGroup;
|
||||||
class Channel;
|
class Channel;
|
||||||
}
|
}
|
||||||
enum FMOD_RESULT : int;
|
enum FMOD_RESULT : int;
|
||||||
enum FMOD_SPEAKERMODE : int;
|
enum FMOD_SPEAKERMODE : int;
|
||||||
|
@ -45,9 +45,9 @@ constexpr AssetID INVALID_ASSET_ID {0};
|
||||||
// Asset type enum
|
// Asset type enum
|
||||||
enum class AssetType : AssetTypeMeta
|
enum class AssetType : AssetTypeMeta
|
||||||
{
|
{
|
||||||
INVALID,
|
INVALID,
|
||||||
SHADER,
|
SHADER,
|
||||||
SHADER_BUILT_IN,
|
SHADER_BUILT_IN,
|
||||||
TEXTURE,
|
TEXTURE,
|
||||||
MODEL,
|
MODEL,
|
||||||
SCENE,
|
SCENE,
|
||||||
|
@ -56,7 +56,7 @@ enum class AssetType : AssetTypeMeta
|
||||||
MESH,
|
MESH,
|
||||||
SCRIPT,
|
SCRIPT,
|
||||||
FONT,
|
FONT,
|
||||||
MAX_COUNT
|
MAX_COUNT
|
||||||
};
|
};
|
||||||
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
constexpr size_t TYPE_COUNT{ static_cast<size_t>(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 MODEL_EXTENSION{ ".shmodel" };
|
||||||
|
|
||||||
constexpr std::string_view EXTENSIONS[] = {
|
constexpr std::string_view EXTENSIONS[] = {
|
||||||
AUDIO_EXTENSION,
|
AUDIO_EXTENSION,
|
||||||
SHADER_EXTENSION,
|
SHADER_EXTENSION,
|
||||||
SHADER_BUILT_IN_EXTENSION,
|
SHADER_BUILT_IN_EXTENSION,
|
||||||
TEXTURE_EXTENSION,
|
TEXTURE_EXTENSION,
|
||||||
MODEL_EXTENSION,
|
MODEL_EXTENSION,
|
||||||
SCENE_EXTENSION,
|
SCENE_EXTENSION,
|
||||||
PREFAB_EXTENSION,
|
PREFAB_EXTENSION,
|
||||||
MATERIAL_EXTENSION,
|
MATERIAL_EXTENSION,
|
||||||
"dummy",
|
"dummy",
|
||||||
SCRIPT_EXTENSION,
|
SCRIPT_EXTENSION,
|
||||||
FONT_EXTENSION,
|
FONT_EXTENSION,
|
||||||
AUDIO_WAV_EXTENSION,
|
AUDIO_WAV_EXTENSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr size_t EXTENSIONS_COUNT{ 11 };
|
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 TTF_EXTENSION{ ".ttf" };
|
||||||
|
|
||||||
constexpr std::string_view EXTERNALS[] = {
|
constexpr std::string_view EXTERNALS[] = {
|
||||||
GLSL_EXTENSION,
|
GLSL_EXTENSION,
|
||||||
DDS_EXTENSION,
|
DDS_EXTENSION,
|
||||||
FBX_EXTENSION,
|
FBX_EXTENSION,
|
||||||
GLTF_EXTENSION,
|
GLTF_EXTENSION,
|
||||||
TTF_EXTENSION
|
TTF_EXTENSION
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,9 +131,9 @@ constexpr std::string_view FRAGMENT_SHADER{ "_FS" };
|
||||||
constexpr std::string_view COMPUTER_SHADER{ "_CS" };
|
constexpr std::string_view COMPUTER_SHADER{ "_CS" };
|
||||||
|
|
||||||
constexpr std::pair<std::string_view, SHADE::SH_SHADER_TYPE> SHADER_IDENTIFIERS[] = {
|
constexpr std::pair<std::string_view, SHADE::SH_SHADER_TYPE> SHADER_IDENTIFIERS[] = {
|
||||||
std::make_pair(VERTEX_SHADER, SHADE::SH_SHADER_TYPE::VERTEX),
|
std::make_pair(VERTEX_SHADER, SHADE::SH_SHADER_TYPE::VERTEX),
|
||||||
std::make_pair(FRAGMENT_SHADER, SHADE::SH_SHADER_TYPE::FRAGMENT),
|
std::make_pair(FRAGMENT_SHADER, SHADE::SH_SHADER_TYPE::FRAGMENT),
|
||||||
std::make_pair(COMPUTER_SHADER, SHADE::SH_SHADER_TYPE::COMPUTE)
|
std::make_pair(COMPUTER_SHADER, SHADE::SH_SHADER_TYPE::COMPUTE)
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 };
|
constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 };
|
||||||
|
|
|
@ -646,31 +646,6 @@ namespace SHADE
|
||||||
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Handle<SHRawAnimation> const clip = (component->GetCurrentClip() ? component->GetCurrentClip()->GetRawAnimation() : Handle<SHRawAnimation>{});
|
|
||||||
const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName<SHRawAnimation>(clip).value_or("") : "";
|
|
||||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME,
|
|
||||||
[component]()
|
|
||||||
{
|
|
||||||
Handle<SHRawAnimation> const clip = (component->GetCurrentClip() ? component->GetCurrentClip()->GetRawAnimation() : Handle<SHRawAnimation>{});
|
|
||||||
return SHResourceManager::GetAssetID<SHRawAnimation>(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<SHAnimationClip>(id));
|
|
||||||
}, SHDragDrop::DRAG_RESOURCE);
|
|
||||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
|
||||||
{
|
|
||||||
if (Handle<SHRawAnimation> const clip = component->GetCurrentClip()->GetRawAnimation())
|
|
||||||
{
|
|
||||||
AssetID assetID = SHResourceManager::GetAssetID<SHRawAnimation>(clip).value_or(0);
|
|
||||||
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||||
#include "Assets/Asset Types/SHShaderAsset.h"
|
#include "Assets/Asset Types/SHShaderAsset.h"
|
||||||
#include "Assets/Asset Types/SHAnimClipAsset.h"
|
#include "Assets/Asset Types/SHAnimClipAsset.h"
|
||||||
|
#include "Assets/Asset Types/SHAnimControllerAsset.h"
|
||||||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||||
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
|
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
|
||||||
|
@ -40,6 +41,7 @@ namespace SHADE
|
||||||
class SHMaterial;
|
class SHMaterial;
|
||||||
struct SHRigNode;
|
struct SHRigNode;
|
||||||
class SHAnimationClip;
|
class SHAnimationClip;
|
||||||
|
class SHAnimationController;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
|
@ -48,16 +50,17 @@ namespace SHADE
|
||||||
/// Template structs that maps a resource to their loaded asset representation type.
|
/// Template structs that maps a resource to their loaded asset representation type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
template<typename T = void>
|
template<typename T = void>
|
||||||
struct SHResourceLoader { using AssetType = void; };
|
struct SHResourceLoader { using AssetType = void; };
|
||||||
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshAsset; };
|
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshAsset; };
|
||||||
template<> struct SHResourceLoader<SHTexture> { using AssetType = SHTextureAsset; };
|
template<> struct SHResourceLoader<SHTexture> { using AssetType = SHTextureAsset; };
|
||||||
template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; };
|
template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; };
|
||||||
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
|
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
|
||||||
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
|
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
|
||||||
template<> struct SHResourceLoader<SHFont> { using AssetType = SHFontAsset; };
|
template<> struct SHResourceLoader<SHFont> { using AssetType = SHFontAsset; };
|
||||||
template<> struct SHResourceLoader<SHRawAnimation> { using AssetType = SHModelAsset; };
|
template<> struct SHResourceLoader<SHRawAnimation> { using AssetType = SHModelAsset; };
|
||||||
template<> struct SHResourceLoader<SHRig> { using AssetType = SHModelAsset; };
|
template<> struct SHResourceLoader<SHRig> { using AssetType = SHModelAsset; };
|
||||||
template<> struct SHResourceLoader<SHAnimationClip> { using AssetType = SHAnimClipAsset; };
|
template<> struct SHResourceLoader<SHAnimationClip> { using AssetType = SHAnimClipAsset; };
|
||||||
|
template<> struct SHResourceLoader<SHAnimationController> { using AssetType = SHAnimControllerAsset; };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Static class responsible for loading and caching runtime resources from their
|
/// Static class responsible for loading and caching runtime resources from their
|
||||||
|
|
|
@ -36,14 +36,16 @@ namespace SHADE
|
||||||
Handle<ResourceType> SHResourceManager::LoadOrGet(AssetID assetId)
|
Handle<ResourceType> SHResourceManager::LoadOrGet(AssetID assetId)
|
||||||
{
|
{
|
||||||
// Check if it is an unsupported type
|
// Check if it is an unsupported type
|
||||||
if (!std::is_same_v<ResourceType, SHMesh> &&
|
if (!std::is_same_v<ResourceType, SHMesh> &&
|
||||||
!std::is_same_v<ResourceType, SHTexture> &&
|
!std::is_same_v<ResourceType, SHTexture> &&
|
||||||
!std::is_same_v<ResourceType, SHVkShaderModule> &&
|
!std::is_same_v<ResourceType, SHVkShaderModule> &&
|
||||||
!std::is_same_v<ResourceType, SHMaterialSpec> &&
|
!std::is_same_v<ResourceType, SHMaterialSpec> &&
|
||||||
!std::is_same_v<ResourceType, SHFont> &&
|
!std::is_same_v<ResourceType, SHFont> &&
|
||||||
!std::is_same_v<ResourceType, SHMaterial> &&
|
!std::is_same_v<ResourceType, SHMaterial> &&
|
||||||
!std::is_same_v<ResourceType, SHRawAnimation> &&
|
!std::is_same_v<ResourceType, SHRawAnimation> &&
|
||||||
!std::is_same_v<ResourceType, SHRig>
|
!std::is_same_v<ResourceType, SHRig> &&
|
||||||
|
!std::is_same_v<ResourceType, SHAnimationClip> &&
|
||||||
|
!std::is_same_v<ResourceType, SHAnimationController>
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
|
static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
|
||||||
|
@ -361,7 +363,7 @@ namespace SHADE
|
||||||
loadedAssetData.emplace_back(assetId);
|
loadedAssetData.emplace_back(assetId);
|
||||||
return resourceHub.Create<ResourceType>(*assetData.anims[0]);
|
return resourceHub.Create<ResourceType>(*assetData.anims[0]);
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<ResourceType, SHAnimClipAsset>)
|
else if constexpr (std::is_same_v<ResourceType, SHAnimationClip>)
|
||||||
{
|
{
|
||||||
loadedAssetData.emplace_back(assetId);
|
loadedAssetData.emplace_back(assetId);
|
||||||
return resourceHub.Create<ResourceType>
|
return resourceHub.Create<ResourceType>
|
||||||
|
@ -371,5 +373,13 @@ namespace SHADE
|
||||||
assetData->lastIndex
|
assetData->lastIndex
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_same_v<ResourceType, SHAnimationController>)
|
||||||
|
{
|
||||||
|
loadedAssetData.emplace_back(assetId);
|
||||||
|
return resourceHub.Create<ResourceType>
|
||||||
|
(
|
||||||
|
// TODO
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -394,13 +394,13 @@ namespace YAML
|
||||||
struct convert<SHAnimatorComponent>
|
struct convert<SHAnimatorComponent>
|
||||||
{
|
{
|
||||||
static constexpr std::string_view RIG_YAML_TAG = "Rig";
|
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)
|
static YAML::Node encode(SHAnimatorComponent const& rhs)
|
||||||
{
|
{
|
||||||
YAML::Node node;
|
YAML::Node node;
|
||||||
node[RIG_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHRig>(rhs.GetRig()).value_or(0);
|
node[RIG_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHRig>(rhs.GetRig()).value_or(0);
|
||||||
node[CLIP_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHAnimationClip>(rhs.GetCurrentClip()).value_or(0);
|
node[AC_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHAnimationController>(rhs.GetAnimationController()).value_or(0);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
static bool decode(YAML::Node const& node, SHAnimatorComponent& rhs)
|
static bool decode(YAML::Node const& node, SHAnimatorComponent& rhs)
|
||||||
|
@ -409,9 +409,9 @@ namespace YAML
|
||||||
{
|
{
|
||||||
rhs.SetRig(SHResourceManager::LoadOrGet<SHRig>(node[RIG_YAML_TAG.data()].as<AssetID>()));
|
rhs.SetRig(SHResourceManager::LoadOrGet<SHRig>(node[RIG_YAML_TAG.data()].as<AssetID>()));
|
||||||
}
|
}
|
||||||
if (node[CLIP_YAML_TAG.data()].IsDefined())
|
if (node[AC_YAML_TAG.data()].IsDefined())
|
||||||
{
|
{
|
||||||
rhs.SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(node[CLIP_YAML_TAG.data()].as<AssetID>()));
|
rhs.SetAnimationController(SHResourceManager::LoadOrGet<SHAnimationController>(node[AC_YAML_TAG.data()].as<AssetID>()));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue