23#include <initializer_list>
58 for (std::string_view ext : {
".m2",
".M2",
".mdx",
".MDX",
".mdl",
".MDL",
".skel",
".SKEL"})
59 if (modelPath.ends_with(ext)) {
60 _stem = std::string{modelPath.substr(0, modelPath.size() - ext.size())};
66 const std::string&
stem()
const {
return _stem; }
69 std::string
skin(std::uint32_t index)
const {
70 return std::format(
"{}{:02}.skin", _stem, index);
74 std::string
lodSkin(std::uint32_t band)
const {
75 return std::format(
"{}_lod{:02}.skin", _stem, band);
80 return std::format(
"{}{:04}-{:02}.anim", _stem, key.
id, key.
variation);
84 std::string
bone(std::uint32_t variant)
const {
85 return std::format(
"{}_{:02}.bone", _stem, variant);
89 std::string
skel()
const {
return _stem +
".skel"; }
92 std::string
phys()
const {
return _stem +
".phys"; }
113 if (e.animId == key.
id && e.subAnimId == key.
variation)
return e.fileId;
119 : _loader{std::move(loader)} {}
124 auto [it, inserted] = _files.try_emplace(key);
126 if (
auto file = _loader(key)) it->second = std::move(*file);
127 if (!it->second)
return {};
129 std::uint32_t lead = 0;
130 if (buf.size() >= 8) std::memcpy(&lead, buf.data(), 4);
133 return target ==
Afm2Magic ? std::span<const std::byte>{buf} : std::span<const std::byte>{};
134 for (std::size_t pos = 0; pos + 8 <= buf.size();) {
136 std::uint32_t size = 0;
137 std::memcpy(&
fourcc, buf.data() + pos, 4);
138 std::memcpy(&size, buf.data() + pos + 4, 4);
139 if (size > buf.size() - pos - 8)
break;
140 if (
fourcc == target)
return std::span<const std::byte>{buf}.subspan(pos + 8, size);
158 template <
typename Sequence>
160 std::span<const std::byte> inlineBase,
161 std::uint32_t target) {
162 return [
this, &sequences, inlineBase, target](std::size_t i) -> std::span<const std::byte> {
163 if (i >= sequences.size())
return inlineBase;
164 const Sequence& s = sequences[i];
165 if (s.isAlias())
return {};
166 if (!s.ownsAnimFile())
return inlineBase;
172 std::function<Result<FileBuffer>(
SequenceKey)> _loader;
173 std::map<SequenceKey, std::optional<FileBuffer>> _files;
187 template <
typename Sequence>
191 if (i >= sequences.size())
return nullptr;
192 const Sequence& s = sequences[i];
193 if (!s.ownsAnimFile())
return nullptr;
194 return &_bufs[
SequenceKey{s.id, s.variationIndex}];
200 const std::map<SequenceKey, FileBuffer>&
entries()
const {
return _bufs; }
207 const auto it = _bufs.find(key);
209 it == _bufs.end() ? std::span<const std::byte>{} : std::span<const std::byte>{it->second});
214 static std::set<SequenceKey>
mergedKeys(std::initializer_list<const AnimBuffers*> sets) {
215 std::set<SequenceKey> keys;
217 for (
const auto& [key, buf] : set->_bufs) keys.insert(key);
222 static void _appendChunk(
FileBuffer& out, std::uint32_t
fourcc, std::span<const std::byte> payload) {
223 const auto size =
static_cast<std::uint32_t
>(payload.size());
224 const std::size_t at = out.size();
226 std::memcpy(out.data() + at, &
fourcc, 4);
227 std::memcpy(out.data() + at + 4, &size, 4);
228 out.insert(out.end(), payload.begin(), payload.end());
231 std::map<SequenceKey, FileBuffer> _bufs;
The owning byte buffer file contents are read into.
The error-handling vocabulary: ErrorCode, Error and the Result<T> alias every fallible wowlib operati...
FourCC chunk identifiers: compile-time conversion of the four-letter codes to the host integers chunk...
Legion+ companion-chunk records (namespace wowlib::formats::m2::chunked::record): the payload types o...
std::expected< T, Error > Result
Every fallible wowlib operation returns Result<T>; bindings translate the error branch into a target-...
std::vector< std::byte > FileBuffer
Owning byte buffer for file contents read out of a client storage.
The offset-format storage vocabulary and serializer engine for the M2 family, in one header.
Resolution of SequenceData members while writing: which buffer each outer element's nested data block...
std::function< FileBuffer *(std::size_t i) > sequenceSink
The destination buffer for outer element i's nested data — the .anim file buffer being assembled for ...
One AFID entry: which FileDataID serves a sequence's .anim data.