public static void ConvertToComposeData(UnityEngine.Object targetObject) { var targetMesh = Utils.ExtractMesh(targetObject); if (targetMesh == null) { return; } var materials = Utils.ExtractMaterials(targetObject); int numBS = targetMesh.blendShapeCount; if (numBS == 0) { Debug.Log("BlendShapeInspector: This mesh has no BlendShape."); return; } var baseMesh = Instantiate(targetMesh); baseMesh.name = targetMesh.name; baseMesh.ClearBlendShapes(); var baseGO = Utils.MeshToGameObject(baseMesh, Vector3.zero, materials); var builder = baseGO.AddComponent <BlendShapeBuilder>(); var data = builder.data.blendShapeData; data.Clear(); for (int bi = 0; bi < numBS; ++bi) { var name = targetMesh.GetBlendShapeName(bi); int numFrames = targetMesh.GetBlendShapeFrameCount(bi); var gos = ExtractBlendShapeFrames(targetMesh, bi, -1, materials); float step = 100.0f / numFrames; float weight = step; var bsd = new BlendShapeData(); data.Add(bsd); bsd.name = name; foreach (var go in gos) { var fd = new BlendShapeFrameData(); bsd.frames.Add(fd); fd.mesh = go; fd.weight = weight; weight += step; } } Undo.RegisterCreatedObjectUndo(baseGO, "BlendShapeBuilder"); Selection.activeObject = baseGO; BlendShapeBuilderWindow.Open(); }
void OnAddFrame(BlendShapeData bsd) { Undo.RecordObject(this, "BlendShapeBuilder"); var frame = new BlendShapeFrameData(); bsd.frames.Add(frame); bsd.NormalizeWeights(); var meshBase = Utils.ExtractMesh(m_target.gameObject); if (meshBase == null) { return; } var meshNew = Instantiate(meshBase); meshNew.name = meshNew.name.Replace("(Clone)", ":" + bsd.name + "[" + (bsd.frames.Count - 1) + "]"); frame.mesh = Utils.MeshToGameObject(meshNew, m_target.gameObject); Undo.RegisterCreatedObjectUndo(frame.mesh, "BlendShapeBuilder"); }
public void DrawBlendShapeBuilder() { if (m_target == null) { return; } var m_data = m_target.data; bool repaint = false; GUILayout.BeginHorizontal(); { GUILayout.Label("Base Mesh", GUILayout.Width(70)); var rect = EditorGUILayout.GetControlRect(); var width = rect.width; var pos = rect.position; EditorGUI.ObjectField(new Rect(pos, new Vector2(width, 16)), m_data.baseMesh, typeof(UnityEngine.Object), true); } if (GUILayout.Button("Find Targets", GUILayout.Width(80))) { FindValidTargets(); } GUILayout.EndHorizontal(); m_foldBlendShapes = EditorGUILayout.Foldout(m_foldBlendShapes, "BlendShapes"); if (m_foldBlendShapes) { var bsData = m_data.blendShapeData; var evt = Event.current; // handle drag & drop if (evt.type == EventType.DragUpdated || evt.type == EventType.DragPerform) { var dropArea = GUILayoutUtility.GetLastRect(); if (dropArea.Contains(evt.mousePosition)) { DragAndDrop.visualMode = DragAndDropVisualMode.Copy; if (evt.type == EventType.DragPerform) { DragAndDrop.AcceptDrag(); Undo.RecordObject(m_target, "BlendShapeBuilder"); foreach (var obj in DragAndDrop.objectReferences) { if (IsValidTarget(obj)) { var bsd = new BlendShapeData(); bsd.name = obj.name; bsd.frames.Add(new BlendShapeFrameData { mesh = obj }); m_data.blendShapeData.Add(bsd); } } } evt.Use(); } } BlendShapeData delBS = null; foreach (var data in bsData) { GUILayout.BeginHorizontal(); GUILayout.Space(indentSize); GUILayout.BeginVertical("Box"); GUILayout.BeginHorizontal(); data.fold = EditorGUILayout.Foldout(data.fold, data.name); if (GUILayout.Button("-", GUILayout.Width(20))) { Undo.RecordObject(m_target, "BlendShapeBuilder"); delBS = data; } GUILayout.EndHorizontal(); if (data.fold) { // handle drag & drop if (evt.type == EventType.DragUpdated || evt.type == EventType.DragPerform) { var dropArea = GUILayoutUtility.GetLastRect(); if (dropArea.Contains(evt.mousePosition)) { DragAndDrop.visualMode = DragAndDropVisualMode.Copy; if (evt.type == EventType.DragPerform) { DragAndDrop.AcceptDrag(); Undo.RecordObject(m_target, "BlendShapeBuilder"); data.ClearInvalidFrames(); foreach (var obj in DragAndDrop.objectReferences) { if (IsValidTarget(obj)) { data.frames.Add(new BlendShapeFrameData { mesh = obj }); } } data.NormalizeWeights(); } evt.Use(); } } GUILayout.BeginHorizontal(); GUILayout.Space(indentSize); GUILayout.BeginVertical(); { var rect = EditorGUILayout.GetControlRect(); var width = rect.width; var pos = rect.position; EditorGUI.BeginChangeCheck(); EditorGUI.LabelField(new Rect(pos, new Vector2(width, 16)), "Name"); pos.x += 50; width -= 50; var name = EditorGUI.TextField(new Rect(pos, new Vector2(width, 16)), data.name); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_target, "BlendShapeBuilder"); data.name = name; } } EditorGUILayout.LabelField(new GUIContent("Frames", "Weight Mesh Vertex Normal Tangent")); GUILayout.BeginHorizontal(); GUILayout.Space(indentSize); GUILayout.BeginVertical(); BlendShapeFrameData delFrame = null; int numFrames = data.frames.Count; int numV = 0, numN = 0, numT = 0; foreach (var frame in data.frames) { if (frame.vertex) { ++numV; } if (frame.normal) { ++numN; } if (frame.tangent) { ++numT; } GUILayout.BeginHorizontal(); var rect = EditorGUILayout.GetControlRect(); var width = rect.width; var pos = rect.position; EditorGUI.BeginChangeCheck(); var w = EditorGUI.FloatField(new Rect(pos, new Vector2(36, 16)), frame.weight); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_target, "BlendShapeBuilder"); frame.weight = w; } pos.x += 40; EditorGUI.BeginChangeCheck(); var m = EditorGUI.ObjectField(new Rect(pos, new Vector2(width - 40, 16)), frame.mesh, typeof(UnityEngine.Object), true); if (EditorGUI.EndChangeCheck()) { if (IsValidTarget(m)) { Undo.RecordObject(m_target, "BlendShapeBuilder"); frame.mesh = m; } } if (GUILayout.Button("Edit", GUILayout.Width(50))) { OnEditFrame(frame); } EditorGUI.BeginChangeCheck(); var v = GUILayout.Toggle(frame.vertex, "V", GUILayout.Width(25)); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_target, "BlendShapeBuilder"); frame.vertex = v; } EditorGUI.BeginChangeCheck(); var n = GUILayout.Toggle(frame.normal, "N", GUILayout.Width(25)); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_target, "BlendShapeBuilder"); frame.normal = n; } EditorGUI.BeginChangeCheck(); var t = GUILayout.Toggle(frame.tangent, "T", GUILayout.Width(25)); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_target, "BlendShapeBuilder"); frame.tangent = t; } if (GUILayout.Button("-", GUILayout.Width(20))) { delFrame = frame; } GUILayout.EndHorizontal(); } if (delFrame != null) { Undo.RecordObject(m_target, "BlendShapeBuilder"); data.frames.Remove(delFrame); data.NormalizeWeights(); } GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (numFrames > 0) { bool v = false; EditorGUI.BeginChangeCheck(); if (numV == numFrames || numV == 0) { v = GUILayout.Toggle(numV == numFrames, "V", GUILayout.Width(25)); } else { v = GUILayout.Toggle(numV == numFrames, "V", "ToggleMixed", GUILayout.Width(25)); } if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_target, "BlendShapeBuilder"); foreach (var frame in data.frames) { frame.vertex = v; } } EditorGUI.BeginChangeCheck(); if (numN == numFrames || numN == 0) { v = GUILayout.Toggle(numN == numFrames, "N", GUILayout.Width(25)); } else { v = GUILayout.Toggle(numN == numFrames, "N", "ToggleMixed", GUILayout.Width(25)); } if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_target, "BlendShapeBuilder"); foreach (var frame in data.frames) { frame.normal = v; } } EditorGUI.BeginChangeCheck(); if (numT == numFrames || numT == 0) { v = GUILayout.Toggle(numT == numFrames, "T", GUILayout.Width(25)); } else { v = GUILayout.Toggle(numT == numFrames, "T", "ToggleMixed", GUILayout.Width(25)); } if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(m_target, "BlendShapeBuilder"); foreach (var frame in data.frames) { frame.tangent = v; } } } if (GUILayout.Button("+", GUILayout.Width(20))) { OnAddFrame(data); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("Normalize Weights", GUILayout.Width(120))) { Undo.RecordObject(m_target, "BlendShapeBuilder"); data.NormalizeWeights(); } if (GUILayout.Button("Sort By Weights", GUILayout.Width(110))) { Undo.RecordObject(m_target, "BlendShapeBuilder"); data.SortByWeights(); } if (GUILayout.Button("Clear", GUILayout.Width(60))) { Undo.RecordObject(m_target, "BlendShapeBuilder"); data.frames.Clear(); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.Space(10); GUILayout.EndHorizontal(); } GUILayout.EndVertical(); GUILayout.EndHorizontal(); } if (delBS != null) { bsData.Remove(delBS); } GUILayout.BeginHorizontal(); GUILayout.Space(indentSize); GUILayout.BeginHorizontal("Box"); GUILayout.FlexibleSpace(); if (GUILayout.Button("+", GUILayout.Width(20))) { Undo.RecordObject(m_target, "BlendShapeBuilder"); var tmp = new BlendShapeData(); tmp.name = "NewBlendShape" + bsData.Count; bsData.Add(tmp); } GUILayout.EndHorizontal(); GUILayout.EndHorizontal(); } GUILayout.Space(8); m_data.preserveExistingBlendShapes = GUILayout.Toggle(m_data.preserveExistingBlendShapes, "Preserve Existing BlendShapes"); GUILayout.BeginHorizontal(); if (GUILayout.Button("Update Mesh", GUILayout.Width(150))) { Build(true); } if (GUILayout.Button("Generate New Asset", GUILayout.Width(150))) { var result = Build(); string path = EditorUtility.SaveFilePanel("Generate New Asset", "Assets", Utils.SanitizeForFileName(m_data.baseMesh.name), "asset"); if (path.Length > 0) { var dataPath = Application.dataPath; if (!path.StartsWith(dataPath)) { Debug.LogError("Invalid path: Path must be under " + dataPath); } else { path = path.Replace(dataPath, "Assets"); AssetDatabase.CreateAsset(result, path); Debug.Log("Asset exported: " + path); } } } GUILayout.EndHorizontal(); GUILayout.Space(6); if (repaint) { RepaintAllViews(); } }