123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- using System.Collections;
- using System.Collections.Generic;
- namespace Rokid.UXR.Interaction
- {
- /// <summary>
- /// A registry that houses a set of concrete Interactables.
- /// 包含一组具体可交互对象的注册表。
- /// </summary>
- public class InteractableRegistry<TInteractor, TInteractable>
- where TInteractor : Interactor<TInteractor, TInteractable>
- where TInteractable : Interactable<TInteractor, TInteractable>
- {
- /// <summary>
- /// Allocation-free collection that can be iterated over
- /// to provide a pruned list of Interactables.
- /// </summary>
- public struct InteractableSet : IEnumerable<TInteractable>
- {
- private readonly IReadOnlyList<TInteractable> _data;
- private readonly ISet<TInteractable> _onlyInclude;
- private readonly TInteractor _testAgainst;
- /// <summary>
- /// A pruned set of interactables from the
- /// <see cref="InteractableRegistry{TInteractor, TInteractable}"/>
- /// </summary>
- /// <param name="onlyInclude">Include only these interactables from
- /// the base <see cref="_interactables"/> collection.
- /// Provide a null value to skip this filtering.</param>
- /// <param name="testAgainst">Filter against an interactor.
- /// Provide a null value to skip this filtering.</param>
- public InteractableSet(
- ISet<TInteractable> onlyInclude,
- TInteractor testAgainst)
- {
- _data = _interactables;
- _onlyInclude = onlyInclude;
- _testAgainst = testAgainst;
- }
- public Enumerator GetEnumerator()
- {
- return new Enumerator(this);
- }
- IEnumerator<TInteractable> IEnumerable<TInteractable>.GetEnumerator()
- {
- return GetEnumerator();
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- private bool Include(TInteractable interactable)
- {
- // Skip interactables not contained in a provided subset
- if (_onlyInclude != null)
- {
- if (!_onlyInclude.Contains(interactable))
- {
- return false;
- }
- }
- // Skip interactables that fail test against interactable
- if (_testAgainst != null)
- {
- if (!_testAgainst.CanSelect(interactable))
- {
- return false;
- }
- if (!interactable.CanBeSelectedBy(_testAgainst))
- {
- return false;
- }
- }
- return true;
- }
- public struct Enumerator : IEnumerator<TInteractable>
- {
- private readonly InteractableSet _set;
- private int _position;
- private IReadOnlyList<TInteractable> Data => _set._data;
- public Enumerator(in InteractableSet set)
- {
- _set = set;
- _position = -1;
- }
- public TInteractable Current
- {
- get
- {
- if (Data == null || _position < 0)
- {
- throw new System.InvalidOperationException();
- }
- return Data[_position];
- }
- }
- object IEnumerator.Current => Current;
- public bool MoveNext()
- {
- if (Data == null)
- {
- return false;
- }
- do
- {
- _position++;
- } while (_position < Data.Count &&
- !_set.Include(Data[_position]));
- return _position < Data.Count;
- }
- public void Reset()
- {
- _position = -1;
- }
- public void Dispose()
- {
- }
- }
- }
- private static List<TInteractable> _interactables;
- public InteractableRegistry()
- {
- _interactables = new List<TInteractable>();
- }
- public virtual void Register(TInteractable interactable)
- {
- _interactables.Add(interactable);
- }
- public virtual void Unregister(TInteractable interactable)
- {
- _interactables.Remove(interactable);
- }
- /// <summary>
- /// Returns a filtered collection of interactables
- /// </summary>
- /// <param name="interactor">Only interactables that can be selected by
- /// this interactor will be returned</param>
- /// <param name="onlyInclude">Only interactables included in this
- /// subset will be included in the returned collection</param>
- protected InteractableSet List(TInteractor interactor,
- HashSet<TInteractable> onlyInclude)
- {
- return new InteractableSet(onlyInclude, interactor);
- }
- /// <summary>
- /// Returns a filtered collection of interactables
- /// </summary>
- /// <param name="interactor">Only interactables that can be selected by
- /// this interactor will be returned</param>
- public virtual InteractableSet List(TInteractor interactor)
- {
- return new InteractableSet(null, interactor);
- }
- /// <summary>
- /// Returns all interactables in this registry
- /// </summary>
- public virtual InteractableSet List()
- {
- return new InteractableSet(null, null);
- }
- }
- }
|