#include "stdafx.h" #include "Animation.h" namespace Assets { Animation::Animation() : Animation(0) { } Animation::Animation(uint32_t BoneCount) : Animation(BoneCount, 30.0f) { } Animation::Animation(uint32_t BoneCount, float FrameRate) : Bones(BoneCount), Looping(false), FrameRate(FrameRate), Name("error"), TransformSpace(AnimationTransformSpace::Local), RotationInterpolation(AnimationRotationInterpolation::Quaternion) { } List& Animation::GetNodeCurves(const String& NodeName) { if (Curves.ContainsKey(NodeName)) return Curves[NodeName]; Curves.Add(NodeName, List()); return Curves[NodeName]; } void Animation::AddNotification(const String& Name, uint32_t Frame) { if (Notificiations.ContainsKey(Name)) Notificiations[Name].EmplaceBack(Frame); Notificiations.Add(Name, List()); Notificiations[Name].EmplaceBack(Frame); } const uint32_t Animation::FrameCount(bool Legacy) const { uint32_t Result = 0; for (auto& Kvp : Curves) { for (auto& Curve : Kvp.Value()) { if (Legacy) { // Used for animation types which do not support non-bone like curves // So we only have quaternion rotation, translations, and scales if (Curve.Property == CurveProperty::RotateQuaternion || (Curve.Property >= CurveProperty::TranslateX && Curve.Property <= CurveProperty::TranslateZ) || (Curve.Property >= CurveProperty::ScaleX && Curve.Property <= CurveProperty::ScaleZ)) { for (auto& Keyframe : Curve.Keyframes) Result = max(Result, Keyframe.Frame.Integer32); } } else { // Support all curves for (auto& Keyframe : Curve.Keyframes) Result = max(Result, Keyframe.Frame.Integer32); } } } for (auto& NoteTrack : Notificiations) for (auto& Note : NoteTrack.Value()) Result = max(Result, Note); // Frame count is the length of the animation in frames // Frames start at index 0, so we add one to get the count return Result + 1; } const uint32_t Animation::NotificationCount() const { uint32_t Result = 0; for (auto& NoteTrack : Notificiations) Result += NoteTrack.Value().Count(); return Result; } void Animation::Scale(float Factor) { for (auto& Kvp : Curves) { for (auto& Curve : Kvp.Value()) { // Translation keyframes are scaled here... if (Curve.Property >= CurveProperty::TranslateX && Curve.Property <= CurveProperty::TranslateZ) { for (auto& Keyframe : Curve.Keyframes) { Keyframe.Value.Float *= Factor; } } } } for (auto& Bone : Bones) { if (Bone.GetFlag(BoneFlags::HasLocalSpaceMatrices)) { Bone.SetLocalPosition(Bone.LocalPosition() * Factor); } if (Bone.GetFlag(BoneFlags::HasGlobalSpaceMatrices)) { Bone.SetGlobalPosition(Bone.GlobalPosition() * Factor); } } } void Animation::RemoveEmptyNodes() { for (auto& Kvp : Curves) { for (int32_t i = ((int32_t)Kvp.Value().Count() - 1); i >= 0; i--) { if (Kvp.Value()[i].Keyframes.Count() == 0) { Kvp.Value().RemoveAt(i); } } } } }