using System.Collections.Generic;
using AcDream.Core.Physics;
namespace AcDream.App.Rendering.Wb;
///
/// Per-entity render state for animated entities (characters, creatures,
/// equipped items). Holds AC-specific per-instance customizations the WB
/// atlas cache doesn't carry: AnimPartChange override map +
/// HiddenParts bitmask. Also holds a reference to acdream's existing
/// — Phase N.4 explicitly does not touch
/// the sequencer; we just route through it at draw time.
///
///
/// Lifecycle: created by EntitySpawnAdapter.OnCreate (Task 17) when
/// a server CreateObject is processed; destroyed by
/// EntitySpawnAdapter.OnRemove on RemoveObject. The mesh
/// data backing each part is cached in WB's ObjectMeshManager;
/// per-instance customizations don't go through the atlas — they overlay
/// at draw time.
///
///
public sealed class AnimatedEntityState
{
private readonly Dictionary _partGfxObjOverrides = new();
private ulong _hiddenMask = 0;
/// Reference to acdream's existing animation sequencer.
/// Phase N.4 doesn't touch the sequencer; the draw dispatcher consumes
/// per-part transforms it produces per frame.
public AnimationSequencer Sequencer { get; }
public AnimatedEntityState(AnimationSequencer sequencer)
{
System.ArgumentNullException.ThrowIfNull(sequencer);
Sequencer = sequencer;
}
/// Set the HiddenParts bitmask for this entity. Bit
/// i set hides part i at draw time.
public void HideParts(ulong hiddenMask) => _hiddenMask = hiddenMask;
/// True if part partIdx should be skipped at draw
/// time. Returns false for part indices outside [0, 63].
public bool IsPartHidden(int partIdx)
{
if (partIdx < 0 || partIdx >= 64) return false;
return (_hiddenMask & (1ul << partIdx)) != 0;
}
/// Override the GfxObj id for a Setup part. Used for
/// AnimPartChange — e.g. wielding a weapon swaps the hand-part's
/// GfxObj.
public void SetPartOverride(int partIdx, ulong gfxObjId)
=> _partGfxObjOverrides[partIdx] = gfxObjId;
/// Look up the GfxObj override for a part. Returns false if
/// no override is set (caller should fall back to Setup default).
public bool TryGetPartOverride(int partIdx, out ulong gfxObjId)
=> _partGfxObjOverrides.TryGetValue(partIdx, out gfxObjId);
/// Resolve the GfxObj id for :
/// override if set, else . Used by the
/// draw dispatcher to pick the right cached mesh data per part.
public ulong ResolvePartGfxObj(int partIdx, ulong setupDefault)
=> TryGetPartOverride(partIdx, out var ov) ? ov : setupDefault;
}