com.alicizax.unity.ui.exten.../Runtime/UXComponent/Hotkey/UXHotkeyRegisterManager.cs

677 lines
21 KiB
C#
Raw Normal View History

2025-10-13 20:20:01 +08:00
#if INPUTSYSTEM_SUPPORT
2025-12-09 20:30:11 +08:00
using System;
2026-03-20 13:11:41 +08:00
using System.Collections.Generic;
2025-12-24 15:13:57 +08:00
using System.Runtime.CompilerServices;
2026-03-20 13:11:41 +08:00
using AlicizaX.UI.Runtime;
2025-10-13 20:20:01 +08:00
using UnityEngine;
using UnityEngine.InputSystem;
namespace UnityEngine.UI
2025-10-13 20:20:01 +08:00
{
2025-12-24 15:13:57 +08:00
internal enum EHotkeyPressType : byte
2025-10-13 20:20:01 +08:00
{
2025-12-24 15:13:57 +08:00
Started = 0,
Performed = 1
2025-12-09 20:30:11 +08:00
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
internal readonly struct HotkeyRegistration
2025-12-09 20:30:11 +08:00
{
2026-03-20 13:11:41 +08:00
public readonly IHotkeyTrigger Trigger;
public readonly EHotkeyPressType PressType;
2025-12-09 20:30:11 +08:00
2025-12-24 15:13:57 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2026-03-20 13:11:41 +08:00
public HotkeyRegistration(IHotkeyTrigger trigger, EHotkeyPressType pressType)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
Trigger = trigger;
PressType = pressType;
2025-10-13 20:20:01 +08:00
}
2025-12-24 15:13:57 +08:00
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
internal sealed class HotkeyScope
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
public HotkeyScope(UIHolderObjectBase holder)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
Holder = holder;
HierarchyDepth = GetHierarchyDepth(holder.transform);
2026-04-15 14:15:27 +08:00
ParentHolder = FindParentHolder(holder);
BlocksLowerScopes = ParentHolder == null;
2025-12-24 15:13:57 +08:00
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
public readonly UIHolderObjectBase Holder;
2026-04-15 14:15:27 +08:00
public readonly UIHolderObjectBase ParentHolder;
2026-03-20 13:11:41 +08:00
public readonly int HierarchyDepth;
public readonly bool BlocksLowerScopes;
public readonly Dictionary<string, List<HotkeyRegistration>> RegistrationsByAction = new(StringComparer.Ordinal);
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
public bool LifecycleActive;
public ulong ActivationSerial;
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
public Action OnBeforeShow;
public Action OnBeforeClosed;
public Action OnDestroy;
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
private Canvas _canvas;
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
public Canvas Canvas
{
get
{
if (_canvas == null && Holder != null)
{
_canvas = Holder.GetComponent<Canvas>();
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
return _canvas;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int GetHierarchyDepth(Transform current)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
int depth = 0;
while (current != null)
{
depth++;
current = current.parent;
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
return depth;
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static UIHolderObjectBase FindParentHolder(UIHolderObjectBase holder)
{
if (holder == null)
{
return null;
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
Transform current = holder.transform.parent;
while (current != null)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
if (current.TryGetComponent<UIHolderObjectBase>(out var parentHolder))
{
return parentHolder;
}
current = current.parent;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
return null;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
}
internal sealed class ActionRegistrationBucket
{
public InputActionReference ActionReference;
public Action<InputAction.CallbackContext> StartedHandler;
public Action<InputAction.CallbackContext> PerformedHandler;
public int StartedCount;
public int PerformedCount;
public int TotalCount => StartedCount + PerformedCount;
}
internal readonly struct TriggerRegistration
{
public readonly string ActionId;
public readonly UIHolderObjectBase Holder;
public readonly EHotkeyPressType PressType;
public TriggerRegistration(string actionId, UIHolderObjectBase holder, EHotkeyPressType pressType)
{
ActionId = actionId;
Holder = holder;
PressType = pressType;
}
}
internal static class UXHotkeyRegisterManager
{
private static readonly Dictionary<string, ActionRegistrationBucket> _actions = new(StringComparer.Ordinal);
private static readonly Dictionary<IHotkeyTrigger, TriggerRegistration> _triggerMap = new();
private static readonly Dictionary<UIHolderObjectBase, HotkeyScope> _scopes = new();
private static readonly List<HotkeyScope> _leafScopes = new();
private static readonly HashSet<UIHolderObjectBase> _ancestorHolders = new();
private static ulong _serialCounter;
2025-10-13 20:20:01 +08:00
#if UNITY_EDITOR
2025-12-15 19:38:08 +08:00
[UnityEditor.Callbacks.DidReloadScripts]
2025-12-09 20:30:11 +08:00
internal static void ClearHotkeyRegistry()
2025-10-13 20:20:01 +08:00
{
2026-03-20 13:11:41 +08:00
IHotkeyTrigger[] triggers = new IHotkeyTrigger[_triggerMap.Count];
int index = 0;
foreach (var kvp in _triggerMap)
2025-12-09 20:30:11 +08:00
{
2026-03-20 13:11:41 +08:00
triggers[index++] = kvp.Key;
2025-12-09 20:30:11 +08:00
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
for (int i = 0; i < triggers.Length; i++)
{
UnregisterHotkey(triggers[i]);
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
_actions.Clear();
_triggerMap.Clear();
_scopes.Clear();
_leafScopes.Clear();
_ancestorHolders.Clear();
_serialCounter = 0;
2025-12-09 20:30:11 +08:00
}
2025-10-13 20:20:01 +08:00
#endif
2025-12-24 15:13:57 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2026-03-20 13:11:41 +08:00
internal static void RegisterHotkey(IHotkeyTrigger trigger, UIHolderObjectBase holder, InputActionReference action, EHotkeyPressType pressType)
2025-12-09 20:30:11 +08:00
{
2026-03-20 13:11:41 +08:00
if (trigger == null || holder == null || action == null || action.action == null)
{
2025-12-09 20:30:11 +08:00
return;
2026-03-20 13:11:41 +08:00
}
UnregisterHotkey(trigger);
2025-10-13 20:20:01 +08:00
2025-12-09 20:30:11 +08:00
string actionId = action.action.id.ToString();
2026-03-20 13:11:41 +08:00
HotkeyScope scope = GetOrCreateScope(holder);
ActionRegistrationBucket bucket = GetOrCreateBucket(actionId, action);
HotkeyRegistration registration = new HotkeyRegistration(trigger, pressType);
AdjustBucketSubscription(bucket, pressType, true);
AddScopeRegistration(scope, actionId, registration);
if (scope.LifecycleActive)
{
scope.ActivationSerial = ++_serialCounter;
}
_triggerMap[trigger] = new TriggerRegistration(actionId, holder, pressType);
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void UnregisterHotkey(IHotkeyTrigger trigger)
{
if (trigger == null || !_triggerMap.TryGetValue(trigger, out var triggerRegistration))
2025-12-09 20:30:11 +08:00
{
2025-12-24 15:13:57 +08:00
return;
2025-12-09 20:30:11 +08:00
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
if (_actions.TryGetValue(triggerRegistration.ActionId, out var bucket))
{
RemoveActionRegistration(bucket, triggerRegistration.PressType, triggerRegistration.ActionId);
}
if (_scopes.TryGetValue(triggerRegistration.Holder, out var scope))
{
RemoveScopeRegistration(scope, triggerRegistration.ActionId, trigger);
ReleaseScopeIfEmpty(scope);
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
_triggerMap.Remove(trigger);
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ActionRegistrationBucket GetOrCreateBucket(string actionId, InputActionReference action)
{
if (_actions.TryGetValue(actionId, out var bucket))
2025-10-13 20:20:01 +08:00
{
2026-03-20 13:11:41 +08:00
return bucket;
}
2025-12-09 20:30:11 +08:00
2026-03-20 13:11:41 +08:00
bucket = new ActionRegistrationBucket
{
ActionReference = action,
StartedHandler = _ => Dispatch(actionId, EHotkeyPressType.Started),
PerformedHandler = _ => Dispatch(actionId, EHotkeyPressType.Performed)
};
_actions[actionId] = bucket;
return bucket;
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
private static HotkeyScope GetOrCreateScope(UIHolderObjectBase holder)
{
if (_scopes.TryGetValue(holder, out var scope))
{
return scope;
2025-12-09 20:30:11 +08:00
}
2026-03-20 13:11:41 +08:00
scope = new HotkeyScope(holder)
{
LifecycleActive = IsHolderVisible(holder),
ActivationSerial = ++_serialCounter
};
scope.OnBeforeShow = () => ActivateScope(holder);
scope.OnBeforeClosed = () => DeactivateScope(holder);
scope.OnDestroy = () => DestroyScope(holder);
holder.OnWindowBeforeShowEvent += scope.OnBeforeShow;
holder.OnWindowBeforeClosedEvent += scope.OnBeforeClosed;
holder.OnWindowDestroyEvent += scope.OnDestroy;
_scopes[holder] = scope;
return scope;
2025-10-13 20:20:01 +08:00
}
2026-03-20 13:11:41 +08:00
private static void ActivateScope(UIHolderObjectBase holder)
2025-12-09 20:30:11 +08:00
{
2026-03-20 13:11:41 +08:00
if (_scopes.TryGetValue(holder, out var scope))
{
scope.LifecycleActive = true;
scope.ActivationSerial = ++_serialCounter;
}
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
private static void DeactivateScope(UIHolderObjectBase holder)
{
if (_scopes.TryGetValue(holder, out var scope))
{
scope.LifecycleActive = false;
}
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
private static void DestroyScope(UIHolderObjectBase holder)
{
if (holder == null || !_scopes.TryGetValue(holder, out var scope))
{
2025-12-24 15:13:57 +08:00
return;
2026-03-20 13:11:41 +08:00
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
List<IHotkeyTrigger> triggers = null;
foreach (var pair in scope.RegistrationsByAction)
{
List<HotkeyRegistration> registrations = pair.Value;
for (int i = 0; i < registrations.Count; i++)
{
triggers ??= new List<IHotkeyTrigger>(registrations.Count);
triggers.Add(registrations[i].Trigger);
}
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
if (triggers != null)
2025-10-13 20:20:01 +08:00
{
2026-03-20 13:11:41 +08:00
for (int i = 0; i < triggers.Count; i++)
2025-10-13 20:20:01 +08:00
{
2026-03-20 13:11:41 +08:00
UnregisterHotkey(triggers[i]);
}
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
DetachScope(scope);
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
private static void DetachScope(HotkeyScope scope)
{
if (scope == null || scope.Holder == null)
{
return;
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
scope.Holder.OnWindowBeforeShowEvent -= scope.OnBeforeShow;
scope.Holder.OnWindowBeforeClosedEvent -= scope.OnBeforeClosed;
scope.Holder.OnWindowDestroyEvent -= scope.OnDestroy;
_scopes.Remove(scope.Holder);
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
private static void ReleaseScopeIfEmpty(HotkeyScope scope)
{
if (scope != null && scope.RegistrationsByAction.Count == 0)
{
DetachScope(scope);
}
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
private static void AddScopeRegistration(HotkeyScope scope, string actionId, HotkeyRegistration registration)
{
if (!scope.RegistrationsByAction.TryGetValue(actionId, out var registrations))
{
registrations = new List<HotkeyRegistration>();
scope.RegistrationsByAction[actionId] = registrations;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
registrations.Add(registration);
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
private static void RemoveScopeRegistration(HotkeyScope scope, string actionId, IHotkeyTrigger trigger)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
if (!scope.RegistrationsByAction.TryGetValue(actionId, out var registrations))
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
return;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
for (int i = registrations.Count - 1; i >= 0; i--)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
if (ReferenceEquals(registrations[i].Trigger, trigger))
{
registrations.RemoveAt(i);
break;
}
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
if (registrations.Count == 0)
{
scope.RegistrationsByAction.Remove(actionId);
}
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
private static void RemoveActionRegistration(ActionRegistrationBucket bucket, EHotkeyPressType pressType, string actionId)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
AdjustBucketSubscription(bucket, pressType, false);
if (bucket.TotalCount == 0)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
_actions.Remove(actionId);
2025-12-24 15:13:57 +08:00
}
}
2026-03-20 13:11:41 +08:00
private static void AdjustBucketSubscription(ActionRegistrationBucket bucket, EHotkeyPressType pressType, bool add)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
InputAction inputAction = bucket.ActionReference != null ? bucket.ActionReference.action : null;
if (inputAction == null)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
return;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
switch (pressType)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
case EHotkeyPressType.Started:
if (add)
{
if (bucket.StartedCount == 0)
{
inputAction.started += bucket.StartedHandler;
}
bucket.StartedCount++;
}
else if (bucket.StartedCount > 0)
{
bucket.StartedCount--;
if (bucket.StartedCount == 0)
{
inputAction.started -= bucket.StartedHandler;
}
}
break;
case EHotkeyPressType.Performed:
if (add)
{
if (bucket.PerformedCount == 0)
{
inputAction.performed += bucket.PerformedHandler;
}
bucket.PerformedCount++;
}
else if (bucket.PerformedCount > 0)
{
bucket.PerformedCount--;
if (bucket.PerformedCount == 0)
{
inputAction.performed -= bucket.PerformedHandler;
}
}
break;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
if (bucket.TotalCount > 0)
{
inputAction.Enable();
}
else
{
inputAction.Disable();
}
2025-12-24 15:13:57 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2026-03-20 13:11:41 +08:00
private static void Dispatch(string actionId, EHotkeyPressType pressType)
2025-12-24 15:13:57 +08:00
{
2026-04-15 14:15:27 +08:00
HotkeyScope leafScope = GetTopLeafScope();
if (leafScope == null)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
return;
2025-12-24 15:13:57 +08:00
}
2026-04-15 14:15:27 +08:00
TryDispatchToScopeChain(leafScope, actionId, pressType);
2026-03-20 13:11:41 +08:00
}
private static bool TryDispatchToScopeChain(HotkeyScope leafScope, string actionId, EHotkeyPressType pressType)
{
2026-04-15 14:15:27 +08:00
HotkeyScope current = leafScope;
while (current != null)
2025-12-24 15:13:57 +08:00
{
2026-04-15 14:15:27 +08:00
if (TryGetLatestRegistration(current, actionId, pressType, out var registration))
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
registration.Trigger?.HotkeyActionTrigger();
return true;
2025-10-13 20:20:01 +08:00
}
2026-03-20 13:11:41 +08:00
2026-04-15 14:15:27 +08:00
UIHolderObjectBase parentHolder = current.ParentHolder;
current = parentHolder != null && _scopes.TryGetValue(parentHolder, out var parentScope)
? parentScope
: null;
2025-10-13 20:20:01 +08:00
}
2026-03-20 13:11:41 +08:00
return false;
}
private static bool TryGetLatestRegistration(HotkeyScope scope, string actionId, EHotkeyPressType pressType, out HotkeyRegistration registration)
{
if (scope.RegistrationsByAction.TryGetValue(actionId, out var registrations))
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
for (int i = registrations.Count - 1; i >= 0; i--)
{
HotkeyRegistration candidate = registrations[i];
if (candidate.PressType == pressType && candidate.Trigger != null)
{
registration = candidate;
return true;
}
}
2025-12-24 15:13:57 +08:00
}
2025-10-13 20:20:01 +08:00
2026-03-20 13:11:41 +08:00
registration = default;
return false;
2025-12-09 20:30:11 +08:00
}
2025-10-13 20:20:01 +08:00
2026-04-15 14:15:27 +08:00
private static HotkeyScope GetTopLeafScope()
2025-10-13 20:20:01 +08:00
{
2026-03-20 13:11:41 +08:00
_leafScopes.Clear();
_ancestorHolders.Clear();
foreach (var scope in _scopes.Values)
{
if (!IsScopeActive(scope)
#if UX_NAVIGATION
|| !UXNavigationRuntime.IsHolderWithinTopScope(scope.Holder)
#endif
)
2026-03-20 13:11:41 +08:00
{
continue;
}
2026-04-15 14:15:27 +08:00
UIHolderObjectBase parentHolder = scope.ParentHolder;
2026-03-20 13:11:41 +08:00
while (parentHolder != null)
{
_ancestorHolders.Add(parentHolder);
2026-04-15 14:15:27 +08:00
if (_scopes.TryGetValue(parentHolder, out var parentScope))
{
parentHolder = parentScope.ParentHolder;
}
else
{
break;
}
2026-03-20 13:11:41 +08:00
}
}
foreach (var scope in _scopes.Values)
2025-12-09 20:30:11 +08:00
{
if (IsScopeActive(scope)
#if UX_NAVIGATION
&& UXNavigationRuntime.IsHolderWithinTopScope(scope.Holder)
#endif
&& !_ancestorHolders.Contains(scope.Holder))
2026-03-20 13:11:41 +08:00
{
_leafScopes.Add(scope);
}
2025-12-09 20:30:11 +08:00
}
2025-12-24 15:13:57 +08:00
2026-04-15 14:15:27 +08:00
if (_leafScopes.Count == 0)
{
return null;
}
2026-03-20 13:11:41 +08:00
_leafScopes.Sort(CompareScopePriority);
2026-04-15 14:15:27 +08:00
return _leafScopes[0];
2025-10-13 20:20:01 +08:00
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
private static bool IsScopeActive(HotkeyScope scope)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
if (scope == null || !scope.LifecycleActive)
{
return false;
}
UIHolderObjectBase holder = scope.Holder;
if (holder == null || !holder.IsValid())
{
return false;
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
if (!holder.gameObject.activeInHierarchy)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
return false;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
Canvas canvas = scope.Canvas;
return canvas != null && canvas.gameObject.layer == UIComponent.UIShowLayer;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
private static bool IsHolderVisible(UIHolderObjectBase holder)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
if (holder == null || !holder.gameObject.activeInHierarchy)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
return false;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
Canvas canvas = holder.GetComponent<Canvas>();
return canvas != null && canvas.gameObject.layer == UIComponent.UIShowLayer;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
private static int CompareScopePriority(HotkeyScope left, HotkeyScope right)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
int leftDepth = left.Canvas != null ? left.Canvas.sortingOrder : int.MinValue;
int rightDepth = right.Canvas != null ? right.Canvas.sortingOrder : int.MinValue;
int depthCompare = rightDepth.CompareTo(leftDepth);
if (depthCompare != 0)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
return depthCompare;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
int hierarchyCompare = right.HierarchyDepth.CompareTo(left.HierarchyDepth);
if (hierarchyCompare != 0)
{
return hierarchyCompare;
}
return right.ActivationSerial.CompareTo(left.ActivationSerial);
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
private static UIHolderObjectBase FindParentHolder(UIHolderObjectBase holder)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
if (holder == null)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
return null;
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
Transform current = holder.transform.parent;
while (current != null)
{
if (current.TryGetComponent<UIHolderObjectBase>(out var parentHolder))
{
return parentHolder;
}
current = current.parent;
}
return null;
2025-12-24 15:13:57 +08:00
}
#if UNITY_EDITOR
public static string GetDebugInfo()
{
2026-03-20 13:11:41 +08:00
return $"Actions: {_actions.Count}, Triggers: {_triggerMap.Count}, Scopes: {_scopes.Count}";
2025-12-24 15:13:57 +08:00
}
#endif
2025-10-13 20:20:01 +08:00
}
}
2026-03-20 13:11:41 +08:00
namespace UnityEngine.UI
2025-10-13 20:20:01 +08:00
{
2026-03-20 13:11:41 +08:00
public static class UXHotkeyHotkeyExtension
2025-10-13 20:20:01 +08:00
{
2026-03-20 13:11:41 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void BindHotKey(this IHotkeyTrigger trigger)
2025-10-13 20:20:01 +08:00
{
2026-03-20 13:11:41 +08:00
if (trigger?.HotkeyAction == null)
{
return;
}
if (trigger is not Component component)
{
return;
}
UIHolderObjectBase holder = component.GetComponentInParent<UIHolderObjectBase>(true);
if (holder == null)
{
Debug.LogWarning($"{nameof(HotkeyComponent)} could not find a {nameof(UIHolderObjectBase)} owner.", component);
return;
}
UXHotkeyRegisterManager.RegisterHotkey(trigger, holder, trigger.HotkeyAction, trigger.HotkeyPressType);
2025-10-13 20:20:01 +08:00
}
2026-03-20 13:11:41 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void UnBindHotKey(this IHotkeyTrigger trigger)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
if (trigger?.HotkeyAction != null)
{
UXHotkeyRegisterManager.UnregisterHotkey(trigger);
}
2025-12-24 15:13:57 +08:00
}
2026-03-20 13:11:41 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void BindHotKeyBatch(this IHotkeyTrigger[] triggers)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
if (triggers == null)
{
return;
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
for (int i = 0; i < triggers.Length; i++)
{
triggers[i]?.BindHotKey();
}
}
2025-12-24 15:13:57 +08:00
2026-03-20 13:11:41 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void UnBindHotKeyBatch(this IHotkeyTrigger[] triggers)
2025-12-24 15:13:57 +08:00
{
2026-03-20 13:11:41 +08:00
if (triggers == null)
{
return;
}
for (int i = 0; i < triggers.Length; i++)
{
triggers[i]?.UnBindHotKey();
}
2025-12-24 15:13:57 +08:00
}
2025-10-13 20:20:01 +08:00
}
}
#endif