366 lines
10 KiB
C#
366 lines
10 KiB
C#
|
//======= Copyright (c) Valve Corporation, All rights reserved. ===============
|
|||
|
//
|
|||
|
// Purpose: Handles the spawning and returning of the ItemPackage
|
|||
|
//
|
|||
|
//=============================================================================
|
|||
|
|
|||
|
using UnityEngine;
|
|||
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Collections.ObjectModel;
|
|||
|
using UnityEngine.Events;
|
|||
|
#if UNITY_EDITOR
|
|||
|
using UnityEditor;
|
|||
|
#endif
|
|||
|
|
|||
|
namespace Valve.VR.InteractionSystem
|
|||
|
{
|
|||
|
//-------------------------------------------------------------------------
|
|||
|
[RequireComponent( typeof( Interactable ) )]
|
|||
|
public class ItemPackageSpawner : MonoBehaviour
|
|||
|
{
|
|||
|
public ItemPackage itemPackage
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return _itemPackage;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
CreatePreviewObject();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public ItemPackage _itemPackage;
|
|||
|
|
|||
|
public bool useItemPackagePreview = true;
|
|||
|
private bool useFadedPreview = false;
|
|||
|
private GameObject previewObject;
|
|||
|
|
|||
|
public bool requireGrabActionToTake = false;
|
|||
|
public bool requireReleaseActionToReturn = false;
|
|||
|
public bool showTriggerHint = false;
|
|||
|
|
|||
|
[EnumFlags]
|
|||
|
public Hand.AttachmentFlags attachmentFlags = Hand.defaultAttachmentFlags;
|
|||
|
|
|||
|
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
|
|||
|
|
|||
|
public bool acceptDifferentItems = false;
|
|||
|
|
|||
|
private GameObject spawnedItem;
|
|||
|
private bool itemIsSpawned = false;
|
|||
|
|
|||
|
public UnityEvent pickupEvent;
|
|||
|
public UnityEvent dropEvent;
|
|||
|
|
|||
|
public bool justPickedUpItem = false;
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void CreatePreviewObject()
|
|||
|
{
|
|||
|
if ( !useItemPackagePreview )
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
ClearPreview();
|
|||
|
|
|||
|
if ( useItemPackagePreview )
|
|||
|
{
|
|||
|
if ( itemPackage == null )
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( useFadedPreview == false ) // if we don't have a spawned item out there, use the regular preview
|
|||
|
{
|
|||
|
if ( itemPackage.previewPrefab != null )
|
|||
|
{
|
|||
|
previewObject = Instantiate( itemPackage.previewPrefab, transform.position, Quaternion.identity ) as GameObject;
|
|||
|
previewObject.transform.parent = transform;
|
|||
|
previewObject.transform.localRotation = Quaternion.identity;
|
|||
|
}
|
|||
|
}
|
|||
|
else // there's a spawned item out there. Use the faded preview
|
|||
|
{
|
|||
|
if ( itemPackage.fadedPreviewPrefab != null )
|
|||
|
{
|
|||
|
previewObject = Instantiate( itemPackage.fadedPreviewPrefab, transform.position, Quaternion.identity ) as GameObject;
|
|||
|
previewObject.transform.parent = transform;
|
|||
|
previewObject.transform.localRotation = Quaternion.identity;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
void Start()
|
|||
|
{
|
|||
|
VerifyItemPackage();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void VerifyItemPackage()
|
|||
|
{
|
|||
|
if ( itemPackage == null )
|
|||
|
{
|
|||
|
ItemPackageNotValid();
|
|||
|
}
|
|||
|
|
|||
|
if ( itemPackage.itemPrefab == null )
|
|||
|
{
|
|||
|
ItemPackageNotValid();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void ItemPackageNotValid()
|
|||
|
{
|
|||
|
Debug.LogError("<b>[SteamVR Interaction]</b> ItemPackage assigned to " + gameObject.name + " is not valid. Destroying this game object.", this);
|
|||
|
Destroy( gameObject );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void ClearPreview()
|
|||
|
{
|
|||
|
foreach ( Transform child in transform )
|
|||
|
{
|
|||
|
if ( Time.time > 0 )
|
|||
|
{
|
|||
|
GameObject.Destroy( child.gameObject );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
GameObject.DestroyImmediate( child.gameObject );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
void Update()
|
|||
|
{
|
|||
|
if ( ( itemIsSpawned == true ) && ( spawnedItem == null ) )
|
|||
|
{
|
|||
|
itemIsSpawned = false;
|
|||
|
useFadedPreview = false;
|
|||
|
dropEvent.Invoke();
|
|||
|
CreatePreviewObject();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void OnHandHoverBegin( Hand hand )
|
|||
|
{
|
|||
|
ItemPackage currentAttachedItemPackage = GetAttachedItemPackage( hand );
|
|||
|
|
|||
|
if ( currentAttachedItemPackage == itemPackage ) // the item at the top of the hand's stack has an associated ItemPackage
|
|||
|
{
|
|||
|
if ( takeBackItem && !requireReleaseActionToReturn ) // if we want to take back matching items and aren't waiting for a trigger press
|
|||
|
{
|
|||
|
TakeBackItem( hand );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!requireGrabActionToTake) // we don't require trigger press for pickup. Spawn and attach object.
|
|||
|
{
|
|||
|
SpawnAndAttachObject( hand, GrabTypes.Scripted );
|
|||
|
}
|
|||
|
|
|||
|
if (requireGrabActionToTake && showTriggerHint )
|
|||
|
{
|
|||
|
hand.ShowGrabHint("PickUp");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void TakeBackItem( Hand hand )
|
|||
|
{
|
|||
|
RemoveMatchingItemsFromHandStack( itemPackage, hand );
|
|||
|
|
|||
|
if ( itemPackage.packageType == ItemPackage.ItemPackageType.TwoHanded )
|
|||
|
{
|
|||
|
RemoveMatchingItemsFromHandStack( itemPackage, hand.otherHand );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private ItemPackage GetAttachedItemPackage( Hand hand )
|
|||
|
{
|
|||
|
GameObject currentAttachedObject = hand.currentAttachedObject;
|
|||
|
|
|||
|
if ( currentAttachedObject == null ) // verify the hand is holding something
|
|||
|
{
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
ItemPackageReference packageReference = hand.currentAttachedObject.GetComponent<ItemPackageReference>();
|
|||
|
if ( packageReference == null ) // verify the item in the hand is matchable
|
|||
|
{
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
ItemPackage attachedItemPackage = packageReference.itemPackage; // return the ItemPackage reference we find.
|
|||
|
|
|||
|
return attachedItemPackage;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void HandHoverUpdate( Hand hand )
|
|||
|
{
|
|||
|
if ( takeBackItem && requireReleaseActionToReturn )
|
|||
|
{
|
|||
|
if (hand.isActive)
|
|||
|
{
|
|||
|
ItemPackage currentAttachedItemPackage = GetAttachedItemPackage( hand );
|
|||
|
if (currentAttachedItemPackage == itemPackage && hand.IsGrabEnding(currentAttachedItemPackage.gameObject))
|
|||
|
{
|
|||
|
TakeBackItem( hand );
|
|||
|
return; // So that we don't pick up an ItemPackage the same frame that we return it
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( requireGrabActionToTake )
|
|||
|
{
|
|||
|
GrabTypes startingGrab = hand.GetGrabStarting();
|
|||
|
|
|||
|
if (startingGrab != GrabTypes.None)
|
|||
|
{
|
|||
|
SpawnAndAttachObject( hand, GrabTypes.Scripted);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void OnHandHoverEnd( Hand hand )
|
|||
|
{
|
|||
|
if ( !justPickedUpItem && requireGrabActionToTake && showTriggerHint )
|
|||
|
{
|
|||
|
hand.HideGrabHint();
|
|||
|
}
|
|||
|
|
|||
|
justPickedUpItem = false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void RemoveMatchingItemsFromHandStack( ItemPackage package, Hand hand )
|
|||
|
{
|
|||
|
if (hand == null)
|
|||
|
return;
|
|||
|
|
|||
|
for ( int i = 0; i < hand.AttachedObjects.Count; i++ )
|
|||
|
{
|
|||
|
ItemPackageReference packageReference = hand.AttachedObjects[i].attachedObject.GetComponent<ItemPackageReference>();
|
|||
|
if ( packageReference != null )
|
|||
|
{
|
|||
|
ItemPackage attachedObjectItemPackage = packageReference.itemPackage;
|
|||
|
if ( ( attachedObjectItemPackage != null ) && ( attachedObjectItemPackage == package ) )
|
|||
|
{
|
|||
|
GameObject detachedItem = hand.AttachedObjects[i].attachedObject;
|
|||
|
hand.DetachObject( detachedItem );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType packageType, Hand hand )
|
|||
|
{
|
|||
|
for ( int i = 0; i < hand.AttachedObjects.Count; i++ )
|
|||
|
{
|
|||
|
ItemPackageReference packageReference = hand.AttachedObjects[i].attachedObject.GetComponent<ItemPackageReference>();
|
|||
|
if ( packageReference != null )
|
|||
|
{
|
|||
|
if ( packageReference.itemPackage.packageType == packageType )
|
|||
|
{
|
|||
|
GameObject detachedItem = hand.AttachedObjects[i].attachedObject;
|
|||
|
hand.DetachObject( detachedItem );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------
|
|||
|
private void SpawnAndAttachObject( Hand hand, GrabTypes grabType )
|
|||
|
{
|
|||
|
if ( hand.otherHand != null )
|
|||
|
{
|
|||
|
//If the other hand has this item package, take it back from the other hand
|
|||
|
ItemPackage otherHandItemPackage = GetAttachedItemPackage( hand.otherHand );
|
|||
|
if ( otherHandItemPackage == itemPackage )
|
|||
|
{
|
|||
|
TakeBackItem( hand.otherHand );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( showTriggerHint )
|
|||
|
{
|
|||
|
hand.HideGrabHint();
|
|||
|
}
|
|||
|
|
|||
|
if ( itemPackage.otherHandItemPrefab != null )
|
|||
|
{
|
|||
|
if ( hand.otherHand.hoverLocked )
|
|||
|
{
|
|||
|
Debug.Log( "<b>[SteamVR Interaction]</b> Not attaching objects because other hand is hoverlocked and we can't deliver both items." );
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 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
|
|||
|
if ( itemPackage.packageType == ItemPackage.ItemPackageType.OneHanded )
|
|||
|
{
|
|||
|
RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.OneHanded, hand );
|
|||
|
RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.TwoHanded, hand );
|
|||
|
RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.TwoHanded, hand.otherHand );
|
|||
|
}
|
|||
|
|
|||
|
// if we're trying to spawn a two-handed item, remove one and two-handed items from both hands
|
|||
|
if ( itemPackage.packageType == ItemPackage.ItemPackageType.TwoHanded )
|
|||
|
{
|
|||
|
RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.OneHanded, hand );
|
|||
|
RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.OneHanded, hand.otherHand );
|
|||
|
RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.TwoHanded, hand );
|
|||
|
RemoveMatchingItemTypesFromHand( ItemPackage.ItemPackageType.TwoHanded, hand.otherHand );
|
|||
|
}
|
|||
|
|
|||
|
spawnedItem = GameObject.Instantiate( itemPackage.itemPrefab );
|
|||
|
spawnedItem.SetActive( true );
|
|||
|
hand.AttachObject( spawnedItem, grabType, attachmentFlags );
|
|||
|
|
|||
|
if ( ( itemPackage.otherHandItemPrefab != null ) && ( hand.otherHand.isActive ) )
|
|||
|
{
|
|||
|
GameObject otherHandObjectToAttach = GameObject.Instantiate( itemPackage.otherHandItemPrefab );
|
|||
|
otherHandObjectToAttach.SetActive( true );
|
|||
|
hand.otherHand.AttachObject( otherHandObjectToAttach, grabType, attachmentFlags );
|
|||
|
}
|
|||
|
|
|||
|
itemIsSpawned = true;
|
|||
|
|
|||
|
justPickedUpItem = true;
|
|||
|
|
|||
|
if ( takeBackItem )
|
|||
|
{
|
|||
|
useFadedPreview = true;
|
|||
|
pickupEvent.Invoke();
|
|||
|
CreatePreviewObject();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|