using System.Collections.Generic; using GeometryTD.CustomEvent; using GeometryTD.CustomUtility; 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 _itemClickActionMap = new Dictionary(); private readonly Dictionary _itemDescSeedMap = new Dictionary(); private readonly HashSet _participantTowerIds = new HashSet(); private readonly HashSet _compAreaTowerIds = new HashSet(); private sealed class ItemDescSeed { public string Title; public string TypeText; public string Description; public TagType[] Tags; public TagRuntimeData[] TagRuntimes; } 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 (_itemClickActionMap.TryGetValue(args.ItemId, out RepoItemClickActionType mappedAction)) { clickActionType = mappedAction; } 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), TagRuntimes = CloneTagRuntimes(seed.TagRuntimes) }); } private static TagType[] CloneTags(TagType[] tags) { return tags != null ? (TagType[])tags.Clone() : System.Array.Empty(); } private static TagRuntimeData[] CloneTagRuntimes(TagRuntimeData[] tagRuntimes) { return InventoryCloneUtility.CloneTagRuntimes(tagRuntimes); } private void OnRepoItemDragEnded(object sender, GameEventArgs e) { if (!IsEventFromCurrentForm(sender)) { return; } if (!(e is RepoItemDragEndedEventArgs args)) { return; } if (Form == null || !_itemClickActionMap.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; } 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; } ParticipantTowerAssignResult result = _useCase.TryAddParticipantTower(args.TowerItemId); if (result == null || !result.IsSuccess) { if (result != null) { Log.Warning( "RepoFormController denied participant assignment. TowerId={0}, FailureReason={1}, ValidationFailureReason={2}.", result.TowerInstanceId, result.FailureReason, result.ValidationFailureReason); } 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 private static string[] CloneTagTexts(string[] tagTexts) { return tagTexts != null ? (string[])tagTexts.Clone() : System.Array.Empty(); } } }