123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- using UnityEngine.Assertions;
- namespace Rokid.UXR.Interaction {
- /// <summary>
- /// Interactable provides a base template for any kind of interactable object.
- /// An Interactable can have Hover and HandleSelected Interactor(s) acting on it.
- /// Concrete Interactables can define whether they have a One-to-One or
- /// One-to-Many relationship with their associated concrete Interactors.
- /// Interactable 为任何类型的可交互对象提供了一个基本模板。
- /// Interactable 可以有 Hover 和 HandleSelected Interactor(s) 作用于它。
- /// 具体的可交互对象可以定义它们是否具有一对一或
- /// 与其关联的具体交互器的一对多关系。
- /// </summary>
- public abstract class Interactable<TInteractor, TInteractable> : MonoBehaviour, IInteractable
- where TInteractor : Interactor<TInteractor, TInteractable>
- where TInteractable : Interactable<TInteractor, TInteractable>
- {
- [SerializeField, Interface(typeof(IGameObjectFilter)), Optional]
- private List<MonoBehaviour> _interactorFilters = new List<MonoBehaviour>();
- private List<IGameObjectFilter> InteractorFilters = null;
-
- /// <summary>
- /// The max Interactors and max selecting Interactors that this Interactable can
- /// have acting on it.
- /// -1 signifies NO limit (can have any number of Interactors)
- /// </summary>
- [SerializeField]
- private int _maxInteractors = -1;
-
- [SerializeField]
- private int _maxSelectingInteractors = -1;
-
- [SerializeField, Optional]
- private UnityEngine.Object _data = null;
- public object Data { get; protected set; } = null;
-
- #region Properties
- public int MaxInteractors
- {
- get
- {
- return _maxInteractors;
- }
- set
- {
- _maxInteractors = value;
- }
- }
-
- public int MaxSelectingInteractors
- {
- get
- {
- return _maxSelectingInteractors;
- }
- set
- {
- _maxSelectingInteractors = value;
- }
- }
- #endregion
-
-
- public IEnumerable<IInteractorView> InteractorViews => _interactors.Cast<IInteractorView>();
- public IEnumerable<IInteractorView> SelectingInteractorViews => _selectingInteractors.Cast<IInteractorView>();
-
- private HashSet<TInteractor> _interactors = new HashSet<TInteractor>();
- private HashSet<TInteractor> _selectingInteractors = new HashSet<TInteractor>();
-
- [SerializeField]
- private InteractableState _state = InteractableState.Normal;
- public event Action<InteractableStateChangeArgs> WhenStateChanged = delegate { };
-
- public event Action<IInteractorView> WhenInteractorViewAdded = delegate { };
- public event Action<IInteractorView> WhenInteractorViewRemoved = delegate { };
- public event Action<IInteractorView> WhenSelectingInteractorViewAdded = delegate { };
- public event Action<IInteractorView> WhenSelectingInteractorViewRemoved = delegate { };
-
- private MultiAction<TInteractor> _whenInteractorAdded = new MultiAction<TInteractor>();
- private MultiAction<TInteractor> _whenInteractorRemoved = new MultiAction<TInteractor>();
- private MultiAction<TInteractor> _whenSelectingInteractorAdded = new MultiAction<TInteractor>();
- private MultiAction<TInteractor> _whenSelectingInteractorRemoved = new MultiAction<TInteractor>();
- public MAction<TInteractor> WhenInteractorAdded => _whenInteractorAdded;
- public MAction<TInteractor> WhenInteractorRemoved => _whenInteractorRemoved;
- public MAction<TInteractor> WhenSelectingInteractorAdded => _whenSelectingInteractorAdded;
- public MAction<TInteractor> WhenSelectingInteractorRemoved => _whenSelectingInteractorRemoved;
-
- public InteractableState State
- {
- get
- {
- return _state;
- }
- private set
- {
- if (_state == value) return;
- InteractableState previousState = _state;
- _state = value;
- WhenStateChanged(new InteractableStateChangeArgs(previousState, _state));
- }
- }
-
- private static InteractableRegistry<TInteractor, TInteractable> _registry =
- new InteractableRegistry<TInteractor, TInteractable>();
-
- public static InteractableRegistry<TInteractor, TInteractable> Registry => _registry;
-
- protected virtual void InteractorAdded(TInteractor interactor)
- {
- WhenInteractorViewAdded(interactor);
- _whenInteractorAdded.Invoke(interactor);
- }
- protected virtual void InteractorRemoved(TInteractor interactor)
- {
- WhenInteractorViewRemoved(interactor);
- _whenInteractorRemoved.Invoke(interactor);
- }
-
- protected virtual void SelectingInteractorAdded(TInteractor interactor)
- {
- WhenSelectingInteractorViewAdded(interactor);
- _whenSelectingInteractorAdded.Invoke(interactor);
- }
- protected virtual void SelectingInteractorRemoved(TInteractor interactor)
- {
- WhenSelectingInteractorViewRemoved(interactor);
- _whenSelectingInteractorRemoved.Invoke(interactor);
- }
-
- public ICollection<TInteractor> Interactors => _interactors;
-
- public ICollection<TInteractor> SelectingInteractors => _selectingInteractors;
-
- public void AddInteractor(TInteractor interactor)
- {
- _interactors.Add(interactor);
- InteractorAdded(interactor);
- UpdateInteractableState();
- }
-
- public void RemoveInteractor(TInteractor interactor)
- {
- if (!_interactors.Remove(interactor))
- {
- return;
- }
- interactor.InteractableChangesUpdate();
- InteractorRemoved(interactor);
- UpdateInteractableState();
- }
-
- public void AddSelectingInteractor(TInteractor interactor)
- {
- _selectingInteractors.Add(interactor);
- SelectingInteractorAdded(interactor);
- UpdateInteractableState();
- }
-
- public void RemoveSelectingInteractor(TInteractor interactor)
- {
- if (!_selectingInteractors.Remove(interactor))
- {
- return;
- }
- interactor.InteractableChangesUpdate();
- SelectingInteractorRemoved(interactor);
- UpdateInteractableState();
- }
-
- private void UpdateInteractableState()
- {
-
- if (_selectingInteractors.Count > 0)
- {
- State = InteractableState.Select;
- }
- else if (_interactors.Count > 0)
- {
- State = InteractableState.Hover;
- }
- else
- {
- State = InteractableState.Normal;
- }
- }
-
- public bool CanBeSelectedBy(TInteractor interactor)
- {
-
- if (MaxSelectingInteractors >= 0 &&
- _selectingInteractors.Count == MaxSelectingInteractors)
- {
- return false;
- }
-
- if (MaxInteractors >= 0 &&
- _interactors.Count == MaxInteractors &&
- !_interactors.Contains(interactor))
- {
- return false;
- }
-
- if (InteractorFilters == null)
- {
- return true;
- }
-
- foreach (IGameObjectFilter interactorFilter in InteractorFilters)
- {
- if (!interactorFilter.Filter(interactor.gameObject))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public bool HasInteractor(TInteractor interactor)
- {
- return _interactors.Contains(interactor);
- }
-
- public bool HasSelectingInteractor(TInteractor interactor)
- {
- return _selectingInteractors.Contains(interactor);
- }
-
- public void Enable()
- {
- // RKLog.Info($"====Interaction==== {this.gameObject.name}, register interactable");
- _registry.Register((TInteractable)this);
- State = InteractableState.Normal;
- }
-
- public void Disable()
- {
- List<TInteractor> selectingInteractorsCopy = new List<TInteractor>(_selectingInteractors);
- foreach (TInteractor selectingInteractor in selectingInteractorsCopy)
- {
- RemoveSelectingInteractor(selectingInteractor);
- }
-
- List<TInteractor> interactorsCopy = new List<TInteractor>(_interactors);
- foreach (TInteractor interactor in interactorsCopy)
- {
- RemoveInteractor(interactor);
- }
-
- RKLog.Info($"====Interaction==== {this.gameObject.name}, unregister interactable");
- _registry.Unregister((TInteractable)this);
- }
-
- public void RemoveInteractorByIdentifier(int id)
- {
- TInteractor foundInteractor = null;
- foreach (TInteractor selectingInteractor in _selectingInteractors)
- {
- if (selectingInteractor.Identifier == id)
- {
- foundInteractor = selectingInteractor;
- break;
- }
- }
-
- if (foundInteractor != null)
- {
- RemoveSelectingInteractor(foundInteractor);
- }
-
- foundInteractor = null;
-
- foreach (TInteractor interactor in _interactors)
- {
- if (interactor.Identifier == id)
- {
- foundInteractor = interactor;
- break;
- }
- }
-
- if (foundInteractor == null)
- {
- return;
- }
-
- RemoveInteractor(foundInteractor);
- }
-
- protected virtual void Awake()
- {
- InteractorFilters = _interactorFilters.ConvertAll(mono => mono as IGameObjectFilter);
- }
-
- protected virtual void Start()
- {
- foreach (IGameObjectFilter filter in InteractorFilters)
- {
- Assert.IsNotNull(filter);
- }
-
- if (Data == null)
- {
- _data = this;
- Data = _data;
- }
- }
-
- protected virtual void OnEnable()
- {
- Enable();
- }
-
- protected virtual void OnDisable()
- {
- Disable();
- }
-
- protected virtual void SetRegistry(InteractableRegistry<TInteractor, TInteractable> registry)
- {
- if (registry == _registry) return;
-
- var interactables = _registry.List();
- foreach (TInteractable interactable in interactables)
- {
- registry.Register(interactable);
- _registry.Unregister(interactable);
- }
- _registry = registry;
- }
-
- }
-
- }
|