该项目的目的是同时测试和演示来自 Unity DOTS 技术堆栈的多个新包。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

263 行
6.8 KiB

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.IO;
public static class PoseType
{
public static string tpose = "tpose";
public static string bindpose = "bindpose";
public static string humanpose = "humanpose";
}
[Serializable]
public class Bone : ISerializationCallbackReceiver
{
public string name;
[NonSerialized] public Vector3 position;
[NonSerialized] public Quaternion rotation;
[SerializeField] private float[] pos = new float[3];
[SerializeField] private float[] rot = new float[4];
Bone() {}
public Bone(string name, Vector3 position, Quaternion rotation)
{
this.name = name;
this.position = position;
this.rotation = rotation;
}
public void OnBeforeSerialize()
{
var serializedPosition = position;
var serializedRotation = rotation;
changeHandedness(ref serializedPosition, ref serializedRotation);
pos = new[] { serializedPosition.x, serializedPosition.y, serializedPosition.z };
rot = new[] { serializedRotation.x, serializedRotation.y, serializedRotation.z, serializedRotation.w };
}
public void OnAfterDeserialize()
{
position = new Vector3(pos[0], pos[1], pos[2]);
rotation = new Quaternion(rot[0], rot[1], rot[2], rot[3]);
changeHandedness(ref position, ref rotation);
}
static void changeHandedness(ref Vector3 position, ref Quaternion rotation)
{
var spaceConvertMatrix = Matrix4x4.TRS(new Vector3(0, 0, 0), Quaternion.identity, new Vector3(-1, 1, 1));
var origMatrix = Matrix4x4.TRS(position, rotation, new Vector3(1, 1, 1));
var flippedMatrix = spaceConvertMatrix * origMatrix;
position = new Vector3(flippedMatrix[0, 3], flippedMatrix[1, 3], flippedMatrix[2, 3]);
rotation = QuaternionFromMatrix(flippedMatrix);
}
static Quaternion QuaternionFromMatrix(Matrix4x4 m)
{
return Quaternion.LookRotation(m.GetColumn(2), m.GetColumn(1));
}
}
[Serializable]
public class Pose
{
public string name = "";
public List<Bone> bones = new List<Bone>();
Pose() {}
public Pose(string name, List<Bone> bones)
{
this.name = name;
this.bones = bones;
}
}
[Serializable]
public class Poses
{
public List<Pose> poses = new List<Pose>();
}
public static class SaveLoadPoses
{
static string filepath => $"{Path.GetTempPath()}/Skeleton_Pose.json";
[MenuItem("A2/Animation/Skeleton Pose Interop/Load from tmp folder: Bind Pose (Selected)")]
static void LoadBindPose()
{
LoadPose(PoseType.bindpose);
}
[MenuItem("A2/Animation/Skeleton Pose Interop/Load from tmp folder: T-Pose (Selected)")]
static void LoadRigPose()
{
LoadPose(PoseType.tpose);
}
[MenuItem("A2/Animation/Skeleton Pose Interop/Load from tmp folder: Human Pose (Selected)")]
static void LoadHumanPose()
{
LoadPose(PoseType.humanpose);
}
[MenuItem("A2/Animation/Skeleton Pose Interop/")]
static void SeperateMe()
{
EditorGUILayout.Separator();
}
[MenuItem("A2/Animation/Skeleton Pose Interop/Save to tmp folder: Bind Pose (Selected)")]
static void SaveBindPose()
{
SavePose(PoseType.bindpose);
}
[MenuItem("A2/Animation/Skeleton Pose Interop/Save to tmp folder: T-Pose (Selected)")]
static void SaveRigPose()
{
SavePose(PoseType.tpose);
}
[MenuItem("A2/Animation/Skeleton Pose Interop/Save to tmp folder: Human Pose (Selected)")]
static void SaveHumanPose()
{
SavePose(PoseType.humanpose);
}
static Poses ReadFromJson()
{
var poses = new Poses();
if (File.Exists(filepath))
{
var json = File.ReadAllText(filepath);
poses = JsonUtility.FromJson<Poses>(json);
}
if (poses == null)
{
poses = new Poses();
}
return poses;
}
static void WriteToJson(Poses poses)
{
var json = JsonUtility.ToJson(poses, true);
var writer = File.CreateText(filepath);
writer.Close();
File.WriteAllText(filepath, json);
}
static bool LoadPose(string poseType)
{
var poses = ReadFromJson();
foreach (var pose in poses.poses)
{
if (pose.name == poseType)
{
if (SetPose(pose))
{
Debug.Log("Successfully loaded pose: " + poseType);
return true;
}
}
}
Debug.LogWarning("Failed to load pose..: " + poseType);
return false;
}
static void SavePose(string poseType)
{
var poses = ReadFromJson();
var newPose = GetPose(poseType);
if (newPose.bones.Count < 1)
{
Debug.LogWarning("No bones found. Aborting save of pose: " + poseType);
return;
}
var poseWritten = false;
for (var i = 0; i < poses.poses.Count; i++)
{
if (poses.poses[i].name == poseType)
{
poses.poses[i] = newPose;
poseWritten = true;
}
}
if (!poseWritten)
poses.poses.Add(newPose);
WriteToJson(poses);
Debug.Log("Successfully saved pose: " + poseType);
}
static Pose GetPose(string poseType)
{
var bones = new List<Bone>();
var root = Selection.activeGameObject.transform;
var hierarchy = root.GetComponentsInChildren<Transform>(true);
foreach (var bone in hierarchy)
{
bones.Add(new Bone(bone.name, bone.localPosition, bone.localRotation));
}
return new Pose(poseType, bones);
}
static bool SetPose(Pose pose)
{
var selected = Selection.activeGameObject;
if (selected == null) { return false; }
var root = selected.transform;
var hierarchy = root.GetComponentsInChildren<Transform>(true);
var boneMap = new Dictionary<string, Transform>();
foreach (var bone in root.GetComponentsInChildren<Transform>(true))
{
if (!boneMap.ContainsKey(bone.name))
{
boneMap.Add(bone.name, bone);
}
else
{
Debug.Log("Bone already in map: " + bone.name);
}
}
Undo.RecordObjects(hierarchy, "Set Skeleton Pose");
foreach (var bonePose in pose.bones)
{
Transform bone;
boneMap.TryGetValue(bonePose.name, out bone);
if (bone != null)
{
bone.localPosition = bonePose.position;
bone.localRotation = bonePose.rotation;
}
}
return true;
}
}