You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
9.8 KiB
C#
254 lines
9.8 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
namespace RootMotion.Dynamics
|
|
{
|
|
|
|
/// <summary>
|
|
/// Muscle that PuppetMasterProps can be attached to.
|
|
/// </summary>
|
|
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.")]
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public PuppetMasterProp currentProp;
|
|
|
|
[LargeHeader("Additional Pin")]
|
|
|
|
[Tooltip("Offset of the additional pin from this Prop Muscle in local space.")]
|
|
/// <summary>
|
|
/// Offset of the additional pin from this Prop Muscle in local space.
|
|
/// </summary>
|
|
public Vector3 additionalPinOffset = Vector3.forward;
|
|
|
|
public Muscle muscle
|
|
{
|
|
get
|
|
{
|
|
if (_muscle == null) _muscle = puppetMaster.GetMuscle(GetComponent<ConfigurableJoint>());
|
|
return _muscle;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The prop that is actually connected to this PropMuscle. Null if none.
|
|
/// </summary>
|
|
public PuppetMasterProp activeProp { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Delegate used when picking up and dropping props.
|
|
/// </summary>
|
|
/// <param name="prop"></param>
|
|
public delegate void PropDelegate(PuppetMasterProp prop);
|
|
|
|
/// <summary>
|
|
/// Called after a prop has been picked up by this PropMuscle.
|
|
/// </summary>
|
|
public PropDelegate OnPickUpProp;
|
|
|
|
/// <summary>
|
|
/// Called after a prop is dropped by this PropMuscle.
|
|
/// </summary>
|
|
public PropDelegate OnDropProp;
|
|
|
|
private Muscle _muscle;
|
|
private PuppetMasterProp lastProp;
|
|
private Vector3 lastAdditionalPinOffset;
|
|
|
|
/// <summary>
|
|
/// Adding additional pin at runtime.
|
|
/// </summary>
|
|
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<Rigidbody>();
|
|
|
|
var joint = addGO.AddComponent<ConfigurableJoint>();
|
|
joint.connectedBody = muscle.joint.GetComponent<Rigidbody>();
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removing additional pin at runtime
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|