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