96 lines
3.5 KiB
C#
96 lines
3.5 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using Valve.VR.InteractionSystem;
|
|
|
|
[RequireComponent(typeof(Collider))]
|
|
public class Backpack : MonoBehaviour {
|
|
private class HapticPulse {
|
|
public Hand Hand;
|
|
public ushort Duration;
|
|
|
|
public HapticPulse(Hand hand, ushort duration = 2000) {
|
|
Hand = hand;
|
|
Duration = duration;
|
|
}
|
|
}
|
|
|
|
public Hand.AttachmentFlags GrabFlags;
|
|
public Hand[] Hands;
|
|
public List<Throwable> Contents = new List<Throwable>();
|
|
|
|
private Collider Collider;
|
|
private List<HapticPulse> PulseQueue = new List<HapticPulse>(4);
|
|
private float NextHapticTime = 0;
|
|
private bool[] HandReminded = new bool[] { false, false };
|
|
|
|
private void Awake() {
|
|
Collider = GetComponent<Collider>();
|
|
if (Hands.Length > HandReminded.Length) {
|
|
Debug.LogError($"Backpack has >{HandReminded.Length} hands assigned, please update HandReminded accordingly.");
|
|
}
|
|
}
|
|
|
|
private void Update() {
|
|
for (int I = 0; I < Hands.Length; I++) {
|
|
bool HandInBag = IsHandInBag(Hands[I]);
|
|
if (!HandReminded[I] && HandInBag) {
|
|
HandReminded[I] = true;
|
|
if (PulseQueue.Count == 0) {
|
|
PulseQueue.Add(new HapticPulse(Hands[I], 1000));
|
|
}
|
|
} else if (HandReminded[I] && !HandInBag) {
|
|
HandReminded[I] = false;
|
|
if (PulseQueue.Count == 0) {
|
|
PulseQueue.Add(new HapticPulse(Hands[I], 500));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Time.time >= NextHapticTime && PulseQueue.Count > 0) {
|
|
HapticPulse NextPulse = PulseQueue[0];
|
|
// Note: using the microsecond-based haptic pulses to avoid Vive wands getting stuck vibrating.
|
|
// Don't know why it happens, and didn't find much info by googling.
|
|
NextPulse.Hand.TriggerHapticPulse(NextPulse.Duration);
|
|
NextHapticTime = Time.time + Time.deltaTime;
|
|
PulseQueue.RemoveAt(0);
|
|
}
|
|
}
|
|
|
|
private bool IsHandInBag(Hand hand) {
|
|
Vector3 DeltaFromBag = hand.transform.position - Collider.ClosestPoint(hand.transform.position);
|
|
return DeltaFromBag.magnitude < hand.hoverSphereRadius;
|
|
}
|
|
|
|
public void Grab(Hand hand) {
|
|
if (IsHandInBag(hand) && Contents.Count > 0) {
|
|
int Index = Contents.Count - 1;
|
|
Throwable Item = Contents[Index];
|
|
Item.gameObject.SetActive(true);
|
|
hand.AttachObject(Item.gameObject, hand.IsGrabbingWithType(GrabTypes.Pinch) ? GrabTypes.Pinch : GrabTypes.Grip, GrabFlags);
|
|
Contents.RemoveAt(Index);
|
|
|
|
PulseQueue.Clear();
|
|
PulseQueue.Add(new HapticPulse(hand, 2_000));
|
|
PulseQueue.Add(new HapticPulse(hand, 4_000));
|
|
PulseQueue.Add(new HapticPulse(hand, 8_000));
|
|
}
|
|
}
|
|
|
|
public void Store(Hand hand) {
|
|
if (hand.currentAttachedObject != null) {
|
|
Throwable Item = hand.currentAttachedObject.GetComponent<Throwable>();
|
|
ItemVR Torch = hand.currentAttachedObject.GetComponent<ItemVR>();
|
|
bool IsBurningTorch = Torch != null && (Torch.Ignited && !Torch.Extinguished);
|
|
if (IsHandInBag(hand) && Item != null && !IsBurningTorch) {
|
|
Contents.Add(Item);
|
|
hand.DetachObject(Item.gameObject);
|
|
Item.gameObject.SetActive(false);
|
|
|
|
PulseQueue.Clear();
|
|
PulseQueue.Add(new HapticPulse(hand, 15_000));
|
|
}
|
|
}
|
|
}
|
|
}
|