using System; using System.Collections.Generic; using Sirenix.OdinInspector; using UnityEngine; using UnityEngine.InputSystem; namespace DDD { public static class EnumExtensions { public static IEnumerable GetFlags(this T input) where T : Enum { foreach (T value in Enum.GetValues(typeof(T))) { int intValue = Convert.ToInt32(value); int inputValue = Convert.ToInt32(input); if (intValue != 0 && (inputValue & intValue) == intValue) yield return value; } } } public abstract class PopupUi : BasePopupUi where TInputEnum : Enum where TViewModel : SimpleViewModel { [SerializeField, Required] protected BaseUiActionsInputBinding _uiActionsInputBinding; protected readonly List<(InputAction action, Action handler)> _registeredHandlers = new(); protected TViewModel _viewModel; protected override void Awake() { base.Awake(); _viewModel = GetComponent(); } protected override void TryRegister() { base.TryRegister(); if (_viewModel && _bindingContext != null) { _bindingContext.SetDataContext(_viewModel); _viewModel.PropertyChanged += OnViewModelPropertyChanged; } // PopupUi의 입력 바인딩 등록 foreach (var actionEnum in _uiActionsInputBinding.BindingActions.GetFlags()) { if (actionEnum.Equals(default(TInputEnum))) continue; var inputAction = InputManager.Instance.GetAction(_uiActionsInputBinding.InputActionMaps, actionEnum.ToString()); if (inputAction == null) continue; var startedHandler = new Action(context => { OnInputStarted(actionEnum, context); }); inputAction.started += startedHandler; var performedHandler = new Action(context => { OnInputPerformed(actionEnum, context); }); inputAction.performed += performedHandler; var canceledHandler = new Action(context => { OnInputCanceled(actionEnum, context); }); inputAction.canceled += canceledHandler; _registeredHandlers.Add((inputAction, startedHandler)); _registeredHandlers.Add((inputAction, performedHandler)); _registeredHandlers.Add((inputAction, canceledHandler)); } InputActionMaps = _uiActionsInputBinding.InputActionMaps; } protected override void TryUnregister() { base.TryUnregister(); if (_viewModel != null) { _viewModel.PropertyChanged -= OnViewModelPropertyChanged; } // 입력 핸들러 해제 foreach (var (action, handler) in _registeredHandlers) { if (action != null) { action.started -= handler; action.performed -= handler; action.canceled -= handler; } } _registeredHandlers.Clear(); } public override void Open(OpenPopupUiEvent evt) { base.Open(evt); _viewModel?.Initialize(); if (IsTopPopup) { InputManager.Instance.SwitchCurrentActionMap(_uiActionsInputBinding.InputActionMaps); } } public override void Close() { base.Close(); _viewModel?.Cleanup(); } // 입력 처리 메서드들 protected virtual bool OnInputStarted(TInputEnum actionEnum, InputAction.CallbackContext context) => IsTopPopup; protected virtual bool OnInputPerformed(TInputEnum actionEnum, InputAction.CallbackContext context) => IsTopPopup; protected virtual bool OnInputCanceled(TInputEnum actionEnum, InputAction.CallbackContext context) => IsTopPopup; } }