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.

361 lines
10 KiB

  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. //
  3. // Purpose: Handles the spawning and returning of the ItemPackage
  4. //
  5. //=============================================================================
  6. using UnityEngine;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using System.Collections.ObjectModel;
  10. using UnityEngine.Events;
  11. #if UNITY_EDITOR
  12. using UnityEditor;
  13. #endif
  14. namespace Valve.VR.InteractionSystem
  15. {
  16. //-------------------------------------------------------------------------
  17. [RequireComponent( typeof( Interactable ) )]
  18. public class ItemPackageSpawner : MonoBehaviour
  19. {
  20. public ItemPackage itemPackage
  21. {
  22. get
  23. {
  24. return _itemPackage;
  25. }
  26. set
  27. {
  28. CreatePreviewObject();
  29. }
  30. }
  31. public ItemPackage _itemPackage;
  32. private bool useItemPackagePreview = true;
  33. private bool useFadedPreview = false;
  34. private GameObject previewObject;
  35. public bool requireTriggerPressToTake = false;
  36. public bool requireTriggerPressToReturn = false;
  37. public bool showTriggerHint = false;
  38. [EnumFlags]
  39. public Hand.AttachmentFlags attachmentFlags = Hand.defaultAttachmentFlags;
  40. public string attachmentPoint;
  41. public bool takeBackItem = false; // if a hand enters this trigger and has the item this spawner dispenses at the top of the stack, remove it from the stack
  42. public bool acceptDifferentItems = false;
  43. private GameObject spawnedItem;
  44. private bool itemIsSpawned = false;
  45. public UnityEvent pickupEvent;
  46. public UnityEvent dropEvent;
  47. public bool justPickedUpItem = false;
  48. //-------------------------------------------------
  49. private void CreatePreviewObject()
  50. {
  51. if ( !useItemPackagePreview )
  52. {
  53. return;
  54. }
  55. ClearPreview();
  56. if ( useItemPackagePreview )
  57. {
  58. if ( itemPackage == null )
  59. {
  60. return;
  61. }
  62. if ( useFadedPreview == false ) // if we don't have a spawned item out there, use the regular preview
  63. {
  64. if ( itemPackage.previewPrefab != null )
  65. {
  66. previewObject = Instantiate( itemPackage.previewPrefab, transform.position, Quaternion.identity ) as GameObject;
  67. previewObject.transform.parent = transform;
  68. previewObject.transform.localRotation = Quaternion.identity;
  69. }
  70. }
  71. else // there's a spawned item out there. Use the faded preview
  72. {
  73. if ( itemPackage.fadedPreviewPrefab != null )
  74. {
  75. previewObject = Instantiate( itemPackage.fadedPreviewPrefab, transform.position, Quaternion.identity ) as GameObject;
  76. previewObject.transform.parent = transform;
  77. previewObject.transform.localRotation = Quaternion.identity;
  78. }
  79. }
  80. }
  81. }
  82. //-------------------------------------------------
  83. void Start()
  84. {
  85. VerifyItemPackage();
  86. }
  87. //-------------------------------------------------
  88. private void VerifyItemPackage()
  89. {
  90. if ( itemPackage == null )
  91. {
  92. ItemPackageNotValid();
  93. }
  94. if ( itemPackage.itemPrefab == null )
  95. {
  96. ItemPackageNotValid();
  97. }
  98. }
  99. //-------------------------------------------------
  100. private void ItemPackageNotValid()
  101. {
  102. Debug.LogError( "ItemPackage assigned to " + gameObject.name + " is not valid. Destroying this game object." );
  103. Destroy( gameObject );
  104. }
  105. //-------------------------------------------------
  106. private void ClearPreview()
  107. {
  108. foreach ( Transform child in transform )
  109. {
  110. if ( Time.time > 0 )
  111. {
  112. GameObject.Destroy( child.gameObject );
  113. }
  114. else
  115. {
  116. GameObject.DestroyImmediate( child.gameObject );
  117. }
  118. }
  119. }
  120. //-------------------------------------------------
  121. void Update()
  122. {
  123. if ( ( itemIsSpawned == true ) && ( spawnedItem == null ) )
  124. {
  125. itemIsSpawned = false;
  126. useFadedPreview = false;
  127. dropEvent.Invoke();
  128. CreatePreviewObject();
  129. }
  130. }
  131. //-------------------------------------------------
  132. private void OnHandHoverBegin( Hand hand )
  133. {
  134. ItemPackage currentAttachedItemPackage = GetAttachedItemPackage( hand );
  135. if ( currentAttachedItemPackage == itemPackage ) // the item at the top of the hand's stack has an associated ItemPackage
  136. {
  137. if ( takeBackItem && !requireTriggerPressToReturn ) // if we want to take back matching items and aren't waiting for a trigger press
  138. {
  139. TakeBackItem( hand );
  140. }
  141. }
  142. if ( !requireTriggerPressToTake ) // we don't require trigger press for pickup. Spawn and attach object.
  143. {
  144. SpawnAndAttachObject( hand );
  145. }
  146. if ( requireTriggerPressToTake && showTriggerHint )
  147. {
  148. ControllerButtonHints.ShowTextHint( hand, Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger, "PickUp" );
  149. }
  150. }
  151. //-------------------------------------------------
  152. private void TakeBackItem( Hand hand )
  153. {
  154. RemoveMatchingItemsFromHandStack( itemPackage, hand );
  155. if ( itemPackage.packageType == ItemPackage.ItemPackageType.TwoHanded )
  156. {
  157. RemoveMatchingItemsFromHandStack( itemPackage, hand.otherHand );
  158. }
  159. }
  160. //-------------------------------------------------
  161. private ItemPackage GetAttachedItemPackage( Hand hand )
  162. {
  163. GameObject currentAttachedObject = hand.currentAttachedObject;
  164. if ( currentAttachedObject == null ) // verify the hand is holding something
  165. {
  166. return null;
  167. }
  168. ItemPackageReference packageReference = hand.currentAttachedObject.GetComponent<ItemPackageReference>();
  169. if ( packageReference == null ) // verify the item in the hand is matchable
  170. {
  171. return null;
  172. }
  173. ItemPackage attachedItemPackage = packageReference.itemPackage; // return the ItemPackage reference we find.
  174. return attachedItemPackage;
  175. }
  176. //-------------------------------------------------
  177. private void HandHoverUpdate( Hand hand )
  178. {
  179. if ( takeBackItem && requireTriggerPressToReturn )
  180. {
  181. if ( hand.controller != null && hand.controller.GetHairTriggerDown() )
  182. {
  183. ItemPackage currentAttachedItemPackage = GetAttachedItemPackage( hand );
  184. if ( currentAttachedItemPackage == itemPackage )
  185. {
  186. TakeBackItem( hand );
  187. return; // So that we don't pick up an ItemPackage the same frame that we return it
  188. }
  189. }
  190. }
  191. if ( requireTriggerPressToTake )
  192. {
  193. if ( hand.controller != null && hand.controller.GetHairTriggerDown() )
  194. {
  195. SpawnAndAttachObject( hand );
  196. }
  197. }
  198. }
  199. //-------------------------------------------------
  200. private void OnHandHoverEnd( Hand hand )
  201. {
  202. if ( !justPickedUpItem && requireTriggerPressToTake && showTriggerHint )
  203. {
  204. ControllerButtonHints.HideTextHint( hand, Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger );
  205. }
  206. justPickedUpItem = false;
  207. }
  208. //-------------------------------------------------
  209. private void RemoveMatchingItemsFromHandStack( ItemPackage package, Hand hand )
  210. {
  211. for ( int i = 0; i < hand.AttachedObjects.Count; i++ )
  212. {
  213. ItemPackageReference packageReference = hand.AttachedObjects[i].attachedObject.GetComponent<ItemPackageReference>();
  214. if ( packageReference != null )
  215. {
  216. ItemPackage attachedObjectItemPackage = packageReference.itemPackage;
  217. if ( ( attachedObjectItemPackage != null ) && ( attachedObjectItemPackage == package ) )
  218. {
  219. GameObject detachedItem = hand.AttachedObjects[i].attachedObject;
  220. hand.DetachObject( detachedItem );
  221. }
  222. }
  223. }
  224. }
  225. //-------------------------------------------------
  226. private void RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType packageType, Hand hand )
  227. {
  228. for ( int i = 0; i < hand.AttachedObjects.Count; i++ )
  229. {
  230. ItemPackageReference packageReference = hand.AttachedObjects[i].attachedObject.GetComponent<ItemPackageReference>();
  231. if ( packageReference != null )
  232. {
  233. if ( packageReference.itemPackage.packageType == packageType )
  234. {
  235. GameObject detachedItem = hand.AttachedObjects[i].attachedObject;
  236. hand.DetachObject( detachedItem );
  237. }
  238. }
  239. }
  240. }
  241. //-------------------------------------------------
  242. private void SpawnAndAttachObject( Hand hand )
  243. {
  244. if ( hand.otherHand != null )
  245. {
  246. //If the other hand has this item package, take it back from the other hand
  247. ItemPackage otherHandItemPackage = GetAttachedItemPackage( hand.otherHand );
  248. if ( otherHandItemPackage == itemPackage )
  249. {
  250. TakeBackItem( hand.otherHand );
  251. }
  252. }
  253. if ( showTriggerHint )
  254. {
  255. ControllerButtonHints.HideTextHint( hand, Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger );
  256. }
  257. if ( itemPackage.otherHandItemPrefab != null )
  258. {
  259. if ( hand.otherHand.hoverLocked )
  260. {
  261. //Debug.Log( "Not attaching objects because other hand is hoverlocked and we can't deliver both items." );
  262. return;
  263. }
  264. }
  265. // if we're trying to spawn a one-handed item, remove one and two-handed items from this hand and two-handed items from both hands
  266. if ( itemPackage.packageType == ItemPackage.ItemPackageType.OneHanded )
  267. {
  268. RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.OneHanded, hand );
  269. RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.TwoHanded, hand );
  270. RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.TwoHanded, hand.otherHand );
  271. }
  272. // if we're trying to spawn a two-handed item, remove one and two-handed items from both hands
  273. if ( itemPackage.packageType == ItemPackage.ItemPackageType.TwoHanded )
  274. {
  275. RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.OneHanded, hand );
  276. RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.OneHanded, hand.otherHand );
  277. RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.TwoHanded, hand );
  278. RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.TwoHanded, hand.otherHand );
  279. }
  280. spawnedItem = GameObject.Instantiate( itemPackage.itemPrefab );
  281. spawnedItem.SetActive( true );
  282. hand.AttachObject( spawnedItem, attachmentFlags, attachmentPoint );
  283. if ( ( itemPackage.otherHandItemPrefab != null ) && ( hand.otherHand.controller != null ) )
  284. {
  285. GameObject otherHandObjectToAttach = GameObject.Instantiate( itemPackage.otherHandItemPrefab );
  286. otherHandObjectToAttach.SetActive( true );
  287. hand.otherHand.AttachObject( otherHandObjectToAttach, attachmentFlags );
  288. }
  289. itemIsSpawned = true;
  290. justPickedUpItem = true;
  291. if ( takeBackItem )
  292. {
  293. useFadedPreview = true;
  294. pickupEvent.Invoke();
  295. CreatePreviewObject();
  296. }
  297. }
  298. }
  299. }