Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

524 lines
30 KiB

  1. // Interact Object Appearance|Interactables|35030
  2. namespace VRTK
  3. {
  4. using UnityEngine;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. /// <summary>
  8. /// Event Payload
  9. /// </summary>
  10. /// <param name="affectingObject">The GameObject that is being affected.</param>
  11. /// <param name="monitoringObject">The Interactable Object that is being monitored.</param>
  12. /// <param name="interactionType">The type of interaction initiating the event.</param>
  13. public struct InteractObjectAppearanceEventArgs
  14. {
  15. public GameObject affectingObject;
  16. public GameObject objectToIgnore;
  17. public VRTK_InteractableObject monitoringObject;
  18. public VRTK_InteractableObject.InteractionType interactionType;
  19. }
  20. /// <summary>
  21. /// Event Payload
  22. /// </summary>
  23. /// <param name="sender">this object</param>
  24. /// <param name="e"><see cref="InteractObjectAppearanceEventArgs"/></param>
  25. public delegate void InteractObjectAppearanceEventHandler(object sender, InteractObjectAppearanceEventArgs e);
  26. /// <summary>
  27. /// Determine whether the `Object To Affect` should be visible or hidden by default or on interaction (near touch, touch, grab, use).
  28. /// </summary>
  29. /// <remarks>
  30. /// **Required Components:**
  31. /// * `VRTK_InteractableObject` - The Interactable Object component to detect interactions on. This must be applied on the same GameObject as this script if one is not provided via the `Object To Monitor` parameter.
  32. ///
  33. /// **Script Usage:**
  34. /// * Place the `VRTK_InteractObjectAppearance` script on either:
  35. /// * The GameObject of the Interactable Object to detect interactions on.
  36. /// * Any other scene GameObject and provide a valid `VRTK_InteractableObject` component to the `Object To Monitor` parameter of this script.
  37. /// * Optionally provide a GameObject to the `Object To Affect` parameter to determine which GameObject to affect the appearance of.
  38. /// </remarks>
  39. /// <example>
  40. /// `VRTK/Examples/008_Controller_UsingAGrabbedObject` shows that the controller can be hidden when touching, grabbing and using an object.
  41. /// </example>
  42. [AddComponentMenu("VRTK/Scripts/Interactions/Interactables/VRTK_InteractObjectAppearance")]
  43. public class VRTK_InteractObjectAppearance : VRTK_InteractableListener
  44. {
  45. /// <summary>
  46. /// The valid interacting object.
  47. /// </summary>
  48. public enum ValidInteractingObject
  49. {
  50. /// <summary>
  51. /// Any GameObject is considered a valid interacting object.
  52. /// </summary>
  53. Anything,
  54. /// <summary>
  55. /// Only a game controller is considered a valid interacting objcet.
  56. /// </summary>
  57. EitherController,
  58. /// <summary>
  59. /// Any GameObject except a game controller is considered a valid interacting object.
  60. /// </summary>
  61. NeitherController,
  62. /// <summary>
  63. /// Only the left game controller is considered a valid interacting objcet.
  64. /// </summary>
  65. LeftControllerOnly,
  66. /// <summary>
  67. /// Only the right game controller is considered a valid interacting objcet.
  68. /// </summary>
  69. RightControllerOnly
  70. }
  71. [Header("General Settings")]
  72. [Tooltip("The GameObject to affect the appearance of. If this is null then then the interacting object will be used (usually the controller).")]
  73. public GameObject objectToAffect;
  74. [SerializeField]
  75. [Tooltip("The Interactable Object to monitor for the interaction event (near touch/touch/grab/use).")]
  76. protected VRTK_InteractableObject objectToMonitor;
  77. [Header("Default Appearance Settings")]
  78. [Tooltip("If this is checked then the `Object To Affect` will be an active GameObject when the script is enabled. If it's unchecked then it will be disabled. This only takes effect if `Affect Interacting Object` is unticked.")]
  79. public bool gameObjectActiveByDefault = true;
  80. [Tooltip("If this is checked then the `Object To Affect` will have visible renderers when the script is enabled. If it's unchecked then it will have it's renderers disabled. This only takes effect if `Affect Interacting Object` is unticked.")]
  81. public bool rendererVisibleByDefault = true;
  82. [Header("Near Touch Appearance Settings")]
  83. [Tooltip("If this is checked then the `Object To Affect` will be an active GameObject when the `Object To Monitor` is near touched. If it's unchecked then it will be disabled on near touch.")]
  84. public bool gameObjectActiveOnNearTouch = true;
  85. [Tooltip("If this is checked then the `Object To Affect` will have visible renderers when the `Object To Monitor` is near touched. If it's unchecked then it will have it's renderers disabled on near touch.")]
  86. public bool rendererVisibleOnNearTouch = true;
  87. [Tooltip("The amount of time to wait before the near touch appearance settings are applied after the near touch event.")]
  88. public float nearTouchAppearanceDelay = 0f;
  89. [Tooltip("The amount of time to wait before the previous appearance settings are applied after the near untouch event.")]
  90. public float nearUntouchAppearanceDelay = 0f;
  91. [Tooltip("Determines what type of interacting object will affect the appearance of the `Object To Affect` after the near touch and near untouch event.")]
  92. public ValidInteractingObject validNearTouchInteractingObject = ValidInteractingObject.Anything;
  93. [Header("Touch Appearance Settings")]
  94. [Tooltip("If this is checked then the `Object To Affect` will be an active GameObject when the `Object To Monitor` is touched. If it's unchecked then it will be disabled on touch.")]
  95. public bool gameObjectActiveOnTouch = true;
  96. [Tooltip("If this is checked then the `Object To Affect` will have visible renderers when the `Object To Monitor` is touched. If it's unchecked then it will have it's renderers disabled on touch.")]
  97. public bool rendererVisibleOnTouch = true;
  98. [Tooltip("The amount of time to wait before the touch appearance settings are applied after the touch event.")]
  99. public float touchAppearanceDelay = 0f;
  100. [Tooltip("The amount of time to wait before the previous appearance settings are applied after the untouch event.")]
  101. public float untouchAppearanceDelay = 0f;
  102. [Tooltip("Determines what type of interacting object will affect the appearance of the `Object To Affect` after the touch/untouch event.")]
  103. public ValidInteractingObject validTouchInteractingObject = ValidInteractingObject.Anything;
  104. [Header("Grab Appearance Settings")]
  105. [Tooltip("If this is checked then the `Object To Affect` will be an active GameObject when the `Object To Monitor` is grabbed. If it's unchecked then it will be disabled on grab.")]
  106. public bool gameObjectActiveOnGrab = true;
  107. [Tooltip("If this is checked then the `Object To Affect` will have visible renderers when the `Object To Monitor` is grabbed. If it's unchecked then it will have it's renderers disabled on grab.")]
  108. public bool rendererVisibleOnGrab = true;
  109. [Tooltip("The amount of time to wait before the grab appearance settings are applied after the grab event.")]
  110. public float grabAppearanceDelay = 0f;
  111. [Tooltip("The amount of time to wait before the previous appearance settings are applied after the ungrab event.")]
  112. public float ungrabAppearanceDelay = 0f;
  113. [Tooltip("Determines what type of interacting object will affect the appearance of the `Object To Affect` after the grab/ungrab event.")]
  114. public ValidInteractingObject validGrabInteractingObject = ValidInteractingObject.Anything;
  115. [Header("Use Appearance Settings")]
  116. [Tooltip("If this is checked then the `Object To Affect` will be an active GameObject when the `Object To Monitor` is used. If it's unchecked then it will be disabled on use.")]
  117. public bool gameObjectActiveOnUse = true;
  118. [Tooltip("If this is checked then the `Object To Affect` will have visible renderers when the `Object To Monitor` is used. If it's unchecked then it will have it's renderers disabled on use.")]
  119. public bool rendererVisibleOnUse = true;
  120. [Tooltip("The amount of time to wait before the use appearance settings are applied after the use event.")]
  121. public float useAppearanceDelay = 0f;
  122. [Tooltip("The amount of time to wait before the previous appearance settings are applied after the unuse event.")]
  123. public float unuseAppearanceDelay = 0f;
  124. [Tooltip("Determines what type of interacting object will affect the appearance of the `Object To Affect` after the use/unuse event.")]
  125. public ValidInteractingObject validUseInteractingObject = ValidInteractingObject.Anything;
  126. /// <summary>
  127. /// Emitted when the GameObject on the `Object To Affect` is enabled.
  128. /// </summary>
  129. public event InteractObjectAppearanceEventHandler GameObjectEnabled;
  130. /// <summary>
  131. /// Emitted when the GameObject on the `Object To Affect` is disabled.
  132. /// </summary>
  133. public event InteractObjectAppearanceEventHandler GameObjectDisabled;
  134. /// <summary>
  135. /// Emitted when the Renderers on the `Object To Affect` are enabled.
  136. /// </summary>
  137. public event InteractObjectAppearanceEventHandler RenderersEnabled;
  138. /// <summary>
  139. /// Emitted when the Renderers on the `Object To Affect` are disabled.
  140. /// </summary>
  141. public event InteractObjectAppearanceEventHandler RenderersDisabled;
  142. protected Dictionary<GameObject, bool> currentRenderStates = new Dictionary<GameObject, bool>();
  143. protected Dictionary<GameObject, bool> currentGameObjectStates = new Dictionary<GameObject, bool>();
  144. protected Dictionary<GameObject, Coroutine> affectingRoutines = new Dictionary<GameObject, Coroutine>();
  145. protected HashSet<GameObject> nearTouchingObjects = new HashSet<GameObject>();
  146. protected HashSet<GameObject> touchingObjects = new HashSet<GameObject>();
  147. public virtual void OnGameObjectEnabled(InteractObjectAppearanceEventArgs e)
  148. {
  149. if (GameObjectEnabled != null)
  150. {
  151. GameObjectEnabled(this, e);
  152. }
  153. }
  154. public virtual void OnGameObjectDisabled(InteractObjectAppearanceEventArgs e)
  155. {
  156. if (GameObjectDisabled != null)
  157. {
  158. GameObjectDisabled(this, e);
  159. }
  160. }
  161. public virtual void OnRenderersEnabled(InteractObjectAppearanceEventArgs e)
  162. {
  163. if (RenderersEnabled != null)
  164. {
  165. RenderersEnabled(this, e);
  166. }
  167. }
  168. public virtual void OnRenderersDisabled(InteractObjectAppearanceEventArgs e)
  169. {
  170. if (RenderersDisabled != null)
  171. {
  172. RenderersDisabled(this, e);
  173. }
  174. }
  175. protected virtual void OnEnable()
  176. {
  177. currentRenderStates.Clear();
  178. currentGameObjectStates.Clear();
  179. affectingRoutines.Clear();
  180. nearTouchingObjects.Clear();
  181. touchingObjects.Clear();
  182. EnableListeners();
  183. if (objectToAffect != null)
  184. {
  185. ToggleState(objectToAffect, gameObjectActiveByDefault, rendererVisibleByDefault, VRTK_InteractableObject.InteractionType.None);
  186. }
  187. }
  188. protected virtual void OnDisable()
  189. {
  190. DisableListeners();
  191. CancelRoutines();
  192. }
  193. protected override bool SetupListeners(bool throwError)
  194. {
  195. objectToMonitor = (objectToMonitor == null ? GetComponentInParent<VRTK_InteractableObject>() : objectToMonitor);
  196. if (objectToMonitor != null)
  197. {
  198. objectToMonitor.InteractableObjectDisabled += InteractableObjectDisabled;
  199. objectToMonitor.SubscribeToInteractionEvent(VRTK_InteractableObject.InteractionType.NearTouch, InteractableObjectNearTouched);
  200. objectToMonitor.SubscribeToInteractionEvent(VRTK_InteractableObject.InteractionType.NearUntouch, InteractableObjectNearUntouched);
  201. objectToMonitor.SubscribeToInteractionEvent(VRTK_InteractableObject.InteractionType.Touch, InteractableObjectTouched);
  202. objectToMonitor.SubscribeToInteractionEvent(VRTK_InteractableObject.InteractionType.Untouch, InteractableObjectUntouched);
  203. objectToMonitor.SubscribeToInteractionEvent(VRTK_InteractableObject.InteractionType.Grab, InteractableObjectGrabbed);
  204. objectToMonitor.SubscribeToInteractionEvent(VRTK_InteractableObject.InteractionType.Ungrab, InteractableObjectUngrabbed);
  205. objectToMonitor.SubscribeToInteractionEvent(VRTK_InteractableObject.InteractionType.Use, InteractableObjectUsed);
  206. objectToMonitor.SubscribeToInteractionEvent(VRTK_InteractableObject.InteractionType.Unuse, InteractableObjectUnused);
  207. return true;
  208. }
  209. else if (throwError)
  210. {
  211. VRTK_Logger.Error(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.REQUIRED_COMPONENT_MISSING_NOT_INJECTED, "VRTK_InteractObjectAppearance", "VRTK_InteractableObject", "objectToMonitor", "current or parent"));
  212. }
  213. return false;
  214. }
  215. protected override void TearDownListeners()
  216. {
  217. if (objectToMonitor != null)
  218. {
  219. RestoreDefaults();
  220. objectToMonitor.InteractableObjectDisabled -= InteractableObjectDisabled;
  221. objectToMonitor.UnsubscribeFromInteractionEvent(VRTK_InteractableObject.InteractionType.Touch, InteractableObjectTouched);
  222. objectToMonitor.UnsubscribeFromInteractionEvent(VRTK_InteractableObject.InteractionType.Untouch, InteractableObjectUntouched);
  223. objectToMonitor.UnsubscribeFromInteractionEvent(VRTK_InteractableObject.InteractionType.Grab, InteractableObjectGrabbed);
  224. objectToMonitor.UnsubscribeFromInteractionEvent(VRTK_InteractableObject.InteractionType.Ungrab, InteractableObjectUngrabbed);
  225. objectToMonitor.UnsubscribeFromInteractionEvent(VRTK_InteractableObject.InteractionType.Use, InteractableObjectUsed);
  226. objectToMonitor.UnsubscribeFromInteractionEvent(VRTK_InteractableObject.InteractionType.Unuse, InteractableObjectUnused);
  227. }
  228. }
  229. protected virtual InteractObjectAppearanceEventArgs SetPayload(GameObject affectingObject, VRTK_InteractableObject.InteractionType interactionType)
  230. {
  231. InteractObjectAppearanceEventArgs e;
  232. e.affectingObject = affectingObject;
  233. e.monitoringObject = objectToMonitor;
  234. e.objectToIgnore = ObjectToIgnore();
  235. e.interactionType = interactionType;
  236. return e;
  237. }
  238. protected virtual void RestoreDefaults()
  239. {
  240. if (objectToMonitor != null && objectToMonitor.IsTouched())
  241. {
  242. foreach (GameObject touchingObject in new HashSet<GameObject>(touchingObjects))
  243. {
  244. ToggleState(touchingObject, gameObjectActiveByDefault, rendererVisibleByDefault, VRTK_InteractableObject.InteractionType.None);
  245. }
  246. foreach (GameObject nearTouchingObject in new HashSet<GameObject>(nearTouchingObjects))
  247. {
  248. ToggleState(nearTouchingObject, gameObjectActiveByDefault, rendererVisibleByDefault, VRTK_InteractableObject.InteractionType.None);
  249. }
  250. }
  251. }
  252. protected virtual GameObject ObjectToIgnore()
  253. {
  254. return (objectToAffect == null ? objectToMonitor.gameObject : null);
  255. }
  256. protected virtual void EmitRenderEvent(GameObject objectToToggle, bool rendererShow, VRTK_InteractableObject.InteractionType interactionType)
  257. {
  258. if (rendererShow)
  259. {
  260. OnRenderersEnabled(SetPayload(objectToToggle, interactionType));
  261. }
  262. else
  263. {
  264. OnRenderersDisabled(SetPayload(objectToToggle, interactionType));
  265. }
  266. }
  267. protected virtual void EmitGameObjectEvent(GameObject objectToToggle, bool gameObjectShow, VRTK_InteractableObject.InteractionType interactionType)
  268. {
  269. if (gameObjectShow)
  270. {
  271. OnGameObjectEnabled(SetPayload(objectToToggle, interactionType));
  272. }
  273. else
  274. {
  275. OnGameObjectDisabled(SetPayload(objectToToggle, interactionType));
  276. }
  277. }
  278. protected virtual void ToggleState(GameObject objectToToggle, bool gameObjectShow, bool rendererShow, VRTK_InteractableObject.InteractionType interactionType)
  279. {
  280. if (objectToToggle != null)
  281. {
  282. if (!currentRenderStates.ContainsKey(objectToToggle) || currentRenderStates[objectToToggle] != rendererShow)
  283. {
  284. VRTK_ObjectAppearance.ToggleRenderer(rendererShow, objectToToggle, ObjectToIgnore());
  285. EmitRenderEvent(objectToToggle, rendererShow, interactionType);
  286. }
  287. if (!currentGameObjectStates.ContainsKey(objectToToggle) || currentGameObjectStates[objectToToggle] != gameObjectShow)
  288. {
  289. objectToToggle.SetActive(gameObjectShow);
  290. EmitGameObjectEvent(objectToToggle, gameObjectShow, interactionType);
  291. }
  292. VRTK_SharedMethods.AddDictionaryValue(currentRenderStates, objectToToggle, rendererShow, true);
  293. VRTK_SharedMethods.AddDictionaryValue(currentGameObjectStates, objectToToggle, gameObjectShow, true);
  294. }
  295. }
  296. protected virtual IEnumerator ToggleStateAfterTime(GameObject objectToToggle, bool gameObjectShow, bool rendererShow, float delayTime, VRTK_InteractableObject.InteractionType interactionType)
  297. {
  298. yield return new WaitForSeconds(delayTime);
  299. ToggleState(objectToToggle, gameObjectShow, rendererShow, interactionType);
  300. }
  301. protected virtual void CancelRoutines(GameObject currentAffectingObject = null)
  302. {
  303. if (currentAffectingObject != null)
  304. {
  305. Coroutine currentAffectingRoutine = VRTK_SharedMethods.GetDictionaryValue(affectingRoutines, currentAffectingObject);
  306. if (currentAffectingRoutine != null)
  307. {
  308. StopCoroutine(currentAffectingRoutine);
  309. }
  310. }
  311. else
  312. {
  313. foreach (KeyValuePair<GameObject, Coroutine> affectingRouting in affectingRoutines)
  314. {
  315. if (currentAffectingObject == affectingRouting.Key && affectingRouting.Value != null)
  316. {
  317. StopCoroutine(affectingRouting.Value);
  318. }
  319. }
  320. }
  321. }
  322. protected virtual GameObject GetActualController(GameObject givenObject)
  323. {
  324. VRTK_ControllerReference controllerReference = VRTK_ControllerReference.GetControllerReference(givenObject);
  325. if (VRTK_ControllerReference.IsValid(controllerReference))
  326. {
  327. return controllerReference.actual;
  328. }
  329. else
  330. {
  331. return givenObject;
  332. }
  333. }
  334. protected virtual void InteractableObjectDisabled(object sender, InteractableObjectEventArgs e)
  335. {
  336. if (objectToMonitor != null && !objectToMonitor.gameObject.activeInHierarchy)
  337. {
  338. RestoreDefaults();
  339. }
  340. }
  341. protected virtual bool IsValidInteractingObject(GameObject givenObject, ValidInteractingObject givenInteractingObjectValidType)
  342. {
  343. if (gameObject.activeInHierarchy)
  344. {
  345. VRTK_ControllerReference controllerReference = VRTK_ControllerReference.GetControllerReference(givenObject);
  346. switch (givenInteractingObjectValidType)
  347. {
  348. case ValidInteractingObject.Anything:
  349. return true;
  350. case ValidInteractingObject.EitherController:
  351. return VRTK_ControllerReference.IsValid(controllerReference);
  352. case ValidInteractingObject.NeitherController:
  353. return !VRTK_ControllerReference.IsValid(controllerReference);
  354. case ValidInteractingObject.LeftControllerOnly:
  355. return (VRTK_ControllerReference.IsValid(controllerReference) && controllerReference.hand == SDK_BaseController.ControllerHand.Left);
  356. case ValidInteractingObject.RightControllerOnly:
  357. return (VRTK_ControllerReference.IsValid(controllerReference) && controllerReference.hand == SDK_BaseController.ControllerHand.Right);
  358. }
  359. }
  360. return false;
  361. }
  362. protected virtual void InteractableObjectNearTouched(object sender, InteractableObjectEventArgs e)
  363. {
  364. if (IsValidInteractingObject(e.interactingObject, validNearTouchInteractingObject))
  365. {
  366. GameObject nearTouchAffectedObject = (objectToAffect == null ? GetActualController(e.interactingObject) : objectToAffect);
  367. CancelRoutines(nearTouchAffectedObject);
  368. nearTouchingObjects.Add(nearTouchAffectedObject);
  369. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, nearTouchAffectedObject, StartCoroutine(ToggleStateAfterTime(nearTouchAffectedObject, gameObjectActiveOnNearTouch, rendererVisibleOnNearTouch, nearTouchAppearanceDelay, VRTK_InteractableObject.InteractionType.NearTouch)), true);
  370. }
  371. }
  372. protected virtual void InteractableObjectNearUntouched(object sender, InteractableObjectEventArgs e)
  373. {
  374. if (IsValidInteractingObject(e.interactingObject, validNearTouchInteractingObject))
  375. {
  376. GameObject nearTouchAffectedObject = (objectToAffect == null ? GetActualController(e.interactingObject) : objectToAffect);
  377. CancelRoutines(nearTouchAffectedObject);
  378. nearTouchingObjects.Remove(nearTouchAffectedObject);
  379. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, nearTouchAffectedObject, StartCoroutine(ToggleStateAfterTime(nearTouchAffectedObject, gameObjectActiveByDefault, rendererVisibleByDefault, nearUntouchAppearanceDelay, VRTK_InteractableObject.InteractionType.NearUntouch)), true);
  380. }
  381. }
  382. protected virtual void InteractableObjectTouched(object sender, InteractableObjectEventArgs e)
  383. {
  384. if (IsValidInteractingObject(e.interactingObject, validTouchInteractingObject))
  385. {
  386. GameObject touchAffectedObject = (objectToAffect == null ? GetActualController(e.interactingObject) : objectToAffect);
  387. CancelRoutines(touchAffectedObject);
  388. touchingObjects.Add(touchAffectedObject);
  389. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, touchAffectedObject, StartCoroutine(ToggleStateAfterTime(touchAffectedObject, gameObjectActiveOnTouch, rendererVisibleOnTouch, touchAppearanceDelay, VRTK_InteractableObject.InteractionType.Touch)), true);
  390. }
  391. }
  392. protected virtual void InteractableObjectUntouched(object sender, InteractableObjectEventArgs e)
  393. {
  394. if (IsValidInteractingObject(e.interactingObject, validTouchInteractingObject))
  395. {
  396. GameObject touchAffectedObject = (objectToAffect == null ? GetActualController(e.interactingObject) : objectToAffect);
  397. CancelRoutines(touchAffectedObject);
  398. touchingObjects.Remove(touchAffectedObject);
  399. if (objectToMonitor.IsNearTouched())
  400. {
  401. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, touchAffectedObject, StartCoroutine(ToggleStateAfterTime(touchAffectedObject, gameObjectActiveOnNearTouch, rendererVisibleOnNearTouch, untouchAppearanceDelay, VRTK_InteractableObject.InteractionType.NearTouch)), true);
  402. }
  403. else
  404. {
  405. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, touchAffectedObject, StartCoroutine(ToggleStateAfterTime(touchAffectedObject, gameObjectActiveByDefault, rendererVisibleByDefault, untouchAppearanceDelay, VRTK_InteractableObject.InteractionType.Untouch)), true);
  406. }
  407. }
  408. }
  409. protected virtual void InteractableObjectGrabbed(object sender, InteractableObjectEventArgs e)
  410. {
  411. if (IsValidInteractingObject(e.interactingObject, validGrabInteractingObject))
  412. {
  413. GameObject grabAffectedObject = (objectToAffect == null ? GetActualController(e.interactingObject) : objectToAffect);
  414. CancelRoutines(grabAffectedObject);
  415. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, grabAffectedObject, StartCoroutine(ToggleStateAfterTime(grabAffectedObject, gameObjectActiveOnGrab, rendererVisibleOnGrab, grabAppearanceDelay, VRTK_InteractableObject.InteractionType.Grab)), true);
  416. }
  417. }
  418. protected virtual void InteractableObjectUngrabbed(object sender, InteractableObjectEventArgs e)
  419. {
  420. if (IsValidInteractingObject(e.interactingObject, validGrabInteractingObject))
  421. {
  422. GameObject grabAffectedObject = (objectToAffect == null ? GetActualController(e.interactingObject) : objectToAffect);
  423. CancelRoutines(grabAffectedObject);
  424. if (objectToMonitor.IsUsing())
  425. {
  426. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, grabAffectedObject, StartCoroutine(ToggleStateAfterTime(grabAffectedObject, gameObjectActiveOnUse, rendererVisibleOnUse, ungrabAppearanceDelay, VRTK_InteractableObject.InteractionType.Ungrab)), true);
  427. }
  428. else if (objectToMonitor.IsTouched())
  429. {
  430. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, grabAffectedObject, StartCoroutine(ToggleStateAfterTime(grabAffectedObject, gameObjectActiveOnTouch, rendererVisibleOnTouch, ungrabAppearanceDelay, VRTK_InteractableObject.InteractionType.Ungrab)), true);
  431. }
  432. else if (objectToMonitor.IsNearTouched())
  433. {
  434. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, grabAffectedObject, StartCoroutine(ToggleStateAfterTime(grabAffectedObject, gameObjectActiveOnNearTouch, rendererVisibleOnNearTouch, ungrabAppearanceDelay, VRTK_InteractableObject.InteractionType.NearTouch)), true);
  435. }
  436. else
  437. {
  438. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, grabAffectedObject, StartCoroutine(ToggleStateAfterTime(grabAffectedObject, gameObjectActiveByDefault, rendererVisibleByDefault, ungrabAppearanceDelay, VRTK_InteractableObject.InteractionType.Ungrab)), true);
  439. }
  440. }
  441. }
  442. protected virtual void InteractableObjectUsed(object sender, InteractableObjectEventArgs e)
  443. {
  444. if (IsValidInteractingObject(e.interactingObject, validUseInteractingObject))
  445. {
  446. GameObject useAffectedObject = (objectToAffect == null ? GetActualController(e.interactingObject) : objectToAffect);
  447. CancelRoutines(useAffectedObject);
  448. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, useAffectedObject, StartCoroutine(ToggleStateAfterTime(useAffectedObject, gameObjectActiveOnUse, rendererVisibleOnUse, useAppearanceDelay, VRTK_InteractableObject.InteractionType.Use)), true);
  449. }
  450. }
  451. protected virtual void InteractableObjectUnused(object sender, InteractableObjectEventArgs e)
  452. {
  453. if (IsValidInteractingObject(e.interactingObject, validUseInteractingObject))
  454. {
  455. GameObject useAffectedObject = (objectToAffect == null ? GetActualController(e.interactingObject) : objectToAffect);
  456. CancelRoutines(useAffectedObject);
  457. if (objectToMonitor.IsGrabbed())
  458. {
  459. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, useAffectedObject, StartCoroutine(ToggleStateAfterTime(useAffectedObject, gameObjectActiveOnGrab, rendererVisibleOnGrab, unuseAppearanceDelay, VRTK_InteractableObject.InteractionType.Unuse)), true);
  460. }
  461. else if (objectToMonitor.IsTouched())
  462. {
  463. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, useAffectedObject, StartCoroutine(ToggleStateAfterTime(useAffectedObject, gameObjectActiveOnTouch, rendererVisibleOnTouch, unuseAppearanceDelay, VRTK_InteractableObject.InteractionType.Unuse)), true);
  464. }
  465. else if (objectToMonitor.IsNearTouched())
  466. {
  467. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, useAffectedObject, StartCoroutine(ToggleStateAfterTime(useAffectedObject, gameObjectActiveOnNearTouch, rendererVisibleOnNearTouch, unuseAppearanceDelay, VRTK_InteractableObject.InteractionType.NearTouch)), true);
  468. }
  469. else
  470. {
  471. VRTK_SharedMethods.AddDictionaryValue(affectingRoutines, useAffectedObject, StartCoroutine(ToggleStateAfterTime(useAffectedObject, gameObjectActiveByDefault, rendererVisibleByDefault, unuseAppearanceDelay, VRTK_InteractableObject.InteractionType.Unuse)), true);
  472. }
  473. }
  474. }
  475. }
  476. }