InteractorGroup.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. namespace Rokid.UXR.Interaction
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using UnityEngine.Assertions;
  7. /// <summary>
  8. /// InteractorGroup coordinates between a set of Interactors to
  9. /// determine which Interactor(s) should be enabled at a time.
  10. ///
  11. /// By default, Interactors are prioritized in list order (first = highest priority).
  12. /// Interactors can also be prioritized with an optional ICandidateComparer
  13. /// 交互器组合 在一组交互器之间进行协调,以确定一次应启用哪些交互器。
  14. /// 默认情况下,交互器按列表顺序排列优先级(第一个 = 最高优先级)。
  15. /// 还可以使用可选的 ICandidateComparer 对交互器进行优先级排序
  16. /// </summary>
  17. public class InteractorGroup : MonoBehaviour, IInteractor
  18. {
  19. [SerializeField, Interface(typeof(IInteractor))]
  20. private List<MonoBehaviour> _interactors;
  21. protected List<IInteractor> Interactors;
  22. public bool IsRootDriver { get; set; } = true;
  23. private IInteractor _candidateInteractor = null;
  24. private IInteractor _activeInteractor = null;
  25. [SerializeField, Interface(typeof(ICandidateComparer)), Optional]
  26. private MonoBehaviour _interactorComparer;
  27. [SerializeField, Optional]
  28. private UnityEngine.Object _data = null;
  29. public object Data { get; protected set; } = null;
  30. public int MaxIterationsPerFrame = 3;
  31. protected ICandidateComparer CandidateComparer = null;
  32. public event Action<InteractorStateChangeArgs> WhenStateChanged = delegate { };
  33. public event Action WhenPreprocessed = delegate { };
  34. public event Action WhenProcessed = delegate { };
  35. public event Action WhenPostprocessed = delegate { };
  36. protected virtual void Awake()
  37. {
  38. Interactors = _interactors.ConvertAll(mono => mono as IInteractor);
  39. CandidateComparer = _interactorComparer as ICandidateComparer;
  40. }
  41. protected virtual void Start()
  42. {
  43. foreach (IInteractor interactor in Interactors)
  44. {
  45. Assert.IsNotNull(interactor);
  46. }
  47. foreach (IInteractor interactor in Interactors)
  48. {
  49. interactor.IsRootDriver = false;
  50. }
  51. if (_interactorComparer != null)
  52. {
  53. Assert.IsNotNull(CandidateComparer);
  54. }
  55. if (Data == null)
  56. {
  57. _data = this;
  58. Data = _data;
  59. }
  60. }
  61. public void Preprocess()
  62. {
  63. foreach (IInteractor interactor in Interactors)
  64. {
  65. interactor.Preprocess();
  66. }
  67. WhenPreprocessed();
  68. }
  69. public void Process()
  70. {
  71. if (_activeInteractor != null)
  72. {
  73. _activeInteractor.Process();
  74. }
  75. WhenProcessed();
  76. }
  77. public void Postprocess()
  78. {
  79. foreach (IInteractor interactor in Interactors)
  80. {
  81. interactor.Postprocess();
  82. }
  83. if (_activeInteractor != null && _activeInteractor.State == InteractorState.Disabled)
  84. {
  85. _activeInteractor = null;
  86. }
  87. WhenPostprocessed();
  88. }
  89. public void ProcessCandidate()
  90. {
  91. _candidateInteractor = null;
  92. foreach (IInteractor interactor in Interactors)
  93. {
  94. interactor.ProcessCandidate();
  95. if (interactor.HasCandidate)
  96. {
  97. if (_candidateInteractor == null ||
  98. Compare(_candidateInteractor, interactor) > 0)
  99. {
  100. _candidateInteractor = interactor;
  101. }
  102. }
  103. }
  104. if (_candidateInteractor == null && Interactors.Count > 0)
  105. {
  106. _candidateInteractor = Interactors[Interactors.Count - 1];
  107. }
  108. }
  109. public void Enable()
  110. {
  111. if (_activeInteractor == null)
  112. {
  113. return;
  114. }
  115. _activeInteractor.Enable();
  116. }
  117. public void Disable()
  118. {
  119. foreach (IInteractor interactor in Interactors)
  120. {
  121. interactor.Disable();
  122. }
  123. State = InteractorState.Disabled;
  124. }
  125. public void Hover()
  126. {
  127. if (State != InteractorState.Normal)
  128. {
  129. return;
  130. }
  131. _activeInteractor = _candidateInteractor;
  132. _activeInteractor.Hover();
  133. State = InteractorState.Hover;
  134. }
  135. public void Unhover()
  136. {
  137. if (State != InteractorState.Hover)
  138. {
  139. return;
  140. }
  141. if (_activeInteractor != null)
  142. {
  143. _activeInteractor.Unhover();
  144. }
  145. _activeInteractor = null;
  146. State = InteractorState.Normal;
  147. }
  148. public void Select()
  149. {
  150. if (State != InteractorState.Hover)
  151. {
  152. return;
  153. }
  154. _activeInteractor.Select();
  155. State = InteractorState.Select;
  156. }
  157. public void Unselect()
  158. {
  159. if (State != InteractorState.Select)
  160. {
  161. return;
  162. }
  163. if (_activeInteractor != null)
  164. {
  165. _activeInteractor.Unselect();
  166. }
  167. State = InteractorState.Hover;
  168. }
  169. public bool ShouldHover => _activeInteractor != null && _activeInteractor.ShouldHover;
  170. public bool ShouldUnhover => _activeInteractor == null ||
  171. _activeInteractor.ShouldUnhover ||
  172. _activeInteractor != _candidateInteractor;
  173. public bool ShouldSelect => _activeInteractor != null && _activeInteractor.ShouldSelect;
  174. public bool ShouldUnselect => _activeInteractor == null || _activeInteractor.ShouldUnselect;
  175. private void DisableAllInteractorsExcept(IInteractor enabledInteractor)
  176. {
  177. foreach (IInteractor interactor in Interactors)
  178. {
  179. if (interactor == enabledInteractor) continue;
  180. interactor.Disable();
  181. }
  182. }
  183. public int Identifier => _activeInteractor != null
  184. ? _activeInteractor.Identifier
  185. : Interactors[Interactors.Count - 1].Identifier;
  186. public bool HasCandidate => _candidateInteractor != null && _candidateInteractor.HasCandidate;
  187. public object CandidateProperties => HasCandidate ? _candidateInteractor.CandidateProperties : null;
  188. public bool HasInteractable => _activeInteractor != null &&
  189. _activeInteractor.HasInteractable;
  190. public bool HasSelectedInteractable => State == InteractorState.Select &&
  191. _activeInteractor.HasSelectedInteractable;
  192. private InteractorState _state = InteractorState.Normal;
  193. public InteractorState State
  194. {
  195. get
  196. {
  197. return _state;
  198. }
  199. private set
  200. {
  201. if (_state == value)
  202. {
  203. return;
  204. }
  205. InteractorState previousState = _state;
  206. _state = value;
  207. WhenStateChanged(new InteractorStateChangeArgs(
  208. previousState, _state
  209. ));
  210. }
  211. }
  212. public virtual void AddInteractor(IInteractor interactor)
  213. {
  214. Interactors.Add(interactor);
  215. interactor.IsRootDriver = false;
  216. MonoBehaviour interactorMono = interactor as MonoBehaviour;
  217. if (interactorMono != null)
  218. {
  219. _interactors.Add(interactor as MonoBehaviour);
  220. }
  221. }
  222. public virtual void RemoveInteractor(IInteractor interactor)
  223. {
  224. if (!Interactors.Remove(interactor))
  225. {
  226. return;
  227. }
  228. interactor.IsRootDriver = true;
  229. MonoBehaviour interactorMono = interactor as MonoBehaviour;
  230. if (interactorMono != null)
  231. {
  232. _interactors.Remove(interactor as MonoBehaviour);
  233. }
  234. }
  235. private int Compare(IInteractor a, IInteractor b)
  236. {
  237. if (!a.HasCandidate && !b.HasCandidate)
  238. {
  239. return -1;
  240. }
  241. if (a.HasCandidate && b.HasCandidate)
  242. {
  243. if (CandidateComparer == null)
  244. {
  245. return -1;
  246. }
  247. int result = CandidateComparer.Compare(a.CandidateProperties, b.CandidateProperties);
  248. return result > 0 ? 1 : -1;
  249. }
  250. return a.HasCandidate ? -1 : 1;
  251. }
  252. protected virtual void Update()
  253. {
  254. if (!IsRootDriver)
  255. {
  256. return;
  257. }
  258. Drive();
  259. }
  260. public void Drive()
  261. {
  262. Preprocess();
  263. InteractorState previousState = State;
  264. for (int i = 0; i < MaxIterationsPerFrame; i++)
  265. {
  266. if (State == InteractorState.Normal ||
  267. (State == InteractorState.Hover && previousState != InteractorState.Normal))
  268. {
  269. ProcessCandidate();
  270. }
  271. previousState = State;
  272. Process();
  273. if (State == InteractorState.Disabled)
  274. {
  275. break;
  276. }
  277. if (State == InteractorState.Normal)
  278. {
  279. if (_candidateInteractor != null && _activeInteractor != _candidateInteractor)
  280. {
  281. _activeInteractor = _candidateInteractor;
  282. Enable();
  283. DisableAllInteractorsExcept(_activeInteractor);
  284. }
  285. if (ShouldHover)
  286. {
  287. Hover();
  288. continue;
  289. }
  290. break;
  291. }
  292. if (State == InteractorState.Hover)
  293. {
  294. if (ShouldSelect)
  295. {
  296. Select();
  297. continue;
  298. }
  299. if (ShouldUnhover)
  300. {
  301. Unhover();
  302. continue;
  303. }
  304. break;
  305. }
  306. if (State == InteractorState.Select)
  307. {
  308. if (ShouldUnselect)
  309. {
  310. Unselect();
  311. continue;
  312. }
  313. break;
  314. }
  315. }
  316. Postprocess();
  317. }
  318. }
  319. }