#nullable enable using System.Collections.Generic; using Demo2.Domain; using Demo2.ECS; using Unity.Collections; using Unity.Entities; using UnityEngine; namespace Demo2.Runtime { public sealed class Demo2MachineProxyPool : MonoBehaviour { [SerializeField] private Sprite[] machineSprites = new Sprite[8]; private readonly Dictionary _active = new(); private readonly Stack _pool = new(); private readonly HashSet _seen = new(); private readonly List _stale = new(); public void SetSprites(Sprite[] sprites) => machineSprites = sprites; public void Refresh(Demo2EcsWorld? world) { if (world == null) { ReleaseAll(); return; } var manager = world.EntityManager; var query = manager.CreateEntityQuery(typeof(Demo2StableId), typeof(Demo2GridPosition), typeof(Demo2MachineState)); using var entities = query.ToEntityArray(Allocator.Temp); using var ids = query.ToComponentDataArray(Allocator.Temp); using var positions = query.ToComponentDataArray(Allocator.Temp); _seen.Clear(); for (var i = 0; i < entities.Length; i++) { var id = ids[i].Value; _seen.Add(id); if (!_active.TryGetValue(id, out var renderer)) { renderer = Acquire(); _active[id] = renderer; } var machine = manager.GetComponentData(entities[i]); renderer.name = $"MachineProxy_{id}_{machine.Kind}"; renderer.transform.position = new Vector3(positions[i].X + 0.5f, Demo2Protocol.GridHeight - positions[i].Y - 0.5f, 0); renderer.transform.rotation = Quaternion.Euler(0, 0, -90f * machine.Rotation); renderer.transform.localScale = Vector3.one * 0.92f; renderer.sprite = SpriteFor(machine.Kind); renderer.color = machine.Faults > 0 ? new Color(1f, 0.52f, 0.42f) : Color.white; } _stale.Clear(); foreach (var pair in _active) if (!_seen.Contains(pair.Key)) _stale.Add(pair.Key); foreach (var id in _stale) { Release(_active[id]); _active.Remove(id); } } private SpriteRenderer Acquire() { if (_pool.Count > 0) { var reused = _pool.Pop(); reused.gameObject.SetActive(true); return reused; } var go = new GameObject("MachineProxy"); go.transform.SetParent(transform, false); var renderer = go.AddComponent(); renderer.sortingOrder = 5; return renderer; } private void Release(SpriteRenderer renderer) { renderer.gameObject.SetActive(false); _pool.Push(renderer); } private void ReleaseAll() { foreach (var renderer in _active.Values) Release(renderer); _active.Clear(); } private Sprite? SpriteFor(Demo2MachineKind kind) { var index = kind == Demo2MachineKind.NightShiftSmelter ? (int)Demo2MachineKind.Smelter : (int)kind; return index >= 0 && index < machineSprites.Length ? machineSprites[index] : null; } } }