comparison Orchestland/Assets/LeapMotion/Widgets/Scripts/Physics/LeapPhysicsBase.cs @ 1:f7675884f2a1

Add Orchestland project
author Daiki OYAKAWA <e135764@ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2015 23:09:20 +0900
parents
children
comparison
equal deleted inserted replaced
0:347d21cdfc22 1:f7675884f2a1
1 using System;
2 using UnityEngine;
3
4 namespace LMWidgets
5 {
6 public enum LeapPhysicsState
7 {
8 Interacting, // Responsible for moving the widgets with the fingers
9 Reflecting, // Responsible for reflecting widget information and simulating the physics
10 Disabled // State in which the widget is disabled
11 }
12
13 /// <summary>
14 /// Base class for physics.
15 /// Handles state changes between Interacting and Reflecting.
16 /// </summary>
17 public abstract class LeapPhysicsBase : MonoBehaviour
18 {
19 protected event EventHandler<LMWidgets.EventArg<LeapPhysicsState>> StateChangeHandler;
20
21 private LeapPhysicsState m_state = LeapPhysicsState.Reflecting; // Don't set this directly. Use accessor.
22 protected GameObject m_target = null;
23 protected Vector3 m_pivot = Vector3.zero;
24 protected Vector3 m_targetPivot = Vector3.zero;
25
26 /// <summary>
27 /// Represents the current Physics state.
28 /// </summary>
29 /// <remarks>
30 /// Use this property to set the state rather than the m_state field so that proper events and functions are called on changes.
31 /// Chaning the property will also call onInteractionEnabled and onInteractionDisabled as appropritate.
32 /// </remarks>
33 protected LeapPhysicsState State {
34 get {
35 return m_state;
36 }
37 set {
38
39 // Call enabled and disabled functions as appropriate.
40 if ( m_state != LeapPhysicsState.Disabled && value == LeapPhysicsState.Disabled ) {
41 onInteractionDisabled();
42 }
43 else if ( m_state == LeapPhysicsState.Disabled && value != LeapPhysicsState.Disabled ) {
44 onInteractionEnabled();
45 }
46
47 m_state = value; // Update underlying value
48
49 // Fire changed event
50 EventHandler<LMWidgets.EventArg<LeapPhysicsState>> handler = StateChangeHandler;
51 if ( handler != null ) { handler(this, new EventArg<LeapPhysicsState>(State)); }
52 }
53 }
54
55 /// <summary>
56 /// Represents whether the widget is enabled or disabled.
57 /// </summary>
58 public bool Interactable {
59 get {
60 return !(State == LeapPhysicsState.Disabled);
61 }
62 set {
63 if (State == LeapPhysicsState.Disabled && value == true ) {
64 State = LeapPhysicsState.Reflecting;
65 }
66 else if (State != LeapPhysicsState.Disabled && value == false) {
67 State = LeapPhysicsState.Disabled;
68 }
69 }
70 }
71
72 // Apply the physics interactions when the hand is no longer interacting with the object
73 protected abstract void ApplyPhysics();
74 // Apply interactions with the objects
75 protected abstract void ApplyInteractions();
76 // Apply constraints for the object (e.g. Constrain movements along a specific axis)
77 protected abstract void ApplyConstraints();
78
79 /// <summary>
80 /// Called when widget becomes interactable.
81 /// </summary>
82 /// <remarks>
83 /// Implement this function to handle changes to the widget when interaction is enabled (ie. starting an enable animation)
84 /// </remarks>
85 protected virtual void onInteractionEnabled() {}
86 /// <summary>
87 /// Called when widget becomes non-interactable.
88 /// </summary>
89 /// <remarks>
90 /// Implement this function to handle changes to the widget when interaction is disabled (ie. starting a disable animation)
91 /// </remarks>
92 protected virtual void onInteractionDisabled() {}
93
94 /// <summary>
95 /// Resets the pivots
96 /// </summary>
97 protected virtual void ResetPivots()
98 {
99 m_pivot = transform.localPosition;
100 if (m_target != null)
101 m_targetPivot = transform.parent.InverseTransformPoint(m_target.transform.position);
102 }
103
104 /// <summary>
105 /// Returns true or false by checking if "HandModel" exits in the parent of the collider
106 /// </summary>
107 /// <param name="collider"></param>
108 /// <returns></returns>
109 private bool IsHand(Collider collider)
110 {
111 return collider.transform.parent && collider.transform.parent.parent && collider.transform.parent.parent.GetComponent<HandModel>();
112 }
113
114 /// <summary>
115 /// Change the state of the physics to "Interacting" if no other hands were interacting and if the collider is a hand
116 /// </summary>
117 /// <param name="collider"></param>
118 protected virtual void OnTriggerEnter(Collider collider)
119 {
120 if (m_target == null && IsHand(collider) && State != LeapPhysicsState.Disabled)
121 {
122 State = LeapPhysicsState.Interacting;
123 m_target = collider.gameObject;
124 ResetPivots();
125 }
126 }
127
128 /// <summary>
129 /// Change the state of the physics to "Reflecting" if the object exiting is the hand
130 /// </summary>
131 /// <param name="collider"></param>
132 protected virtual void OnTriggerExit(Collider collider)
133 {
134 // TODO: Use interpolation to determine if the hand should still continue interacting with the widget to solve low-FPS
135 // TODO(cont): It should solve low-FPS or fast hand movement problems
136 if (collider.gameObject == m_target)
137 {
138 State = LeapPhysicsState.Reflecting;
139 m_target = null;
140 }
141 }
142
143 protected virtual void Awake()
144 {
145 if (GetComponent<Collider>() == null)
146 {
147 Debug.LogWarning("This Widget lacks a collider. Will not function as expected.");
148 }
149 }
150
151 protected virtual void FixedUpdate()
152 {
153 if (m_target == null && State == LeapPhysicsState.Interacting)
154 {
155 State = LeapPhysicsState.Reflecting;
156 }
157
158 switch (State)
159 {
160 case LeapPhysicsState.Interacting:
161 ApplyInteractions();
162 break;
163 case LeapPhysicsState.Reflecting:
164 ApplyPhysics();
165 break;
166 case LeapPhysicsState.Disabled:
167 break;
168 default:
169 break;
170 }
171 ApplyConstraints();
172 }
173 }
174 }