|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
|
|
namespace RootMotion.Dynamics
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
public class PuppetMasterLite : MonoBehaviour
|
|
|
|
|
|
{
|
|
|
|
|
|
public Transform targetRoot;
|
|
|
|
|
|
public bool fixTargetTransforms = true;
|
|
|
|
|
|
public float blendTime = 0.1f;
|
|
|
|
|
|
[Range(0f, 1f)] public float mappingWeight = 1f;
|
|
|
|
|
|
[Range(0f, 1f)] public float pinWeight = 1f;
|
|
|
|
|
|
[Range(0f, 1f)] public float muscleWeight = 1f;
|
|
|
|
|
|
|
|
|
|
|
|
public float muscleSpring = 1000f;
|
|
|
|
|
|
public float muscleDamper = 100f;
|
|
|
|
|
|
public bool updateJointAnchors = true;
|
|
|
|
|
|
public bool angularPinning;
|
|
|
|
|
|
|
|
|
|
|
|
[LargeHeader("Individual Muscle Settings")]
|
|
|
|
|
|
public MuscleLite[] muscles = new MuscleLite[0];
|
|
|
|
|
|
|
|
|
|
|
|
public delegate void PuppetMasterLiteDelegate();
|
|
|
|
|
|
public PuppetMasterLiteDelegate OnRead;
|
|
|
|
|
|
public PuppetMasterLiteDelegate OnWrite;
|
|
|
|
|
|
|
|
|
|
|
|
private Animator targetAnimator;
|
|
|
|
|
|
private bool animatorDisabled;
|
|
|
|
|
|
private bool fixedFrame;
|
|
|
|
|
|
private UpdateMode updateMode = UpdateMode.Normal;
|
|
|
|
|
|
|
|
|
|
|
|
public enum UpdateMode
|
|
|
|
|
|
{
|
|
|
|
|
|
Normal,
|
|
|
|
|
|
Fixed
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Start()
|
|
|
|
|
|
{
|
|
|
|
|
|
Initiate();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Activate()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (gameObject.activeInHierarchy) return;
|
|
|
|
|
|
|
|
|
|
|
|
mappingWeight = 0f;
|
|
|
|
|
|
foreach (MuscleLite m in muscles)
|
|
|
|
|
|
{
|
|
|
|
|
|
m.Reset();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gameObject.SetActive(true);
|
|
|
|
|
|
|
|
|
|
|
|
foreach (MuscleLite m in muscles)
|
|
|
|
|
|
{
|
|
|
|
|
|
m.rigidbody.WakeUp();
|
|
|
|
|
|
m.MoveToTarget();
|
|
|
|
|
|
m.ClearVelocities();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Read();
|
|
|
|
|
|
|
|
|
|
|
|
StopAllCoroutines();
|
|
|
|
|
|
StartCoroutine(Activation());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private IEnumerator Activation()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (blendTime <= 0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
mappingWeight = 1f;
|
|
|
|
|
|
yield break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while (mappingWeight < 1f)
|
|
|
|
|
|
{
|
|
|
|
|
|
mappingWeight = Mathf.MoveTowards(mappingWeight, 1f, Time.deltaTime * (1f / blendTime));
|
|
|
|
|
|
yield return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Deactivate()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!gameObject.activeInHierarchy) return;
|
|
|
|
|
|
|
|
|
|
|
|
StopAllCoroutines();
|
|
|
|
|
|
StartCoroutine(Deactivation());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private IEnumerator Deactivation()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (blendTime > 0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
while (mappingWeight > 0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
mappingWeight = Mathf.MoveTowards(mappingWeight, 0f, Time.deltaTime * (1f / blendTime));
|
|
|
|
|
|
yield return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (animatorDisabled) targetAnimator.enabled = true;
|
|
|
|
|
|
animatorDisabled = false;
|
|
|
|
|
|
gameObject.SetActive(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Initiate()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (targetRoot.gameObject.layer == gameObject.layer) Debug.LogError("Target Root is on the same layer as PuppetMasterLite! Please use different layers and make sure collisions between those layers are disabled in the Layer Collision Matrix.", transform);
|
|
|
|
|
|
|
|
|
|
|
|
targetAnimator = targetRoot.GetComponentInChildren<Animator>();
|
|
|
|
|
|
if (targetAnimator != null && targetAnimator.updateMode == AnimatorUpdateMode.AnimatePhysics) updateMode = UpdateMode.Fixed;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (MuscleLite m in muscles)
|
|
|
|
|
|
{
|
|
|
|
|
|
m.Initiate(muscles);
|
|
|
|
|
|
//m.mappingWeightMlp = 0f;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Update()
|
|
|
|
|
|
{
|
|
|
|
|
|
updateMode = targetAnimator == null || targetAnimator.updateMode != AnimatorUpdateMode.AnimatePhysics ? UpdateMode.Normal : UpdateMode.Fixed;
|
|
|
|
|
|
if (updateMode == UpdateMode.Fixed) return;
|
|
|
|
|
|
|
|
|
|
|
|
FixTargetTransforms();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void FixTargetTransforms()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!fixTargetTransforms) return;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (MuscleLite m in muscles)
|
|
|
|
|
|
{
|
|
|
|
|
|
m.FixTargetTransforms();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void FixedUpdate()
|
|
|
|
|
|
{
|
|
|
|
|
|
fixedFrame = true;
|
|
|
|
|
|
|
|
|
|
|
|
if (updateMode == UpdateMode.Fixed)
|
|
|
|
|
|
{
|
|
|
|
|
|
FixTargetTransforms();
|
|
|
|
|
|
|
|
|
|
|
|
if (targetAnimator.enabled || (!targetAnimator.enabled && animatorDisabled))
|
|
|
|
|
|
{
|
|
|
|
|
|
targetAnimator.enabled = false;
|
|
|
|
|
|
animatorDisabled = true;
|
|
|
|
|
|
targetAnimator.Update(Time.fixedDeltaTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
animatorDisabled = false;
|
|
|
|
|
|
targetAnimator.enabled = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Read();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (MuscleLite m in muscles)
|
|
|
|
|
|
{
|
|
|
|
|
|
m.Update(pinWeight, muscleWeight, muscleSpring, muscleDamper, angularPinning);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void LateUpdate()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (animatorDisabled) targetAnimator.enabled = true;
|
|
|
|
|
|
animatorDisabled = false;
|
|
|
|
|
|
|
|
|
|
|
|
switch (updateMode)
|
|
|
|
|
|
{
|
|
|
|
|
|
case UpdateMode.Fixed:
|
|
|
|
|
|
if (fixedFrame) Write();
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
Read();
|
|
|
|
|
|
Write();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fixedFrame = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Read()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (OnRead != null) OnRead();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (MuscleLite m in muscles)
|
|
|
|
|
|
{
|
|
|
|
|
|
m.Read();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (updateJointAnchors)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (MuscleLite m in muscles)
|
|
|
|
|
|
{
|
|
|
|
|
|
m.UpdateAnchor(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Write()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (MuscleLite m in muscles)
|
|
|
|
|
|
{
|
|
|
|
|
|
m.Map(mappingWeight);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (OnWrite != null) OnWrite();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnDrawGizmosSelected()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Application.isPlaying) return;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < muscles.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
muscles[i].name = i.ToString() + ": " + (muscles[i].joint != null ? muscles[i].joint.name : "Missing Joint reference!");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|