PixelBullet  0.0.1
A C++ game engine
Loading...
Searching...
No Matches
skeleton_animation_component.h
1#pragma once
2
3#include "pixelbullet/filesystem/virtual_path.h"
4#include "pixelbullet/filesystem/virtual_path_serialization.h"
5#include "pixelbullet/scene/components/animation_state_component.h"
6#include "pixelbullet/scene/entity_id.h"
7#include "pixelbullet/serialization/node.h"
8
9#include <string>
10#include <string_view>
11#include <unordered_map>
12#include <vector>
13
14namespace pixelbullet
15{
17{
18 std::string name = "Default";
19 VirtualPath clip_asset;
20};
21
22inline bool operator==(const SkeletonAnimationClipBinding& lhs, const SkeletonAnimationClipBinding& rhs)
23{
24 return lhs.name == rhs.name && lhs.clip_asset == rhs.clip_asset;
25}
26
27inline bool operator!=(const SkeletonAnimationClipBinding& lhs, const SkeletonAnimationClipBinding& rhs)
28{
29 return !(lhs == rhs);
30}
31
33{
34 VirtualPath skeleton_asset;
35 std::vector<EntityId> joint_entities;
36 std::vector<SkeletonAnimationClipBinding> clips;
37};
38
39inline bool operator==(const SkeletonAnimationComponent& lhs, const SkeletonAnimationComponent& rhs)
40{
41 return lhs.skeleton_asset == rhs.skeleton_asset && lhs.joint_entities == rhs.joint_entities && lhs.clips == rhs.clips;
42}
43
44inline bool operator!=(const SkeletonAnimationComponent& lhs, const SkeletonAnimationComponent& rhs)
45{
46 return !(lhs == rhs);
47}
48
49inline std::string NormalizeSkeletonAnimationClipName(std::string_view name, std::string_view fallback)
50{
51 std::string normalized = name.empty() ? std::string(fallback) : std::string(name);
52 if (normalized.empty())
53 {
54 normalized = std::string(fallback);
55 }
56 return normalized;
57}
58
59inline void NormalizeSkeletonAnimationComponent(SkeletonAnimationComponent& component)
60{
61 std::unordered_map<std::string, std::size_t> counts;
62 for (SkeletonAnimationClipBinding& clip : component.clips)
63 {
64 std::string normalized_name = NormalizeSkeletonAnimationClipName(clip.name, "Default");
65 const auto [it, inserted] = counts.emplace(normalized_name, 0u);
66 if (!inserted)
67 {
68 ++it->second;
69 normalized_name += " " + std::to_string(it->second + 1u);
70 }
71 clip.name = std::move(normalized_name);
72 }
73}
74
75inline const SkeletonAnimationClipBinding* FindSkeletonAnimationClipBinding(const SkeletonAnimationComponent& component,
76 const std::string_view name)
77{
78 for (const SkeletonAnimationClipBinding& clip : component.clips)
79 {
80 if (clip.name == name)
81 {
82 return &clip;
83 }
84 }
85 return nullptr;
86}
87
88inline SkeletonAnimationClipBinding* FindSkeletonAnimationClipBinding(SkeletonAnimationComponent& component, const std::string_view name)
89{
90 for (SkeletonAnimationClipBinding& clip : component.clips)
91 {
92 if (clip.name == name)
93 {
94 return &clip;
95 }
96 }
97 return nullptr;
98}
99
100inline const SkeletonAnimationClipBinding* ResolveActiveSkeletonAnimationClipBinding(const SkeletonAnimationComponent& component,
101 const AnimationStateComponent* state = nullptr)
102{
103 if (component.clips.empty())
104 {
105 return nullptr;
106 }
107
108 if (state != nullptr && !state->active_clip.empty())
109 {
110 if (const SkeletonAnimationClipBinding* clip = FindSkeletonAnimationClipBinding(component, state->active_clip))
111 {
112 return clip;
113 }
114 }
115
116 return &component.clips.front();
117}
118
119inline Node& operator<<(Node& node, const SkeletonAnimationClipBinding& clip)
120{
121 node["name"] << clip.name;
122 node["clipAsset"] << clip.clip_asset;
123 return node;
124}
125
126inline const Node& operator>>(const Node& node, SkeletonAnimationClipBinding& clip)
127{
128 if (node.has_property("name"))
129 {
130 node["name"] >> clip.name;
131 }
132 else
133 {
134 clip.name = "Default";
135 }
136 node["clipAsset"] >> clip.clip_asset;
137 return node;
138}
139
140inline Node& operator<<(Node& node, const SkeletonAnimationComponent& component)
141{
142 node["skeletonAsset"] << component.skeleton_asset;
143 node["jointEntities"] << component.joint_entities;
144 node["clips"] << component.clips;
145 return node;
146}
147
148inline const Node& operator>>(const Node& node, SkeletonAnimationComponent& component)
149{
150 node["skeletonAsset"] >> component.skeleton_asset;
151 if (node.has_property("jointEntities"))
152 {
153 node["jointEntities"] >> component.joint_entities;
154 }
155 else
156 {
157 component.joint_entities.clear();
158 }
159 if (node.has_property("clips"))
160 {
161 node["clips"] >> component.clips;
162 }
163 else
164 {
165 component.clips.clear();
166 }
167 NormalizeSkeletonAnimationComponent(component);
168 return node;
169}
170} // namespace pixelbullet
Represents a hierarchical node capable of storing various data types and supporting YAML serializatio...
Definition node.h:49
Definition virtual_path.h:10
Definition animation_state_component.h:10
Definition skeleton_animation_component.h:17
Definition skeleton_animation_component.h:33