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.

223 lines
8.1 KiB
C#

using UnityEngine;
using System.Collections;
using System;
namespace RootMotion.Dynamics
{
public partial class PuppetMaster : MonoBehaviour
{
#if UNITY_EDITOR
[ContextMenu("Save Settings As Humanoid Config")]
private void SaveToHumanoidConfig()
{
var path = "Assets/Saved Humanoid Config.asset";
if (targetRoot == null)
{
Debug.LogWarning("Please assign 'Target Root' for PuppetMaster using a Humanoid Config.", transform);
return;
}
if (targetAnimator == null)
{
Debug.LogError("PuppetMaster 'Target Root' does not have an Animator component. Can not use Humanoid Config.", transform);
return;
}
if (!targetAnimator.isHuman)
{
Debug.LogError("PuppetMaster target is not a Humanoid. Can not use Humanoid Config.", transform);
return;
}
var p = ScriptableObject.CreateInstance<PuppetMasterHumanoidConfig>();
p.state = state;
p.stateSettings = stateSettings;
p.mode = mode;
p.blendTime = blendTime;
p.fixTargetTransforms = fixTargetTransforms;
p.solverIterationCount = solverIterationCount;
p.visualizeTargetPose = visualizeTargetPose;
p.mappingWeight = mappingWeight;
p.pinWeight = pinWeight;
p.muscleWeight = muscleWeight;
p.muscleSpring = muscleSpring;
p.muscleDamper = muscleDamper;
p.pinPow = pinPow;
p.pinDistanceFalloff = pinDistanceFalloff;
p.angularPinning = angularPinning;
p.updateJointAnchors = updateJointAnchors;
p.supportTranslationAnimation = supportTranslationAnimation;
p.angularLimits = angularLimits;
p.internalCollisions = internalCollisions;
p.muscles = new PuppetMasterHumanoidConfig.HumanoidMuscle[muscles.Length];
var allHumanBodyBones = (HumanBodyBones[])System.Enum.GetValues(typeof(HumanBodyBones));
for (int i = 0; i < muscles.Length; i++)
{
var m = muscles[i];
var h = new PuppetMasterHumanoidConfig.HumanoidMuscle();
h.props = new Muscle.Props();
h.bone = GetHumanBodyBone(m.target, allHumanBodyBones);
h.props.group = m.props.group;
h.props.mappingWeight = m.props.mappingWeight;
h.props.muscleDamper = m.props.muscleDamper;
h.props.muscleWeight = m.props.muscleWeight;
h.props.pinWeight = m.props.pinWeight;
p.muscles[i] = h;
}
UnityEditor.AssetDatabase.CreateAsset(p, path);
UnityEditor.AssetDatabase.SaveAssets();
UnityEditor.AssetDatabase.Refresh();
var saved = UnityEditor.AssetDatabase.LoadAssetAtPath(path, typeof(PuppetMasterHumanoidConfig)) as PuppetMasterHumanoidConfig;
if (saved != null)
{
Debug.Log("PuppetMasterHumanoidConfig successfully created at " + path);
UnityEditor.Selection.activeObject = saved;
}
}
private HumanBodyBones GetHumanBodyBone(Transform t, HumanBodyBones[] allBones)
{
for (int i = 0; i < allBones.Length - 1; i++)
{
var bone = allBones[i];
if (targetAnimator.GetBoneTransform(bone) == t) return bone;
}
//Debug.LogError("Unable to find HumanBodyBone of Transform " + t.name, transform);
return HumanBodyBones.LastBone;
}
#endif
}
[CreateAssetMenu(fileName = "PuppetMaster Humanoid Config", menuName = "PuppetMaster/Humanoid Config", order = 1)]
public class PuppetMasterHumanoidConfig : ScriptableObject
{
[System.Serializable]
public class HumanoidMuscle
{
[HideInInspector] public string name;
public HumanBodyBones bone;
public Muscle.Props props;
}
[LargeHeader("Simulation")]
public PuppetMaster.State state;
public PuppetMaster.StateSettings stateSettings = PuppetMaster.StateSettings.Default;
public PuppetMaster.Mode mode;
public float blendTime = 0.1f;
public bool fixTargetTransforms = true;
public int solverIterationCount = 6;
public bool visualizeTargetPose = true;
[LargeHeader("Master Weights")]
[Range(0f, 1f)] public float mappingWeight = 1f;
[Range(0f, 1f)] public float pinWeight = 1f;
[Range(0f, 1f)] public float muscleWeight = 1f;
[LargeHeader("Joint and Muscle Settings")]
public float muscleSpring = 100f;
public float muscleDamper = 0f;
[Range(1f, 8f)] public float pinPow = 4f;
[Range(0f, 100f)] public float pinDistanceFalloff = 5;
public bool angularPinning;
public bool updateJointAnchors = true;
public bool supportTranslationAnimation;
public bool angularLimits;
public bool internalCollisions;
[LargeHeader("Individual Muscle Settings")]
public HumanoidMuscle[] muscles = new HumanoidMuscle[0];
/// <summary>
/// Applies this config to the specified PuppetMaster.
/// </summary>
/// <param name="p">P.</param>
public void ApplyTo(PuppetMaster p)
{
if (p.targetRoot == null)
{
Debug.LogWarning("Please assign 'Target Root' for PuppetMaster using a Humanoid Config.", p.transform);
return;
}
if (p.targetAnimator == null)
{
Debug.LogError("PuppetMaster 'Target Root' does not have an Animator component. Can not use Humanoid Config.", p.transform);
return;
}
if (!p.targetAnimator.isHuman)
{
Debug.LogError("PuppetMaster target is not a Humanoid. Can not use Humanoid Config.", p.transform);
return;
}
p.state = state;
p.stateSettings = stateSettings;
p.mode = mode;
p.blendTime = blendTime;
p.fixTargetTransforms = fixTargetTransforms;
p.solverIterationCount = solverIterationCount;
p.visualizeTargetPose = visualizeTargetPose;
p.mappingWeight = mappingWeight;
p.pinWeight = pinWeight;
p.muscleWeight = muscleWeight;
p.muscleSpring = muscleSpring;
p.muscleDamper = muscleDamper;
p.pinPow = pinPow;
p.pinDistanceFalloff = pinDistanceFalloff;
p.angularPinning = angularPinning;
p.updateJointAnchors = updateJointAnchors;
p.supportTranslationAnimation = supportTranslationAnimation;
p.angularLimits = angularLimits;
p.internalCollisions = internalCollisions;
for (int i = 0; i < muscles.Length; i++)
{
var m = GetMuscle(muscles[i].bone, p.targetAnimator, p);
if (m == null && i < p.muscles.Length)
{
m = p.muscles[i];
}
if (m != null)
{
var h = muscles[i];
m.props.group = h.props.group;
m.props.mappingWeight = h.props.mappingWeight;
//m.props.mapPosition = h.props.mapPosition;
m.props.muscleDamper = h.props.muscleDamper;
m.props.muscleWeight = h.props.muscleWeight;
m.props.pinWeight = h.props.pinWeight;
}
}
}
private Muscle GetMuscle(HumanBodyBones boneId, Animator animator, PuppetMaster puppetMaster)
{
if (boneId == HumanBodyBones.LastBone) return null;
Transform bone = animator.GetBoneTransform(boneId);
if (bone == null) return null;
foreach (Muscle m in puppetMaster.muscles)
{
if (m.target == bone) return m;
}
return null;
}
}
}