diff --git a/Jolt/Skeleton/SkeletalAnimation.cpp b/Jolt/Skeleton/SkeletalAnimation.cpp index 4bf87007e..27ff583f7 100644 --- a/Jolt/Skeleton/SkeletalAnimation.cpp +++ b/Jolt/Skeleton/SkeletalAnimation.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include JPH_NAMESPACE_BEGIN @@ -107,4 +109,57 @@ void SkeletalAnimation::Sample(float inTime, SkeletonPose &ioPose) const } } +void SkeletalAnimation::SaveBinaryState(StreamOut &inStream) const +{ + inStream.Write((uint32)mAnimatedJoints.size()); + for (const AnimatedJoint &j : mAnimatedJoints) + { + // Write Joint name and number of keyframes + inStream.Write(j.mJointName); + inStream.Write((uint32)j.mKeyframes.size()); + for (const Keyframe &k : j.mKeyframes) + { + inStream.Write(k.mTime); + inStream.Write(k.mRotation); + inStream.Write(k.mTranslation); + } + } + + // Save additional parameters + inStream.Write(mIsLooping); +} + +SkeletalAnimation::AnimationResult SkeletalAnimation::sRestoreFromBinaryState(StreamIn &inStream) +{ + AnimationResult result; + + Ref animation = new SkeletalAnimation; + + // Restore animated joints + uint32 len = 0; + inStream.Read(len); + animation->mAnimatedJoints.resize(len); + for (AnimatedJoint &j : animation->mAnimatedJoints) + { + // Read joint name + inStream.Read(j.mJointName); + + // Read keyframes + len = 0; + inStream.Read(len); + j.mKeyframes.resize(len); + for (Keyframe &k : j.mKeyframes) + { + inStream.Read(k.mTime); + inStream.Read(k.mRotation); + inStream.Read(k.mTranslation); + } + } + + // Read additional parameters + inStream.Read(animation->mIsLooping); + result.Set(animation); + return result; +} + JPH_NAMESPACE_END diff --git a/Jolt/Skeleton/SkeletalAnimation.h b/Jolt/Skeleton/SkeletalAnimation.h index 344c6046f..a5769f14c 100644 --- a/Jolt/Skeleton/SkeletalAnimation.h +++ b/Jolt/Skeleton/SkeletalAnimation.h @@ -5,6 +5,8 @@ #pragma once #include +#include +#include #include JPH_NAMESPACE_BEGIN @@ -62,6 +64,10 @@ class JPH_EXPORT SkeletalAnimation : public RefTarget /// Scale the size of all joints by inScale void ScaleJoints(float inScale); + /// If the animation is looping or not. If an animation is looping, the animation will continue playing after completion + void SetIsLooping(bool inIsLooping) { mIsLooping = inIsLooping; } + bool IsLooping() const { return mIsLooping; } + /// Get the (interpolated) joint transforms at time inTime void Sample(float inTime, SkeletonPose &ioPose) const; @@ -69,6 +75,14 @@ class JPH_EXPORT SkeletalAnimation : public RefTarget const AnimatedJointVector & GetAnimatedJoints() const { return mAnimatedJoints; } AnimatedJointVector & GetAnimatedJoints() { return mAnimatedJoints; } + /// Saves the state of this animation in binary form to inStream. + void SaveBinaryState(StreamOut &inStream) const; + + using AnimationResult = Result>; + + /// Restore a saved ragdoll from inStream + static AnimationResult sRestoreFromBinaryState(StreamIn &inStream); + private: AnimatedJointVector mAnimatedJoints; ///< List of joints and keyframes bool mIsLooping = true; ///< If this animation loops back to start