/* * Actual draw. Pipeline is 'deferred' list of GDI calls */ public static void Draw(Skeleton skeleton, Pipeline pipeline) { skeleton.UpdateWorldTransform(); foreach (Slot slot in skeleton.Slots) { if (slot.Attachment == null) { continue; } if (slot.Attachment.GetType() == typeof(RegionAttachment)) { RegionAttachment attach = (RegionAttachment)slot.Attachment; AtlasRegion region = (AtlasRegion)attach.RendererObject; float[] worldVertices = new float[2 * 4]; attach.ComputeWorldVertices(slot.Bone, worldVertices); var color = Color.FromArgb((int)(slot.A * 255), (int)(slot.R * 255), (int)(slot.G * 255), (int)(slot.B * 255)); DrawRegionAttachmnent(pipeline, region, worldVertices, color, slot.Data.BlendMode); } else if (slot.Attachment.GetType() == typeof(MeshAttachment)) { MeshAttachment attach = (MeshAttachment)slot.Attachment; AtlasRegion region = (AtlasRegion)attach.RendererObject; float[] worldVertices = new float[attach.WorldVerticesLength]; attach.ComputeWorldVertices(slot, worldVertices); int[] triangles = attach.Triangles; var color = Color.FromArgb((int)(slot.A * 255), (int)(slot.R * 255), (int)(slot.G * 255), (int)(slot.B * 255)); DrawMeshAttachmnent(pipeline, region, attach.RegionUVs, worldVertices, triangles, color, slot.Data.BlendMode); } else { } } }
/// <summary>Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.</summary> /// <param name="x">The horizontal distance between the skeleton origin and the left side of the AABB.</param> /// <param name="y">The vertical distance between the skeleton origin and the bottom side of the AABB.</param> /// <param name="width">The width of the AABB</param> /// <param name="height">The height of the AABB.</param> /// <param name="vertexBuffer">Reference to hold a float[]. May be a null reference. This method will assign it a new float[] with the appropriate size as needed.</param> public void GetBounds(out float x, out float y, out float width, out float height, ref float[] vertexBuffer) { float[] temp = vertexBuffer; temp = temp ?? new float[8]; var drawOrderItems = this.drawOrder.Items; float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue; for (int i = 0, n = this.drawOrder.Count; i < n; i++) { Slot slot = drawOrderItems[i]; int verticesLength = 0; float[] vertices = null; Attachment attachment = slot.attachment; var regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { verticesLength = 8; vertices = temp; if (vertices.Length < 8) { vertices = temp = new float[8]; } regionAttachment.ComputeWorldVertices(slot.bone, temp, 0); } else { var meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { MeshAttachment mesh = meshAttachment; verticesLength = mesh.WorldVerticesLength; vertices = temp; if (vertices.Length < verticesLength) { vertices = temp = new float[verticesLength]; } mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0); } } if (vertices != null) { for (int ii = 0; ii < verticesLength; ii += 2) { float vx = vertices[ii], vy = vertices[ii + 1]; minX = Math.Min(minX, vx); minY = Math.Min(minY, vy); maxX = Math.Max(maxX, vx); maxY = Math.Max(maxY, vy); } } } x = minX; y = minY; width = maxX - minX; height = maxY - minY; vertexBuffer = temp; }
static Mesh ExtractMeshAttachment (string name, MeshAttachment attachment, Mesh mesh = null) { var slot = GetExtractionSlot(); slot.Bone.X = 0; slot.Bone.Y = 0; slot.Bone.UpdateWorldTransform(); Vector2[] uvs = ExtractUV(attachment.UVs); float[] floatVerts = new float[attachment.Vertices.Length]; attachment.ComputeWorldVertices(slot, floatVerts); Vector3[] verts = ExtractVerts(floatVerts); int[] triangles = attachment.Triangles; Color color = new Color(attachment.R, attachment.G, attachment.B, attachment.A); if (mesh == null) mesh = new Mesh(); mesh.triangles = new int[0]; mesh.vertices = verts; mesh.uv = uvs; mesh.triangles = triangles; Color[] colors = new Color[verts.Length]; for (int i = 0; i < verts.Length; i++) colors[i] = color; mesh.colors = colors; mesh.RecalculateBounds(); mesh.RecalculateNormals(); mesh.name = name; return mesh; }
static Mesh ExtractWeightedMeshAttachment (string name, MeshAttachment attachment, int slotIndex, SkeletonData skeletonData, List<Transform> boneList, Mesh mesh = null) { if (attachment.Bones == null) throw new System.ArgumentException("Mesh is not weighted.", "attachment"); Skeleton skeleton = new Skeleton(skeletonData); skeleton.UpdateWorldTransform(); float[] floatVerts = new float[attachment.WorldVerticesLength]; attachment.ComputeWorldVertices(skeleton.Slots.Items[slotIndex], floatVerts); Vector2[] uvs = ExtractUV(attachment.UVs); Vector3[] verts = ExtractVerts(floatVerts); int[] triangles = attachment.Triangles; Color color = new Color(attachment.R, attachment.G, attachment.B, attachment.A); mesh = mesh ?? new Mesh(); mesh.triangles = new int[0]; mesh.vertices = verts; mesh.uv = uvs; mesh.triangles = triangles; Color[] colors = new Color[verts.Length]; for (int i = 0; i < verts.Length; i++) colors[i] = color; mesh.colors = colors; mesh.name = name; mesh.RecalculateNormals(); mesh.RecalculateBounds(); // Handle weights and binding var weightTable = new Dictionary<int, BoneWeightContainer>(); var warningBuilder = new System.Text.StringBuilder(); int[] bones = attachment.Bones; float[] weights = attachment.Vertices; for (int w = 0, v = 0, b = 0, n = bones.Length; v < n; w += 2) { int nn = bones[v++] + v; for (; v < nn; v++, b += 3) { Transform boneTransform = boneList[bones[v]]; int vIndex = w / 2; BoneWeightContainer container; if (weightTable.ContainsKey(vIndex)) container = weightTable[vIndex]; else { container = new BoneWeightContainer(); weightTable.Add(vIndex, container); } float weight = weights[b + 2]; container.Add(boneTransform, weight); } } BoneWeight[] boneWeights = new BoneWeight[weightTable.Count]; for (int i = 0; i < weightTable.Count; i++) { BoneWeight bw = new BoneWeight(); var container = weightTable[i]; var pairs = container.pairs.OrderByDescending(pair => pair.weight).ToList(); for (int b = 0; b < pairs.Count; b++) { if (b > 3) { if (warningBuilder.Length == 0) warningBuilder.Insert(0, "[Weighted Mesh: " + name + "]\r\nUnity only supports 4 weight influences per vertex! The 4 strongest influences will be used.\r\n"); warningBuilder.AppendFormat("{0} ignored on vertex {1}!\r\n", pairs[b].bone.name, i); continue; } int boneIndex = boneList.IndexOf(pairs[b].bone); float weight = pairs[b].weight; switch (b) { case 0: bw.boneIndex0 = boneIndex; bw.weight0 = weight; break; case 1: bw.boneIndex1 = boneIndex; bw.weight1 = weight; break; case 2: bw.boneIndex2 = boneIndex; bw.weight2 = weight; break; case 3: bw.boneIndex3 = boneIndex; bw.weight3 = weight; break; } } boneWeights[i] = bw; } Matrix4x4[] bindPoses = new Matrix4x4[boneList.Count]; for (int i = 0; i < boneList.Count; i++) { bindPoses[i] = boneList[i].worldToLocalMatrix; } mesh.boneWeights = boneWeights; mesh.bindposes = bindPoses; string warningString = warningBuilder.ToString(); if (warningString.Length > 0) Debug.LogWarning(warningString); return mesh; }
public void Draw(Skeleton skeleton) { float[] vertices = this.vertices; List <Slot> drawOrder = skeleton.DrawOrder; float skeletonR = skeleton.R, skeletonG = skeleton.G, skeletonB = skeleton.B, skeletonA = skeleton.A; for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrder[i]; Attachment attachment = slot.Attachment; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; BlendState blend = slot.Data.AdditiveBlending ? BlendState.Additive : defaultBlendState; if (device.BlendState != blend) { End(); device.BlendState = blend; } MeshItem item = batcher.NextItem(4, 6); item.triangles = quadTriangles; VertexPositionColorTexture[] itemVertices = item.vertices; AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject; item.texture = (Texture2D)region.page.rendererObject; Color color; float a = skeletonA * slot.A * regionAttachment.A; if (premultipliedAlpha) { color = new Color( skeletonR * slot.R * regionAttachment.R * a, skeletonG * slot.G * regionAttachment.G * a, skeletonB * slot.B * regionAttachment.B * a, a); } else { color = new Color( skeletonR * slot.R * regionAttachment.R, skeletonG * slot.G * regionAttachment.G, skeletonB * slot.B * regionAttachment.B, a); } itemVertices[TL].Color = color; itemVertices[BL].Color = color; itemVertices[BR].Color = color; itemVertices[TR].Color = color; regionAttachment.ComputeWorldVertices(slot.Bone, vertices); itemVertices[TL].Position.X = vertices[RegionAttachment.X1]; itemVertices[TL].Position.Y = vertices[RegionAttachment.Y1]; itemVertices[TL].Position.Z = 0; itemVertices[BL].Position.X = vertices[RegionAttachment.X2]; itemVertices[BL].Position.Y = vertices[RegionAttachment.Y2]; itemVertices[BL].Position.Z = 0; itemVertices[BR].Position.X = vertices[RegionAttachment.X3]; itemVertices[BR].Position.Y = vertices[RegionAttachment.Y3]; itemVertices[BR].Position.Z = 0; itemVertices[TR].Position.X = vertices[RegionAttachment.X4]; itemVertices[TR].Position.Y = vertices[RegionAttachment.Y4]; itemVertices[TR].Position.Z = 0; float[] uvs = regionAttachment.UVs; itemVertices[TL].TextureCoordinate.X = uvs[RegionAttachment.X1]; itemVertices[TL].TextureCoordinate.Y = uvs[RegionAttachment.Y1]; itemVertices[BL].TextureCoordinate.X = uvs[RegionAttachment.X2]; itemVertices[BL].TextureCoordinate.Y = uvs[RegionAttachment.Y2]; itemVertices[BR].TextureCoordinate.X = uvs[RegionAttachment.X3]; itemVertices[BR].TextureCoordinate.Y = uvs[RegionAttachment.Y3]; itemVertices[TR].TextureCoordinate.X = uvs[RegionAttachment.X4]; itemVertices[TR].TextureCoordinate.Y = uvs[RegionAttachment.Y4]; } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; int vertexCount = mesh.Vertices.Length; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(slot, vertices); int[] triangles = mesh.Triangles; MeshItem item = batcher.NextItem(vertexCount, triangles.Length); item.triangles = triangles; AtlasRegion region = (AtlasRegion)mesh.RendererObject; item.texture = (Texture2D)region.page.rendererObject; Color color; float a = skeletonA * slot.A * mesh.A; if (premultipliedAlpha) { color = new Color( skeletonR * slot.R * mesh.R * a, skeletonG * slot.G * mesh.G * a, skeletonB * slot.B * mesh.B * a, a); } else { color = new Color( skeletonR * slot.R * mesh.R, skeletonG * slot.G * mesh.G, skeletonB * slot.B * mesh.B, a); } float[] uvs = mesh.UVs; VertexPositionColorTexture[] itemVertices = item.vertices; for (int ii = 0, v = 0; v < vertexCount; ii++, v += 2) { itemVertices[ii].Color = color; itemVertices[ii].Position.X = vertices[v]; itemVertices[ii].Position.Y = vertices[v + 1]; itemVertices[ii].Position.Z = 0; itemVertices[ii].TextureCoordinate.X = uvs[v]; itemVertices[ii].TextureCoordinate.Y = uvs[v + 1]; } } else if (attachment is SkinnedMeshAttachment) { SkinnedMeshAttachment mesh = (SkinnedMeshAttachment)attachment; int vertexCount = mesh.UVs.Length; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } mesh.ComputeWorldVertices(slot, vertices); int[] triangles = mesh.Triangles; MeshItem item = batcher.NextItem(vertexCount, triangles.Length); item.triangles = triangles; AtlasRegion region = (AtlasRegion)mesh.RendererObject; item.texture = (Texture2D)region.page.rendererObject; Color color; float a = skeletonA * slot.A * mesh.A; if (premultipliedAlpha) { color = new Color( skeletonR * slot.R * mesh.R * a, skeletonG * slot.G * mesh.G * a, skeletonB * slot.B * mesh.B * a, a); } else { color = new Color( skeletonR * slot.R * mesh.R, skeletonG * slot.G * mesh.G, skeletonB * slot.B * mesh.B, a); } float[] uvs = mesh.UVs; VertexPositionColorTexture[] itemVertices = item.vertices; for (int ii = 0, v = 0; v < vertexCount; ii++, v += 2) { itemVertices[ii].Color = color; itemVertices[ii].Position.X = vertices[v]; itemVertices[ii].Position.Y = vertices[v + 1]; itemVertices[ii].Position.Z = 0; itemVertices[ii].TextureCoordinate.X = uvs[v]; itemVertices[ii].TextureCoordinate.Y = uvs[v + 1]; } } } }
public void GetBounds(out float x, out float y, out float width, out float height, ref float[] vertexBuffer) { float[] worldVertices = vertexBuffer; if (worldVertices != null) { worldVertices = worldVertices; } else { worldVertices = new float[8]; } Slot[] items = this.drawOrder.Items; float num = 2.147484E+09f; float num2 = 2.147484E+09f; float num3 = -2.147484E+09f; float num4 = -2.147484E+09f; int index = 0; int count = this.drawOrder.Count; while (index < count) { Slot slot = items[index]; int worldVerticesLength = 0; float[] numArray2 = null; Attachment attachment = slot.attachment; RegionAttachment attachment2 = attachment as RegionAttachment; if (attachment2 != null) { worldVerticesLength = 8; numArray2 = worldVertices; if (numArray2.Length < 8) { numArray2 = worldVertices = new float[8]; } attachment2.ComputeWorldVertices(slot.bone, worldVertices, 0, 2); } else { MeshAttachment attachment3 = attachment as MeshAttachment; if (attachment3 != null) { MeshAttachment attachment4 = attachment3; worldVerticesLength = attachment4.WorldVerticesLength; numArray2 = worldVertices; if (numArray2.Length < worldVerticesLength) { numArray2 = worldVertices = new float[worldVerticesLength]; } attachment4.ComputeWorldVertices(slot, 0, worldVerticesLength, worldVertices, 0, 2); } } if (numArray2 != null) { for (int i = 0; i < worldVerticesLength; i += 2) { float num9 = numArray2[i]; float num10 = numArray2[i + 1]; num = Math.Min(num, num9); num2 = Math.Min(num2, num10); num3 = Math.Max(num3, num9); num4 = Math.Max(num4, num10); } } index++; } x = num; y = num2; width = num3 - num; height = num4 - num2; vertexBuffer = worldVertices; }
public void Draw(Skeleton skeleton) { var drawOrder = skeleton.DrawOrder; var drawOrderItems = skeleton.DrawOrder.Items; float skeletonR = skeleton.R, skeletonG = skeleton.G, skeletonB = skeleton.B, skeletonA = skeleton.A; Color color = new Color(); if (VertexEffect != null) { VertexEffect.Begin(skeleton); } for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrderItems[i]; Attachment attachment = slot.Attachment; float attachmentColorR, attachmentColorG, attachmentColorB, attachmentColorA; Texture2D texture = null; int verticesCount = 0; float[] vertices = this.vertices; int indicesCount = 0; int[] indices = null; float[] uvs = null; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; attachmentColorR = regionAttachment.R; attachmentColorG = regionAttachment.G; attachmentColorB = regionAttachment.B; attachmentColorA = regionAttachment.A; AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject; texture = (Texture2D)region.page.rendererObject; verticesCount = 4; regionAttachment.ComputeWorldVertices(slot.Bone, vertices, 0, 2); indicesCount = 6; indices = quadTriangles; uvs = regionAttachment.UVs; } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; attachmentColorR = mesh.R; attachmentColorG = mesh.G; attachmentColorB = mesh.B; attachmentColorA = mesh.A; AtlasRegion region = (AtlasRegion)mesh.RendererObject; texture = (Texture2D)region.page.rendererObject; int vertexCount = mesh.WorldVerticesLength; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } verticesCount = vertexCount >> 1; mesh.ComputeWorldVertices(slot, vertices); indicesCount = mesh.Triangles.Length; indices = mesh.Triangles; uvs = mesh.UVs; } else if (attachment is ClippingAttachment) { ClippingAttachment clip = (ClippingAttachment)attachment; clipper.ClipStart(slot, clip); continue; } else { continue; } // set blend state BlendState blend = slot.Data.BlendMode == BlendMode.Additive ? BlendState.Additive : defaultBlendState; if (device.BlendState != blend) { //End(); //device.BlendState = blend; } // calculate color float a = skeletonA * slot.A * attachmentColorA; if (premultipliedAlpha) { color = new Color( skeletonR * slot.R * attachmentColorR * a, skeletonG * slot.G * attachmentColorG * a, skeletonB * slot.B * attachmentColorB * a, a); } else { color = new Color( skeletonR * slot.R * attachmentColorR, skeletonG * slot.G * attachmentColorG, skeletonB * slot.B * attachmentColorB, a); } Color darkColor = new Color(); if (slot.HasSecondColor) { if (premultipliedAlpha) { darkColor = new Color(slot.R2 * a, slot.G2 * a, slot.B2 * a); } else { darkColor = new Color(slot.R2 * a, slot.G2 * a, slot.B2 * a); } } darkColor.A = premultipliedAlpha ? (byte)255 : (byte)0; // clip if (clipper.IsClipping) { clipper.ClipTriangles(vertices, verticesCount << 1, indices, indicesCount, uvs); vertices = clipper.ClippedVertices.Items; verticesCount = clipper.ClippedVertices.Count >> 1; indices = clipper.ClippedTriangles.Items; indicesCount = clipper.ClippedTriangles.Count; uvs = clipper.ClippedUVs.Items; } if (verticesCount == 0 || indicesCount == 0) { continue; } // submit to batch MeshItem item = batcher.NextItem(verticesCount, indicesCount); item.texture = texture; for (int ii = 0, nn = indicesCount; ii < nn; ii++) { item.triangles[ii] = indices[ii]; } VertexPositionColorTextureColor[] itemVertices = item.vertices; for (int ii = 0, v = 0, nn = verticesCount << 1; v < nn; ii++, v += 2) { itemVertices[ii].Color = color; itemVertices[ii].Color2 = darkColor; itemVertices[ii].Position.X = vertices[v]; itemVertices[ii].Position.Y = vertices[v + 1]; itemVertices[ii].Position.Z = 0; itemVertices[ii].TextureCoordinate.X = uvs[v]; itemVertices[ii].TextureCoordinate.Y = uvs[v + 1]; if (VertexEffect != null) { VertexEffect.Transform(ref itemVertices[ii]); } } clipper.ClipEnd(slot); } clipper.ClipEnd(); if (VertexEffect != null) { VertexEffect.End(); } }
public void GetBounds(out float x, out float y, out float width, out float height, ref float[] vertexBuffer) { float[] array = vertexBuffer; array = (array ?? new float[8]); Slot[] items = drawOrder.Items; float num = 2.14748365E+09f; float num2 = 2.14748365E+09f; float num3 = -2.14748365E+09f; float num4 = -2.14748365E+09f; int i = 0; for (int count = drawOrder.Count; i < count; i++) { Slot slot = items[i]; int num5 = 0; float[] array2 = null; Attachment attachment = slot.attachment; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { num5 = 8; array2 = array; if (array2.Length < 8) { array2 = (array = new float[8]); } regionAttachment.ComputeWorldVertices(slot.bone, array, 0); } else { MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { MeshAttachment meshAttachment2 = meshAttachment; num5 = meshAttachment2.WorldVerticesLength; array2 = array; if (array2.Length < num5) { array2 = (array = new float[num5]); } meshAttachment2.ComputeWorldVertices(slot, 0, num5, array, 0); } } if (array2 != null) { for (int j = 0; j < num5; j += 2) { float val = array2[j]; float val2 = array2[j + 1]; num = Math.Min(num, val); num2 = Math.Min(num2, val2); num3 = Math.Max(num3, val); num4 = Math.Max(num4, val2); } } } x = num; y = num2; width = num3 - num; height = num4 - num2; vertexBuffer = array; }