您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
200 行
5.9 KiB
200 行
5.9 KiB
using UnityEngine;
|
|
using UnityEditor;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Unity.DemoTeam.DigitalHuman
|
|
{
|
|
[CustomEditor(typeof(SkinAttachmentTarget))]
|
|
public class SkinAttachmentTargetEditor : Editor
|
|
{
|
|
private HashSet<SkinAttachmentTarget> attachmentTargetSet = new HashSet<SkinAttachmentTarget>();
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
attachmentTargetSet.Clear();
|
|
|
|
if (target == null)
|
|
return;
|
|
|
|
var driver = target as SkinAttachmentTarget;
|
|
if (driver == null)
|
|
return;
|
|
|
|
if (driver.attachData == null)
|
|
{
|
|
EditorGUILayout.HelpBox("Must bind SkinAttachmentData asset before use.", MessageType.Error);
|
|
base.OnInspectorGUI();
|
|
return;
|
|
}
|
|
|
|
EditorGUILayout.HelpBox("Currently bound to " + driver.attachData + "\nChecksum: " + driver.attachData.Checksum(), MessageType.Info);
|
|
DrawGUIAttachmentData(driver.attachData);
|
|
DrawGUIAttachmentDataValidation(driver);
|
|
EditorGUILayout.Separator();
|
|
|
|
base.OnInspectorGUI();
|
|
EditorGUILayout.Separator();
|
|
|
|
GUILayout.Label(string.Format("Attachments ({0})", driver.subjects.Count), EditorStyles.boldLabel);
|
|
var checksum = driver.attachData.Checksum();
|
|
var checksumFailed = driver.CommitRequired();
|
|
for (int i = 0; i != driver.subjects.Count; i++)
|
|
{
|
|
var attachment = driver.subjects[i];
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.ObjectField(attachment, typeof(SkinAttachment), false);
|
|
SkinAttachmentEditor.DrawGUIDetach(attachment, attachmentTargetSet);
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
if (checksumFailed)
|
|
{
|
|
if (checksum != attachment.Checksum())
|
|
{
|
|
Color color = GUI.color;
|
|
GUI.color = Color.red;
|
|
GUILayout.Label("Checksum FAILED: " + attachment.Checksum(), EditorStyles.helpBox);
|
|
GUI.color = color;
|
|
}
|
|
else
|
|
{
|
|
GUILayout.Label("Checksum passed: " + attachment.Checksum(), EditorStyles.helpBox);
|
|
}
|
|
}
|
|
|
|
if (i >= driver.subjects.Count || driver.subjects[i] != attachment)
|
|
i--;
|
|
}
|
|
|
|
SkinAttachmentEditor.CommitTargetChanges(attachmentTargetSet);
|
|
}
|
|
|
|
void DrawGUIAttachmentData(SkinAttachmentData attachData)
|
|
{
|
|
if (DrawGUIGrowShrink("Poses", ref attachData.pose, attachData.poseCount))
|
|
{
|
|
attachData.Persist();
|
|
}
|
|
if (DrawGUIGrowShrink("Items" , ref attachData.item, attachData.itemCount))
|
|
{
|
|
attachData.Persist();
|
|
}
|
|
}
|
|
|
|
void DrawGUIAttachmentDataValidation(SkinAttachmentTarget driver)
|
|
{
|
|
var checksum = driver.attachData.Checksum();
|
|
var checksumFailed = driver.CommitRequired();
|
|
if (checksumFailed)
|
|
{
|
|
EditorGUILayout.HelpBox("Rebuild required: Checksum of driver or one or more subjects does not match checksum of data.", MessageType.Warning);
|
|
}
|
|
else if (driver.attachData.subjectCount != driver.subjects.Count)
|
|
{
|
|
EditorGUILayout.HelpBox("Rebuild suggested: Data contains poses that are no longer referenced.", MessageType.Warning);
|
|
}
|
|
|
|
if (GUILayout.Button("Rebuild"))
|
|
{
|
|
driver.CommitSubjects();
|
|
}
|
|
}
|
|
|
|
bool DrawGUIGrowShrink<T>(string label, ref T[] buffer, int count)
|
|
{
|
|
var capacity = buffer.Length;
|
|
var capacityChanged = false;
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
{
|
|
GUILayout.Button(string.Empty, GUILayout.ExpandWidth(true));
|
|
EditorGUI.ProgressBar(GUILayoutUtility.GetLastRect(), count / (float)capacity, label + ": " + count + " / " + capacity);
|
|
|
|
if (GUILayout.Button("Grow", GUILayout.ExpandWidth(false)))
|
|
{
|
|
ArrayUtils.ResizeChecked(ref buffer, buffer.Length * 2);
|
|
capacityChanged = true;
|
|
}
|
|
|
|
EditorGUI.BeginDisabledGroup(count > capacity / 2);
|
|
if (GUILayout.Button("Shrink", GUILayout.ExpandWidth(false)))
|
|
{
|
|
ArrayUtils.ResizeChecked(ref buffer, buffer.Length / 2);
|
|
capacityChanged = true;
|
|
}
|
|
EditorGUI.EndDisabledGroup();
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
return capacityChanged;
|
|
}
|
|
|
|
void OnSceneGUI()
|
|
{
|
|
var driver = target as SkinAttachmentTarget;
|
|
if (driver == null)
|
|
return;
|
|
|
|
if (driver.showMouseOver)
|
|
{
|
|
DrawSceneGUIMouseOver(driver);
|
|
}
|
|
}
|
|
|
|
public static void DrawSceneGUIMouseOver(SkinAttachmentTarget driver)
|
|
{
|
|
var mouseScreen = Event.current.mousePosition;
|
|
var mouseWorldRay = HandleUtility.GUIPointToWorldRay(mouseScreen);
|
|
|
|
var objectRayPos = driver.transform.InverseTransformPoint(mouseWorldRay.origin);
|
|
var objectRayDir = driver.transform.InverseTransformDirection(mouseWorldRay.direction);
|
|
|
|
var meshInfo = driver.GetCachedMeshInfo();
|
|
if (meshInfo.valid == false)
|
|
return;
|
|
|
|
var vertex = meshInfo.meshVertexBSP.RaycastApprox(ref objectRayPos, ref objectRayDir, 10);
|
|
if (vertex == -1)
|
|
return;
|
|
|
|
using (var scope = new Handles.DrawingScope(Color.blue, driver.transform.localToWorldMatrix))
|
|
{
|
|
const int maxDepth = 3;
|
|
|
|
var triangleColor = Handles.color;
|
|
var triangleDepth = 0;
|
|
|
|
using (var triangleBFS = new UnsafeBFS(meshInfo.meshAdjacency.triangleCount))
|
|
{
|
|
foreach (var triangle in meshInfo.meshAdjacency.vertexTriangles[vertex])
|
|
{
|
|
triangleBFS.Insert(triangle);
|
|
}
|
|
|
|
while (triangleBFS.MoveNext() && triangleBFS.depth < maxDepth)
|
|
{
|
|
if (triangleDepth < triangleBFS.depth)
|
|
{
|
|
triangleDepth = triangleBFS.depth;
|
|
Handles.color = Color.Lerp(triangleColor, Color.clear, Mathf.InverseLerp(0, maxDepth, triangleDepth));
|
|
}
|
|
|
|
var _e = meshInfo.meshAdjacency.triangleVertices[triangleBFS.position].GetEnumerator();
|
|
int v0 = _e.ReadNext();
|
|
int v1 = _e.ReadNext();
|
|
int v2 = _e.ReadNext();
|
|
|
|
Handles.DrawLine(meshInfo.meshBuffers.vertexPositions[v0], meshInfo.meshBuffers.vertexPositions[v1]);
|
|
Handles.DrawLine(meshInfo.meshBuffers.vertexPositions[v1], meshInfo.meshBuffers.vertexPositions[v2]);
|
|
Handles.DrawLine(meshInfo.meshBuffers.vertexPositions[v2], meshInfo.meshBuffers.vertexPositions[v0]);
|
|
|
|
foreach (var triangle in meshInfo.meshAdjacency.triangleTriangles[triangleBFS.position])
|
|
{
|
|
triangleBFS.Insert(triangle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|