using System.Collections.Generic; using GameFramework.ObjectPool; using GeometryTD.CustomEvent; using GeometryTD.Definition; using GeometryTD.PoolObjectBase; using UnityEngine; using UnityEngine.EventSystems; using UnityGameFramework.Runtime; namespace GeometryTD.UI { public class ParticipantArea : MonoBehaviour, IDropHandler { [SerializeField] private Transform _content; [SerializeField] private RepoItem _itemTemplate; [SerializeField] private int _instancePoolCapacity = 8; private readonly List _activeItems = new List(); private readonly HashSet _boundItemIds = new HashSet(); private IObjectPool _itemPool; private string _poolName; private int _maxCount = 4; public void OnInit(ParticipantAreaContext context) { OnReset(); EnsurePool(); _maxCount = Mathf.Max(1, context != null ? context.MaxCount : 4); if (context?.Items == null || context.Items.Length <= 0) { return; } for (int i = 0; i < context.Items.Length; i++) { RepoItemContext itemContext = context.Items[i]; if (itemContext == null || itemContext.InstanceId <= 0) { continue; } RepoItem item = CreateOrSpawnItem(); if (item == null) { continue; } item.gameObject.SetActive(true); item.OnInit(itemContext); _activeItems.Add(item); _boundItemIds.Add(itemContext.InstanceId); } } public void OnReset() { for (int i = _activeItems.Count - 1; i >= 0; i--) { RepoItem item = _activeItems[i]; if (item == null) { continue; } item.OnReset(); item.gameObject.SetActive(false); _itemPool?.Unspawn(item); } _activeItems.Clear(); _boundItemIds.Clear(); _maxCount = 4; } private void OnDestroy() { OnReset(); _itemPool?.ReleaseAllUnused(); } public bool CanAssign(RepoItemContext itemContext) { if (itemContext == null || itemContext.InstanceId <= 0) { return false; } if (itemContext.ComponentSlotType != TowerCompSlotType.None) { return false; } if (_boundItemIds.Contains(itemContext.InstanceId)) { return false; } if (_boundItemIds.Count >= _maxCount) { return false; } return true; } public void OnDrop(PointerEventData eventData) { if (eventData == null) { return; } GameObject pointerDrag = eventData.pointerDrag; if (pointerDrag == null) { return; } RepoItem repoItem = pointerDrag.GetComponent() ?? pointerDrag.GetComponentInParent(); if (repoItem == null) { return; } RepoItemContext itemContext = repoItem.Context; bool assigned = CanAssign(itemContext); repoItem.SetDropResult(assigned); if (!assigned) { return; } GameEntry.Event.Fire(this, RepoParticipantAssignRequestedEventArgs.Create(itemContext.InstanceId)); } private void EnsurePool() { if (_itemPool != null) { return; } _poolName = $"ParticipantRepoItemPool_{GetInstanceID()}"; _itemPool = GameEntry.ObjectPool.CreateSingleSpawnObjectPool(_poolName, _instancePoolCapacity); } private RepoItem CreateOrSpawnItem() { if (_itemPool == null) { return null; } RepoItemObject itemObject = _itemPool.Spawn(); RepoItem item = itemObject != null ? (RepoItem)itemObject.Target : null; if (item == null) { if (_itemTemplate == null) { Log.Warning("ParticipantArea requires an item template."); return null; } item = Instantiate(_itemTemplate); _itemPool.Register(RepoItemObject.Create(item), true); } if (_content != null) { item.transform.SetParent(_content, false); } return item; } } }