3#include "pixelbullet/scene/components/animation_state_component.h"
4#include "pixelbullet/serialization/node.h"
10#include <unordered_map>
17 float time_seconds = 0.0f;
18 std::vector<float> weights;
23 return lhs.time_seconds == rhs.time_seconds && lhs.weights == rhs.weights;
26inline bool operator!=(
const MorphWeightsKeyframe& lhs,
const MorphWeightsKeyframe& rhs)
31inline void NormalizeMorphWeightsAnimationKeys(std::vector<MorphWeightsKeyframe>& keys)
33 for (
auto& key : keys)
35 key.time_seconds = std::max(key.time_seconds, 0.0f);
38 std::stable_sort(keys.begin(), keys.end(),
41 std::vector<MorphWeightsKeyframe> normalized;
42 normalized.reserve(keys.size());
45 if (!normalized.empty() && std::abs(normalized.back().time_seconds - key.time_seconds) <= 0.0001f)
47 normalized.back() = key;
51 normalized.push_back(key);
55 keys = std::move(normalized);
58inline float ResolveMorphWeightsAnimationClipLength(
const std::vector<MorphWeightsKeyframe>& keys)
noexcept
60 return keys.empty() ? 0.0f : std::max(keys.back().time_seconds, 0.0f);
65 std::string name =
"Default";
66 std::vector<MorphWeightsKeyframe> keys;
71 return lhs.name == rhs.name && lhs.keys == rhs.keys;
74inline bool operator!=(
const MorphWeightsAnimationClip& lhs,
const MorphWeightsAnimationClip& rhs)
79inline std::string NormalizeMorphAnimationClipName(std::string_view name, std::string_view fallback)
81 std::string normalized = name.empty() ? std::string(fallback) : std::string(name);
82 if (normalized.empty())
84 normalized = std::string(fallback);
91 NormalizeMorphWeightsAnimationKeys(clip.keys);
96 return ResolveMorphWeightsAnimationClipLength(clip.keys);
101 std::vector<MorphWeightsAnimationClip> clips;
106 return lhs.clips == rhs.clips;
109inline bool operator!=(
const MorphWeightsAnimationComponent& lhs,
const MorphWeightsAnimationComponent& rhs)
111 return !(lhs == rhs);
116 std::unordered_map<std::string, std::size_t> counts;
119 NormalizeMorphWeightsAnimationClip(clip);
120 std::string normalized_name = NormalizeMorphAnimationClipName(clip.name,
"Default");
121 const auto [it, inserted] = counts.emplace(normalized_name, 0u);
125 normalized_name +=
" " + std::to_string(it->second + 1u);
127 clip.name = std::move(normalized_name);
132 const std::string_view name)
136 if (clip.name == name)
148 if (clip.name == name)
159 if (component.clips.empty())
164 if (state !=
nullptr && !state->active_clip.empty())
172 return &component.clips.front();
180 return ResolveMorphWeightsAnimationClipLength(*clip);
188 return ResolveMorphWeightsAnimationClipLength(component,
nullptr);
193 node[
"timeSeconds"] << keyframe.time_seconds;
194 node[
"weights"] << keyframe.weights;
200 node[
"timeSeconds"] >> keyframe.time_seconds;
201 if (node.HasProperty(
"weights"))
203 node[
"weights"] >> keyframe.weights;
207 keyframe.weights.clear();
209 keyframe.time_seconds = std::max(keyframe.time_seconds, 0.0f);
215 node[
"name"] << clip.name;
216 node[
"keys"] << clip.keys;
222 if (node.HasProperty(
"name"))
224 node[
"name"] >> clip.name;
228 clip.name =
"Default";
231 if (node.HasProperty(
"keys"))
233 node[
"keys"] >> clip.keys;
240 NormalizeMorphWeightsAnimationClip(clip);
246 node[
"clips"] << component.clips;
252 component.clips.clear();
253 if (node.HasProperty(
"clips"))
255 node[
"clips"] >> component.clips;
260 clip.name =
"Default";
261 if (node.HasProperty(
"keys"))
263 node[
"keys"] >> clip.keys;
265 NormalizeMorphWeightsAnimationClip(clip);
266 if (!clip.keys.empty() || node.HasProperty(
"enabled"))
268 component.clips.push_back(std::move(clip));
272 NormalizeMorphWeightsAnimationComponent(component);
Represents a hierarchical node capable of storing various data types and supporting YAML serializatio...
Definition node.h:45
Definition animation_state_component.h:10
Definition morph_weights_animation_component.h:64
Definition morph_weights_animation_component.h:100
Definition morph_weights_animation_component.h:16