2024-01-18 12:14:00 +01:00

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
}
}