using UnityEngine; using System.Collections; namespace RootMotion.Dynamics { /// /// Muscle that PuppetMasterProps can be attached to. /// public class PropMuscle : MonoBehaviour { [HideInInspector] public PuppetMaster puppetMaster; [Tooltip("The PuppetMasterProp currently held by this Prop Muscle. To pick up a prop, just assign it as propMuscle.currentProp. To drop, set propMuscle.currentProp to null. Replacing this value with another prop drops any previously held props.")] /// /// The PuppetMasterProp currently held by this Prop Muscle. To pick up a prop, just assign it as propMuscle.currentProp. To drop, set propMuscle.currentProp to null. Replacing this value with another prop drops any previously held props. /// public PuppetMasterProp currentProp; [LargeHeader("Additional Pin")] [Tooltip("Offset of the additional pin from this Prop Muscle in local space.")] /// /// Offset of the additional pin from this Prop Muscle in local space. /// public Vector3 additionalPinOffset = Vector3.forward; public Muscle muscle { get { if (_muscle == null) _muscle = puppetMaster.GetMuscle(GetComponent()); return _muscle; } } /// /// The prop that is actually connected to this PropMuscle. Null if none. /// public PuppetMasterProp activeProp { get; private set; } /// /// Delegate used when picking up and dropping props. /// /// public delegate void PropDelegate(PuppetMasterProp prop); /// /// Called after a prop has been picked up by this PropMuscle. /// public PropDelegate OnPickUpProp; /// /// Called after a prop is dropped by this PropMuscle. /// public PropDelegate OnDropProp; private Muscle _muscle; private PuppetMasterProp lastProp; private Vector3 lastAdditionalPinOffset; /// /// Adding additional pin at runtime. /// public bool AddAdditionalPin() { if (!puppetMaster.initiated) { Debug.LogError("Can not call AddAdditionalPin on an uninitiated PuppetMaster.", transform); return false; } if (muscle.additionalPin != null) return false; var addGO = new GameObject("Additional Pin"); addGO.gameObject.layer = gameObject.layer; addGO.transform.parent = transform; addGO.transform.localPosition = additionalPinOffset; addGO.transform.localRotation = Quaternion.identity; lastAdditionalPinOffset = additionalPinOffset; addGO.AddComponent(); var joint = addGO.AddComponent(); joint.connectedBody = muscle.joint.GetComponent(); joint.autoConfigureConnectedAnchor = false; joint.connectedAnchor = additionalPinOffset; joint.xMotion = ConfigurableJointMotion.Locked; joint.yMotion = ConfigurableJointMotion.Locked; joint.zMotion = ConfigurableJointMotion.Locked; joint.angularXMotion = ConfigurableJointMotion.Locked; joint.angularYMotion = ConfigurableJointMotion.Locked; joint.angularZMotion = ConfigurableJointMotion.Locked; var addTargetGO = new GameObject("Additional Pin Target"); addTargetGO.layer = muscle.target.gameObject.layer; addTargetGO.transform.parent = muscle.target; addTargetGO.transform.position = addGO.transform.position; addTargetGO.transform.rotation = addGO.transform.rotation; muscle.additionalPin = joint; muscle.additionalPinTarget = addTargetGO.transform; muscle.InitiateAdditionalPin(); //muscle.additionalPin.gameObject.hideFlags = HideFlags.HideInHierarchy; //muscle.additionalPinTarget.gameObject.hideFlags = HideFlags.HideInHierarchy; return true; } /// /// Removing additional pin at runtime /// public bool RemoveAdditionalPin() { if (!puppetMaster.initiated) { Debug.LogError("Can not call RemoveAdditionalPin on an uninitiated PuppetMaster.", transform); return false; } if (muscle.additionalPin == null) return false; //muscle.additionalPin.gameObject.hideFlags = HideFlags.None; //muscle.additionalPinTarget.gameObject.hideFlags = HideFlags.None; Destroy(muscle.additionalPin.gameObject); Destroy(muscle.additionalPinTarget.gameObject); muscle.additionalPin = null; muscle.additionalPinTarget = null; return true; } public void OnInitiate() { muscle.isPropMuscle = true; if (currentProp == null && activeProp == null) puppetMaster.DisconnectMuscleRecursive(muscle.index, MuscleDisconnectMode.Sever, true); } public void TakeOver() { currentProp = null; lastProp = null; activeProp = null; puppetMaster.DisconnectMuscleRecursive(muscle.index, MuscleDisconnectMode.Sever, true); } public void OnUpdate() { if (currentProp != lastProp && !puppetMaster.IsDisconnecting(muscle.index) && !puppetMaster.IsReconnecting(muscle.index)) { // Drop any previously held props if (lastProp != null) { lastProp.Drop(puppetMaster, muscle.index); activeProp = null; if (OnDropProp != null) OnDropProp(lastProp); } if (currentProp != null) { // Take over if currentProp is held by anoth prop muscle foreach (PropMuscle otherPropMuscle in puppetMaster.propMuscles) { if (otherPropMuscle != this) { if (otherPropMuscle.currentProp == currentProp) otherPropMuscle.TakeOver(); } } // Reconnect Prop Muscle if (muscle.state.isDisconnected) { puppetMaster.ReconnectMuscleRecursive(muscle.index); } // Pick up the new prop currentProp.PickUp(puppetMaster, muscle.index); muscle.rigidbody.centerOfMass = currentProp.localCenterOfMass; if (currentProp.inertiaTensor != Vector3.zero) muscle.rigidbody.inertiaTensor = currentProp.inertiaTensor; //muscle.rigidbody.ResetInertiaTensor(); // This seems to have a bug, inertia tensor increases with every pick-up. activeProp = currentProp; if (OnPickUpProp != null) OnPickUpProp(currentProp); } else { // If no current prop, disconnect this prop muscle. puppetMaster.DisconnectMuscleRecursive(muscle.index, MuscleDisconnectMode.Sever, true); } lastProp = currentProp; } if (currentProp != null) { muscle.rigidbody.mass = currentProp.mass; if (muscle.additionalPin != null) { muscle.additionalPinWeight = currentProp.additionalPinWeight; muscle.additionalRigidbody.mass = currentProp.additionalPinMass;// * Mathf.Max(muscle.additionalPinWeight, currentProp.mass * 0.1f); muscle.additionalRigidbody.drag = muscle.rigidbody.drag; muscle.additionalRigidbody.angularDrag = muscle.rigidbody.angularDrag; muscle.additionalRigidbody.useGravity = muscle.rigidbody.useGravity; muscle.additionalRigidbody.inertiaTensor = Vector3.one * 0.00001f; //muscle.additionalRigidbody.ResetInertiaTensor(); Vector3 f = additionalPinOffset + currentProp.additionalPinOffsetAdd; if (lastAdditionalPinOffset != f) { muscle.additionalPinTarget.localPosition = f; muscle.additionalPin.connectedAnchor = f; lastAdditionalPinOffset = f; } } } } void OnDrawGizmosSelected() { if (Application.isPlaying) return; if (muscle.target == null) return; //muscle.target.gameObject.hideFlags = HideFlags.None; muscle.target.position = transform.position; muscle.target.rotation = transform.rotation; if (muscle.additionalPin != null && muscle.additionalPinTarget != null) { //muscle.additionalPin.gameObject.hideFlags = HideFlags.None; //muscle.additionalPinTarget.gameObject.hideFlags = HideFlags.None; muscle.additionalPin.transform.localPosition = additionalPinOffset; muscle.additionalPin.transform.localRotation = Quaternion.identity; muscle.additionalPinTarget.position = muscle.additionalPin.transform.position; muscle.additionalPinTarget.rotation = muscle.additionalPin.transform.rotation; } } } }