### view Orchestland/Assets/LeapMotion/Scripts/Utils/MagneticPinch.cs @ 1:f7675884f2a1

author Daiki OYAKAWA Fri, 17 Jul 2015 23:09:20 +0900
line wrap: on
line source

﻿/******************************************************************************\
* Copyright (C) Leap Motion, Inc. 2011-2014.                                   *
* Leap Motion proprietary. Licensed under Apache 2.0                           *
\******************************************************************************/

using UnityEngine;
using System.Collections;
using Leap;

/**
* Detects pinches and grabs the closest rigidbody if it's within a given range.
*
* Attach this script to the physics hand object assinged to the HandController in a scene.
*/
public class MagneticPinch : MonoBehaviour {

public const float TRIGGER_DISTANCE_RATIO = 0.7f;

/** The stiffness of the spring force used to move the object toward the hand. */
public float forceSpringConstant = 100.0f;
/** The maximum range at which an object can be picked up.*/
public float magnetDistance = 2.0f;

protected bool pinching_;
protected Collider grabbed_;

void Start() {
pinching_ = false;
grabbed_ = null;
}

/** Finds an object to grab and grabs it. */
void OnPinch(Vector3 pinch_position) {
pinching_ = true;

// Check if we pinched a movable object and grab the closest one that's not part of the hand.
Collider[] close_things = Physics.OverlapSphere(pinch_position, magnetDistance);
Vector3 distance = new Vector3(magnetDistance, 0.0f, 0.0f);

for (int j = 0; j < close_things.Length; ++j) {
Vector3 new_distance = pinch_position - close_things[j].transform.position;
if (close_things[j].GetComponent<Rigidbody>() != null && new_distance.magnitude < distance.magnitude &&
!close_things[j].transform.IsChildOf(transform)) {
grabbed_ = close_things[j];
distance = new_distance;
}
}
}

/** Clears the pinch state. */
void OnRelease() {
grabbed_ = null;
pinching_ = false;
}

/**
* Checks whether the hand is pinching and updates the position of the pinched object.
*/
void Update() {
bool trigger_pinch = false;
HandModel hand_model = GetComponent<HandModel>();
Hand leap_hand = hand_model.GetLeapHand();

if (leap_hand == null)
return;

// Scale trigger distance by thumb proximal bone length.
Vector leap_thumb_tip = leap_hand.Fingers[0].TipPosition;
float proximal_length = leap_hand.Fingers[0].Bone(Bone.BoneType.TYPE_PROXIMAL).Length;
float trigger_distance = proximal_length * TRIGGER_DISTANCE_RATIO;

// Check thumb tip distance to joints on all other fingers.
// If it's close enough, start pinching.
for (int i = 1; i < HandModel.NUM_FINGERS && !trigger_pinch; ++i) {
Finger finger = leap_hand.Fingers[i];

for (int j = 0; j < FingerModel.NUM_BONES && !trigger_pinch; ++j) {
Vector leap_joint_position = finger.Bone((Bone.BoneType)j).NextJoint;
if (leap_joint_position.DistanceTo(leap_thumb_tip) < trigger_distance)
trigger_pinch = true;
}
}

Vector3 pinch_position = hand_model.fingers[0].GetTipPosition();

// Only change state if it's different.
if (trigger_pinch && !pinching_)
OnPinch(pinch_position);
else if (!trigger_pinch && pinching_)
OnRelease();

// Accelerate what we are grabbing toward the pinch.
if (grabbed_ != null) {
Vector3 distance = pinch_position - grabbed_.transform.position;