95 lines
3.4 KiB
C#
95 lines
3.4 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>();
|
|||
|
if (IsHandInBag(hand) && Item != null) {
|
|||
|
Contents.Add(Item);
|
|||
|
hand.DetachObject(Item.gameObject);
|
|||
|
Item.gameObject.SetActive(false);
|
|||
|
|
|||
|
PulseQueue.Clear();
|
|||
|
PulseQueue.Add(new HapticPulse(hand, 15_000));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|