Per-entity render state for the per-instance rendering tier (server-spawned characters / creatures / equipped items). Holds: - partGfxObjOverrides: Dictionary<int, ulong> — AnimPartChange swaps (e.g. wielding a weapon replaces a hand-part's GfxObj). - hiddenMask: ulong — HiddenParts bitmask. Bit i set hides part i. - AnimationSequencer reference — N.4 doesn't touch the sequencer; this just exposes it for the draw dispatcher. Public API: HideParts / IsPartHidden / SetPartOverride / TryGetPartOverride / ResolvePartGfxObj. Bounds-checked (partIdx < 0 or >= 64 → IsPartHidden returns false). Twelve tests covering the type, the AnimPartChange resolution helper, and the HiddenParts bitmask edge cases (theories for 0b0/0b1/MSB/all-ones, plus negative-index + out-of-range guards). Consumed by Task 17's EntitySpawnAdapter (creates one per CreateObject) and Task 22's WbDrawDispatcher (reads via per-part draw loop). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
56 lines
1.6 KiB
C#
56 lines
1.6 KiB
C#
using AcDream.App.Rendering.Wb;
|
|
using AcDream.Core.Physics;
|
|
using DatReaderWriter.DBObjs;
|
|
using Xunit;
|
|
|
|
namespace AcDream.Core.Tests.Rendering.Wb;
|
|
|
|
public sealed class HiddenPartsTests
|
|
{
|
|
[Theory]
|
|
[InlineData(0b0000_0000ul, 0, false)]
|
|
[InlineData(0b0000_0001ul, 0, true)]
|
|
[InlineData(0b1000_0000ul, 7, true)]
|
|
[InlineData(0b1000_0000ul, 6, false)]
|
|
[InlineData(0xFFFF_FFFF_FFFF_FFFFul, 63, true)]
|
|
public void IsPartHidden_RespectsBitmaskBit(ulong mask, int partIdx, bool expected)
|
|
{
|
|
var state = MakeState();
|
|
state.HideParts(mask);
|
|
Assert.Equal(expected, state.IsPartHidden(partIdx));
|
|
}
|
|
|
|
[Fact]
|
|
public void IsPartHidden_NegativeIdx_ReturnsFalse()
|
|
{
|
|
var state = MakeState();
|
|
state.HideParts(0xFFFF_FFFF_FFFF_FFFFul);
|
|
Assert.False(state.IsPartHidden(-1));
|
|
}
|
|
|
|
[Fact]
|
|
public void IsPartHidden_PartIdxOver64_ReturnsFalse()
|
|
{
|
|
var state = MakeState();
|
|
state.HideParts(0xFFFF_FFFF_FFFF_FFFFul);
|
|
Assert.False(state.IsPartHidden(64));
|
|
}
|
|
|
|
[Fact]
|
|
public void HideParts_DefaultsToNoneHidden()
|
|
{
|
|
var state = MakeState();
|
|
for (int i = 0; i < 64; i++)
|
|
Assert.False(state.IsPartHidden(i));
|
|
}
|
|
|
|
private static AnimatedEntityState MakeState() => new(MakeSequencer());
|
|
|
|
private static AnimationSequencer MakeSequencer()
|
|
=> new AnimationSequencer(new Setup(), new MotionTable(), new NullAnimationLoader());
|
|
|
|
private sealed class NullAnimationLoader : IAnimationLoader
|
|
{
|
|
public Animation? LoadAnimation(uint id) => null;
|
|
}
|
|
}
|