protected override void DoWindow(int windowId) { float labelWidth = EditorGUIUtility.labelWidth; bool wideMode = EditorGUIUtility.wideMode; EditorGUIUtility.wideMode = true; EditorGUILayout.BeginHorizontal(); string[] names = spriteMeshCache.GetBoneNames("None"); int index = spriteMeshCache.bindPoses.IndexOf(spriteMeshCache.selectedBindPose); index = EditorGUILayout.Popup(index + 1, names, GUILayout.Width(75f)) - 1; if (index >= 0 && index < spriteMeshCache.bindPoses.Count) { spriteMeshCache.selectedBindPose = spriteMeshCache.bindPoses[index]; } else { spriteMeshCache.selectedBindPose = null; } EditorGUI.BeginChangeCheck(); EditorGUI.BeginDisabledGroup(spriteMeshCache.selectedBindPose == null); if (Event.current.type == EventType.MouseUp || Event.current.type == EventType.MouseDown) { m_Weight = 0f; m_TempWeights.Clear(); if (spriteMeshCache.selection.Count == 0) { m_TempWeights = spriteMeshCache.boneWeights.ToList(); } else { m_TempWeights = spriteMeshCache.selectedNodes.ConvertAll(n => spriteMeshCache.GetBoneWeight(n)); } } EditorGUIUtility.fieldWidth = 35f; m_Weight = EditorGUILayout.Slider(m_Weight, -1f, 1f); EditorGUIUtility.fieldWidth = 0f; if (EditorGUI.EndChangeCheck()) { spriteMeshCache.RegisterUndo("modify weights"); List <Node> nodes = null; if (spriteMeshCache.selection.Count == 0) { nodes = spriteMeshCache.nodes; } else { nodes = spriteMeshCache.selectedNodes; } for (int i = 0; i < nodes.Count; i++) { Node node = nodes[i]; BoneWeight tempWeight = m_TempWeights[i]; tempWeight.SetBoneIndexWeight(index, tempWeight.GetBoneWeight(index) + m_Weight, !EditorGUI.actionKey, true); spriteMeshCache.SetBoneWeight(node, tempWeight); } } EditorGUI.EndDisabledGroup(); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent("Smooth", "Smooth weights"))) { spriteMeshCache.RegisterUndo("smooth weights"); List <Node> targetNodes = spriteMeshCache.nodes; if (spriteMeshCache.selection.Count > 0) { targetNodes = spriteMeshCache.selectedNodes; } spriteMeshCache.SmoothWeights(targetNodes); } if (GUILayout.Button(new GUIContent("Auto", "Calculate automatic weights"))) { spriteMeshCache.RegisterUndo("calculate weights"); List <Node> targetNodes = spriteMeshCache.nodes; if (spriteMeshCache.selection.Count > 0) { targetNodes = spriteMeshCache.selectedNodes; } spriteMeshCache.CalculateAutomaticWeights(targetNodes); } GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); EditorGUIUtility.labelWidth = 50f; overlayColors = EditorGUILayout.Toggle("Overlay", overlayColors); EditorGUIUtility.labelWidth = 30f; showPie = EditorGUILayout.Toggle("Pies", showPie); GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); EditorGUIUtility.labelWidth = labelWidth; EditorGUIUtility.wideMode = wideMode; }
public void CalculateAutomaticWeights(List <Node> targetNodes) { float pixelsPerUnit = SpriteMeshUtils.GetSpritePixelsPerUnit(spriteMesh.sprite); if (nodes.Count <= 0) { Debug.Log("Cannot calculate automatic weights from a SpriteMesh with no vertices."); return; } if (bindPoses.Count <= 0) { Debug.Log("Cannot calculate automatic weights. Specify bones to the SpriteMeshInstance."); return; } if (spriteMesh && bindPoses.Count > 1) { List <Vector2> controlPoints = new List <Vector2>(bindPoses.Count * 2); List <IndexedEdge> controlPointEdges = new List <IndexedEdge>(bindPoses.Count); foreach (BindInfo bindInfo in bindPoses) { Vector2 tip = SpriteMeshUtils.VertexToTexCoord(spriteMesh, pivotPoint, bindInfo.position, pixelsPerUnit); Vector2 tail = SpriteMeshUtils.VertexToTexCoord(spriteMesh, pivotPoint, bindInfo.endPoint, pixelsPerUnit); int index1 = -1; if (!ContainsVector(tip, controlPoints, 0.01f, out index1)) { index1 = controlPoints.Count; controlPoints.Add(tip); } int index2 = -1; if (!ContainsVector(tail, controlPoints, 0.01f, out index2)) { index2 = controlPoints.Count; controlPoints.Add(tail); } IndexedEdge edge = new IndexedEdge(index1, index2); controlPointEdges.Add(edge); } float[,] weightArray; BbwPlugin.CalculateBbw(m_TexVertices.ToArray(), indexedEdges.ToArray(), controlPoints.ToArray(), controlPointEdges.ToArray(), out weightArray); FillBoneWeights(targetNodes, weightArray); isDirty = true; } else { BoneWeight boneWeight = BoneWeight.Create(); boneWeight.boneIndex0 = 0; boneWeight.weight0 = 1f; foreach (Node node in targetNodes) { SetBoneWeight(node, boneWeight); } } }
void DoVerticesInspector() { if (spriteMeshCache.selection.Count > 0) { string[] names = spriteMeshCache.GetBoneNames("Unassigned"); BoneWeight boneWeight = BoneWeight.Create(); EditorGUI.BeginChangeCheck(); bool mixedBoneIndex0 = false; bool mixedBoneIndex1 = false; bool mixedBoneIndex2 = false; bool mixedBoneIndex3 = false; bool changedIndex0 = false; bool changedIndex1 = false; bool changedIndex2 = false; bool changedIndex3 = false; bool mixedWeight = false; if (spriteMeshCache.multiselection) { mixedWeight = true; int boneIndex = -1; mixedBoneIndex0 = IsMixedBoneIndex(0, out boneIndex); if (!mixedBoneIndex0) { boneWeight.boneIndex0 = boneIndex; } mixedBoneIndex1 = IsMixedBoneIndex(1, out boneIndex); if (!mixedBoneIndex1) { boneWeight.boneIndex1 = boneIndex; } mixedBoneIndex2 = IsMixedBoneIndex(2, out boneIndex); if (!mixedBoneIndex2) { boneWeight.boneIndex2 = boneIndex; } mixedBoneIndex3 = IsMixedBoneIndex(3, out boneIndex); if (!mixedBoneIndex3) { boneWeight.boneIndex3 = boneIndex; } } else { boneWeight = spriteMeshCache.GetBoneWeight(spriteMeshCache.selectedNode); } EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck(); boneWeight = EditorGUIExtra.Weight(boneWeight, 0, names, mixedBoneIndex0, mixedWeight); changedIndex0 = EditorGUI.EndChangeCheck(); EditorGUI.BeginChangeCheck(); boneWeight = EditorGUIExtra.Weight(boneWeight, 1, names, mixedBoneIndex1, mixedWeight); changedIndex1 = EditorGUI.EndChangeCheck(); EditorGUI.BeginChangeCheck(); boneWeight = EditorGUIExtra.Weight(boneWeight, 2, names, mixedBoneIndex2, mixedWeight); changedIndex2 = EditorGUI.EndChangeCheck(); EditorGUI.BeginChangeCheck(); boneWeight = EditorGUIExtra.Weight(boneWeight, 3, names, mixedBoneIndex3, mixedWeight); changedIndex3 = EditorGUI.EndChangeCheck(); if (EditorGUI.EndChangeCheck()) { spriteMeshCache.RegisterUndo("modify weights"); if (spriteMeshCache.multiselection) { List <Node> selectedNodes = spriteMeshCache.selectedNodes; foreach (Node node in selectedNodes) { BoneWeight l_boneWeight = spriteMeshCache.GetBoneWeight(node); if (!mixedBoneIndex0 || changedIndex0) { l_boneWeight.SetWeight(0, boneWeight.boneIndex0, l_boneWeight.weight0); } if (!mixedBoneIndex1 || changedIndex1) { l_boneWeight.SetWeight(1, boneWeight.boneIndex1, l_boneWeight.weight1); } if (!mixedBoneIndex2 || changedIndex2) { l_boneWeight.SetWeight(2, boneWeight.boneIndex2, l_boneWeight.weight2); } if (!mixedBoneIndex3 || changedIndex3) { l_boneWeight.SetWeight(3, boneWeight.boneIndex3, l_boneWeight.weight3); } spriteMeshCache.SetBoneWeight(node, l_boneWeight); } } else { spriteMeshCache.SetBoneWeight(spriteMeshCache.selectedNode, boneWeight); } } EditorGUI.showMixedValue = false; } }
public void SetBoneWeight(Node node, BoneWeight boneWeight) { boneWeights[node.index] = boneWeight; isDirty = true; }
public void SmoothWeights(List <Node> targetNodes) { float[,] weights = new float[nodes.Count, bindPoses.Count]; Array.Clear(weights, 0, weights.Length); List <int> usedIndices = new List <int>(); for (int i = 0; i < nodes.Count; i++) { usedIndices.Clear(); BoneWeight weight = boneWeights[i]; if (weight.boneIndex0 >= 0) { weights[i, weight.boneIndex0] = weight.weight0; usedIndices.Add(weight.boneIndex0); } if (weight.boneIndex1 >= 0 && !usedIndices.Contains(weight.boneIndex1)) { weights[i, weight.boneIndex1] = weight.weight1; usedIndices.Add(weight.boneIndex1); } if (weight.boneIndex2 >= 0 && !usedIndices.Contains(weight.boneIndex2)) { weights[i, weight.boneIndex2] = weight.weight2; usedIndices.Add(weight.boneIndex2); } if (weight.boneIndex3 >= 0 && !usedIndices.Contains(weight.boneIndex3)) { weights[i, weight.boneIndex3] = weight.weight3; usedIndices.Add(weight.boneIndex3); } } float[] denominator = new float[nodes.Count]; float[,] smoothedWeights = new float[nodes.Count, bindPoses.Count]; Array.Clear(smoothedWeights, 0, smoothedWeights.Length); for (int i = 0; i < indices.Count / 3; ++i) { for (int j = 0; j < 3; ++j) { int j1 = (j + 1) % 3; int j2 = (j + 2) % 3; for (int k = 0; k < bindPoses.Count; ++k) { smoothedWeights[indices[i * 3 + j], k] += weights[indices[i * 3 + j1], k] + weights[indices[i * 3 + j2], k]; } denominator[indices[i * 3 + j]] += 2; } } for (int i = 0; i < nodes.Count; ++i) { for (int j = 0; j < bindPoses.Count; ++j) { smoothedWeights[i, j] /= denominator[i]; } } float[,] smoothedWeightsTransposed = new float[bindPoses.Count, nodes.Count]; for (int i = 0; i < nodes.Count; ++i) { for (int j = 0; j < bindPoses.Count; ++j) { smoothedWeightsTransposed[j, i] = smoothedWeights[i, j]; } } FillBoneWeights(targetNodes, smoothedWeightsTransposed); isDirty = true; }
BoneWeight CreateBoneWeightFromWeights(List <float> weights) { BoneWeight boneWeight = new BoneWeight(); float weight = 0f; int index = -1; weight = weights.Max(); if (weight < 0.01f) { weight = 0f; } index = weight > 0f? weights.IndexOf(weight) : -1; boneWeight.weight0 = weight; boneWeight.boneIndex0 = index; if (index >= 0) { weights[index] = 0f; } weight = weights.Max(); if (weight < 0.01f) { weight = 0f; } index = weight > 0f? weights.IndexOf(weight) : -1; boneWeight.weight1 = weight; boneWeight.boneIndex1 = index; if (index >= 0) { weights[index] = 0f; } weight = weights.Max(); if (weight < 0.01f) { weight = 0f; } index = weight > 0f? weights.IndexOf(weight) : -1; boneWeight.weight2 = weight; boneWeight.boneIndex2 = index; if (index >= 0) { weights[index] = 0f; } weight = weights.Max(); if (weight < 0.01f) { weight = 0f; } index = weight > 0f? weights.IndexOf(weight) : -1; boneWeight.weight3 = weight; boneWeight.boneIndex3 = index; float sum = boneWeight.weight0 + boneWeight.weight1 + boneWeight.weight2 + boneWeight.weight3; if (sum > 0f) { boneWeight.weight0 /= sum; boneWeight.weight1 /= sum; boneWeight.weight2 /= sum; boneWeight.weight3 /= sum; } return(boneWeight); }
public static void UpdateAssets(SpriteMesh spriteMesh, SpriteMeshData spriteMeshData) { if (spriteMesh && spriteMeshData) { string spriteMeshPath = AssetDatabase.GetAssetPath(spriteMesh); SerializedObject spriteMeshSO = new SerializedObject(spriteMesh); SerializedProperty sharedMeshProp = spriteMeshSO.FindProperty("m_SharedMesh"); SerializedProperty sharedMaterialsProp = spriteMeshSO.FindProperty("m_SharedMaterials"); if (!spriteMesh.sharedMesh) { Mesh mesh = new Mesh(); mesh.hideFlags = HideFlags.HideInHierarchy; AssetDatabase.AddObjectToAsset(mesh, spriteMeshPath); spriteMeshSO.Update(); sharedMeshProp.objectReferenceValue = mesh; spriteMeshSO.ApplyModifiedProperties(); EditorUtility.SetDirty(mesh); } spriteMesh.sharedMesh.name = spriteMesh.name; if (spriteMesh.sharedMaterials.Length == 0) { Material material = new Material(Shader.Find("Sprites/Default")); material.mainTexture = SpriteUtility.GetSpriteTexture(spriteMesh.sprite, false); AssetDatabase.AddObjectToAsset(material, spriteMeshPath); spriteMeshSO.Update(); sharedMaterialsProp.arraySize = 1; sharedMaterialsProp.GetArrayElementAtIndex(0).objectReferenceValue = material; spriteMeshSO.ApplyModifiedProperties(); } for (int i = 0; i < spriteMesh.sharedMaterials.Length; i++) { Material material = spriteMesh.sharedMaterials [i]; if (material) { if (spriteMesh.sprite) { material.mainTexture = SpriteUtility.GetSpriteTexture(spriteMesh.sprite, false); } material.name = spriteMesh.name + "_" + i; material.hideFlags = HideFlags.HideInHierarchy; EditorUtility.SetDirty(material); } } spriteMeshData.hideFlags = HideFlags.HideInHierarchy; EditorUtility.SetDirty(spriteMeshData); int width = 0; int height = 0; GetSpriteTextureSize(spriteMesh.sprite, ref width, ref height); Vector3[] vertices = GetMeshVertices(spriteMesh.sprite, spriteMeshData); Vector2 textureWidthHeightInv = new Vector2(1f / width, 1f / height); Vector2[] uvs = (new List <Vector2>(spriteMeshData.vertices)).ConvertAll(v => Vector2.Scale(v, textureWidthHeightInv)).ToArray(); Vector3[] normals = (new List <Vector3>(vertices)).ConvertAll(v => Vector3.back).ToArray(); BoneWeight[] boneWeightsData = spriteMeshData.boneWeights; if (boneWeightsData.Length != spriteMeshData.vertices.Length) { boneWeightsData = new BoneWeight[spriteMeshData.vertices.Length]; } List <UnityEngine.BoneWeight> boneWeights = new List <UnityEngine.BoneWeight>(boneWeightsData.Length); List <float> verticesOrder = new List <float>(spriteMeshData.vertices.Length); for (int i = 0; i < boneWeightsData.Length; i++) { BoneWeight boneWeight = boneWeightsData[i]; List <KeyValuePair <int, float> > pairs = new List <KeyValuePair <int, float> >(); pairs.Add(new KeyValuePair <int, float>(boneWeight.boneIndex0, boneWeight.weight0)); pairs.Add(new KeyValuePair <int, float>(boneWeight.boneIndex1, boneWeight.weight1)); pairs.Add(new KeyValuePair <int, float>(boneWeight.boneIndex2, boneWeight.weight2)); pairs.Add(new KeyValuePair <int, float>(boneWeight.boneIndex3, boneWeight.weight3)); pairs = pairs.OrderByDescending(s => s.Value).ToList(); UnityEngine.BoneWeight boneWeight2 = new UnityEngine.BoneWeight(); boneWeight2.boneIndex0 = Mathf.Max(0, pairs[0].Key); boneWeight2.boneIndex1 = Mathf.Max(0, pairs[1].Key); boneWeight2.boneIndex2 = Mathf.Max(0, pairs[2].Key); boneWeight2.boneIndex3 = Mathf.Max(0, pairs[3].Key); boneWeight2.weight0 = pairs[0].Value; boneWeight2.weight1 = pairs[1].Value; boneWeight2.weight2 = pairs[2].Value; boneWeight2.weight3 = pairs[3].Value; boneWeights.Add(boneWeight2); float vertexOrder = i; if (spriteMeshData.bindPoses.Length > 0) { vertexOrder = spriteMeshData.bindPoses[boneWeight2.boneIndex0].zOrder * boneWeight2.weight0 + spriteMeshData.bindPoses[boneWeight2.boneIndex1].zOrder * boneWeight2.weight1 + spriteMeshData.bindPoses[boneWeight2.boneIndex2].zOrder * boneWeight2.weight2 + spriteMeshData.bindPoses[boneWeight2.boneIndex3].zOrder * boneWeight2.weight3; } verticesOrder.Add(vertexOrder); } List <WeightedTriangle> weightedTriangles = new List <WeightedTriangle>(spriteMeshData.indices.Length / 3); for (int i = 0; i < spriteMeshData.indices.Length; i += 3) { int p1 = spriteMeshData.indices[i]; int p2 = spriteMeshData.indices[i + 1]; int p3 = spriteMeshData.indices[i + 2]; weightedTriangles.Add(new WeightedTriangle(p1, p2, p3, verticesOrder[p1], verticesOrder[p2], verticesOrder[p3])); } weightedTriangles = weightedTriangles.OrderBy(t => t.weight).ToList(); List <int> indices = new List <int>(spriteMeshData.indices.Length); for (int i = 0; i < weightedTriangles.Count; ++i) { WeightedTriangle t = weightedTriangles[i]; indices.Add(t.p1); indices.Add(t.p2); indices.Add(t.p3); } List <Matrix4x4> bindposes = (new List <BindInfo>(spriteMeshData.bindPoses)).ConvertAll(p => p.bindPose); for (int i = 0; i < bindposes.Count; i++) { Matrix4x4 bindpose = bindposes [i]; bindpose.m23 = 0f; bindposes[i] = bindpose; } spriteMesh.sharedMesh.Clear(); spriteMesh.sharedMesh.vertices = vertices; spriteMesh.sharedMesh.uv = uvs; spriteMesh.sharedMesh.triangles = indices.ToArray(); spriteMesh.sharedMesh.normals = normals; spriteMesh.sharedMesh.boneWeights = boneWeights.ToArray(); spriteMesh.sharedMesh.bindposes = bindposes.ToArray(); spriteMesh.sharedMesh.RecalculateBounds(); RebuildBlendShapes(spriteMesh); } }
public static void UpdateAssets(SpriteMesh spriteMesh) { if (spriteMesh) { string spriteMeshPath = AssetDatabase.GetAssetPath(spriteMesh); GameObject go = AssetDatabase.LoadAssetAtPath(spriteMeshPath, typeof(GameObject)) as GameObject; Mesh mesh = AssetDatabase.LoadAssetAtPath(spriteMeshPath, typeof(Mesh)) as Mesh; Material material = AssetDatabase.LoadAssetAtPath(spriteMeshPath, typeof(Material)) as Material; spriteMesh.name = go.name; if (!mesh) { mesh = new Mesh(); AssetDatabase.AddObjectToAsset(mesh, spriteMeshPath); } mesh.name = go.name; if (!material) { material = new Material(Shader.Find("Unlit/Transparent")); material.mainTexture = spriteMesh.sprite.texture; AssetDatabase.AddObjectToAsset(material, spriteMeshPath); } material.name = go.name; List <Vector3> vertices = new List <Vector3>(spriteMesh.texVertices.Count); List <Vector2> uvs = new List <Vector2>(spriteMesh.texVertices.Count); List <Vector3> normals = new List <Vector3>(spriteMesh.texVertices.Count); List <BoneWeight> boneWeights = new List <BoneWeight>(spriteMesh.texVertices.Count); for (int i = 0; i < spriteMesh.texVertices.Count; i++) { Vertex vertex = spriteMesh.texVertices[i]; vertices.Add(TexCoordToVertex(spriteMesh, vertex.vertex)); uvs.Add(new Vector2(vertex.vertex.x / spriteMesh.sprite.texture.width, vertex.vertex.y / spriteMesh.sprite.texture.height)); normals.Add(Vector3.back); List <KeyValuePair <int, float> > pairs = new List <KeyValuePair <int, float> >(); pairs.Add(new KeyValuePair <int, float>(vertex.boneWeight.boneIndex0, vertex.boneWeight.weight0)); pairs.Add(new KeyValuePair <int, float>(vertex.boneWeight.boneIndex1, vertex.boneWeight.weight1)); pairs.Add(new KeyValuePair <int, float>(vertex.boneWeight.boneIndex2, vertex.boneWeight.weight2)); pairs.Add(new KeyValuePair <int, float>(vertex.boneWeight.boneIndex3, vertex.boneWeight.weight3)); pairs = pairs.OrderByDescending(s => s.Value).ToList(); BoneWeight boneWeight = new BoneWeight(); boneWeight.boneIndex0 = pairs[0].Key; boneWeight.boneIndex1 = pairs[1].Key; boneWeight.boneIndex2 = pairs[2].Key; boneWeight.boneIndex3 = pairs[3].Key; boneWeight.weight0 = pairs[0].Value; boneWeight.weight1 = pairs[1].Value; boneWeight.weight2 = pairs[2].Value; boneWeight.weight3 = pairs[3].Value; boneWeights.Add(boneWeight); } mesh.Clear(); mesh.vertices = vertices.ToArray(); mesh.uv = uvs.ToArray(); mesh.triangles = spriteMesh.indices.ToArray(); mesh.normals = normals.ToArray(); mesh.boneWeights = boneWeights.ToArray(); mesh.bindposes = spriteMesh.bindPoses.ConvertAll(bindPose => bindPose.bindPose).ToArray(); mesh.RecalculateBounds(); } }