329 lines
14 KiB
C#
329 lines
14 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using Passer;
|
|
using Passer.Humanoid.Tracking;
|
|
|
|
namespace Passer.Humanoid {
|
|
|
|
[CustomEditor(typeof(Pose))]
|
|
public class Pose_Editor : Editor {
|
|
private Pose pose;
|
|
|
|
#region Enable
|
|
public void OnEnable() {
|
|
pose = (Pose)target;
|
|
if (pose.bonePoses == null)
|
|
pose.bonePoses = new List<BonePose>();
|
|
}
|
|
#endregion
|
|
|
|
#region Disable
|
|
public void OnDisable() {
|
|
pose.Cleanup();
|
|
}
|
|
#endregion
|
|
|
|
private enum Reference {
|
|
HumanoidLocal,
|
|
BoneLocal
|
|
}
|
|
|
|
#region Inspector
|
|
public override void OnInspectorGUI() {
|
|
for (int i = 0; i < pose.bonePoses.Count; i++) {
|
|
BonePose bonePoses = pose.bonePoses[i];
|
|
if (bonePoses == null)
|
|
continue;
|
|
|
|
if (bonePoses.boneRef.type == BoneType.SideBones && bonePoses.boneRef.side == Side.AnySide) {
|
|
EditorGUILayout.HelpBox("Configure AnySide like Left Side", MessageType.Info);
|
|
}
|
|
EditorGUILayout.BeginHorizontal();
|
|
bonePoses.boneRef.type = (BoneType)EditorGUILayout.EnumPopup(bonePoses.boneRef.type, GUILayout.Width(159));
|
|
Bone oldBoneId = bonePoses.boneRef.boneId;
|
|
SideBone oldSideBoneId = bonePoses.boneRef.sideBoneId;
|
|
BoneSelector(ref bonePoses.boneRef);
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
if (bonePoses.boneRef.boneId != oldBoneId || bonePoses.boneRef.sideBoneId != oldSideBoneId)
|
|
PresetReferenceBone(bonePoses.boneRef, ref bonePoses.referenceBoneRef);
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.LabelField("Reference", GUILayout.MaxWidth(65));
|
|
bonePoses.referenceBoneRef.type = (BoneType)EditorGUILayout.EnumPopup(bonePoses.referenceBoneRef.type, GUILayout.Width(90));
|
|
|
|
BoneSelector(ref bonePoses.referenceBoneRef); EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUI.indentLevel++;
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
bonePoses.setTranslation = EditorGUILayout.ToggleLeft("Translation", bonePoses.setTranslation, GUILayout.MaxWidth(131));
|
|
if (bonePoses.setTranslation)
|
|
bonePoses.translation = EditorGUILayout.Vector3Field("", bonePoses.translation);
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
bonePoses.setRotation = EditorGUILayout.ToggleLeft("Rotation", bonePoses.setRotation, GUILayout.MaxWidth(131));
|
|
if (bonePoses.setRotation) {
|
|
Vector3 eulerAngles = EditorGUILayout.Vector3Field("", bonePoses.rotation.eulerAngles);
|
|
if (eulerAngles != bonePoses.rotation.eulerAngles)
|
|
bonePoses.rotation.eulerAngles = eulerAngles;
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
bonePoses.setScale = EditorGUILayout.ToggleLeft("Scale", bonePoses.setScale, GUILayout.MaxWidth(131));
|
|
if (bonePoses.setScale)
|
|
bonePoses.scale = EditorGUILayout.Vector3Field("", bonePoses.scale);
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
Buttons();
|
|
EditorUtility.SetDirty(pose);
|
|
}
|
|
|
|
private void PresetReferenceBone(BoneReference bone, ref BoneReference referenceBone) {
|
|
if (referenceBone.boneId != Bone.None)
|
|
return;
|
|
|
|
if (bone.isFacialBone)
|
|
referenceBone.centerBoneId = CenterBone.Head;
|
|
if (bone.isHandBone) {
|
|
referenceBone.sideBoneId = SideBone.Hand;
|
|
referenceBone.type = BoneType.SideBones;
|
|
}
|
|
}
|
|
|
|
private void BoneSelector(ref BoneReference bone) {
|
|
switch (bone.type) {
|
|
case BoneType.AllBones:
|
|
bone.boneId = (Bone)EditorGUILayout.EnumPopup(bone.boneId);
|
|
return;
|
|
case BoneType.CenterBones:
|
|
CenterBone centerBone = (CenterBone)EditorGUILayout.EnumPopup(bone.centerBoneId);
|
|
if (centerBone != CenterBone.Unknown)
|
|
bone.centerBoneId = centerBone;
|
|
return;
|
|
case BoneType.SideBones:
|
|
if (bone.boneId == Bone.None) {
|
|
SideBone sideBoneId = bone.sideBoneId;
|
|
bone.sideBoneId = (SideBone)EditorGUILayout.EnumPopup(sideBoneId);
|
|
}
|
|
else {
|
|
bone.sideBoneId = (SideBone)EditorGUILayout.EnumPopup(bone.sideBoneId);
|
|
}
|
|
bone.side = (Side)EditorGUILayout.EnumPopup(bone.side, GUILayout.Width(80));
|
|
return;
|
|
case BoneType.FaceBones:
|
|
bone.faceBoneId = (FacialBone)EditorGUILayout.EnumPopup(bone.faceBoneId);
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
#region Buttons
|
|
private void Buttons() {
|
|
EditorGUILayout.BeginHorizontal();
|
|
AddBoneButton();
|
|
ClearAllButton();
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
private void AddBoneButton() {
|
|
if (GUILayout.Button("Add Bone")) {
|
|
//PoseBone newBone = new PoseBone();
|
|
//PoseBone newBone = ScriptableObject.CreateInstance<PoseBone>();
|
|
//pose.bones.Add(newBone);
|
|
pose.AddBone(Bone.None);
|
|
}
|
|
}
|
|
private void ClearAllButton() {
|
|
if (GUILayout.Button("Clear All")) {
|
|
pose.bonePoses = new List<BonePose>();
|
|
//pose.boneArray = new BonePose[0];
|
|
}
|
|
|
|
}
|
|
#endregion
|
|
#endregion
|
|
|
|
public static void PoseMixerInspector(PoseMixer poseMixer, HumanoidControl humanoid, Side side = Side.AnySide) {
|
|
int i = 0;
|
|
foreach (MixedPose pose in poseMixer.mixedPoses) {
|
|
Pose oldPose = pose.pose;
|
|
HumanoidPoseInspector(poseMixer, pose, i, humanoid, side);
|
|
if (pose.pose != oldPose && pose.pose == null) {
|
|
// We deleted a pose, let's undo it's effect
|
|
pose.value = 0;
|
|
pose.pose = oldPose;
|
|
poseMixer.ShowPose(humanoid);
|
|
pose.pose = null;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
Pose addPose = (Pose)EditorGUILayout.ObjectField(null, typeof(Pose), false, GUILayout.Width(200));
|
|
if (addPose != null) {
|
|
MixedPose newPose = poseMixer.Add();
|
|
newPose.pose = addPose;
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
public static MixedPose HumanoidPoseInspector(PoseMixer poseMixer, MixedPose mixedPose, int poseIx, HumanoidControl humanoid, Side side = Side.AnySide) {
|
|
EditorGUILayout.BeginHorizontal();
|
|
|
|
if (poseMixer.poseMode == PoseMixer.PoseMode.Set)
|
|
mixedPose.pose = (Pose)EditorGUILayout.ObjectField(mixedPose.pose, typeof(Pose), false, GUILayout.Width(200));
|
|
else
|
|
mixedPose.pose = (Pose)EditorGUILayout.ObjectField(mixedPose.pose, typeof(Pose), false);
|
|
if (mixedPose.pose != null) {
|
|
if (mixedPose.isEdited) {
|
|
EditorGUILayout.Slider(mixedPose.value, 0, 1);
|
|
poseMixer.SetPoseValue(poseIx, 1);
|
|
}
|
|
else if (poseMixer.poseMode == PoseMixer.PoseMode.Set)
|
|
{
|
|
float value = EditorGUILayout.Slider(mixedPose.value, 0, 1);
|
|
if (value != mixedPose.value) {
|
|
poseMixer.SetPoseValue(poseIx, value);
|
|
}
|
|
}
|
|
if (!Application.isPlaying || side == Side.AnySide) {
|
|
bool isEdited = EditorGUILayout.Toggle(mixedPose.isEdited, "button", GUILayout.Width(19));
|
|
if (mixedPose.isEdited != isEdited)
|
|
SceneView.RepaintAll();
|
|
mixedPose.isEdited = isEdited;
|
|
}
|
|
else {
|
|
EditorGUILayout.FloatField(mixedPose.score);
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.EndHorizontal();
|
|
if (mixedPose.isEdited) {
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.LabelField(" ", GUILayout.Width(200));
|
|
mixedPose.additive = EditorGUILayout.ToggleLeft("Additive", mixedPose.additive);
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
return mixedPose;
|
|
}
|
|
|
|
#region Scene
|
|
|
|
static int boneIndex = -1;
|
|
public static void UpdateScene(HumanoidControl humanoid, ITarget target, PoseMixer poseMixer, ref BonePose selectedBone, Side side = Side.AnySide) {
|
|
//if (!Application.isPlaying)
|
|
// poseMixer.ShowPose(humanoid);
|
|
|
|
MixedPose currentPose = poseMixer.GetEditedPose();
|
|
if (currentPose == null || !currentPose.isEdited) {
|
|
UnityEditor.Tools.hidden = false;
|
|
return;
|
|
}
|
|
|
|
UnityEditor.Tools.hidden = true;
|
|
|
|
HumanoidTarget.TargetedBone[] bones = target.GetBones();
|
|
int[] controlIds = new int[bones.Length];
|
|
Bone[] boneIds = new Bone[bones.Length];
|
|
|
|
for (int i = 0; i < bones.Length; i++) {
|
|
if (bones[i] == null || bones[i].bone == null || bones[i].bone.transform == null)
|
|
continue;
|
|
|
|
#if UNITY_2022_1_OR_NEWER
|
|
Handles.FreeMoveHandle(bones[i].bone.transform.position, 0.002F, Vector3.zero, DotHandleCapSaveID);
|
|
#else
|
|
Handles.FreeMoveHandle(bones[i].bone.transform.position, bones[i].bone.transform.rotation, 0.002F, Vector3.zero, DotHandleCapSaveID);
|
|
#endif
|
|
|
|
|
|
controlIds[i] = lastControlID;
|
|
boneIds[i] = bones[i].boneId;
|
|
}
|
|
|
|
FindSelectedHandle(controlIds, boneIds, ref boneIndex);
|
|
if (boneIndex == -1)
|
|
return;
|
|
|
|
HumanoidTarget.TargetedBone targetedBone = FindTargetedBone(bones, boneIds[boneIndex]);
|
|
if (targetedBone == null || targetedBone.bone.transform == null)
|
|
return;
|
|
|
|
GUIStyle style = new GUIStyle();
|
|
style.normal.textColor = Color.yellow;
|
|
Handles.Label(targetedBone.bone.transform.position + Vector3.up * 0.01F, targetedBone.name, style);
|
|
Handles.color = Color.white;
|
|
|
|
switch (UnityEditor.Tools.current) {
|
|
case Tool.Move:
|
|
selectedBone = currentPose.pose.CheckBone(boneIds[boneIndex], true);
|
|
Vector3 handlePosition = Handles.PositionHandle(targetedBone.target.transform.position, targetedBone.bone.transform.rotation);
|
|
targetedBone.target.transform.position = handlePosition;
|
|
selectedBone.setTranslation = true;
|
|
selectedBone.SetReferenceLocal(humanoid, side);
|
|
selectedBone.UpdateTranslation(humanoid, side);
|
|
break;
|
|
case Tool.Rotate:
|
|
selectedBone = currentPose.pose.CheckBone(boneIds[boneIndex], true);
|
|
Quaternion handleRotation = Handles.RotationHandle(targetedBone.target.transform.rotation, targetedBone.bone.transform.position);
|
|
targetedBone.target.transform.rotation = handleRotation;
|
|
selectedBone.setRotation = true;
|
|
selectedBone.SetReferenceLocal(humanoid, side);
|
|
selectedBone.UpdateRotation(humanoid, side);
|
|
break;
|
|
case Tool.Scale:
|
|
//Handles.ScaleHandle(selectedBone.transform.localScale, selectedBone.transform.position, selectedBone.transform.rotation, HandleUtility.GetHandleSize(selectedBone.transform.position));
|
|
// need to all morphScale first...
|
|
break;
|
|
}
|
|
|
|
Handles.BeginGUI();
|
|
ResetBoneButton(selectedBone, humanoid);
|
|
Handles.EndGUI();
|
|
|
|
}
|
|
|
|
private static void ResetBoneButton(BonePose selectedBone, HumanoidControl humanoid) {
|
|
if (GUILayout.Button("Reset Bone", GUILayout.Width(100))) {
|
|
Debug.Log("Got it to work.");
|
|
selectedBone.setRotation = false;
|
|
selectedBone.rotation = Quaternion.identity;
|
|
HumanoidTarget.TargetedBone targetedBone = humanoid.GetBone(selectedBone.boneRef.boneId);
|
|
targetedBone.target.transform.localRotation = selectedBone.rotation;
|
|
}
|
|
}
|
|
|
|
private static HumanoidTarget.TargetedBone FindTargetedBone(HumanoidTarget.TargetedBone[] bones, Tracking.Bone boneId) {
|
|
foreach (HumanoidTarget.TargetedBone bone in bones) {
|
|
if (bone.boneId == boneId)
|
|
return bone;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
static int lastControlID;
|
|
public static void DotHandleCapSaveID(int controlID, Vector3 position, Quaternion rotation, float size, EventType et) {
|
|
lastControlID = controlID;
|
|
Handles.DotHandleCap(controlID, position, rotation, size, et);
|
|
}
|
|
|
|
private static void FindSelectedHandle(int[] controlIds, Tracking.Bone[] boneIds, ref int boneIndex) {
|
|
for (int i = 0; i < controlIds.Length; i++) {
|
|
if (controlIds[i] != 0 && controlIds[i] == GUIUtility.hotControl) {
|
|
boneIndex = i;
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|