Repository navigation
C#: M2 record family bases — collection counts read through the common base - #6
Merged
Merged
Conversation
… M2Root User report: reading root.Sequences.Count through the common base needed a six-arm per-era switch — the M2 record families were the ONE group still welding standalone (the old BASED distinction), so their collection members never hoisted onto M2Root. Structural fix, riding welder-csharp 3cdf95b (pin bumped): - ~24 version-agnostic bases: M2SequenceBase / M2CompBoneBase / M2CameraBase / M2ParticleBase / M2RibbonBase / the material and scene records / both skin records / M2EventTrackBase (the versioned detail::M2TrackBase event family — mind the pre-existing name), plus template M2TrackFamilyBase<T> for the nine M2Track value families (alias-welded in gen_m2 via M2Track*Fam aliases in m2_ranges.hpp). All carry weld_as(family name) + the family-surface macro, and every base defaults operator== — the concretes' defaulted equality requires comparable bases (first build failure). - All 24 joined the facade BASED set: ForVersion works on every record family, and the standalone factory partials became real base partials. - The multi-level family surface then hoists M2Root.Sequences / Bones / ParticleEmitters / Attachments / ... as FamilyVector<RecordBase> — the user's switch collapses to root.Sequences.Count on the base, with era-checked element access riding along. Same for M2SkinProfile.Sections and every other record collection. Upstream fixes this shape forced (welder-csharp PR#6): base upcast thunks now survive alias-welded SPECIALIZATION bases (cpp_name/upath collapse to the namespace for a specialization — deferred anchor + symtok instead), and the AsSpan diagnostics name the right call per element kind (the "specific ADT" report was Vector<SMLayer>/Vector<Vector<byte>> misuse of the scalar AsSpan, unconditional but caught per tile). FamilySurfaceTests locks the reported scenario: counts through the base, population through the concrete observed via the base view, and M2Sequence.ForVersion. Full native rebuild; dotnet test 36/36. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… main Tree byte-identical to the 3cdf95b branch head this previously pinned. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n track-base welds Three pieces riding the record-bases branch: 1. THE CANONICAL TIMELINE SURFACE (C++, welded -> all three languages): timeline_count / key_count / timeline_timestamps / timeline_values on both M2Track layouts, and the values-less trio on both event-track layouts. Pre-WotLK slices the shared global timeline by the inclusive interpolation ranges (clamped; a global-sequence-driven or rangeless track exposes the whole array as timeline 0); WotLK+ indexes the per-sequence arrays (an external sequence's timeline is empty until its .anim loads); out-of-range timelines error (InvalidEntityState). Identical signatures per family -> the family surface hoists them onto M2TrackC3Vector etc., so the TBC->WotLK track redesign no longer forces a branch: C# reads through the base, typed Python writes one Protocol[V] the stubs satisfy structurally. Accessors COPY (correctness first); hot loops keep the two-arm concrete/span path. A native semantics test covers slicing, clamping and errors on both layouts; guide/m2.md walks the same loop trilingually. 2. IAnimTimeline (facade-declared, user-requested): the timing trio is signature-identical across every track family and the event tracks, so the facade partials declare ONE interface the synthesized dispatchers implement implicitly - timing-driven systems hold IAnimTimeline over all ten families, era-agnostic. Value access stays per-family typed. 3. CI FIX: the record-bases commit broke the Python module - the module walk registers the fifteen PLAIN record bases, but the nine M2TrackFamilyBase<T> INSTANTIATIONS are invisible to a walk, so the track concretes bound an unregistered base and nanobind aborted at import (the macOS bindings job's stubgen crash). welds_m2.cpp now welds the nine Fam aliases before the concretes; wowlib_py + wowlib_pyi build clean locally and the stubs carry the bases + timeline defs. dotnet test: 37/37 (timeline dispatch through the base across both eras, the IAnimTimeline loop over track+event families, out-of-range errors). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…-Werror=sign-conversion The timeline copy accessors added begin() + size_t (operator+ takes the SIGNED difference_type); local builds carry no warning flags, so it only surfaced in the CI bindings jobs. std::span::subspan takes size_t natively - same windows, no arithmetic on iterators. All four track layouts instantiate clean under -Werror=sign-conversion locally; the semantic test still passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ord-bases # Conflicts: # cmake/Dependencies.cmake
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two user reports, one PR. Rides skarndev/welder-csharp#6 (pinned at
3cdf95b) — merge that first.Report 2 (the big one):
root.Sequences.Countneeded a six-arm era switchThe M2 record families were the one group still welding standalone, so their collection members never hoisted onto
M2Root. They now have version-agnostic welded bases — the same architecture every other family already had:M2SequenceBase,M2CompBoneBase,M2CameraBase,M2ParticleBase, the material/scene/effects records, both skin records,M2EventTrackBase, plus a templateM2TrackFamilyBase<T>alias-welded per value type for the nineM2Trackfamilies. All marked for the family surface; all joined the facadeBASEDset (ForVersionnow works on every record family).M2Root.Sequences/Bones/ParticleEmitters/Attachments/… asFamilyVector<RecordBase>— the user's switch collapses to:directly on the base-typed
M2Root, with era-checked element access riding along.Two upstream rod bugs this shape exposed, fixed in welder-csharp#6: base upcast thunks collapsed alias-welded specialization bases to their namespace (
cpp_name/upathcollect no identifiers from a specialization → invalid^^nssplice + colliding symbols; now the deferred anchor +symtok), and C++-side, defaultedoperator==on the records requires comparable bases (every new base defaults its own).Report 1: "AsSpan() requires a scalar or enum element type" on a specific ADT
Not data-dependent: the consumer called scalar
AsSpan()onchunk.Layers(Vector<SMLayer>— records, the right call isAsDataSpan()) andchunk.AlphaMaps(Vector<Vector<byte>>— nested, iterate). Their per-tile catch made the first tile reaching the layered path look special. welder-csharp#6 makes all three failure messages name the element type and the correct call.Verified
FamilySurfaceTestslocks the reported scenario (counts via the base, population via the concrete observed through the base view,M2Sequence.ForVersion). Full native rebuild (new upcast thunks);dotnet test: 36/36.🤖 Generated with Claude Code