using System.Collections.Generic; using GeometryTD.CustomEvent; using GeometryTD.Definition; using GameFramework.Event; using UnityEngine; using UnityGameFramework.Runtime; namespace GeometryTD.UI { public partial class RepoFormController : UIFormControllerCommonBase { private const int MaxParticipantCount = 4; private RepoFormUseCase _useCase; private readonly Dictionary _itemContextMap = new Dictionary(); private readonly Dictionary _itemDescSeedMap = new Dictionary(); private readonly HashSet _participantTowerIds = new HashSet(); private sealed class ItemDescSeed { public string Title; public string TypeText; public string Description; public TagType[] Tags; } protected override UIFormType UIFormTypeId => UIFormType.RepoForm; protected override void RefreshUI(RepoForm form, RepoFormContext context) { form.RefreshUI(context); ApplyParticipantSelection(); } protected override void SubscribeCustomEvents() { GameEntry.Event.Subscribe(RepoItemClickedEventArgs.EventId, OnRepoItemClicked); GameEntry.Event.Subscribe(RepoItemDragEndedEventArgs.EventId, OnRepoItemDragEnded); GameEntry.Event.Subscribe(CombineSlotClickedEventArgs.EventId, OnCombineSlotClicked); GameEntry.Event.Subscribe(RepoCombineRequestedEventArgs.EventId, OnRepoCombineRequested); GameEntry.Event.Subscribe(RepoParticipantAssignRequestedEventArgs.EventId, OnRepoParticipantAssignRequested); GameEntry.Event.Subscribe(RepoFormReturnEventArgs.EventId, OnRepoFormReturn); } protected override void UnsubscribeCustomEvents() { GameEntry.Event.Unsubscribe(RepoItemClickedEventArgs.EventId, OnRepoItemClicked); GameEntry.Event.Unsubscribe(RepoItemDragEndedEventArgs.EventId, OnRepoItemDragEnded); GameEntry.Event.Unsubscribe(CombineSlotClickedEventArgs.EventId, OnCombineSlotClicked); GameEntry.Event.Unsubscribe(RepoCombineRequestedEventArgs.EventId, OnRepoCombineRequested); GameEntry.Event.Unsubscribe(RepoParticipantAssignRequestedEventArgs.EventId, OnRepoParticipantAssignRequested); GameEntry.Event.Unsubscribe(RepoFormReturnEventArgs.EventId, OnRepoFormReturn); } public override int? OpenUI(object userData = null) { if (userData is RepoFormContext repoFormContext) { return OpenUIInternal(repoFormContext); } if (userData is RepoFormRawData rawDataFromUserData) { return OpenUI(rawDataFromUserData); } if (userData != null) { Log.Warning("RepoFormController.OpenUI() userData type is invalid."); return null; } if (_useCase == null) { Log.Error("RepoFormController.OpenUI() useCase is null."); return null; } RepoFormRawData rawData = _useCase.CreateInitialModel(); return OpenUI(rawData); } public int? OpenUI(RepoFormRawData rawData) { RepoFormContext context = BuildContext(rawData); return OpenUIInternal(context); } public override void BindUseCase(IUIUseCase useCase) { if (!(useCase is RepoFormUseCase repoFormUseCase)) { Log.Error("RepoFormController.BindUseCase() useCase is invalid."); return; } _useCase = repoFormUseCase; } #region Event Handlers private void OnRepoItemClicked(object sender, GameEventArgs e) { if (!IsEventFromCurrentForm(sender)) { return; } if (!(e is RepoItemClickedEventArgs args)) { return; } RepoItemClickActionType clickActionType = RepoItemClickActionType.OpenDetail; if (sender is RepoItem clickedItem && clickedItem.Context != null) { clickActionType = clickedItem.Context.ClickActionType; } else if (_itemContextMap.TryGetValue(args.ItemId, out RepoItemContext itemContextFromMap) && itemContextFromMap != null) { clickActionType = itemContextFromMap.ClickActionType; } if (args.ItemId <= 0) { return; } if (clickActionType == RepoItemClickActionType.RemoveParticipant) { if (_useCase == null || Form == null) { return; } if (!_useCase.TryRemoveParticipantTower(args.ItemId)) { return; } RefreshParticipantAreaOnly(); return; } if (!_itemDescSeedMap.TryGetValue(args.ItemId, out ItemDescSeed seed)) { return; } GameEntry.UIRouter.OpenUI(UIFormType.ItemDescForm, new ItemDescFormRawData { Title = seed.Title, TypeText = seed.TypeText, Description = seed.Description ?? string.Empty, Price = 0, TargetPos = args.TargetPos, Tags = CloneTags(seed.Tags) }); } private void OnRepoItemDragEnded(object sender, GameEventArgs e) { if (!IsEventFromCurrentForm(sender)) { return; } if (!(e is RepoItemDragEndedEventArgs args)) { return; } if (Form == null || !_itemContextMap.ContainsKey(args.ItemId)) { return; } Form.SetRepoItemSelected(args.ItemId, args.Assigned); } private void OnCombineSlotClicked(object sender, GameEventArgs e) { if (!IsEventFromCurrentForm(sender)) { return; } if (!(e is CombineSlotClickedEventArgs args)) { return; } if (Form == null) { return; } if (Form.TryClearCombineSlot(args.SlotIndex, out long removedItemId) && removedItemId > 0) { Form.SetRepoItemSelected(removedItemId, false); } } private void OnRepoFormReturn(object sender, GameEventArgs e) { if (!IsEventFromCurrentForm(sender) || !(e is RepoFormReturnEventArgs)) { return; } if (Form == null) { return; } this.CloseUI(); } private void OnRepoCombineRequested(object sender, GameEventArgs e) { if (!IsEventFromCurrentForm(sender)) { return; } if (!(e is RepoCombineRequestedEventArgs args)) { return; } if (_useCase == null || Form == null) { return; } if (!_useCase.TryAssembleTower(args.MuzzleItemId, args.BearingItemId, args.BaseItemId)) { return; } RepoFormRawData latestRawData = _useCase.CreateInitialModel(); RepoFormContext latestContext = BuildContext(latestRawData); if (latestContext != null) { Form.RefreshUI(latestContext); ApplyParticipantSelection(); } } private void OnRepoParticipantAssignRequested(object sender, GameEventArgs e) { if (!IsEventFromCurrentForm(sender)) { return; } if (!(e is RepoParticipantAssignRequestedEventArgs args)) { return; } if (_useCase == null || Form == null || args.TowerItemId <= 0) { return; } if (!_useCase.TryAddParticipantTower(args.TowerItemId)) { return; } RefreshParticipantAreaOnly(); } private bool IsEventFromCurrentForm(object sender) { if (Form == null) { return false; } if (ReferenceEquals(sender, Form)) { return true; } if (sender is Component component) { RepoForm ownerForm = component.GetComponentInParent(); return ownerForm == Form; } return false; } #endregion } }