public static bool FindTriangle(this SpriteMeshData spriteMeshData, Vector2 point, out Vector3Int indices, out Vector3 barycentricCoords) { indices = Vector3Int.zero; barycentricCoords = Vector3.zero; if (spriteMeshData.indices.Count < 3) { return(false); } int triangleCount = spriteMeshData.indices.Count / 3; for (int i = 0; i < triangleCount; ++i) { indices.x = spriteMeshData.indices[i * 3]; indices.y = spriteMeshData.indices[i * 3 + 1]; indices.z = spriteMeshData.indices[i * 3 + 2]; MeshModuleUtility.Barycentric( point, spriteMeshData.vertices[indices.x].position, spriteMeshData.vertices[indices.y].position, spriteMeshData.vertices[indices.z].position, out barycentricCoords); if (barycentricCoords.x >= 0f && barycentricCoords.y >= 0f && barycentricCoords.z >= 0f) { return(true); } } return(false); }
public static Matrix4x4 CalculateRootMatrix(this SpriteMeshData spriteMeshData) { Matrix4x4 rootMatrix = new Matrix4x4(); rootMatrix.SetTRS(spriteMeshData.frame.position, Quaternion.identity, Vector3.one); return(rootMatrix); }
public static void CalculateWeights(this SpriteMeshData spriteMeshData, IWeightsGenerator weightsGenerator, ISelection selection, float filterTolerance) { Vector2[] controlPoints; Edge[] bones; int[] pins; spriteMeshData.GetControlPoints(out controlPoints, out bones, out pins); Vector2[] vertices = new Vector2[spriteMeshData.vertices.Count]; for (int i = 0; i < spriteMeshData.vertices.Count; ++i) { vertices[i] = spriteMeshData.vertices[i].position; } BoneWeight[] boneWeights = weightsGenerator.Calculate(vertices, spriteMeshData.edges.ToArray(), controlPoints, bones, pins); Debug.Assert(boneWeights.Length == spriteMeshData.vertices.Count); for (int i = 0; i < spriteMeshData.vertices.Count; ++i) { if (selection == null || (selection.Count == 0 || selection.IsSelected(i))) { EditableBoneWeight editableBoneWeight = EditableBoneWeightUtility.CreateFromBoneWeight(boneWeights[i]); if (filterTolerance > 0f) { editableBoneWeight.FilterChannels(filterTolerance); editableBoneWeight.NormalizeChannels(); } spriteMeshData.vertices[i].editableBoneWeight = editableBoneWeight; } } }
public static void ClearWeights(this SpriteMeshData spriteMeshData, ISelection selection) { for (int i = 0; i < spriteMeshData.vertices.Count; ++i) { if (selection == null || (selection.Count == 0 || selection.IsSelected(i))) { spriteMeshData.vertices[i].editableBoneWeight.SetFromBoneWeight(default(BoneWeight)); } } }
public static void NormalizeWeights(this SpriteMeshData spriteMeshData, ISelection selection) { for (int i = 0; i < spriteMeshData.vertices.Count; ++i) { if (selection == null || (selection.Count == 0 || selection.IsSelected(i))) { spriteMeshData.vertices[i].editableBoneWeight.NormalizeChannels(); } } }
public static void UpdateSpriteBoneDataWorldPosition(this SpriteMeshData spriteMeshData, Matrix4x4[] localToWorldMatrices) { Debug.Assert(spriteMeshData.bones.Count == localToWorldMatrices.Length); for (int i = 0; i < spriteMeshData.bones.Count; ++i) { var spriteBoneData = spriteMeshData.bones[i]; spriteBoneData.position = localToWorldMatrices[i].MultiplyPoint(Vector2.zero); spriteBoneData.endPosition = localToWorldMatrices[i].MultiplyPoint(Vector2.right * spriteBoneData.length); } }
public static void GetMultiEditChannelData(this SpriteMeshData spriteMeshData, ISelection selection, int channelIndex, out bool channelEnabled, out BoneWeightData boneWeightData, out bool isChannelEnabledMixed, out bool isBoneIndexMixed, out bool isWeightMixed) { if (selection == null) { throw new ArgumentNullException("selection is null"); } bool first = true; channelEnabled = false; boneWeightData = new BoneWeightData(); isChannelEnabledMixed = false; isBoneIndexMixed = false; isWeightMixed = false; foreach (int i in selection) { EditableBoneWeight editableBoneWeight = spriteMeshData.vertices[i].editableBoneWeight; BoneWeightData otherBoneWeightData = editableBoneWeight.GetBoneWeightData(channelIndex); if (first) { channelEnabled = editableBoneWeight.IsChannelEnabled(channelIndex); boneWeightData.boneIndex = otherBoneWeightData.boneIndex; boneWeightData.weight = otherBoneWeightData.weight; first = false; } else { if (channelEnabled != editableBoneWeight.IsChannelEnabled(channelIndex)) { isChannelEnabledMixed = true; channelEnabled = false; } if (boneWeightData.boneIndex != otherBoneWeightData.boneIndex) { isBoneIndexMixed = true; boneWeightData.boneIndex = -1; } if (boneWeightData.weight != otherBoneWeightData.weight) { isWeightMixed = true; boneWeightData.weight = 0f; } } } }
public static GUIContent[] GetBoneNameList(SpriteMeshData spriteMeshData) { List <GUIContent> names = new List <GUIContent>(); for (int i = 0; i < spriteMeshData.bones.Count; i++) { var bone = spriteMeshData.bones[i]; names.Add(new GUIContent(i + " " + bone.name)); } return(names.ToArray()); }
public static void Triangulate(this SpriteMeshData spriteMeshData, ITriangulator triangulator) { Debug.Assert(triangulator != null); m_VerticesTemp.Clear(); for (int i = 0; i < spriteMeshData.vertices.Count; ++i) { m_VerticesTemp.Add(spriteMeshData.vertices[i].position); } triangulator.Triangulate(m_VerticesTemp, spriteMeshData.edges, spriteMeshData.indices); }
public static void OutlineFromAlpha(this SpriteMeshData spriteMeshData, IOutlineGenerator outlineGenerator, ITextureDataProvider textureDataProvider, float outlineDetail, byte alphaTolerance) { Debug.Assert(textureDataProvider != null); Debug.Assert(textureDataProvider.texture != null); int width, height; textureDataProvider.GetTextureActualWidthAndHeight(out width, out height); Vector2 scale = new Vector2(textureDataProvider.texture.width / (float)width, textureDataProvider.texture.height / (float)height); Vector2 scaleInv = new Vector2(1f / scale.x, 1f / scale.y); Vector2 rectOffset = spriteMeshData.frame.size * 0.5f + spriteMeshData.frame.position; Rect scaledRect = spriteMeshData.frame; scaledRect.min = Vector2.Scale(scaledRect.min, scale); scaledRect.max = Vector2.Scale(scaledRect.max, scale); spriteMeshData.vertices.Clear(); spriteMeshData.edges.Clear(); Vector2[][] paths; outlineGenerator.GenerateOutline(textureDataProvider.texture, scaledRect, outlineDetail, alphaTolerance, false, out paths); int vertexIndexBase = 0; for (int i = 0; i < paths.Length; ++i) { int numPathVertices = paths[i].Length; for (int j = 0; j <= numPathVertices; j++) { if (j < numPathVertices) { spriteMeshData.vertices.Add(new Vertex2D(Vector2.Scale(paths[i][j], scaleInv) + rectOffset)); } if (j > 0) { spriteMeshData.edges.Add(new Edge(vertexIndexBase + j - 1, vertexIndexBase + j % numPathVertices)); } } vertexIndexBase += numPathVertices; } }
public static void SortTrianglesByDepth(this SpriteMeshData spriteMeshData) { List <float> vertexOrderList = new List <float>(spriteMeshData.vertices.Count); for (int i = 0; i < spriteMeshData.vertices.Count; i++) { float vertexOrder = 0; if (spriteMeshData.bones.Count > 0) { BoneWeight boneWeight = spriteMeshData.vertices[i].editableBoneWeight.ToBoneWeight(false); float orderBone0 = spriteMeshData.bones[boneWeight.boneIndex0].depth; float orderBone1 = spriteMeshData.bones[boneWeight.boneIndex1].depth; float orderBone2 = spriteMeshData.bones[boneWeight.boneIndex2].depth; float orderBone3 = spriteMeshData.bones[boneWeight.boneIndex3].depth; vertexOrder = orderBone0 * boneWeight.weight0 + orderBone1 * boneWeight.weight1 + orderBone2 * boneWeight.weight2 + orderBone3 * boneWeight.weight3; } vertexOrderList.Add(vertexOrder); } List <WeightedTriangle> weightedTriangles = new List <WeightedTriangle>(spriteMeshData.indices.Count / 3); for (int i = 0; i < spriteMeshData.indices.Count; i += 3) { int p1 = spriteMeshData.indices[i]; int p2 = spriteMeshData.indices[i + 1]; int p3 = spriteMeshData.indices[i + 2]; float weight = (vertexOrderList[p1] + vertexOrderList[p2] + vertexOrderList[p3]) / 3f; weightedTriangles.Add(new WeightedTriangle(p1, p2, p3, weight)); } weightedTriangles = weightedTriangles.OrderBy(t => t.weight).ToList(); spriteMeshData.indices.Clear(); for (int i = 0; i < weightedTriangles.Count; ++i) { WeightedTriangle triangle = weightedTriangles[i]; spriteMeshData.indices.Add(triangle.p1); spriteMeshData.indices.Add(triangle.p2); spriteMeshData.indices.Add(triangle.p3); } }
public static void CalculateWeightsSafe(this SpriteMeshData spriteMeshData, IWeightsGenerator weightsGenerator, ISelection selection, float filterTolerance) { SerializableSelection tempSelection = new SerializableSelection(); GenericSelector <Vertex2D> vertexSelector = new GenericSelector <Vertex2D>(); vertexSelector.items = spriteMeshData.vertices; vertexSelector.selection = tempSelection; vertexSelector.Filter = (int i) => { return(vertexSelector.items[i].editableBoneWeight.GetWeightSum() == 0f && (selection == null || selection.Count == 0 || selection.IsSelected(i))); }; vertexSelector.Select(); if (tempSelection.Count > 0) { spriteMeshData.CalculateWeights(weightsGenerator, tempSelection, filterTolerance); } }
public static void Subdivide(this SpriteMeshData spriteMeshData, ITriangulator triangulator, float largestAreaFactor) { Debug.Assert(triangulator != null); m_VerticesTemp.Clear(); for (int i = 0; i < spriteMeshData.vertices.Count; ++i) { m_VerticesTemp.Add(spriteMeshData.vertices[i].position); } triangulator.Tessellate(0f, 0f, 0f, largestAreaFactor, 100, m_VerticesTemp, spriteMeshData.edges, spriteMeshData.indices); spriteMeshData.vertices.Clear(); for (int i = 0; i < m_VerticesTemp.Count; ++i) { spriteMeshData.vertices.Add(new Vertex2D(m_VerticesTemp[i])); } }
public static void GetControlPoints(this SpriteMeshData spriteMeshData, out Vector2[] points, out Edge[] edges, out int[] pins) { points = null; edges = null; List <Vector2> pointList = new List <Vector2>(); List <Edge> edgeList = new List <Edge>(); List <int> pinList = new List <int>(); foreach (var bone in spriteMeshData.bones) { if (bone.length > 0f) { Vector2 endPosition = bone.position + (bone.endPosition - bone.position).normalized * bone.length * 0.99f; int index1 = FindPoint(pointList, bone.position, 0.01f); int index2 = FindPoint(pointList, endPosition, 0.01f); if (index1 == -1) { pointList.Add(bone.position); index1 = pointList.Count - 1; } if (index2 == -1) { pointList.Add(endPosition); index2 = pointList.Count - 1; } edgeList.Add(new Edge(index1, index2)); } else if (bone.length == 0f) { pointList.Add(bone.position); pinList.Add(pointList.Count - 1); } } points = pointList.ToArray(); edges = edgeList.ToArray(); pins = pinList.ToArray(); }
public static void SetMultiEditChannelData(this SpriteMeshData spriteMeshData, ISelection selection, int channelIndex, bool referenceChannelEnabled, bool newChannelEnabled, BoneWeightData referenceData, BoneWeightData newData) { if (selection == null) { throw new ArgumentNullException("selection is null"); } bool channelEnabledChanged = referenceChannelEnabled != newChannelEnabled; bool boneIndexChanged = referenceData.boneIndex != newData.boneIndex; bool weightChanged = referenceData.weight != newData.weight; foreach (int i in selection) { EditableBoneWeight editableBoneWeight = spriteMeshData.vertices[i].editableBoneWeight; BoneWeightData data = editableBoneWeight.GetBoneWeightData(channelIndex); if (channelEnabledChanged) { editableBoneWeight.EnableChannel(channelIndex, newChannelEnabled); } if (boneIndexChanged) { data.boneIndex = newData.boneIndex; } if (weightChanged) { data.weight = newData.weight; } editableBoneWeight.SetBoneWeightData(channelIndex, data); if (channelEnabledChanged || weightChanged) { editableBoneWeight.CompensateOtherChannels(channelIndex); } } }
public override void OnModuleActivate() { InitStyles(); Undo.undoRedoPerformed += UndoRedoPerformed; spriteEditor.enableMouseMoveEvent = true; IGUIWrapper guiWrapper = new GUIWrapper(); m_SpriteMeshCache = ScriptableObject.CreateInstance <SpriteMeshCache>(); m_Triangulator = new Triangulator(); m_WeightGenerator = new BoundedBiharmonicWeightsGenerator(); m_OutlineGenerator = new OutlineGenerator(); m_UndoObject = new UndoObject(m_SpriteMeshCache); m_SpriteMeshController = new SpriteMeshController(); m_SpriteMeshView = new SpriteMeshView(guiWrapper); m_BindPoseController = new BindPoseController(); m_BindPoseView = new BindPoseView(guiWrapper); m_RectSelectionTool = new RectSelectionTool(m_SpriteMeshCache); m_UnselectTool = new UnselectTool(m_SpriteMeshCache); m_WeightEditor = new WeightEditor(); m_BrushWeightTool = new BrushWeightTool(); m_SliderWeightTool = new SliderWeightTool(); m_WeightInspector = new WeightInspector(m_SpriteMeshCache); m_BoneInspector = new BoneInspector(m_SpriteMeshCache); m_MeshPreview = new MeshPreview(); var dataProvider = spriteEditor.GetDataProvider <ISpriteEditorDataProvider>(); var boneProvider = spriteEditor.GetDataProvider <ISpriteBoneDataProvider>(); var spriteMeshProvider = spriteEditor.GetDataProvider <ISpriteMeshDataProvider>(); var spriteRects = dataProvider.GetSpriteRects(); var textureProvider = spriteEditor.GetDataProvider <ITextureDataProvider>(); m_MeshPreview.textureDataProvider = textureProvider; for (var i = 0; i < spriteRects.Length; i++) { var spriteRect = spriteRects[i]; var spriteMeshData = new SpriteMeshData(); spriteMeshData.spriteID = spriteRect.spriteID; spriteMeshData.frame = spriteRect.rect; spriteMeshData.pivot = spriteRect.rect.position + Vector2.Scale(spriteRect.rect.size, spriteRect.pivot); spriteMeshData.bones = MeshModuleUtility.CreateSpriteBoneData(boneProvider.GetBones(spriteRect.spriteID), spriteMeshData.CalculateRootMatrix()); var metaVertices = spriteMeshProvider.GetVertices(spriteRect.spriteID); foreach (var mv in metaVertices) { var v = new Vertex2D(mv.position + spriteRect.rect.position, mv.boneWeight); spriteMeshData.vertices.Add(v); } spriteMeshData.indices = new List <int>(spriteMeshProvider.GetIndices(spriteRect.spriteID)); Vector2Int[] edges = spriteMeshProvider.GetEdges(spriteRect.spriteID); foreach (var e in edges) { spriteMeshData.edges.Add(new Edge(e.x, e.y)); } m_SpriteMeshCache.AddSpriteMeshData(spriteMeshData); } m_WeightEditorWindow = new ModuleWindow(Contents.weightEditor.text, new Rect(0f, 0f, 300f, 195f)); m_WeightEditorWindow.windowGUICallback = WeightEditorInspector; m_InspectorWindow = new ModuleWindow(Contents.inspector.text, new Rect(0f, 0f, 300f, 95f)); m_GenerateGeometryMenuContents.settings = m_GenerateGeometrySettings; m_GenerateGeometryMenuContents.onGenerateGeometry = OnGenerateGeometry; m_BindPoseController.onSkinPreviewChanged += () => { m_MeshPreview.SetSkinningDirty(); }; m_MeshPreview.SetMeshDirty(); m_CachedSpriteMeshData = selectedSpriteMeshData; }