Added extra field in animation clip container for time multiplier #427
|
@ -20,12 +20,13 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame)
|
SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame, float playbackMultiplier)
|
||||||
: rawAnim { rawAnimHandle }
|
: rawAnim { rawAnimHandle }
|
||||||
, startFrameIndex { firstFrame }
|
, startFrameIndex { firstFrame }
|
||||||
, endFrameIndex { lastFrame }
|
, endFrameIndex { lastFrame }
|
||||||
, duration { 0.0f }
|
, duration { 0.0f }
|
||||||
, startTimeStamp { 0.0f }
|
, startTimeStamp { 0.0f }
|
||||||
|
, playbackSpeedMultiplier { playbackMultiplier }
|
||||||
{
|
{
|
||||||
if (!rawAnim)
|
if (!rawAnim)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -41,25 +41,39 @@ namespace SHADE
|
||||||
/// <param name="rawAnimHandle">Handle to the raw animation data.</param>
|
/// <param name="rawAnimHandle">Handle to the raw animation data.</param>
|
||||||
/// <param name="firstFrame">First frame to be played.</param>
|
/// <param name="firstFrame">First frame to be played.</param>
|
||||||
/// <param name="lastFrame">Last frame to be played.</param>
|
/// <param name="lastFrame">Last frame to be played.</param>
|
||||||
SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame);
|
/// <param name="playbackMultiplier">Multiplier for the playback speed.</param>
|
||||||
|
SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame, float playbackMultiplier = 1.0f);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
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; }
|
|
||||||
inline float GetStartTimeStamp() const noexcept { return startTimeStamp; }
|
inline float GetStartTimeStamp() const noexcept { return startTimeStamp; }
|
||||||
|
inline float GetPlaybackSpeedMultiplier() const noexcept { return playbackSpeedMultiplier; }
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the duration of the animation as if the playback speed multiplier is
|
||||||
|
/// in it's default value of 1.0f.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Duration of the animation in seconds.</returns>
|
||||||
|
inline float GetTotalDuration() const noexcept { return duration; }
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the duration of the animation with the playback speed multiplier
|
||||||
|
/// taken into account.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True duration of the animation in seconds.</returns>
|
||||||
|
inline float GetTrueDuration() const noexcept { return duration / playbackSpeedMultiplier; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
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
|
float duration; // Total playback time
|
||||||
float startTimeStamp; // Starting time stamp of the raw anim
|
float startTimeStamp; // Starting time stamp of the raw anim
|
||||||
|
float playbackSpeedMultiplier; // Multiplier applied to the playback of an animation clip
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -62,18 +62,21 @@ namespace SHADE
|
||||||
if (!instData.CurrentNode)
|
if (!instData.CurrentNode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Get the clip
|
||||||
|
Handle<SHAnimationClip> clip = instData.CurrentNode->Clip;
|
||||||
|
|
||||||
// Update the current playback
|
// Update the current playback
|
||||||
instData.ClipPlaybackTime += dt;
|
instData.ClipPlaybackTime += dt * clip->GetPlaybackSpeedMultiplier();
|
||||||
|
|
||||||
// Check if we finished playing
|
// Check if we finished playing
|
||||||
const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - instData.CurrentNode->Clip->GetStartTimeStamp();
|
const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - clip->GetStartTimeStamp();
|
||||||
if (CLIP_CURR_PLAYED_TIME > instData.CurrentNode->Clip->GetTotalDuration())
|
if (CLIP_CURR_PLAYED_TIME > clip->GetTotalDuration())
|
||||||
{
|
{
|
||||||
// Clamp
|
// Clamp
|
||||||
instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp() + instData.CurrentNode->Clip->GetTotalDuration();
|
instData.ClipPlaybackTime = clip->GetStartTimeStamp() + clip->GetTotalDuration();
|
||||||
|
|
||||||
// Go to next state
|
// Go to next state
|
||||||
Handle<SHAnimationClip> originalClip = instData.CurrentNode->Clip;
|
Handle<SHAnimationClip> originalClip = clip;
|
||||||
bool stateChanged = false;
|
bool stateChanged = false;
|
||||||
for (const auto& transition : instData.CurrentNode->Transitions)
|
for (const auto& transition : instData.CurrentNode->Transitions)
|
||||||
{
|
{
|
||||||
|
|
|
@ -254,7 +254,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
void SHAnimatorComponent::updateManualClipState(float dt)
|
void SHAnimatorComponent::updateManualClipState(float dt)
|
||||||
{
|
{
|
||||||
currPlaybackTime += dt;
|
currPlaybackTime += dt * currClip->GetPlaybackSpeedMultiplier();
|
||||||
const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp();
|
const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp();
|
||||||
if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration())
|
if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration())
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace SHADE
|
||||||
uint32_t firstIndex;
|
uint32_t firstIndex;
|
||||||
uint32_t lastIndex;
|
uint32_t lastIndex;
|
||||||
AssetID animRawDataAssetId; // Not serialised, only populated during runtime from parent asset
|
AssetID animRawDataAssetId; // Not serialised, only populated during runtime from parent asset
|
||||||
|
float playbackMultiplier = 1.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SH_API SHAnimClipContainerAsset final : SHAssetData
|
struct SH_API SHAnimClipContainerAsset final : SHAssetData
|
||||||
|
|
|
@ -54,6 +54,7 @@ namespace SHADE
|
||||||
newAssetName.clear();
|
newAssetName.clear();
|
||||||
firstIndex = 0;
|
firstIndex = 0;
|
||||||
lastIndex = rawAnimation->GetTotalFrames();
|
lastIndex = rawAnimation->GetTotalFrames();
|
||||||
|
playbackMultiplier = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign callback
|
// Assign callback
|
||||||
|
@ -72,6 +73,9 @@ namespace SHADE
|
||||||
SHEditorUI::PushID(1);
|
SHEditorUI::PushID(1);
|
||||||
SHEditorUI::InputUnsignedInt("Last Frame Index", lastIndex);
|
SHEditorUI::InputUnsignedInt("Last Frame Index", lastIndex);
|
||||||
SHEditorUI::PopID();
|
SHEditorUI::PopID();
|
||||||
|
SHEditorUI::PushID(2);
|
||||||
|
SHEditorUI::InputFloat("Playback Multiplier", playbackMultiplier);
|
||||||
|
SHEditorUI::PopID();
|
||||||
|
|
||||||
// Invalid values
|
// Invalid values
|
||||||
const bool INVALID_CONFIG = newAssetName.empty() || firstIndex > lastIndex;
|
const bool INVALID_CONFIG = newAssetName.empty() || firstIndex > lastIndex;
|
||||||
|
@ -88,6 +92,7 @@ namespace SHADE
|
||||||
animClip->firstIndex = firstIndex;
|
animClip->firstIndex = firstIndex;
|
||||||
animClip->lastIndex = lastIndex;
|
animClip->lastIndex = lastIndex;
|
||||||
animClip->animRawDataAssetId = SHResourceManager::GetAssetID<SHRawAnimation>(rawAnimation).value_or(0);
|
animClip->animRawDataAssetId = SHResourceManager::GetAssetID<SHRawAnimation>(rawAnimation).value_or(0);
|
||||||
|
animClip->playbackMultiplier = playbackMultiplier;
|
||||||
SHAssetManager::SaveAsset(containerAsset->id);
|
SHAssetManager::SaveAsset(containerAsset->id);
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
|
@ -168,6 +173,7 @@ namespace SHADE
|
||||||
|
|
||||||
int firstIndex = animClip->GetStartFrameIndex();
|
int firstIndex = animClip->GetStartFrameIndex();
|
||||||
int endIndex = animClip->GetEndFrameIndex();
|
int endIndex = animClip->GetEndFrameIndex();
|
||||||
|
float playbackMp = animClip->GetPlaybackSpeedMultiplier();
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text(animClipName.has_value() ? animClipName.value().c_str() : "");
|
ImGui::Text(animClipName.has_value() ? animClipName.value().c_str() : "");
|
||||||
|
@ -183,12 +189,18 @@ namespace SHADE
|
||||||
[&]() { return endIndex; },
|
[&]() { return endIndex; },
|
||||||
[&](int i) { endIndex = i; }
|
[&](int i) { endIndex = i; }
|
||||||
);
|
);
|
||||||
|
changed |= SHEditorWidgets::DragFloat
|
||||||
|
(
|
||||||
|
"Playback Multiplier",
|
||||||
|
[&]() { return playbackMp; },
|
||||||
|
[&](float f) { playbackMp = f; }
|
||||||
|
);
|
||||||
|
|
||||||
// If there's a change we need to commit changes
|
// If there's a change we need to commit changes
|
||||||
if (changed && firstIndex < endIndex)
|
if (changed && firstIndex < endIndex)
|
||||||
{
|
{
|
||||||
// Update runtime asset
|
// Update runtime asset
|
||||||
*animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex);
|
*animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex, playbackMp);
|
||||||
|
|
||||||
// Update serialized asset
|
// Update serialized asset
|
||||||
auto assetId = SHResourceManager::GetAssetID(animClip);
|
auto assetId = SHResourceManager::GetAssetID(animClip);
|
||||||
|
@ -197,6 +209,7 @@ namespace SHADE
|
||||||
auto const animAsset = SHAssetManager::GetData<SHAnimClipAsset>(assetId.value());
|
auto const animAsset = SHAssetManager::GetData<SHAnimClipAsset>(assetId.value());
|
||||||
animAsset->firstIndex = firstIndex;
|
animAsset->firstIndex = firstIndex;
|
||||||
animAsset->lastIndex = endIndex;
|
animAsset->lastIndex = endIndex;
|
||||||
|
animAsset->playbackMultiplier = playbackMp;
|
||||||
SHAssetManager::SaveAsset(containerAsset->id);
|
SHAssetManager::SaveAsset(containerAsset->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ namespace SHADE
|
||||||
std::string newAssetName;
|
std::string newAssetName;
|
||||||
uint32_t firstIndex = 0;
|
uint32_t firstIndex = 0;
|
||||||
uint32_t lastIndex = 0;
|
uint32_t lastIndex = 0;
|
||||||
|
float playbackMultiplier = 1.0f;
|
||||||
Handle<SHRawAnimation> rawAnimation;
|
Handle<SHRawAnimation> rawAnimation;
|
||||||
SHAsset* containerAsset{nullptr};
|
SHAsset* containerAsset{nullptr};
|
||||||
SHAnimClipContainerAsset* container{nullptr};
|
SHAnimClipContainerAsset* container{nullptr};
|
||||||
|
|
|
@ -372,7 +372,8 @@ namespace SHADE
|
||||||
(
|
(
|
||||||
LoadOrGet<SHRawAnimation>(assetData.animRawDataAssetId),
|
LoadOrGet<SHRawAnimation>(assetData.animRawDataAssetId),
|
||||||
assetData.firstIndex,
|
assetData.firstIndex,
|
||||||
assetData.lastIndex
|
assetData.lastIndex,
|
||||||
|
assetData.playbackMultiplier
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<ResourceType, SHAnimationController>)
|
else if constexpr (std::is_same_v<ResourceType, SHAnimationController>)
|
||||||
|
|
Loading…
Reference in New Issue