fix #175 (take 2): the cycle lookup used the bare style key — silent no-op
The shipped derivation looked up mt.Cycles[DefaultStyle]; the dat Cycles dictionary is keyed by the COMBINED (style << 16) | substate word (CMotionTable.cs:683), so the lookup always missed and the pose override silently fell back to placement frames — user re-test: "175 is not fixed". The pins covered the override plumbing but not the derivation, the one part with no offline fixture. Extract the derivation to Core as MotionTablePose.DefaultStatePartFrames using the retail SetDefaultState chain (StyleDefaults[DefaultStyle] -> combined-key LookupCycle, same wrap arithmetic as CMotionTable.cs:683) and pin it against the REAL dat (human MT 0x09000001 resolves a 34-part pose — this test fails on the old key math). Short poses now apply PER PART (ShadowShapeBuilder already falls back per index) so a door anim posing only the panels still overrides them while the BSP-less header keeps its placement frame. [shape-pose] diagnostic (ACDREAM_DUMP_MOTION) prints mt id + resolved part0 pose per BSP registration so live launches show the actual outcome. Suites: Core 2540 / App 713 / UI 425 / Net 385 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
355e389d4c
commit
bb18614a89
3 changed files with 117 additions and 17 deletions
|
|
@ -150,6 +150,41 @@ public class Issue175HubDoorPoseInspectionTests
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// #175 derivation conformance — REAL-DAT pin for
|
||||
/// <see cref="AcDream.Core.Physics.Motion.MotionTablePose.DefaultStatePartFrames"/>.
|
||||
/// The first cut of the derivation looked up <c>Cycles[DefaultStyle]</c>
|
||||
/// with the bare style word; the dictionary is keyed by the COMBINED
|
||||
/// <c>(style << 16) | substate</c> word (CMotionTable.cs:683), so it
|
||||
/// always missed and the #175 fix silently no-oped. This pin loads the
|
||||
/// human motion table (0x09000001 — guaranteed present, default state
|
||||
/// NonCombat/Ready) and asserts the derivation actually resolves a pose.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void MotionTablePose_DefaultState_ResolvesOnRealTable()
|
||||
{
|
||||
var datDir = Env.GetEnvironmentVariable("ACDREAM_DAT_DIR")
|
||||
?? Path.Combine(Env.GetFolderPath(Env.SpecialFolder.UserProfile),
|
||||
"Documents", "Asheron's Call");
|
||||
if (!Directory.Exists(datDir))
|
||||
{
|
||||
_out.WriteLine($"SKIP: dat directory not found at {datDir}");
|
||||
return;
|
||||
}
|
||||
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var mt = dats.Get<MotionTable>(0x09000001u);
|
||||
Assert.NotNull(mt);
|
||||
|
||||
var pose = AcDream.Core.Physics.Motion.MotionTablePose.DefaultStatePartFrames(
|
||||
mt!, id => dats.Get<Animation>(id));
|
||||
|
||||
Assert.NotNull(pose);
|
||||
_out.WriteLine($"human MT default pose parts={pose!.Count} " +
|
||||
$"part0=({pose[0].Origin.X:F3},{pose[0].Origin.Y:F3},{pose[0].Origin.Z:F3})");
|
||||
Assert.True(pose.Count >= 1);
|
||||
}
|
||||
|
||||
// ── #175 fix pins: ShadowShapeBuilder partPoseOverride ──────────────
|
||||
|
||||
private static Setup MakeTwoPartSetup()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue