242 lines
8.4 KiB
C#
242 lines
8.4 KiB
C#
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
using UnityEngine;
|
|
using System;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
|
|
|
|
namespace UniHumanoid
|
|
{
|
|
[Serializable]
|
|
public struct BoneLimit
|
|
{
|
|
public HumanBodyBones humanBone;
|
|
public string boneName;
|
|
public bool useDefaultValues;
|
|
public Vector3 min;
|
|
public Vector3 max;
|
|
public Vector3 center;
|
|
public float axisLength;
|
|
|
|
public static BoneLimit From(HumanBone bone)
|
|
{
|
|
return new BoneLimit
|
|
{
|
|
humanBone = (HumanBodyBones)Enum.Parse(typeof(HumanBodyBones), bone.humanName.Replace(" ", ""), true),
|
|
boneName = bone.boneName,
|
|
useDefaultValues = bone.limit.useDefaultValues,
|
|
min = bone.limit.min,
|
|
max = bone.limit.max,
|
|
center = bone.limit.center,
|
|
axisLength = bone.limit.axisLength,
|
|
};
|
|
}
|
|
|
|
public static String ToHumanBoneName(HumanBodyBones b)
|
|
{
|
|
foreach (var x in HumanTrait.BoneName)
|
|
{
|
|
if (x.Replace(" ", "") == b.ToString())
|
|
{
|
|
return x;
|
|
}
|
|
}
|
|
|
|
throw new KeyNotFoundException();
|
|
}
|
|
|
|
public HumanBone ToHumanBone()
|
|
{
|
|
return new HumanBone
|
|
{
|
|
boneName = boneName,
|
|
humanName = ToHumanBoneName(humanBone),
|
|
limit = new HumanLimit
|
|
{
|
|
useDefaultValues = useDefaultValues,
|
|
axisLength = axisLength,
|
|
center = center,
|
|
max = max,
|
|
min = min
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class AvatarDescription : ScriptableObject
|
|
{
|
|
public float armStretch = 0.05f;
|
|
public float legStretch = 0.05f;
|
|
public float upperArmTwist = 0.5f;
|
|
public float lowerArmTwist = 0.5f;
|
|
public float upperLegTwist = 0.5f;
|
|
public float lowerLegTwist = 0.5f;
|
|
public float feetSpacing = 0;
|
|
public bool hasTranslationDoF;
|
|
public BoneLimit[] human;
|
|
|
|
public HumanDescription ToHumanDescription(Transform root)
|
|
{
|
|
return new HumanDescription
|
|
{
|
|
skeleton = root.Traverse().Select(x => x.ToSkeletonBone()).ToArray(),
|
|
human = human.Select(x => x.ToHumanBone()).ToArray(),
|
|
armStretch = armStretch,
|
|
legStretch = legStretch,
|
|
upperArmTwist = upperArmTwist,
|
|
lowerArmTwist = lowerArmTwist,
|
|
upperLegTwist = upperLegTwist,
|
|
lowerLegTwist = lowerLegTwist,
|
|
feetSpacing = feetSpacing,
|
|
hasTranslationDoF = hasTranslationDoF,
|
|
};
|
|
}
|
|
|
|
public Avatar CreateAvatar(Transform root)
|
|
{
|
|
return AvatarBuilder.BuildHumanAvatar(root.gameObject, ToHumanDescription(root));
|
|
}
|
|
|
|
public Avatar CreateAvatarAndSetup(Transform root)
|
|
{
|
|
var avatar = CreateAvatar(root);
|
|
avatar.name = name;
|
|
|
|
var animator = root.GetComponent<Animator>();
|
|
if (animator != null)
|
|
{
|
|
var positionMap = root.Traverse().ToDictionary(x => x, x => x.position);
|
|
animator.avatar = avatar;
|
|
foreach (var x in root.Traverse())
|
|
{
|
|
x.position = positionMap[x];
|
|
}
|
|
}
|
|
|
|
var transfer = root.GetComponent<HumanPoseTransfer>();
|
|
if (transfer != null)
|
|
{
|
|
transfer.Avatar = avatar;
|
|
}
|
|
|
|
return avatar;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
public static AvatarDescription CreateFrom(Avatar avatar)
|
|
{
|
|
var description = default(HumanDescription);
|
|
if (!GetHumanDescription(avatar, ref description))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return CreateFrom(description);
|
|
}
|
|
#endif
|
|
|
|
public static AvatarDescription CreateFrom(HumanDescription description)
|
|
{
|
|
var avatarDescription = ScriptableObject.CreateInstance<AvatarDescription>();
|
|
avatarDescription.name = "AvatarDescription";
|
|
avatarDescription.armStretch = description.armStretch;
|
|
avatarDescription.legStretch = description.legStretch;
|
|
avatarDescription.feetSpacing = description.feetSpacing;
|
|
avatarDescription.hasTranslationDoF = description.hasTranslationDoF;
|
|
avatarDescription.lowerArmTwist = description.lowerArmTwist;
|
|
avatarDescription.lowerLegTwist = description.lowerLegTwist;
|
|
avatarDescription.upperArmTwist = description.upperArmTwist;
|
|
avatarDescription.upperLegTwist = description.upperLegTwist;
|
|
avatarDescription.human = description.human.Select(BoneLimit.From).ToArray();
|
|
return avatarDescription;
|
|
}
|
|
|
|
public static AvatarDescription Create(AvatarDescription src=null)
|
|
{
|
|
var avatarDescription = ScriptableObject.CreateInstance<AvatarDescription>();
|
|
avatarDescription.name = "AvatarDescription";
|
|
if (src != null)
|
|
{
|
|
avatarDescription.armStretch = src.armStretch;
|
|
avatarDescription.legStretch = src.legStretch;
|
|
avatarDescription.feetSpacing = src.feetSpacing;
|
|
avatarDescription.upperArmTwist = src.upperArmTwist;
|
|
avatarDescription.lowerArmTwist = src.lowerArmTwist;
|
|
avatarDescription.upperLegTwist = src.upperLegTwist;
|
|
avatarDescription.lowerLegTwist = src.lowerLegTwist;
|
|
}
|
|
else
|
|
{
|
|
avatarDescription.armStretch = 0.05f;
|
|
avatarDescription.legStretch = 0.05f;
|
|
avatarDescription.feetSpacing = 0.0f;
|
|
avatarDescription.lowerArmTwist = 0.5f;
|
|
avatarDescription.upperArmTwist = 0.5f;
|
|
avatarDescription.upperLegTwist = 0.5f;
|
|
avatarDescription.lowerLegTwist = 0.5f;
|
|
}
|
|
return avatarDescription;
|
|
}
|
|
|
|
public static AvatarDescription Create(Transform[] boneTransforms, Skeleton skeleton)
|
|
{
|
|
return Create(skeleton.Bones.Select(
|
|
x => new KeyValuePair<HumanBodyBones, Transform>(x.Key, boneTransforms[x.Value])));
|
|
}
|
|
|
|
public static AvatarDescription Create(IEnumerable<KeyValuePair<HumanBodyBones, Transform>> skeleton)
|
|
{
|
|
var description = Create();
|
|
description.SetHumanBones(skeleton);
|
|
return description;
|
|
}
|
|
|
|
public void SetHumanBones(IEnumerable<KeyValuePair<HumanBodyBones, Transform>> skeleton)
|
|
{
|
|
human = skeleton.Select(x =>
|
|
{
|
|
return new BoneLimit
|
|
{
|
|
humanBone = x.Key,
|
|
boneName = x.Value.name,
|
|
useDefaultValues = true,
|
|
};
|
|
}).ToArray();
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
/// <summary>
|
|
/// * https://answers.unity.com/questions/612177/how-can-i-access-human-avatar-bone-and-muscle-valu.html
|
|
/// </summary>
|
|
/// <param name="target"></param>
|
|
/// <param name="des"></param>
|
|
/// <returns></returns>
|
|
public static bool GetHumanDescription(UnityEngine.Object target, ref HumanDescription des)
|
|
{
|
|
if (target != null)
|
|
{
|
|
var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(target));
|
|
if (importer != null)
|
|
{
|
|
Debug.Log("AssetImporter Type: " + importer.GetType());
|
|
ModelImporter modelImporter = importer as ModelImporter;
|
|
if (modelImporter != null)
|
|
{
|
|
des = modelImporter.humanDescription;
|
|
Debug.Log("## Cool stuff data by ModelImporter ##");
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("## Please Select Imported Model in Project View not prefab or other things ##");
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
}
|
|
}
|