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 TowerRepoItem _towerItemTemplate; [SerializeField] private int _instancePoolCapacity = 8; private bool _isInteractionEnabled = true; 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?.TowerItems == null || context.TowerItems.Length <= 0) { return; } for (int i = 0; i < context.TowerItems.Length; i++) { TowerRepoItemContext itemContext = context.TowerItems[i]; if (itemContext == null || itemContext.InstanceId <= 0) { continue; } TowerRepoItem 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--) { TowerRepoItem 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(IRepoDragItemView dragItem) { if (!_isInteractionEnabled) { return false; } if (dragItem == null || dragItem.InstanceId <= 0) { return false; } if (dragItem.ComponentSlotType != TowerCompSlotType.None) { return false; } if (_boundItemIds.Contains(dragItem.InstanceId)) { return false; } if (_boundItemIds.Count >= _maxCount) { return false; } return true; } public void OnDrop(PointerEventData eventData) { if (!_isInteractionEnabled) { return; } if (eventData == null) { return; } GameObject pointerDrag = eventData.pointerDrag; if (pointerDrag == null) { return; } IRepoDragItemView dragItem = pointerDrag.GetComponent() ?? pointerDrag.GetComponentInParent(); if (dragItem == null) { return; } bool assigned = CanAssign(dragItem); dragItem.SetDropResult(assigned); if (!assigned) { return; } GameEntry.Event.Fire(this, RepoParticipantAssignRequestedEventArgs.Create(dragItem.InstanceId)); } public void SetInteractionEnabled(bool enabled) { _isInteractionEnabled = enabled; } private void EnsurePool() { if (_itemPool != null) { return; } _poolName = $"ParticipantTowerRepoItemPool_{GetInstanceID()}"; _itemPool = GameEntry.ObjectPool.CreateSingleSpawnObjectPool(_poolName, _instancePoolCapacity); } private TowerRepoItem CreateOrSpawnItem() { if (_itemPool == null) { return null; } TowerRepoItemObject itemObject = _itemPool.Spawn(); TowerRepoItem item = itemObject != null ? (TowerRepoItem)itemObject.Target : null; if (item == null) { if (_towerItemTemplate == null) { Log.Warning("ParticipantArea requires a tower item template."); return null; } item = Instantiate(_towerItemTemplate); _itemPool.Register(TowerRepoItemObject.Create(item), true); } if (_content != null) { item.transform.SetParent(_content, false); } return item; } } }