Mercurial > hg > Game > Games
view 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 |
line wrap: on
line source
using System; using UnityEngine; namespace LMWidgets { public enum LeapPhysicsState { Interacting, // Responsible for moving the widgets with the fingers Reflecting, // Responsible for reflecting widget information and simulating the physics Disabled // State in which the widget is disabled } /// <summary> /// Base class for physics. /// Handles state changes between Interacting and Reflecting. /// </summary> public abstract class LeapPhysicsBase : MonoBehaviour { protected event EventHandler<LMWidgets.EventArg<LeapPhysicsState>> StateChangeHandler; private LeapPhysicsState m_state = LeapPhysicsState.Reflecting; // Don't set this directly. Use accessor. protected GameObject m_target = null; protected Vector3 m_pivot = Vector3.zero; protected Vector3 m_targetPivot = Vector3.zero; /// <summary> /// Represents the current Physics state. /// </summary> /// <remarks> /// Use this property to set the state rather than the m_state field so that proper events and functions are called on changes. /// Chaning the property will also call onInteractionEnabled and onInteractionDisabled as appropritate. /// </remarks> protected LeapPhysicsState State { get { return m_state; } set { // Call enabled and disabled functions as appropriate. if ( m_state != LeapPhysicsState.Disabled && value == LeapPhysicsState.Disabled ) { onInteractionDisabled(); } else if ( m_state == LeapPhysicsState.Disabled && value != LeapPhysicsState.Disabled ) { onInteractionEnabled(); } m_state = value; // Update underlying value // Fire changed event EventHandler<LMWidgets.EventArg<LeapPhysicsState>> handler = StateChangeHandler; if ( handler != null ) { handler(this, new EventArg<LeapPhysicsState>(State)); } } } /// <summary> /// Represents whether the widget is enabled or disabled. /// </summary> public bool Interactable { get { return !(State == LeapPhysicsState.Disabled); } set { if (State == LeapPhysicsState.Disabled && value == true ) { State = LeapPhysicsState.Reflecting; } else if (State != LeapPhysicsState.Disabled && value == false) { State = LeapPhysicsState.Disabled; } } } // Apply the physics interactions when the hand is no longer interacting with the object protected abstract void ApplyPhysics(); // Apply interactions with the objects protected abstract void ApplyInteractions(); // Apply constraints for the object (e.g. Constrain movements along a specific axis) protected abstract void ApplyConstraints(); /// <summary> /// Called when widget becomes interactable. /// </summary> /// <remarks> /// Implement this function to handle changes to the widget when interaction is enabled (ie. starting an enable animation) /// </remarks> protected virtual void onInteractionEnabled() {} /// <summary> /// Called when widget becomes non-interactable. /// </summary> /// <remarks> /// Implement this function to handle changes to the widget when interaction is disabled (ie. starting a disable animation) /// </remarks> protected virtual void onInteractionDisabled() {} /// <summary> /// Resets the pivots /// </summary> protected virtual void ResetPivots() { m_pivot = transform.localPosition; if (m_target != null) m_targetPivot = transform.parent.InverseTransformPoint(m_target.transform.position); } /// <summary> /// Returns true or false by checking if "HandModel" exits in the parent of the collider /// </summary> /// <param name="collider"></param> /// <returns></returns> private bool IsHand(Collider collider) { return collider.transform.parent && collider.transform.parent.parent && collider.transform.parent.parent.GetComponent<HandModel>(); } /// <summary> /// Change the state of the physics to "Interacting" if no other hands were interacting and if the collider is a hand /// </summary> /// <param name="collider"></param> protected virtual void OnTriggerEnter(Collider collider) { if (m_target == null && IsHand(collider) && State != LeapPhysicsState.Disabled) { State = LeapPhysicsState.Interacting; m_target = collider.gameObject; ResetPivots(); } } /// <summary> /// Change the state of the physics to "Reflecting" if the object exiting is the hand /// </summary> /// <param name="collider"></param> protected virtual void OnTriggerExit(Collider collider) { // TODO: Use interpolation to determine if the hand should still continue interacting with the widget to solve low-FPS // TODO(cont): It should solve low-FPS or fast hand movement problems if (collider.gameObject == m_target) { State = LeapPhysicsState.Reflecting; m_target = null; } } protected virtual void Awake() { if (GetComponent<Collider>() == null) { Debug.LogWarning("This Widget lacks a collider. Will not function as expected."); } } protected virtual void FixedUpdate() { if (m_target == null && State == LeapPhysicsState.Interacting) { State = LeapPhysicsState.Reflecting; } switch (State) { case LeapPhysicsState.Interacting: ApplyInteractions(); break; case LeapPhysicsState.Reflecting: ApplyPhysics(); break; case LeapPhysicsState.Disabled: break; default: break; } ApplyConstraints(); } } }