campfire/Assets/Scripts/Backpack.cs
2020-05-02 19:00:50 +03:00

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));
}
}
}
}