Compare commits
No commits in common. "6bf99f313cef580a226381b86542d1e4d5d9fef5" and "0f7d062a9fc16e61ef5fd521a56d2ee3c0c99891" have entirely different histories.
6bf99f313c
...
0f7d062a9f
@ -9,16 +9,16 @@ namespace UnityEngine.UI
|
|||||||
internal sealed class UXNavigationRuntime : MonoBehaviour
|
internal sealed class UXNavigationRuntime : MonoBehaviour
|
||||||
{
|
{
|
||||||
private static UXNavigationRuntime _instance;
|
private static UXNavigationRuntime _instance;
|
||||||
private static readonly string CacheLayerName = $"Layer{(int)UILayer.All}-{UILayer.All}";
|
|
||||||
|
|
||||||
|
private const float DiscoveryInterval = 0.5f;
|
||||||
private readonly HashSet<UXNavigationScope> _scopeSet = new();
|
private readonly HashSet<UXNavigationScope> _scopeSet = new();
|
||||||
private readonly List<UXNavigationScope> _scopes = new(32);
|
private readonly List<UXNavigationScope> _scopes = new(32);
|
||||||
private readonly HashSet<Transform> _interactiveLayerRoots = new();
|
private readonly HashSet<Transform> _interactiveLayerRoots = new();
|
||||||
private readonly List<UIHolderObjectBase> _holderBuffer = new(32);
|
|
||||||
|
|
||||||
private Transform _uiCanvasRoot;
|
private Transform _uiCanvasRoot;
|
||||||
private UXNavigationScope _topScope;
|
private UXNavigationScope _topScope;
|
||||||
private GameObject _lastObservedSelection;
|
private GameObject _lastObservedSelection;
|
||||||
|
private float _nextDiscoveryTime;
|
||||||
private bool _discoveryDirty = true;
|
private bool _discoveryDirty = true;
|
||||||
private ulong _activationSerial;
|
private ulong _activationSerial;
|
||||||
private bool _missingEventSystemLogged;
|
private bool _missingEventSystemLogged;
|
||||||
@ -101,6 +101,7 @@ namespace UnityEngine.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
_scopes.Add(scope);
|
_scopes.Add(scope);
|
||||||
|
MarkDiscoveryDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UnregisterScope(UXNavigationScope scope)
|
internal void UnregisterScope(UXNavigationScope scope)
|
||||||
@ -115,9 +116,9 @@ namespace UnityEngine.UI
|
|||||||
_topScope = null;
|
_topScope = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.IsAvailable = false;
|
|
||||||
scope.SetNavigationSuppressed(false);
|
scope.SetNavigationSuppressed(false);
|
||||||
_scopes.Remove(scope);
|
_scopes.Remove(scope);
|
||||||
|
MarkDiscoveryDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void MarkDiscoveryDirty()
|
internal void MarkDiscoveryDirty()
|
||||||
@ -133,7 +134,7 @@ namespace UnityEngine.UI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_discoveryDirty)
|
if (_discoveryDirty || Time.unscaledTime >= _nextDiscoveryTime)
|
||||||
{
|
{
|
||||||
DiscoverScopes();
|
DiscoverScopes();
|
||||||
}
|
}
|
||||||
@ -172,7 +173,6 @@ namespace UnityEngine.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
_uiCanvasRoot = uiModule.UICanvasRoot;
|
_uiCanvasRoot = uiModule.UICanvasRoot;
|
||||||
EnsureWatcher(_uiCanvasRoot);
|
|
||||||
CacheInteractiveLayers();
|
CacheInteractiveLayers();
|
||||||
DiscoverScopes();
|
DiscoverScopes();
|
||||||
}
|
}
|
||||||
@ -185,23 +185,28 @@ namespace UnityEngine.UI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnsureWatcher(_uiCanvasRoot);
|
string cacheLayerName = $"Layer{(int)UILayer.All}-{UILayer.All}";
|
||||||
for (int i = 0; i < _uiCanvasRoot.childCount; i++)
|
for (int i = 0; i < _uiCanvasRoot.childCount; i++)
|
||||||
{
|
{
|
||||||
Transform child = _uiCanvasRoot.GetChild(i);
|
Transform child = _uiCanvasRoot.GetChild(i);
|
||||||
if (child == null || child.name == CacheLayerName)
|
if (child == null || child.name == cacheLayerName)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_interactiveLayerRoots.Add(child);
|
_interactiveLayerRoots.Add(child);
|
||||||
EnsureWatcher(child);
|
if (child.GetComponent<UXNavigationLayerWatcher>() == null)
|
||||||
|
{
|
||||||
|
var watcher = child.gameObject.AddComponent<UXNavigationLayerWatcher>();
|
||||||
|
watcher.Initialize(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DiscoverScopes()
|
private void DiscoverScopes()
|
||||||
{
|
{
|
||||||
_discoveryDirty = false;
|
_discoveryDirty = false;
|
||||||
|
_nextDiscoveryTime = Time.unscaledTime + DiscoveryInterval;
|
||||||
CacheInteractiveLayers();
|
CacheInteractiveLayers();
|
||||||
bool addedScope = false;
|
bool addedScope = false;
|
||||||
|
|
||||||
@ -212,11 +217,10 @@ namespace UnityEngine.UI
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_holderBuffer.Clear();
|
UIHolderObjectBase[] holders = layerRoot.GetComponentsInChildren<UIHolderObjectBase>(true);
|
||||||
layerRoot.GetComponentsInChildren(true, _holderBuffer);
|
for (int i = 0; i < holders.Length; i++)
|
||||||
for (int i = 0; i < _holderBuffer.Count; i++)
|
|
||||||
{
|
{
|
||||||
UIHolderObjectBase holder = _holderBuffer[i];
|
UIHolderObjectBase holder = holders[i];
|
||||||
if (holder == null
|
if (holder == null
|
||||||
|| holder.GetComponent<UXNavigationScope>() != null
|
|| holder.GetComponent<UXNavigationScope>() != null
|
||||||
|| IsNavigationSkipped(holder.transform))
|
|| IsNavigationSkipped(holder.transform))
|
||||||
@ -229,8 +233,6 @@ namespace UnityEngine.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_holderBuffer.Clear();
|
|
||||||
|
|
||||||
if (addedScope)
|
if (addedScope)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _scopes.Count; i++)
|
for (int i = 0; i < _scopes.Count; i++)
|
||||||
@ -240,21 +242,6 @@ namespace UnityEngine.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureWatcher(Transform target)
|
|
||||||
{
|
|
||||||
if (target == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!target.TryGetComponent(out UXNavigationLayerWatcher watcher))
|
|
||||||
{
|
|
||||||
watcher = target.gameObject.AddComponent<UXNavigationLayerWatcher>();
|
|
||||||
}
|
|
||||||
|
|
||||||
watcher.Initialize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private UXNavigationScope FindTopScope()
|
private UXNavigationScope FindTopScope()
|
||||||
{
|
{
|
||||||
UXNavigationScope bestScope = null;
|
UXNavigationScope bestScope = null;
|
||||||
@ -267,7 +254,6 @@ namespace UnityEngine.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool available = IsScopeAvailable(scope);
|
bool available = IsScopeAvailable(scope);
|
||||||
scope.IsAvailable = available;
|
|
||||||
if (scope.WasAvailable != available)
|
if (scope.WasAvailable != available)
|
||||||
{
|
{
|
||||||
scope.WasAvailable = available;
|
scope.WasAvailable = available;
|
||||||
@ -362,7 +348,7 @@ namespace UnityEngine.UI
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool suppress = scope.IsAvailable
|
bool suppress = IsScopeAvailable(scope)
|
||||||
&& _topScope != null
|
&& _topScope != null
|
||||||
&& !ReferenceEquals(scope, _topScope)
|
&& !ReferenceEquals(scope, _topScope)
|
||||||
&& _topScope.BlockLowerScopes
|
&& _topScope.BlockLowerScopes
|
||||||
|
|||||||
@ -21,20 +21,16 @@ namespace UnityEngine.UI
|
|||||||
[SerializeField, Header("自动选中首个可用控件")] private bool _autoSelectFirstAvailable = true;
|
[SerializeField, Header("自动选中首个可用控件")] private bool _autoSelectFirstAvailable = true;
|
||||||
|
|
||||||
private readonly List<Selectable> _cachedSelectables = new(16);
|
private readonly List<Selectable> _cachedSelectables = new(16);
|
||||||
private readonly HashSet<Selectable> _cachedSelectableSet = new();
|
|
||||||
private readonly Dictionary<Selectable, Navigation> _baselineNavigation = new();
|
private readonly Dictionary<Selectable, Navigation> _baselineNavigation = new();
|
||||||
private readonly List<Selectable> _removeBuffer = new(8);
|
private readonly List<Selectable> _removeBuffer = new(8);
|
||||||
private readonly List<Selectable> _selectableScanBuffer = new(16);
|
|
||||||
|
|
||||||
private Canvas _cachedCanvas;
|
private Canvas _cachedCanvas;
|
||||||
private UIHolderObjectBase _cachedHolder;
|
private UIHolderObjectBase _cachedHolder;
|
||||||
private Selectable _lastSelected;
|
private Selectable _lastSelected;
|
||||||
private bool _cacheDirty = true;
|
private bool _cacheDirty = true;
|
||||||
private bool _navigationSuppressed;
|
private bool _navigationSuppressed;
|
||||||
private int _cachedHierarchyDepth = -1;
|
|
||||||
|
|
||||||
internal ulong ActivationSerial { get; set; }
|
internal ulong ActivationSerial { get; set; }
|
||||||
internal bool IsAvailable { get; set; }
|
|
||||||
internal bool WasAvailable { get; set; }
|
internal bool WasAvailable { get; set; }
|
||||||
|
|
||||||
public Selectable DefaultSelectable
|
public Selectable DefaultSelectable
|
||||||
@ -102,14 +98,6 @@ namespace UnityEngine.UI
|
|||||||
_cacheDirty = true;
|
_cacheDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTransformParentChanged()
|
|
||||||
{
|
|
||||||
_cacheDirty = true;
|
|
||||||
_cachedCanvas = null;
|
|
||||||
_cachedHolder = null;
|
|
||||||
_cachedHierarchyDepth = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
private void OnValidate()
|
private void OnValidate()
|
||||||
{
|
{
|
||||||
@ -119,11 +107,6 @@ namespace UnityEngine.UI
|
|||||||
|
|
||||||
internal int GetHierarchyDepth()
|
internal int GetHierarchyDepth()
|
||||||
{
|
{
|
||||||
if (_cachedHierarchyDepth >= 0)
|
|
||||||
{
|
|
||||||
return _cachedHierarchyDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
Transform current = transform;
|
Transform current = transform;
|
||||||
while (current != null)
|
while (current != null)
|
||||||
@ -132,8 +115,7 @@ namespace UnityEngine.UI
|
|||||||
current = current.parent;
|
current = current.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cachedHierarchyDepth = depth;
|
return depth;
|
||||||
return _cachedHierarchyDepth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool Owns(GameObject target)
|
internal bool Owns(GameObject target)
|
||||||
@ -169,7 +151,7 @@ namespace UnityEngine.UI
|
|||||||
for (int i = 0; i < _cachedSelectables.Count; i++)
|
for (int i = 0; i < _cachedSelectables.Count; i++)
|
||||||
{
|
{
|
||||||
Selectable selectable = _cachedSelectables[i];
|
Selectable selectable = _cachedSelectables[i];
|
||||||
if (IsSelectableUsable(selectable))
|
if (IsSelectableValid(selectable))
|
||||||
{
|
{
|
||||||
return selectable;
|
return selectable;
|
||||||
}
|
}
|
||||||
@ -189,7 +171,7 @@ namespace UnityEngine.UI
|
|||||||
|
|
||||||
for (int i = 0; i < _cachedSelectables.Count; i++)
|
for (int i = 0; i < _cachedSelectables.Count; i++)
|
||||||
{
|
{
|
||||||
if (IsSelectableUsable(_cachedSelectables[i]))
|
if (IsSelectableValid(_cachedSelectables[i]))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -205,7 +187,12 @@ namespace UnityEngine.UI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Selectable selectable = GetSelectableFromObject(selectedObject);
|
Selectable selectable = selectedObject.GetComponent<Selectable>();
|
||||||
|
if (selectable == null)
|
||||||
|
{
|
||||||
|
selectable = selectedObject.GetComponentInParent<Selectable>();
|
||||||
|
}
|
||||||
|
|
||||||
if (IsSelectableValid(selectable))
|
if (IsSelectableValid(selectable))
|
||||||
{
|
{
|
||||||
_lastSelected = selectable;
|
_lastSelected = selectable;
|
||||||
@ -214,7 +201,18 @@ namespace UnityEngine.UI
|
|||||||
|
|
||||||
internal bool IsSelectableOwnedAndValid(GameObject selectedObject)
|
internal bool IsSelectableOwnedAndValid(GameObject selectedObject)
|
||||||
{
|
{
|
||||||
return IsSelectableValid(GetSelectableFromObject(selectedObject));
|
if (selectedObject == null || !Owns(selectedObject))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Selectable selectable = selectedObject.GetComponent<Selectable>();
|
||||||
|
if (selectable == null)
|
||||||
|
{
|
||||||
|
selectable = selectedObject.GetComponentInParent<Selectable>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return IsSelectableValid(selectable);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetNavigationSuppressed(bool suppressed)
|
internal void SetNavigationSuppressed(bool suppressed)
|
||||||
@ -261,7 +259,6 @@ namespace UnityEngine.UI
|
|||||||
|
|
||||||
_cacheDirty = false;
|
_cacheDirty = false;
|
||||||
_cachedSelectables.Clear();
|
_cachedSelectables.Clear();
|
||||||
_cachedSelectableSet.Clear();
|
|
||||||
|
|
||||||
if (_explicitSelectables != null && _explicitSelectables.Count > 0)
|
if (_explicitSelectables != null && _explicitSelectables.Count > 0)
|
||||||
{
|
{
|
||||||
@ -272,18 +269,17 @@ namespace UnityEngine.UI
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_selectableScanBuffer.Clear();
|
Selectable[] selectables = GetComponentsInChildren<Selectable>(true);
|
||||||
GetComponentsInChildren(true, _selectableScanBuffer);
|
for (int i = 0; i < selectables.Length; i++)
|
||||||
for (int i = 0; i < _selectableScanBuffer.Count; i++)
|
|
||||||
{
|
{
|
||||||
TryAddSelectable(_selectableScanBuffer[i]);
|
TryAddSelectable(selectables[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_removeBuffer.Clear();
|
_removeBuffer.Clear();
|
||||||
foreach (var pair in _baselineNavigation)
|
foreach (var pair in _baselineNavigation)
|
||||||
{
|
{
|
||||||
if (!_cachedSelectableSet.Contains(pair.Key))
|
if (!_cachedSelectables.Contains(pair.Key))
|
||||||
{
|
{
|
||||||
_removeBuffer.Add(pair.Key);
|
_removeBuffer.Add(pair.Key);
|
||||||
}
|
}
|
||||||
@ -293,8 +289,6 @@ namespace UnityEngine.UI
|
|||||||
{
|
{
|
||||||
_baselineNavigation.Remove(_removeBuffer[i]);
|
_baselineNavigation.Remove(_removeBuffer[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_selectableScanBuffer.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InvalidateSelectableCache()
|
public void InvalidateSelectableCache()
|
||||||
@ -304,7 +298,7 @@ namespace UnityEngine.UI
|
|||||||
|
|
||||||
private void TryAddSelectable(Selectable selectable)
|
private void TryAddSelectable(Selectable selectable)
|
||||||
{
|
{
|
||||||
if (selectable == null || !Owns(selectable.gameObject) || !_cachedSelectableSet.Add(selectable))
|
if (selectable == null || !Owns(selectable.gameObject))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -317,28 +311,11 @@ namespace UnityEngine.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool IsSelectableValid(Selectable selectable)
|
private bool IsSelectableValid(Selectable selectable)
|
||||||
{
|
|
||||||
return IsSelectableUsable(selectable)
|
|
||||||
&& (_cachedSelectableSet.Contains(selectable) || Owns(selectable.gameObject));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsSelectableUsable(Selectable selectable)
|
|
||||||
{
|
{
|
||||||
return selectable != null
|
return selectable != null
|
||||||
&& selectable.IsActive()
|
&& selectable.IsActive()
|
||||||
&& selectable.IsInteractable();
|
&& selectable.IsInteractable()
|
||||||
}
|
&& Owns(selectable.gameObject);
|
||||||
|
|
||||||
private static Selectable GetSelectableFromObject(GameObject selectedObject)
|
|
||||||
{
|
|
||||||
if (selectedObject == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return selectedObject.TryGetComponent(out Selectable selectable)
|
|
||||||
? selectable
|
|
||||||
: selectedObject.GetComponentInParent<Selectable>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,8 +17,6 @@ namespace UnityEngine.UI
|
|||||||
{
|
{
|
||||||
[SerializeField] private List<TransitionData> m_ChildTransitions = new();
|
[SerializeField] private List<TransitionData> m_ChildTransitions = new();
|
||||||
|
|
||||||
private SelectionState _state;
|
|
||||||
|
|
||||||
void StartChildColorTween(TransitionData transitionData, Color targetColor, bool instant)
|
void StartChildColorTween(TransitionData transitionData, Color targetColor, bool instant)
|
||||||
{
|
{
|
||||||
if (transitionData.targetGraphic == null)
|
if (transitionData.targetGraphic == null)
|
||||||
@ -70,8 +68,7 @@ namespace UnityEngine.UI
|
|||||||
protected override void DoStateTransition(SelectionState state, bool instant)
|
protected override void DoStateTransition(SelectionState state, bool instant)
|
||||||
{
|
{
|
||||||
base.DoStateTransition(state, instant);
|
base.DoStateTransition(state, instant);
|
||||||
if (_state == state) return;
|
|
||||||
_state = state;
|
|
||||||
for (int i = 0; i < m_ChildTransitions.Count; i++)
|
for (int i = 0; i < m_ChildTransitions.Count; i++)
|
||||||
{
|
{
|
||||||
TransitionData transitionData = m_ChildTransitions[i];
|
TransitionData transitionData = m_ChildTransitions[i];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user