wowlib 0.0.0
Read & write World of Warcraft client files — a C++26 core
Loading...
Searching...
No Matches
sequence.hpp
Go to the documentation of this file.
1#pragma once
2
8
9#include <cstdint>
10#include <utility>
11
12#include <welder/vocabulary.hpp>
13
14#include <wowlib/core/lang.hpp>
19
25 struct [[
26 =welder::weld,
27 =welder::weld_as("M2Sequence"),
29 =welder::doc(R"(
30 One animation sequence entry. Abstract over the client version; construct a concrete
31 version with M2Sequence.ForVersion / for_version.)")
33 // The concretes default operator== — the base must be comparable too.
34 bool operator==(const M2SequenceBase&) const = default;
35 };
37 enum class [[
38 =welder::weld,
39 =welder::flags,
40 =welder::doc("M2Sequence flags — the 0x20/0x40/0x130 combination decides "
41 "where the sequence's track data lives (.m2 vs .anim file).")
42 ]] SequenceFlags : std::uint32_t {
43 SetsRuntimeBlend [[=welder::doc("Sets 0x80 when loaded (M2Init).")]] = 0x1,
44 TiltIn [[=welder::doc("Model tilts over X/Y by the end of the animation.")]] = 0x2,
45 TiltOut [[=welder::doc("Model starts tilted and returns upright.")]] = 0x4,
46 TiltFixed [[=welder::doc("Model stays tilted for the whole animation.")]] = 0x8,
48 welder::doc("Set at runtime for loaded low-priority sequences.")]] = 0x10,
49 DataInM2 [[=welder::doc("Primary bone sequence: track data is in the .m2 "
50 "itself, not an .anim file.")]] = 0x20,
51 Alias [[=welder::doc("The sequence is an alias: follow alias_next until an "
52 "entry without this flag owns the data.")]] = 0x40,
53 Blended [[=welder::doc("Blend (lerp) into/out of this sequence.")]] = 0x80,
54 StoredInModel [[=welder::doc("Sequence stored in the model (0x100).")]] = 0x100,
56 welder::doc("blend_time is the in/out pair, not one u32.")]] = 0x200,
57 Legion0x800 [[=welder::doc("Seen in Legion 24500 models.")]] = 0x800
58 };
59
64 constexpr bool sequenceDataExternal(std::uint32_t flags) {
65 return (flags & 0x130u) == 0;
66 }
67
68 namespace detail {
69 // The annotated era layouts; instantiate through the canonicalizing
70 // aliases below, never directly.
71 template <ClientVersion V>
72 struct M2Sequence;
73
74 template <ClientVersion V> requires (V < M2PerSequenceTimelines)
75 struct [[
76 =welder::weld,
77 =welder::doc(
78 "An animation sequence, pre-WotLK layout: global start/end timestamps, "
79 "one u32 blend time.")
81 [[=welder::doc("Animation id in AnimationData.dbc.")]]
82 std::uint16_t id = 0;
83 [[=welder::doc("Which variation of the animation this is.")]]
84 std::uint16_t variationIndex = 0;
85 [[=welder::doc("Slice start on the global timeline.")]]
86 std::uint32_t startTimestamp = 0;
87 [[=welder::doc("Slice end on the global timeline.")]]
88 std::uint32_t endTimestamp = 0;
89 [[=welder::doc("Character move speed during the sequence.")]]
90 float movespeed = 0;
91 [[=welder::doc("See SequenceFlags.")]]
93 [[=welder::doc("Playback probability weight (sums to 0x7FFF per id).")]]
94 std::int16_t frequency = 0;
95 [[=welder::doc("Unused alignment padding.")]]
96 std::uint16_t padding = 0;
97 [[=welder::doc("Random repetition bounds; both 0 = no repeat.")]]
99 [[=welder::doc("Transition blend duration, milliseconds.")]]
100 std::uint32_t blendTime = 0;
101 [[=welder::doc("Bounds while the sequence plays.")]]
103 [[=welder::doc("Next variation index, -1 if none.")]]
104 std::int16_t variationNext = -1;
105 [[=welder::doc("Alias target (flags & 0x40 chains).")]]
106 std::uint16_t aliasNext = 0;
107
108 [[=welder::doc("Whether this sequence is an alias (flag 0x40): it owns "
109 "NO track data — resolve it by following alias_next. "
110 "Files still carry stale array records for aliases "
111 "(dead offsets, junk values), so they are never "
112 "chased.")]]
113 constexpr bool isAlias() const {
114 return (std::to_underlying(flags) & 0x40u) != 0;
115 }
116
117 [[=welder::doc("Whether this sequence owns an external .anim file: its "
118 "data is low-priority (0x10/0x20/0x100 all clear) and "
119 "it is no alias.")]]
120 constexpr bool ownsAnimFile() const {
121 return sequenceDataExternal(std::to_underlying(flags)) && !isAlias();
122 }
123
124 bool operator==(const M2Sequence&) const = default;
125 };
126
127 template <ClientVersion V> requires (V >= M2PerSequenceTimelines && V < M2SplitBlendTimes)
128 struct [[
129 =welder::weld,
130 =welder::doc(
131 "An animation sequence, WotLK through MoP layout: an own duration, one "
132 "u32 blend time.")
134 [[=welder::doc("Animation id in AnimationData.dbc.")]]
135 std::uint16_t id = 0;
136 [[=welder::doc("Which variation of the animation this is.")]]
137 std::uint16_t variationIndex = 0;
138 [[=welder::doc("Sequence length, milliseconds.")]]
139 std::uint32_t duration = 0;
140 [[=welder::doc("Character move speed during the sequence.")]]
141 float movespeed = 0;
142 [[=welder::doc("See SequenceFlags.")]]
144 [[=welder::doc("Playback probability weight (sums to 0x7FFF per id).")]]
145 std::int16_t frequency = 0;
146 [[=welder::doc("Unused alignment padding.")]]
147 std::uint16_t padding = 0;
148 [[=welder::doc("Random repetition bounds; both 0 = no repeat.")]]
149 M2Range replay{};
150 [[=welder::doc("Transition blend duration, milliseconds.")]]
151 std::uint32_t blendTime = 0;
152 [[=welder::doc("Bounds while the sequence plays.")]]
153 M2Bounds bounds{};
154 [[=welder::doc("Next variation index, -1 if none.")]]
155 std::int16_t variationNext = -1;
156 [[=welder::doc("Alias target (flags & 0x40 chains).")]]
157 std::uint16_t aliasNext = 0;
158
159 [[=welder::doc("Whether this sequence is an alias (flag 0x40): it owns "
160 "NO track data — resolve it by following alias_next. "
161 "Files still carry stale array records for aliases "
162 "(dead offsets, junk values), so they are never "
163 "chased.")]]
164 constexpr bool isAlias() const {
165 return (std::to_underlying(flags) & 0x40u) != 0;
167
168 [[=welder::doc("Whether this sequence owns an external .anim file: its "
169 "data is low-priority (0x10/0x20/0x100 all clear) and "
170 "it is no alias.")]]
171 constexpr bool ownsAnimFile() const {
172 return sequenceDataExternal(std::to_underlying(flags)) && !isAlias();
173 }
174
175 bool operator==(const M2Sequence&) const = default;
176 };
178 template <ClientVersion V> requires (V >= M2SplitBlendTimes)
179 struct [[
180 =welder::weld,
181 =welder::doc(
182 "An animation sequence, WoD+ layout: an own duration, split "
183 "blend-in/out times.")
185 [[=welder::doc("Animation id in AnimationData.dbc.")]]
186 std::uint16_t id = 0;
187 [[=welder::doc("Which variation of the animation this is.")]]
188 std::uint16_t variationIndex = 0;
189 [[=welder::doc("Sequence length, milliseconds.")]]
190 std::uint32_t duration = 0;
191 [[=welder::doc("Character move speed during the sequence.")]]
192 float movespeed = 0;
193 [[=welder::doc("See SequenceFlags.")]]
195 [[=welder::doc("Playback probability weight (sums to 0x7FFF per id).")]]
196 std::int16_t frequency = 0;
197 [[=welder::doc("Unused alignment padding.")]]
198 std::uint16_t padding = 0;
199 [[=welder::doc("Random repetition bounds; both 0 = no repeat.")]]
200 M2Range replay{};
201 [[=welder::doc("Blend-in duration, milliseconds.")]]
202 std::uint16_t blendTimeIn = 0;
203 [[=welder::doc("Blend-out duration, milliseconds.")]]
204 std::uint16_t blendTimeOut = 0;
205 [[=welder::doc("Bounds while the sequence plays.")]]
206 M2Bounds bounds{};
207 [[=welder::doc("Next variation index, -1 if none.")]]
208 std::int16_t variationNext = -1;
209 [[=welder::doc("Alias target (flags & 0x40 chains).")]]
210 std::uint16_t aliasNext = 0;
211
212 [[=welder::doc("Whether this sequence is an alias (flag 0x40): it owns "
213 "NO track data — resolve it by following alias_next. "
214 "Files still carry stale array records for aliases "
215 "(dead offsets, junk values), so they are never "
216 "chased.")]]
217 constexpr bool isAlias() const {
218 return (std::to_underlying(flags) & 0x40u) != 0;
219 }
220
221 [[=welder::doc("Whether this sequence owns an external .anim file: its "
222 "data is low-priority (0x10/0x20/0x100 all clear) and "
223 "it is no alias.")]]
224 constexpr bool ownsAnimFile() const {
225 return sequenceDataExternal(std::to_underlying(flags)) && !isAlias();
226 }
227
228 bool operator==(const M2Sequence&) const = default;
229 };
230 }
231
236 template <ClientVersion V>
237 using M2Sequence = detail::M2Sequence<canonicalVersion(V, M2SequencePivots, M2Versions)>;
238
239 struct [[
240 =welder::weld,
241 =welder::doc("A pre-WotLK playable-animation fallback: the substitute "
242 "animation id plus how to play it (0 normal, 1 backwards, "
243 "2 frame-by-frame, 3 freeze).")
244 ]] M2SequenceFallback {
245 [[=welder::doc("Substitute animation id in AnimationData.dbc.")]]
246 std::int16_t fallbackAnimationId = 0;
247 [[=welder::doc("Playback mode: 0 normal, 1 backwards, 2 frame-by-frame, "
248 "3 freeze.")]]
249 std::int16_t flags = 0;
250
251 bool operator==(const M2SequenceFallback&) const = default;
252 };
253
254 static_assert(sizeof(M2Sequence<versions::Vanilla>) == 68);
255 static_assert(sizeof(M2Sequence<versions::Wotlk>) == 64);
256 static_assert(sizeof(M2Sequence<versions::Wod>) == 64);
257 static_assert(sizeof(M2SequenceFallback) == 4);
258}
Client version identity, the flavor axis that separates a client's CONTENT version from the engine ge...
Flag-testing convenience for the binary formats' bit-mask enums.
Binding-language identities welder's core does not name.
#define WOWLIB_CS_FAMILY_SURFACE
The C# rod's family-surface opt-in, spellable in every build.
Definition lang.hpp:44
The M2 version vocabulary: the layout pivots record/entity partial specializations key on,...
M2 body record structs (sequences, bones, tracks, textures, cameras, emitters) and their flag enums.
Definition bone.hpp:17
detail::M2Sequence< canonicalVersion(V, M2SequencePivots, M2Versions)> M2Sequence
An animation sequence — the canonicalizing face of detail::M2Sequence: every client version maps to i...
Definition sequence.hpp:195
constexpr bool sequenceDataExternal(std::uint32_t flags)
Whether a WotLK+ sequence keeps its track data in an external .anim file — the client loads one iff n...
Definition sequence.hpp:52
SequenceFlags
M2Sequence flags — the 0x20/0x40/0x130 combination decides where the sequence's track data lives (....
Definition sequence.hpp:34
@ StoredInModel
Sequence stored in the model (0x100).
Definition sequence.hpp:43
@ Blended
Blend (lerp) into/out of this sequence.
Definition sequence.hpp:42
@ SplitBlendTimes
blend_time is the in/out pair, not one u32.
Definition sequence.hpp:44
@ Legion0x800
Seen in Legion 24500 models.
Definition sequence.hpp:45
@ TiltIn
Model tilts over X/Y by the end of the animation.
Definition sequence.hpp:36
@ DataInM2
Primary bone sequence: track data is in the .m2 itself, not an .anim file.
Definition sequence.hpp:40
@ TiltFixed
Model stays tilted for the whole animation.
Definition sequence.hpp:38
@ TiltOut
Model starts tilted and returns upright.
Definition sequence.hpp:37
@ LoadedLowPriority
Set at runtime for loaded low-priority sequences.
Definition sequence.hpp:39
@ Alias
The sequence is an alias: follow alias_next until an entry without this flag owns the data.
Definition sequence.hpp:41
@ SetsRuntimeBlend
Sets 0x80 when loaded (M2Init).
Definition sequence.hpp:35
constexpr ClientVersion M2SplitBlendTimes
WoD (6.0.1): M2Sequence's u32 blendTime splits into the blendTimeIn/blendTimeOut pair.
constexpr std::array M2SequencePivots
M2Sequence: timestamps→duration at WotLK, blend-time split at WoD.
constexpr ClientVersion M2PerSequenceTimelines
WotLK (v264): every M2Track nests one timestamp/value array per sequence (the vanilla single timeline...
constexpr std::array M2Versions
The versions M2 is instantiated (and welded) for: every targeted last-minor-of-major release,...
constexpr ClientVersion canonicalVersion(ClientVersion v, std::span< const ClientVersion > pivots, std::span< const ClientVersion > grid)
The canonical version v collapses to: the FIRST grid version in v's range.
A bounding volume: axis-aligned extent plus sphere radius.
Definition track.hpp:73
An inclusive u32 range: pre-WotLK track interpolation ranges, sequence replay bounds.
Definition track.hpp:60
The version-agnostic base of every M2Sequence<V> (welded as "M2Sequence").
Definition sequence.hpp:28
bool operator==(const M2SequenceBase &) const =default
A pre-WotLK playable-animation fallback: the substitute animation id plus how to play it (0 normal,...
Definition sequence.hpp:198
std::int16_t flags
Playback mode: 0 normal, 1 backwards, 2 frame-by-frame, 3 freeze.
Definition sequence.hpp:202
std::int16_t fallbackAnimationId
Substitute animation id in AnimationData.dbc.
Definition sequence.hpp:200
bool operator==(const M2SequenceFallback &) const =default
constexpr bool ownsAnimFile() const
Whether this sequence owns an external .anim file: its data is low-priority (0x10/0x20/0x100 all clea...
Definition sequence.hpp:98
M2Range replay
Random repetition bounds; both 0 = no repeat.
Definition sequence.hpp:82
std::uint16_t aliasNext
Alias target (flags & 0x40 chains).
Definition sequence.hpp:90
std::uint16_t variationIndex
Which variation of the animation this is.
Definition sequence.hpp:68
std::uint16_t blendTimeOut
Blend-out duration, milliseconds.
Definition sequence.hpp:168
std::uint32_t endTimestamp
Slice end on the global timeline.
Definition sequence.hpp:72
std::uint32_t duration
Sequence length, milliseconds.
Definition sequence.hpp:113
std::int16_t frequency
Playback probability weight (sums to 0x7FFF per id).
Definition sequence.hpp:78
constexpr bool isAlias() const
Whether this sequence is an alias (flag 0x40): it owns NO track data — resolve it by following alias_...
Definition sequence.hpp:93
std::uint32_t blendTime
Transition blend duration, milliseconds.
Definition sequence.hpp:84
M2Bounds bounds
Bounds while the sequence plays.
Definition sequence.hpp:86
std::uint16_t blendTimeIn
Blend-in duration, milliseconds.
Definition sequence.hpp:166
std::uint32_t startTimestamp
Slice start on the global timeline.
Definition sequence.hpp:70
std::uint16_t padding
Unused alignment padding.
Definition sequence.hpp:80
std::uint16_t id
Animation id in AnimationData.dbc.
Definition sequence.hpp:66
std::int16_t variationNext
Next variation index, -1 if none.
Definition sequence.hpp:88
bool operator==(const M2Sequence &) const =default
float movespeed
Character move speed during the sequence.
Definition sequence.hpp:74
The M2 animation vocabulary (namespace wowlib::formats::m2::root::record): the small fixed-size primi...