From ef787624fe7112521c078f49c877e01d5a0858ee Mon Sep 17 00:00:00 2001 From: Kelsi Date: Mon, 30 Mar 2026 14:59:03 -0700 Subject: [PATCH] refactor: name M2 sequence flag, replace empty loop with std::advance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - m2_loader: define kM2SeqFlagEmbeddedData (0x20) with why-comment — when clear, keyframe data lives in external .anim files and M2 offsets are file-relative (reading them from M2 produces garbage). Replaces 3 bare hex literals across parseAnimTrack and ribbon emitter parsing - audio_engine: replace empty for-loop iterator advance with std::advance() for clarity --- src/audio/audio_engine.cpp | 3 ++- src/pipeline/m2_loader.cpp | 14 +++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/audio/audio_engine.cpp b/src/audio/audio_engine.cpp index 1b4d5aa3..c6b060e8 100644 --- a/src/audio/audio_engine.cpp +++ b/src/audio/audio_engine.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -104,7 +105,7 @@ static bool decodeWavCached(const std::vector& wavData, DecodedWavCache constexpr size_t kMaxCachedSounds = 256; if (gDecodedWavCache.size() >= kMaxCachedSounds) { auto it = gDecodedWavCache.begin(); - for (size_t n = gDecodedWavCache.size() / 2; n > 0; --n, ++it) {} + std::advance(it, gDecodedWavCache.size() / 2); gDecodedWavCache.erase(gDecodedWavCache.begin(), it); } gDecodedWavCache.emplace(key, entry); diff --git a/src/pipeline/m2_loader.cpp b/src/pipeline/m2_loader.cpp index 1b518d37..08014f75 100644 --- a/src/pipeline/m2_loader.cpp +++ b/src/pipeline/m2_loader.cpp @@ -384,11 +384,15 @@ std::string readString(const std::vector& data, uint32_t offset, uint32 enum class TrackType { VEC3, QUAT_COMPRESSED, FLOAT }; +// M2 sequence flag: when set, keyframe data is embedded in the M2 file. +// When clear, data lives in an external .anim file and the M2 offsets are +// .anim-relative — reading them from the M2 produces garbage. +constexpr uint32_t kM2SeqFlagEmbeddedData = 0x20; + // Parse an M2 animation track from the binary data. // The track uses an "array of arrays" layout: nTimestamps pairs of {count, offset}. -// sequenceFlags: per-sequence flags; sequences WITHOUT flag 0x20 store their keyframe -// data in external .anim files, so their sub-array offsets are .anim-relative and must -// be skipped when reading from the M2 file. +// sequenceFlags: per-sequence flags; sequences without kM2SeqFlagEmbeddedData store +// their keyframe data in external .anim files, so their sub-array offsets must be skipped. void parseAnimTrack(const std::vector& data, const M2TrackDisk& disk, M2AnimationTrack& track, @@ -408,7 +412,7 @@ void parseAnimTrack(const std::vector& data, // Sequences without flag 0x20 have their animation data in external .anim files. // Their sub-array offsets are .anim-file-relative, not M2-relative, so reading // from the M2 file would produce garbage data. - if (i < sequenceFlags.size() && !(sequenceFlags[i] & 0x20)) continue; + if (i < sequenceFlags.size() && !(sequenceFlags[i] & kM2SeqFlagEmbeddedData)) continue; // Each sub-array header is {uint32_t count, uint32_t offset} = 8 bytes uint32_t tsHeaderOfs = disk.ofsTimestamps + i * 8; uint32_t keyHeaderOfs = disk.ofsKeys + i * 8; @@ -1328,7 +1332,7 @@ M2Model M2Loader::load(const std::vector& m2Data) { if (nSeqs > 0 && nSeqs <= 4096) { track.sequences.resize(nSeqs); for (uint32_t s = 0; s < nSeqs; s++) { - if (s < ribSeqFlags.size() && !(ribSeqFlags[s] & 0x20)) continue; + if (s < ribSeqFlags.size() && !(ribSeqFlags[s] & kM2SeqFlagEmbeddedData)) continue; uint32_t tsHdr = disk.ofsTimestamps + s * 8; uint32_t keyHdr = disk.ofsKeys + s * 8; if (tsHdr + 8 > m2Data.size() || keyHdr + 8 > m2Data.size()) continue;