using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class VR_Hand : MonoBehaviour {
public Animator animator;
public enum WhichHands { Left, Right };
public WhichHands whichHand;
private GameObject hand;
private Transform shoulder;
public Transform handTarget;
private Transform cHandTarget;
private Vector3 dPalm;
public float thumbInput;
public float indexInput;
public float middleInput;
public float ringInput;
public float littleInput;
private Thumb thumb;
private Finger indexFinger;
private Finger middleFinger;
private Finger ringFinger;
private Finger littleFinger;
private Digit[] digits;
private GameObject grabbedObject = null;
private Rigidbody grabbedRigidbody = null;
private GrabbedRigidbody grabbedRBfunc;
private Collider collidedObject;
private Vector3 palmOffset;
private GameObject go;
void OnCollisionStay (Collision otherCollider) {
Transform thisTransform, otherTransform;
if (grabbedObject == null) {
bool fingersCollided = false;
bool thumbCollided = false;
int ncontacts = otherCollider.contacts.Length;
for (int i = 0; i < ncontacts; i++ ) {
thisTransform = otherCollider.contacts[i].thisCollider.transform;
otherTransform = otherCollider.contacts[i].otherCollider.transform;
if (thisTransform == thumb.transform || otherTransform == thumb.transform)
thumbCollided = true;
for (int j = 1; j < digits.Length; j++) {
Finger finger = (Finger) digits[j];
if (thisTransform == finger.transform || otherTransform == finger.transform) {
fingersCollided = true;
}
}
}
bool grabbed = false;
if (fingersCollided && thumbCollided) {
for (int j = 1; j < digits.Length; j++) {
Finger finger = (Finger) digits[j];
if (finger.input > 0 && !finger.hasGrabbed()) {
finger.Grab();
if (!grabbed) {
grabbedObject = otherCollider.gameObject;
grabbedRigidbody = otherCollider.collider.attachedRigidbody;
Grab (grabbedObject, grabbedRigidbody);
grabbed = true;
}
}
}
}
}
}
void Grab(GameObject obj, Rigidbody rb) {
Vector3 palmOffsetWorld = hand.transform.TransformDirection(palmOffset);
GrabbedRigidbody grb = obj.AddComponent<GrabbedRigidbody>();
grabbedRBfunc = grb;
go = new GameObject();
go.transform.parent = hand.transform;
go.transform.localPosition = Enscale(palmOffset, go.transform.localScale);
if (whichHand == WhichHands.Right)
go.transform.localRotation = Quaternion.Euler(20,270,0);
go.transform.localRotation = Quaternion.Euler(-20,270,180);
grb.Kinematize(hand.transform, whichHand == WhichHands.Right, hand.transform.position + palmOffsetWorld, go);
}
private Vector3 Enscale(Vector3 position, Vector3 scale) {
return new Vector3(
position.x * scale.x,
position.y * scale.y,
position.z * scale.z);
}
public abstract class Digit {
public abstract void Init(GameObject hand, Vector3 handRightAxis, WhichHands whichHand);
public abstract void Update(float inputValue);
}
[System.Serializable]
public class Finger : Digit {
public Transform transform;
public float input;
private float val;
private Vector3 axis;
private float grabAmount = 0;
private int nPhalanges;
private Phalanx[] phalanges;
public override void Init(GameObject hand, Vector3 axis_in, WhichHands whichHand) {
if (transform != null) {
axis = axis_in;
phalanges = new Phalanx[3];
phalanges[0] = new Phalanx(transform);
if (phalanges[0].transform.childCount == 1) {
phalanges[1] = new Phalanx(phalanges[0].transform.GetChild(0).transform);
if (phalanges[1].transform.childCount == 1) {
phalanges[2] = new Phalanx(phalanges[1].transform.GetChild(0).transform);
nPhalanges = 3;
} else {
phalanges[2] = null;
nPhalanges = 2;
}
} else {
phalanges[1] = null;
nPhalanges = 1;
}
}
}
private float grabSpeed = 0.1f;
public override void Update(float inputValue) {
if (transform != null) {
input = inputValue;
if (grabAmount > 0)
val = grabAmount;
else {
float d = input - val;
if (d > grabSpeed)
val += grabSpeed;
else if (d < -grabSpeed)
val -= grabSpeed;
else
val += d;
}
Bend();
if (grabAmount > 0) {
if (input < grabAmount) {
grabAmount = 0f;
}
}
}
}
private void Bend() {
switch (nPhalanges) {
case 3:
phalanges[0].Bend(val * 45, axis);
phalanges[1].Bend(val * 90, axis);
phalanges[2].Bend(val * 90, axis);
break;
case 2:
phalanges[0].Bend(val * 90, axis);
phalanges[1].Bend(val * 90, axis);
break;
case 1:
phalanges[0].Bend(val * 135, axis);
break;
}
}
public bool hasGrabbed() {
return (grabAmount > 0);
}
public void Grab() {
grabAmount = val;
}
}
[System.Serializable]
public class Thumb : Digit {
public Transform transform;
public float input;
private float val, grabAmount = 0;
private Vector3 axis1, axis2;
private Quaternion startRotation;
public override void Init(GameObject hand, Vector3 handRightAxis, WhichHands whichHand) {
if (transform != null) {
axis1 = transform.InverseTransformDirection(hand.transform.up);
if (whichHand == WhichHands.Left)
axis2 = transform.InverseTransformDirection(-hand.transform.forward);
else
axis2 = transform.InverseTransformDirection(hand.transform.forward);
startRotation = transform.localRotation;
startRotation *= Quaternion.AngleAxis(45, -axis1);
}
}
private float grabSpeed = 0.1f;
public override void Update(float inputValue) {
if (transform != null) {
input = inputValue;
if (grabAmount > 0)
val = grabAmount;
else {
float d = input - val;
if (d > grabSpeed)
val += grabSpeed;
else if (d < -grabSpeed)
val -= grabSpeed;
else
val += d;
}
transform.localRotation = startRotation * Quaternion.AngleAxis(val * 45, axis1);
transform.localRotation *= Quaternion.AngleAxis(val * 30, axis2);
}
}
}
[System.Serializable]
public class Phalanx {
public Transform transform;
public Quaternion startRotation;
public Phalanx(Transform newTransform) {
transform = newTransform;
startRotation = transform.localRotation;
}
public void Bend(float bendFactor, Vector3 axis) {
transform.localRotation = startRotation * Quaternion.AngleAxis(bendFactor, axis);
}
}
}