ItemPackageSpawner.cs 10 KB

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