public static void ShowBounding(Spine.Slot boundingSlot, Transform transform, LineRenderer lineRender) { Spine.BoundingBoxAttachment bounding = boundingSlot.Attachment as Spine.BoundingBoxAttachment; float[] vertices = bounding.Vertices; int n = vertices.Length / 2; lineRender.SetVertexCount(n); for (int i = 0; i < n; ++i) { float localX = vertices[i * 2 + 0]; float localY = vertices[i * 2 + 1]; float worldX; float worldY; boundingSlot.Bone.localToWorld(localX, localY, out worldX, out worldY); // Vector3 p = new Vector3(worldX, worldY, 0); // p = transform.TransformPoint(p); lineRender.SetPosition(i, new Vector3(worldX, worldY, -1)); } lineRender.transform.position = transform.position; lineRender.transform.rotation = transform.rotation; lineRender.transform.localScale = transform.localScale; }
public Skeleton (SkeletonData data) { if (data == null) throw new ArgumentNullException("data cannot be null."); this.data = data; bones = new List<Bone>(data.bones.Count); foreach (BoneData boneData in data.bones) { Bone parent = boneData.parent == null ? null : bones[data.bones.IndexOf(boneData.parent)]; bones.Add(new Bone(boneData, this, parent)); } slots = new List<Slot>(data.slots.Count); drawOrder = new List<Slot>(data.slots.Count); foreach (SlotData slotData in data.slots) { Bone bone = bones[data.bones.IndexOf(slotData.boneData)]; Slot slot = new Slot(slotData, bone); slots.Add(slot); drawOrder.Add(slot); } ikConstraints = new List<IkConstraint>(data.ikConstraints.Count); foreach (IkConstraintData ikConstraintData in data.ikConstraints) ikConstraints.Add(new IkConstraint(ikConstraintData, this)); UpdateCache(); }
public static PolygonCollider2D AddBoundingBoxAsComponent (BoundingBoxAttachment box, Slot slot, GameObject gameObject, bool isTrigger = true) { if (box == null) return null; var collider = gameObject.AddComponent<PolygonCollider2D>(); collider.isTrigger = isTrigger; SetColliderPointsLocal(collider, slot, box); return collider; }
public Skeleton(SkeletonData data) { if (data == null) throw new ArgumentNullException("data cannot be null."); this.data = data; bones = new ExposedList<Bone>(data.bones.Count); foreach (BoneData boneData in data.bones) { Bone parent = boneData.parent == null ? null : bones.Items[data.bones.IndexOf(boneData.parent)]; Bone bone = new Bone(boneData, this, parent); if (parent != null) parent.children.Add(bone); bones.Add(bone); } slots = new ExposedList<Slot>(data.slots.Count); drawOrder = new ExposedList<Slot>(data.slots.Count); foreach (SlotData slotData in data.slots) { Bone bone = bones.Items[data.bones.IndexOf(slotData.boneData)]; Slot slot = new Slot(slotData, bone); slots.Add(slot); drawOrder.Add(slot); } ikConstraints = new ExposedList<IkConstraint>(data.ikConstraints.Count); foreach (IkConstraintData ikConstraintData in data.ikConstraints) ikConstraints.Add(new IkConstraint(ikConstraintData, this)); transformConstraints = new ExposedList<TransformConstraint>(data.transformConstraints.Count); foreach (TransformConstraintData transformConstraintData in data.transformConstraints) transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); UpdateCache(); UpdateWorldTransform(); }
public Skeleton(SkeletonData data) { if (data == null) throw new ArgumentNullException("data cannot be null."); Data = data; Bones = new List<Bone>(Data.Bones.Count); foreach (BoneData boneData in Data.Bones) { Bone parent = boneData.Parent == null ? null : Bones[Data.Bones.IndexOf(boneData.Parent)]; Bones.Add(new Bone(boneData, parent)); } Slots = new List<Slot>(Data.Slots.Count); DrawOrder = new List<Slot>(Data.Slots.Count); foreach (SlotData slotData in Data.Slots) { Bone bone = Bones[Data.Bones.IndexOf(slotData.BoneData)]; Slot slot = new Slot(slotData, this, bone); Slots.Add(slot); DrawOrder.Add(slot); } R = 1; G = 1; B = 1; A = 1; }
public Spine.Slot GetBoundingSlot(int index) { string name = GetTileName(index); Spine.Slot boundingSlot = _skeletonAnim.Skeleton.FindSlot("_" + name); return(boundingSlot); }
public static bool IsPointInsideBounding(Vector3 worldPoint, Spine.Slot boundingSlot, Transform transform) { worldPoint = transform.InverseTransformPoint(worldPoint); float mx; float my; boundingSlot.Bone.worldToLocal(worldPoint.x, worldPoint.y, out mx, out my); Spine.BoundingBoxAttachment bounding = boundingSlot.Attachment as Spine.BoundingBoxAttachment; float[] vertices = (float[])bounding.Vertices.Clone(); /* * Vector3 p = new Vector3 (); * * int n = vertices.Length / 2; * for(int i = 0; i < n; ++i) * { * float localX = vertices[i * 2 + 0]; * float localY = vertices[i * 2 + 1]; * float worldX; * float worldY; * boundingSlot.Bone.localToWorld(localX, localY, out worldX, out worldY); * * p.Set(worldX, worldY, 0); * p = transform.TransformPoint(p); * * vertices[i * 2 + 0] = p.x; * vertices[i * 2 + 1] = p.y; * } */ bool inside = GeometryHelper.IsPointInsidePolygon(mx, my, vertices); return(inside); }
public void ShowAttackArrow() { FreeArrow(); DataMission dataMission = _dataCampaign.missions [_selectTileIndex]; for (int i = 0; i < DataMission.ARROW_COUNT_MAX; ++i) { DataConfig.CAMPAIGN_ARROW arrow = dataMission.arrows[i]; float arrowRotation = dataMission.arrowsRotation[i]; // arrowRotation = 180; if (arrow != DataConfig.CAMPAIGN_ARROW.UNKNOWN) { string spineName = GetArrowFileName(arrow); GameObject spineArrow = ResourceHelper.Load(spineName); _skeletonAnimArrows.Add(spineArrow); Spine.Slot boundingSlot = GetBoundingSlot(_selectTileIndex); Vector3 center = SpineHelper.CalcTileArrowOffset(boundingSlot, _skeletonAnim.transform, arrowRotation); spineArrow.transform.position = center + new Vector3(0, 0, -1); spineArrow.transform.Rotate(0, 0, arrowRotation); } } }
public void ComputeWorldVertices (Slot slot, int start, int count, float[] worldVertices, int offset) { count += offset; Skeleton skeleton = slot.Skeleton; float x = skeleton.x, y = skeleton.y; var deformArray = slot.attachmentVertices; float[] vertices = this.vertices; int[] bones = this.bones; if (bones == null) { if (deformArray.Count > 0) vertices = deformArray.Items; Bone bone = slot.bone; x += bone.worldX; y += bone.worldY; float a = bone.a, b = bone.b, c = bone.c, d = bone.d; for (int vv = start, w = offset; w < count; vv += 2, w += 2) { float vx = vertices[vv], vy = vertices[vv + 1]; worldVertices[w] = vx * a + vy * b + x; worldVertices[w + 1] = vx * c + vy * d + y; } return; } int v = 0, skip = 0; for (int i = 0; i < start; i += 2) { int n = bones[v]; v += n + 1; skip += n; } Bone[] skeletonBones = skeleton.Bones.Items; if (deformArray.Count == 0) { for (int w = offset, b = skip * 3; w < count; w += 2) { float wx = x, wy = y; int n = bones[v++]; n += v; for (; v < n; v++, b += 3) { Bone bone = skeletonBones[bones[v]]; float vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; } worldVertices[w] = wx; worldVertices[w + 1] = wy; } } else { float[] deform = deformArray.Items; for (int w = offset, b = skip * 3, f = skip << 1; w < count; w += 2) { float wx = x, wy = y; int n = bones[v++]; n += v; for (; v < n; v++, b += 3, f += 2) { Bone bone = skeletonBones[bones[v]]; float vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; } worldVertices[w] = wx; worldVertices[w + 1] = wy; } } }
public static PolygonCollider2D AddBoundingBoxGameObject (string name, BoundingBoxAttachment box, Slot slot, Transform parent, bool isTrigger = true) { var go = new GameObject("[BoundingBox]" + (string.IsNullOrEmpty(name) ? box.Name : name)); var got = go.transform; got.parent = parent; got.localPosition = Vector3.zero; got.localRotation = Quaternion.identity; got.localScale = Vector3.one; return AddBoundingBoxAsComponent(box, slot, go, isTrigger); }
void spRegionAttachment_updateQuad(ref RegionAttachment self, ref Slot slot, CCV3F_C4B_T2F_Quad quad, bool premultipliedAlpha) { float[] vertices = new float[8]; self.ComputeWorldVertices(slot.Skeleton.X, slot.Skeleton.Y, slot.Bone, vertices); float r = (slot.Skeleton.R * slot.R * 255); float g = (slot.Skeleton.G * slot.G * 255); float b = (slot.Skeleton.B * slot.B * 255); float normalizedAlpha = slot.Skeleton.A * slot.A; if (premultipliedAlpha) { r *= normalizedAlpha; g *= normalizedAlpha; b *= normalizedAlpha; } float a = normalizedAlpha * 255; quad.BottomLeft.Colors.R = Convert.ToByte(r); quad.BottomLeft.Colors.G = Convert.ToByte(g); quad.BottomLeft.Colors.B = Convert.ToByte(b); quad.BottomLeft.Colors.A = Convert.ToByte(a); quad.TopLeft.Colors.R = Convert.ToByte(r); quad.TopLeft.Colors.G = Convert.ToByte(g); quad.TopLeft.Colors.B = Convert.ToByte(b); quad.TopLeft.Colors.A = Convert.ToByte(a); quad.TopRight.Colors.R = Convert.ToByte(r); quad.TopRight.Colors.G = Convert.ToByte(g); quad.TopRight.Colors.B = Convert.ToByte(b); quad.TopRight.Colors.A = Convert.ToByte(a); quad.BottomRight.Colors.R = Convert.ToByte(r); quad.BottomRight.Colors.G = Convert.ToByte(g); quad.BottomRight.Colors.B = Convert.ToByte(b); quad.BottomRight.Colors.A = Convert.ToByte(a); quad.BottomLeft.Vertices.X = vertices[RegionAttachment.X1]; quad.BottomLeft.Vertices.Y = vertices[RegionAttachment.Y1]; quad.TopLeft.Vertices.X = vertices[RegionAttachment.X2]; quad.TopLeft.Vertices.Y = vertices[RegionAttachment.Y2]; quad.TopRight.Vertices.X = vertices[RegionAttachment.X3]; quad.TopRight.Vertices.Y = vertices[RegionAttachment.Y3]; quad.BottomRight.Vertices.X = vertices[RegionAttachment.X4]; quad.BottomRight.Vertices.Y = vertices[RegionAttachment.Y4]; quad.BottomLeft.TexCoords.U = self.UVs[RegionAttachment.X1]; quad.BottomLeft.TexCoords.V = self.UVs[RegionAttachment.Y1]; quad.TopLeft.TexCoords.U = self.UVs[RegionAttachment.X2]; quad.TopLeft.TexCoords.V = self.UVs[RegionAttachment.Y2]; quad.TopRight.TexCoords.U = self.UVs[RegionAttachment.X3]; quad.TopRight.TexCoords.V = self.UVs[RegionAttachment.Y3]; quad.BottomRight.TexCoords.U = self.UVs[RegionAttachment.X4]; quad.BottomRight.TexCoords.V = self.UVs[RegionAttachment.Y4]; }
void spRegionAttachment_updateQuad(RegionAttachment self, Slot slot, CCV3F_C4B_T2F_Quad quad, bool premultipliedAlpha = false) { float[] vertices = new float[8]; self.ComputeWorldVertices(slot.Skeleton.X, slot.Skeleton.Y, slot.Bone, vertices); byte r = Convert.ToByte(slot.Skeleton.R * slot.R * 255); byte g =Convert.ToByte( slot.Skeleton.G * slot.G * 255); byte b = Convert.ToByte(slot.Skeleton.B * slot.B * 255); byte normalizedAlpha = Convert.ToByte( slot.Skeleton.A * slot.A); if (premultipliedAlpha) { r *= normalizedAlpha; g *= normalizedAlpha; b *= normalizedAlpha; } byte a = Convert.ToByte(normalizedAlpha * 255); quad.BottomLeft.Colors.R = r; quad.BottomLeft.Colors.G = g; quad.BottomLeft.Colors.B = b; quad.BottomLeft.Colors.A = a; quad.TopLeft.Colors.R = r; quad.TopLeft.Colors.G = g; quad.TopLeft.Colors.B = b; quad.TopLeft.Colors.A = a; quad.TopRight.Colors.R = r; quad.TopRight.Colors.G = g; quad.TopRight.Colors.B = b; quad.TopRight.Colors.A = a; quad.BottomRight.Colors.R = r; quad.BottomRight.Colors.G = g; quad.BottomRight.Colors.B = b; quad.BottomRight.Colors.A = a; quad.BottomLeft.Vertices.X = vertices[VERTEX_X1]; quad.BottomLeft.Vertices.Y = vertices[VERTEX_Y1]; quad.TopLeft.Vertices.X = vertices[VERTEX_X2]; quad.TopLeft.Vertices.Y = vertices[VERTEX_Y2]; quad.TopRight.Vertices.X = vertices[VERTEX_X3]; quad.TopRight.Vertices.Y = vertices[VERTEX_Y3]; quad.BottomRight.Vertices.X = vertices[VERTEX_X4]; quad.BottomRight.Vertices.Y = vertices[VERTEX_Y4]; quad.BottomLeft.TexCoords.U = self.UVs[VERTEX_X1]; quad.BottomLeft.TexCoords.V = self.UVs[VERTEX_Y1]; quad.TopLeft.TexCoords.U = self.UVs[VERTEX_X2]; quad.TopLeft.TexCoords.V = self.UVs[VERTEX_Y2]; quad.TopRight.TexCoords.U = self.UVs[VERTEX_X3]; quad.TopRight.TexCoords.V = self.UVs[VERTEX_Y3]; quad.BottomRight.TexCoords.U = self.UVs[VERTEX_X4]; quad.BottomRight.TexCoords.V = self.UVs[VERTEX_Y4]; }
public void StartReplace() { Spine.Slot baseWQ = skeleton.FindSlot(slot); Spine.Attachment originalAttachment = baseWQ.Attachment; Spine.Attachment newAttachment = originalAttachment.GetRemappedClone (Img, originalAttachment.GetMaterial()); baseWQ.Bone.ScaleY = -thisSlotBaseData.ScaleY; baseWQ.Bone.Rotation = thisSlotBaseData.Rotation - 45; baseWQ.Bone.SetLocalPosition(new Vector2(0, -thisSlotBaseData.Y * 2)); baseWQ.Attachment = newAttachment; }
public PathConstraint (PathConstraintData data, Skeleton skeleton) { if (data == null) throw new ArgumentNullException("data", "data cannot be null."); if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null."); this.data = data; bones = new ExposedList<Bone>(data.Bones.Count); foreach (BoneData boneData in data.bones) bones.Add(skeleton.FindBone(boneData.name)); target = skeleton.FindSlot(data.target.name); position = data.position; spacing = data.spacing; rotateMix = data.rotateMix; translateMix = data.translateMix; }
public void StartReplace2() { Spine.Slot baseWQ = skeleton.FindSlot(slot); Spine.Attachment originalAttachment = baseWQ.Attachment; Spine.Attachment newAttachment = originalAttachment.GetRemappedClone (Img, originalAttachment.GetMaterial()); baseWQ.Attachment = newAttachment; // Spine.Slot otherWQ = skeleton.FindSlot("R_" + slot); Spine.Attachment originalAttachment2 = otherWQ.Attachment; Spine.Attachment newAttachment2 = originalAttachment2.GetRemappedClone (Img, originalAttachment2.GetMaterial()); otherWQ.Attachment = newAttachment2; }
// ========================================================================== // collision public int DetectTileIndex(Vector3 worldPoint) { foreach (Spine.Slot slot in _skeletonAnim.skeleton.slots) { string boneName = slot.Bone.Data.Name; if (!IsTileName(boneName)) { continue; } bool inside = false; Spine.Slot boundingSlot = _skeletonAnim.Skeleton.FindSlot("_" + boneName); if (boundingSlot != null) { inside = SpineHelper.IsPointInsideBounding(worldPoint, boundingSlot, _skeletonAnim.transform); } /* * Spine.BoundingBoxAttachment bounding = boundingSlot.Attachment as Spine.BoundingBoxAttachment; * float[] vertices = (float[])bounding.Vertices.Clone(); * * int n = vertices.Length / 2; * for(int i = 0; i < n; ++i) * { * float localX = vertices[i * 2 + 0]; * float localY = vertices[i * 2 + 1]; * float worldX; * float worldY; * bone.localToWorld(localX, localY, out worldX, out worldY); * * Vector3 p = new Vector3(worldX, worldY, 0); * p = _skeletonAnim.transform.TransformPoint(p); * * vertices[i * 2 + 0] = p.x; * vertices[i * 2 + 1] = p.y; * } * * bool inside = GeometryHelper.IsPointInsidePolygon(mx, my, vertices); */ if (inside) { int index = GetTileIndex(boneName); return(index); } } return(-1); }
private void DrawSlot(Skeleton skeleton, RegionAttachment attachment, Slot slot) { var region = (AtlasRegion)attachment.RendererObject; var thisMaterial = (Material)region.page.rendererObject; var thisBlendMode = slot.Data.AdditiveBlending ? BlendMode.Additive : BlendMode.Normal; var thisBatch = (Batch2D)renderer.FindOrCreateBatch(thisMaterial, thisBlendMode); if (currentBatch != null && currentBatch != thisBatch) renderer.FlushDrawBuffer(currentBatch); currentBatch = thisBatch; attachment.ComputeWorldVertices(skeleton.X, skeleton.Y, slot.Bone, vertices); currentColor = new Color(color.RedValue * slot.R, color.GreenValue * slot.G, color.BlueValue * slot.B, color.AlphaValue * slot.A); AddSlotIndicesAndVertices(attachment.UVs); }
static int FindSlot(IntPtr L) { try { ToLua.CheckArgsCount(L, 2); Spine.Skeleton obj = (Spine.Skeleton)ToLua.CheckObject <Spine.Skeleton>(L, 1); string arg0 = ToLua.CheckString(L, 2); Spine.Slot o = obj.FindSlot(arg0); ToLua.PushObject(L, o); return(1); } catch (Exception e) { return(LuaDLL.toluaL_exception(L, e)); } }
public static Vector3 CalcTileArrowOffset(Spine.Slot boundingSlot, Transform transform, float rotation, float innerRate = 0.7f) { float radius = AngleHelper.AngleToRadius(rotation - 90); Vector3 v = new Vector3(Mathf.Cos(radius), Mathf.Sin(radius)) * 10000; Spine.BoundingBoxAttachment bounding = boundingSlot.Attachment as Spine.BoundingBoxAttachment; float[] vertices = (float[])bounding.Vertices.Clone(); Vector2 p1 = new Vector2(); Vector2 p2 = new Vector2(); int n = vertices.Length / 2; for (int i = 0; i <= n; ++i) { int m = i % n; float localX = vertices[m * 2 + 0]; float localY = vertices[m * 2 + 1]; p2.Set(localX, localY); if (i >= 1) { float intersectDist; Vector2 intersectPoint; if (GeometryHelper.CalcIntersectPoint(Vector2.zero, v, p1, p2, out intersectPoint, out intersectDist)) { intersectPoint *= innerRate; float worldX; float worldY; boundingSlot.Bone.localToWorld(intersectPoint.x, intersectPoint.y, out worldX, out worldY); Vector3 offset = new Vector3(worldX, worldY, 0); offset = transform.TransformPoint(offset); return(offset); } } p1 = p2; } Vector3 boneCenter = new Vector3(boundingSlot.Bone.WorldX, boundingSlot.Bone.WorldY, 0); boneCenter = transform.TransformPoint(boneCenter); return(boneCenter); }
public void Initialize(bool overwrite = false) { if (this.skeletonRenderer != null) { this.skeletonRenderer.Initialize(false); if (!string.IsNullOrEmpty(this.slotName) && (((overwrite || (this.colliderTable.Count <= 0)) || ((this.slot == null) || (this.skeletonRenderer.skeleton != this.slot.Skeleton))) || (this.slotName != this.slot.data.name))) { this.DisposeColliders(); Skeleton skeleton = this.skeletonRenderer.skeleton; this.slot = skeleton.FindSlot(this.slotName); int slotIndex = skeleton.FindSlotIndex(this.slotName); if (this.slot == null) { if (DebugMessages) { Debug.LogWarning($"Slot '{this.slotName}' not found for BoundingBoxFollower on '{base.gameObject.name}'. (Previous colliders were disposed.)"); } } else { if (base.gameObject.activeInHierarchy) { foreach (Skin skin in skeleton.Data.Skins) { this.AddSkin(skin, slotIndex); } if (skeleton.skin != null) { this.AddSkin(skeleton.skin, slotIndex); } } if (DebugMessages && (this.colliderTable.Count == 0)) { if (base.gameObject.activeInHierarchy) { Debug.LogWarning("Bounding Box Follower not valid! Slot [" + this.slotName + "] does not contain any Bounding Box Attachments!"); } else { Debug.LogWarning("Bounding Box Follower tried to rebuild as a prefab."); } } } } } }
private void DisposeColliders() { PolygonCollider2D[] components = base.GetComponents <PolygonCollider2D>(); if (components.Length != 0) { if (Application.isEditor) { if (Application.isPlaying) { foreach (PolygonCollider2D colliderd in components) { if (colliderd != null) { UnityEngine.Object.Destroy(colliderd); } } } else { foreach (PolygonCollider2D colliderd2 in components) { if (colliderd2 != null) { UnityEngine.Object.DestroyImmediate(colliderd2); } } } } else { foreach (PolygonCollider2D colliderd3 in components) { if (colliderd3 != null) { UnityEngine.Object.Destroy(colliderd3); } } } this.slot = null; this.currentAttachment = null; this.currentAttachmentName = null; this.currentCollider = null; this.colliderTable.Clear(); this.nameTable.Clear(); } }
/// <summary> /// Creates the region attachment by texture. /// </summary> /// <returns>The region attachment by texture.</returns> /// <param name="slot">Slot.</param> /// <param name="texture">Texture.</param> private Attachment CreateRegionAttachmentByTexture(Spine.Slot slot, Texture2D texture) { if (slot == null) { return(null); } Spine.RegionAttachment oldAtt = slot.Attachment as Spine.RegionAttachment; if (oldAtt == null || texture == null) { return(null); } Spine.RegionAttachment att = new Spine.RegionAttachment(oldAtt.Name); att.RendererObject = CreateRegion(texture); att.Width = oldAtt.Width; att.Height = oldAtt.Height; att.offset = oldAtt.offset; att.Path = oldAtt.Path; att.R = oldAtt.R; att.G = oldAtt.G; att.B = oldAtt.B; att.A = oldAtt.A; att.X = oldAtt.X; att.y = oldAtt.Y; att.Rotation = oldAtt.Rotation; att.ScaleX = oldAtt.ScaleX; att.ScaleY = oldAtt.ScaleY; att.SetUVs(0f, 1f, 1f, 0f, false); Material mat = new Material(Shader.Find("Sprites/Default")); mat.mainTexture = texture; (att.RendererObject as Spine.AtlasRegion).page.rendererObject = mat; slot.Attachment = att; return(slot.Attachment); }
/// <summary> /// Creates the mesh attachment by texture. /// </summary> /// <returns>The mesh attachment by texture.</returns> /// <param name="slot">Slot.</param> /// <param name="texture">Texture.</param> private Attachment CreateMeshAttachmentByTexture(Spine.Slot slot, Texture2D texture) { if (slot == null) { return(null); } Spine.MeshAttachment oldAtt = slot.Attachment as Spine.MeshAttachment; if (oldAtt == null || texture == null) { return(null); } Spine.MeshAttachment att = new Spine.MeshAttachment(oldAtt.Name); att.RendererObject = CreateRegion(texture); att.Path = oldAtt.Path; att.Bones = oldAtt.Bones; att.Edges = oldAtt.Edges; att.Triangles = oldAtt.triangles; att.Vertices = oldAtt.Vertices; att.WorldVerticesLength = oldAtt.WorldVerticesLength; att.HullLength = oldAtt.HullLength; att.RegionRotate = false; att.RegionU = 0f; att.RegionV = 1f; att.RegionU2 = 1f; att.RegionV2 = 0f; att.RegionUVs = oldAtt.RegionUVs; att.UpdateUVs(); Material mat = new Material(Shader.Find("Sprites/Default")); mat.mainTexture = texture; (att.RendererObject as Spine.AtlasRegion).page.rendererObject = mat; slot.Attachment = att; return(slot.Attachment); }
private void ShowBoundingBox() { if (_boundingBox == null) { _boundingBox = ResourceHelper.Load(AppConfig.FOLDER_PROFAB_CAMPAIGN + "CampaignBoundingBox"); _boundingBoxLineRender = _boundingBox.GetComponent <LineRenderer>(); } if (_selectTileIndex < 0) { _boundingBoxLineRender.SetVertexCount(0); return; } Spine.Slot boundingSlot = GetBoundingSlot(_selectTileIndex); SpineHelper.ShowBounding(boundingSlot, _skeletonAnim.transform, _boundingBoxLineRender); /* * Spine.BoundingBoxAttachment bounding = slot.Attachment as Spine.BoundingBoxAttachment; * float[] vertices = bounding.Vertices; * * int n = vertices.Length / 2; * _boundingBoxLineRender.SetVertexCount (n); * for(int i = 0; i < n; ++i) * { * float localX = vertices[i * 2 + 0]; * float localY = vertices[i * 2 + 1]; * float worldX; * float worldY; * bone.localToWorld(localX, localY, out worldX, out worldY); * * Vector3 p = new Vector3(worldX, worldY, 0); * p = _skeletonAnim.transform.TransformPoint(p); * * _boundingBoxLineRender.SetPosition(i, new Vector3(p.x, p.y, -1)); * } */ }
public void Draw(Skeleton skeleton) { float[] vertices = this.vertices; List <Slot> drawOrder = skeleton.DrawOrder; float x = skeleton.X, y = skeleton.Y; 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(x, y, 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(x, y, 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(x, y, 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]; } } } }
protected override void LoadContent() { skeletonRenderer = new SkeletonRenderer(GraphicsDevice); String name = "spineboy"; // "goblins"; Atlas atlas = new Atlas("data/" + name + ".atlas", new XnaTextureLoader(GraphicsDevice)); SkeletonJson json = new SkeletonJson(atlas); skeleton = new Skeleton(json.ReadSkeletonData("data/" + name + ".json")); if (name == "goblins") skeleton.SetSkin("goblingirl"); skeleton.SetSlotsToSetupPose(); // Without this the skin attachments won't be attached. See SetSkin. // Define mixing between animations. AnimationStateData stateData = new AnimationStateData(skeleton.Data); if (name == "spineboy") { stateData.SetMix("walk", "jump", 0.2f); stateData.SetMix("jump", "walk", 0.4f); } state = new AnimationState(stateData); if (true) { // Event handling for all animations. state.Start += new EventHandler(Start); state.End += new EventHandler(End); state.Complete += new EventHandler<CompleteArgs>(Complete); state.Event += new EventHandler<EventTriggeredArgs>(Event); state.SetAnimation("drawOrder", true); } else { state.SetAnimation("walk", false); QueueEntry entry = state.AddAnimation("jump", false); entry.End += new EventHandler(End); // Event handling for queued animations. state.AddAnimation("walk", true); } skeleton.X = 320; skeleton.Y = 440; skeleton.UpdateWorldTransform(); headSlot = skeleton.FindSlot("head"); }
static void DrawBoundingBox (Slot slot, BoundingBoxAttachment box) { if (box.Vertices.Length <= 0) return; // Handle cases where user creates a BoundingBoxAttachment but doesn't actually define it. var worldVerts = new float[box.Vertices.Length]; box.ComputeWorldVertices(slot, worldVerts); Handles.color = Color.green; Vector3 lastVert = Vector3.back; Vector3 vert = Vector3.back; Vector3 firstVert = new Vector3(worldVerts[0], worldVerts[1], -1); for (int i = 0; i < worldVerts.Length; i += 2) { vert.x = worldVerts[i]; vert.y = worldVerts[i + 1]; if (i > 0) Handles.DrawLine(lastVert, vert); lastVert = vert; } Handles.DrawLine(lastVert, firstVert); }
/// <summary>Fills a Vector2 buffer with local vertices.</summary> /// <param name="va">The VertexAttachment</param> /// <param name="slot">Slot where the attachment belongs.</param> /// <param name="buffer">Correctly-sized buffer. Use attachment's .WorldVerticesLength to get the correct size. If null, a new Vector2[] of the correct size will be allocated.</param> public static Vector2[] GetLocalVertices (this VertexAttachment va, Slot slot, Vector2[] buffer) { int floatsCount = va.worldVerticesLength; int bufferTargetSize = floatsCount >> 1; buffer = buffer ?? new Vector2[bufferTargetSize]; if (buffer.Length < bufferTargetSize) throw new System.ArgumentException(string.Format("Vector2 buffer too small. {0} requires an array of size {1}. Use the attachment's .WorldVerticesLength to get the correct size.", va.Name, floatsCount), "buffer"); if (va.bones == null) { var localVerts = va.vertices; for (int i = 0; i < bufferTargetSize; i++) { int j = i * 2; buffer[i] = new Vector2(localVerts[j], localVerts[j+1]); } } else { var floats = new float[floatsCount]; va.ComputeWorldVertices(slot, floats); Bone sb = slot.bone; float ia, ib, ic, id, bwx = sb.worldX, bwy = sb.worldY; sb.GetWorldToLocalMatrix(out ia, out ib, out ic, out id); for (int i = 0; i < bufferTargetSize; i++) { int j = i * 2; float x = floats[j] - bwx, y = floats[j+1] - bwy; buffer[i] = new Vector2(x * ia + y * ib, x * ic + y * id); } } return buffer; }
/// <summary>Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added /// or removed.</summary> public void UpdateCache() { ExposedList <IUpdatable> updateCache = this.updateCache; updateCache.Clear(); ExposedList <Bone> bones = this.bones; for (int i = 0, n = bones.Count; i < n; i++) { bones.Items[i].sorted = false; } ExposedList <IkConstraint> ikConstraints = this.ikConstraintsSorted; ikConstraints.Clear(); ikConstraints.AddRange(this.ikConstraints); int ikCount = ikConstraints.Count; for (int i = 0, level, n = ikCount; i < n; i++) { IkConstraint ik = ikConstraints.Items[i]; Bone bone = ik.bones.Items[0].parent; for (level = 0; bone != null; level++) { bone = bone.parent; } ik.level = level; } for (int i = 1, ii; i < ikCount; i++) { IkConstraint ik = ikConstraints.Items[i]; int level = ik.level; for (ii = i - 1; ii >= 0; ii--) { IkConstraint other = ikConstraints.Items[ii]; if (other.level < level) { break; } ikConstraints.Items[ii + 1] = other; } ikConstraints.Items[ii + 1] = ik; } for (int i = 0, n = ikConstraints.Count; i < n; i++) { IkConstraint constraint = ikConstraints.Items[i]; Bone target = constraint.target; SortBone(target); ExposedList <Bone> constrained = constraint.bones; Bone parent = constrained.Items[0]; SortBone(parent); updateCache.Add(constraint); SortReset(parent.children); constrained.Items[constrained.Count - 1].sorted = true; } ExposedList <PathConstraint> pathConstraints = this.pathConstraints; for (int i = 0, n = pathConstraints.Count; i < n; i++) { PathConstraint constraint = pathConstraints.Items[i]; Slot slot = constraint.target; int slotIndex = slot.data.index; Bone slotBone = slot.bone; if (skin != null) { SortPathConstraintAttachment(skin, slotIndex, slotBone); } if (data.defaultSkin != null && data.defaultSkin != skin) { SortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone); } for (int ii = 0, nn = data.skins.Count; ii < nn; ii++) { SortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone); } PathAttachment attachment = slot.Attachment as PathAttachment; if (attachment != null) { SortPathConstraintAttachment(attachment, slotBone); } ExposedList <Bone> constrained = constraint.bones; int boneCount = constrained.Count; for (int ii = 0; ii < boneCount; ii++) { SortBone(constrained.Items[ii]); } updateCache.Add(constraint); for (int ii = 0; ii < boneCount; ii++) { SortReset(constrained.Items[ii].children); } for (int ii = 0; ii < boneCount; ii++) { constrained.Items[ii].sorted = true; } } ExposedList <TransformConstraint> transformConstraints = this.transformConstraints; for (int i = 0, n = transformConstraints.Count; i < n; i++) { TransformConstraint constraint = transformConstraints.Items[i]; SortBone(constraint.target); ExposedList <Bone> constrained = constraint.bones; int boneCount = constrained.Count; for (int ii = 0; ii < boneCount; ii++) { SortBone(constrained.Items[ii]); } updateCache.Add(constraint); for (int ii = 0; ii < boneCount; ii++) { SortReset(constrained.Items[ii].children); } for (int ii = 0; ii < boneCount; ii++) { constrained.Items[ii].sorted = true; } } for (int i = 0, n = bones.Count; i < n; i++) { SortBone(bones.Items[i]); } }
public Microsoft.Xna.Framework.Matrix GetWorldTransform(float x, float y, Slot slot, float[] worldVertices) { Microsoft.Xna.Framework.Matrix mat = Microsoft.Xna.Framework.Matrix.Identity; Bone bone = slot.bone; x += bone.worldX; y += bone.worldY; float m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11; return mat; // float[] vertices = this.vertices; // int verticesCount = vertices.Length; // if (slot.attachmentVerticesCount == verticesCount) vertices = slot.AttachmentVertices; // for (int i = 0; i < verticesCount; i += 2) { // float vx = vertices[i]; // float vy = vertices[i + 1]; // worldVertices[i] = vx * m00 + vy * m01 + x; // worldVertices[i + 1] = vx * m10 + vy * m11 + y; // } }
public void ComputeWorldVertices(Slot slot, float[] worldVertices) { ComputeWorldVertices(slot, 0, worldVerticesLength, worldVertices, 0); }
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 attachmentZOffset = zSpacing * i; 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 = attachmentZOffset; 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 ComputeWorldVertices(float x, float y, Slot slot, float[] worldVertices) { Bone bone = slot.bone; x += bone.worldX; y += bone.worldY; float m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11; float[] vertices = this.vertices; if (slot.attachmentVerticesCount == vertices.Length) vertices = slot.AttachmentVertices; for (int i = 0, n = vertices.Length; i < n; i += 2) { float vx = vertices[i]; float vy = vertices[i + 1]; worldVertices[i] = vx * m00 + vy * m01 + x; worldVertices[i + 1] = vx * m10 + vy * m11 + y; } }
public void Draw(Skeleton skeleton) { 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]; RegionAttachment regionAttachment = slot.Attachment as RegionAttachment; if (regionAttachment != null) { BlendState blend = slot.Data.BlendMode == BlendMode.additive ? BlendState.Additive : defaultBlendState; if (device.BlendState != blend) { End(); device.BlendState = blend; } RegionItem item = batcher.NextItem(); AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject; item.texture = (Texture2D)region.page.rendererObject; Color color; float a = skeletonA * slot.A; if (premultipliedAlpha) { color = new Color(skeletonR * slot.R * a, skeletonG * slot.G * a, skeletonB * slot.B * a, a); } else { color = new Color(skeletonR * slot.R, skeletonG * slot.G, skeletonB * slot.B, a); } item.vertexTL.Color = color; item.vertexBL.Color = color; item.vertexBR.Color = color; item.vertexTR.Color = color; float[] vertices = this.vertices; regionAttachment.ComputeWorldVertices(slot.Bone, vertices); item.vertexTL.Position.X = vertices[RegionAttachment.X1]; item.vertexTL.Position.Y = vertices[RegionAttachment.Y1]; item.vertexTL.Position.Z = 0; item.vertexBL.Position.X = vertices[RegionAttachment.X2]; item.vertexBL.Position.Y = vertices[RegionAttachment.Y2]; item.vertexBL.Position.Z = 0; item.vertexBR.Position.X = vertices[RegionAttachment.X3]; item.vertexBR.Position.Y = vertices[RegionAttachment.Y3]; item.vertexBR.Position.Z = 0; item.vertexTR.Position.X = vertices[RegionAttachment.X4]; item.vertexTR.Position.Y = vertices[RegionAttachment.Y4]; item.vertexTR.Position.Z = 0; float[] uvs = regionAttachment.UVs; item.vertexTL.TextureCoordinate.X = uvs[RegionAttachment.X1]; item.vertexTL.TextureCoordinate.Y = uvs[RegionAttachment.Y1]; item.vertexBL.TextureCoordinate.X = uvs[RegionAttachment.X2]; item.vertexBL.TextureCoordinate.Y = uvs[RegionAttachment.Y2]; item.vertexBR.TextureCoordinate.X = uvs[RegionAttachment.X3]; item.vertexBR.TextureCoordinate.Y = uvs[RegionAttachment.Y3]; item.vertexTR.TextureCoordinate.X = uvs[RegionAttachment.X4]; item.vertexTR.TextureCoordinate.Y = uvs[RegionAttachment.Y4]; } } }
protected override void LoadContent() { bool useNormalmapShader = false; Effect spineEffect; if (!useNormalmapShader) { // Two color tint effect. Note that you can also use the default BasicEffect instead. spineEffect = Content.Load <Effect>("spine-xna-example-content\\SpineEffect"); } else { spineEffect = Content.Load <Effect>("spine-xna-example-content\\SpineEffectNormalmap"); spineEffect.Parameters["Light0_Direction"].SetValue(new Vector3(-0.5265408f, 0.5735765f, -0.6275069f)); spineEffect.Parameters["Light0_Diffuse"].SetValue(new Vector3(1, 0.9607844f, 0.8078432f)); spineEffect.Parameters["Light0_Specular"].SetValue(new Vector3(1, 0.9607844f, 0.8078432f)); spineEffect.Parameters["Light0_SpecularExponent"].SetValue(2.0f); } spineEffect.Parameters["World"].SetValue(Matrix.Identity); spineEffect.Parameters["View"].SetValue(Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up)); skeletonRenderer = new SkeletonRenderer(GraphicsDevice); skeletonRenderer.PremultipliedAlpha = false; skeletonRenderer.Effect = spineEffect; skeletonDebugRenderer = new SkeletonDebugRenderer(GraphicsDevice); skeletonDebugRenderer.DisableAll(); skeletonDebugRenderer.DrawClipping = true; // String name = "spineboy-ess"; // String name = "goblins-pro"; String name = "raptor-pro"; // String name = "tank-pro"; //String name = "coin-pro"; if (useNormalmapShader) { name = "raptor-pro"; // we only have normalmaps for raptor } String atlasName = name.Replace("-pro", "").Replace("-ess", ""); if (name == "goblins-pro") { atlasName = "goblins-mesh"; } bool binaryData = false; Atlas atlas; if (!useNormalmapShader) { atlas = new Atlas(assetsFolder + atlasName + ".atlas", new XnaTextureLoader(GraphicsDevice)); } else { atlas = new Atlas(assetsFolder + atlasName + ".atlas", new XnaTextureLoader(GraphicsDevice, loadMultipleTextureLayers: true, textureSuffixes: new string[] { "", "_normals" })); } float scale = 1; if (name == "spineboy-ess") { scale = 0.6f; } if (name == "raptor-pro") { scale = 0.5f; } if (name == "tank-pro") { scale = 0.3f; } if (name == "coin-pro") { scale = 1; } SkeletonData skeletonData; if (binaryData) { SkeletonBinary binary = new SkeletonBinary(atlas); binary.Scale = scale; skeletonData = binary.ReadSkeletonData(assetsFolder + name + ".skel"); } else { SkeletonJson json = new SkeletonJson(atlas); json.Scale = scale; skeletonData = json.ReadSkeletonData(assetsFolder + name + ".json"); } skeleton = new Skeleton(skeletonData); if (name == "goblins-pro") { skeleton.SetSkin("goblin"); } // Define mixing between animations. AnimationStateData stateData = new AnimationStateData(skeleton.Data); state = new AnimationState(stateData); if (name == "spineboy-ess") { skeleton.SetAttachment("head-bb", "head"); stateData.SetMix("run", "jump", 0.2f); stateData.SetMix("jump", "run", 0.4f); // Event handling for all animations. state.Start += Start; state.End += End; state.Complete += Complete; state.Event += Event; state.SetAnimation(0, "run", true); TrackEntry entry = state.AddAnimation(0, "jump", false, 0); entry.End += End; // Event handling for queued animations. state.AddAnimation(0, "run", true, 0); } else if (name == "raptor-pro") { state.SetAnimation(0, "walk", true); state.AddAnimation(1, "gun-grab", false, 2); } else if (name == "coin-pro") { state.SetAnimation(0, "animation", true); } else if (name == "tank-pro") { skeleton.X += 300; state.SetAnimation(0, "drive", true); } else { state.SetAnimation(0, "walk", true); } skeleton.X += 400; skeleton.Y += GraphicsDevice.Viewport.Height; skeleton.UpdateWorldTransform(); headSlot = skeleton.FindSlot("head"); }
public void Draw(Skeleton skeleton) { List <Slot> drawOrder = skeleton.DrawOrder; for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrder[i]; RegionAttachment regionAttachment = slot.Attachment as RegionAttachment; if (regionAttachment != null) { SpriteBatchItem item = batcher.CreateBatchItem(); item.Texture = (Texture2D)regionAttachment.RendererObject; byte r = (byte)(skeleton.R * slot.R * 255); byte g = (byte)(skeleton.G * slot.G * 255); byte b = (byte)(skeleton.B * slot.B * 255); byte a = (byte)(skeleton.A * slot.A * 255); item.vertexTL.Color.R = r; item.vertexTL.Color.G = g; item.vertexTL.Color.B = b; item.vertexTL.Color.A = a; item.vertexBL.Color.R = r; item.vertexBL.Color.G = g; item.vertexBL.Color.B = b; item.vertexBL.Color.A = a; item.vertexBR.Color.R = r; item.vertexBR.Color.G = g; item.vertexBR.Color.B = b; item.vertexBR.Color.A = a; item.vertexTR.Color.R = r; item.vertexTR.Color.G = g; item.vertexTR.Color.B = b; item.vertexTR.Color.A = a; float[] vertices = this.vertices; regionAttachment.ComputeVertices(skeleton.X, skeleton.Y, slot.Bone, vertices); item.vertexTL.Position.X = vertices[RegionAttachment.X1]; item.vertexTL.Position.Y = vertices[RegionAttachment.Y1]; item.vertexTL.Position.Z = 0; item.vertexBL.Position.X = vertices[RegionAttachment.X2]; item.vertexBL.Position.Y = vertices[RegionAttachment.Y2]; item.vertexBL.Position.Z = 0; item.vertexBR.Position.X = vertices[RegionAttachment.X3]; item.vertexBR.Position.Y = vertices[RegionAttachment.Y3]; item.vertexBR.Position.Z = 0; item.vertexTR.Position.X = vertices[RegionAttachment.X4]; item.vertexTR.Position.Y = vertices[RegionAttachment.Y4]; item.vertexTR.Position.Z = 0; float[] uvs = regionAttachment.UVs; item.vertexTL.TextureCoordinate.X = uvs[RegionAttachment.X1]; item.vertexTL.TextureCoordinate.Y = uvs[RegionAttachment.Y1]; item.vertexBL.TextureCoordinate.X = uvs[RegionAttachment.X2]; item.vertexBL.TextureCoordinate.Y = uvs[RegionAttachment.Y2]; item.vertexBR.TextureCoordinate.X = uvs[RegionAttachment.X3]; item.vertexBR.TextureCoordinate.Y = uvs[RegionAttachment.Y3]; item.vertexTR.TextureCoordinate.X = uvs[RegionAttachment.X4]; item.vertexTR.TextureCoordinate.Y = uvs[RegionAttachment.Y4]; } } }
void HeroCharacterSet() { Debug.Log("Hero_Character_Set"); string w0 = "wuqi"; string w1 = "R_wuqi"; weaponBaseData = skeleton.FindSlot(w0).Bone.Data; weaponBaseData2 = skeleton.FindSlot(w1).Bone.Data; // Material M = GetComponent <MeshRenderer>().material; if (skeleton.FindSlot(w0).Attachment != null) { M.shader = skeleton.FindSlot(w0).Attachment.GetMaterial().shader; } if (CMC.notShowWeaponSlot) { skeleton.FindSlot(w0).A = 0; skeleton.FindSlot(w1).A = 0; } else { skeleton.FindSlot(w0).A = 1; skeleton.FindSlot(w1).A = 1; // EquipItem weapon = SDDataManager.Instance.GetEquipItemById(CMC.weaponId); if (weapon == null) { return; } List <Sprite> allSprites = Resources.LoadAll <Sprite>("Spine/WeaponVision/").ToList(); weaponSprite = allSprites.Find(x => x.name == weapon.ID); if (weaponSprite == null) { return; } Spine.Slot baseWQ = skeleton.FindSlot(w0); string an = baseWQ.Data.AttachmentName; Spine.Attachment originalAttachment = baseWQ.Attachment; Spine.Attachment newAttachment = originalAttachment.GetRemappedClone(weaponSprite, M); if (weapon.WeaponRace.WeaponClass == SDConstants.WeaponClass.Sharp) { Spine.Slot otherWQ = skeleton.FindSlot(w1); string newWSName = weaponSprite.name + "_2"; weaponSprite2 = allSprites.Find(x => x.name == newWSName); if (weaponSprite2 != null) { Spine.Attachment oa1 = otherWQ.Attachment; Spine.Attachment newoa1 = oa1.GetRemappedClone(weaponSprite2, M); otherWQ.Attachment = newoa1; } } else if (weapon.WeaponRace.WeaponClass == SDConstants.WeaponClass.Claymore) { baseWQ.Bone.ScaleY = -weaponBaseData.ScaleY; baseWQ.Bone.Rotation = weaponBaseData.Rotation - 45; baseWQ.Bone.SetLocalPosition(new Vector2(0, -weaponBaseData.Y * 2)); } baseWQ.Attachment = newAttachment; } }
public void ComputeWorldVertices (Slot slot, float[] worldVertices) { ComputeWorldVertices(slot, 0, worldVerticesLength, worldVertices, 0); }
float[] ComputeWorldPositions(PathAttachment path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) { Slot target = this.target; float position = this.position; float[] spacesItems = this.spaces.Items, output = this.positions.Resize(spacesCount * 3 + 2).Items, world; bool closed = path.Closed; int verticesLength = path.WorldVerticesLength, curveCount = verticesLength / 6, prevCurve = NONE; float pathLength; if (!path.ConstantSpeed) { float[] lengths = path.Lengths; curveCount -= closed ? 1 : 2; pathLength = lengths[curveCount]; if (percentPosition) { position *= pathLength; } if (percentSpacing) { for (int i = 0; i < spacesCount; i++) { spacesItems[i] *= pathLength; } } world = this.world.Resize(8).Items; for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { float space = spacesItems[i]; position += space; float p = position; if (closed) { p %= pathLength; if (p < 0) { p += pathLength; } curve = 0; } else if (p < 0) { if (prevCurve != BEFORE) { prevCurve = BEFORE; path.ComputeWorldVertices(target, 2, 4, world, 0); } AddBeforePosition(p, world, 0, output, o); continue; } else if (p > pathLength) { if (prevCurve != AFTER) { prevCurve = AFTER; path.ComputeWorldVertices(target, verticesLength - 6, 4, world, 0); } AddAfterPosition(p - pathLength, world, 0, output, o); continue; } // Determine curve containing position. for (;; curve++) { float length = lengths[curve]; if (p > length) { continue; } if (curve == 0) { p /= length; } else { float prev = lengths[curve - 1]; p = (p - prev) / (length - prev); } break; } if (curve != prevCurve) { prevCurve = curve; if (closed && curve == curveCount) { path.ComputeWorldVertices(target, verticesLength - 4, 4, world, 0); path.ComputeWorldVertices(target, 0, 4, world, 4); } else { path.ComputeWorldVertices(target, curve * 6 + 2, 8, world, 0); } } AddCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], output, o, tangents || (i > 0 && space == 0)); } return(output); } // World vertices. if (closed) { verticesLength += 2; world = this.world.Resize(verticesLength).Items; path.ComputeWorldVertices(target, 2, verticesLength - 4, world, 0); path.ComputeWorldVertices(target, 0, 2, world, verticesLength - 4); world[verticesLength - 2] = world[0]; world[verticesLength - 1] = world[1]; } else { curveCount--; verticesLength -= 4; world = this.world.Resize(verticesLength).Items; path.ComputeWorldVertices(target, 2, verticesLength, world, 0); } // Curve lengths. float[] curves = this.curves.Resize(curveCount).Items; pathLength = 0; float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; for (int i = 0, w = 2; i < curveCount; i++, w += 6) { cx1 = world[w]; cy1 = world[w + 1]; cx2 = world[w + 2]; cy2 = world[w + 3]; x2 = world[w + 4]; y2 = world[w + 5]; tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f; tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f; dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f; dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f; ddfx = tmpx * 2 + dddfx; ddfy = tmpy * 2 + dddfy; dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f; dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); dfx += ddfx; dfy += ddfy; ddfx += dddfx; ddfy += dddfy; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); dfx += ddfx; dfy += ddfy; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); dfx += ddfx + dddfx; dfy += ddfy + dddfy; pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); curves[i] = pathLength; x1 = x2; y1 = y2; } if (percentPosition) { position *= pathLength; } if (percentSpacing) { for (int i = 0; i < spacesCount; i++) { spacesItems[i] *= pathLength; } } float[] segments = this.segments; float curveLength = 0; for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { float space = spacesItems[i]; position += space; float p = position; if (closed) { p %= pathLength; if (p < 0) { p += pathLength; } curve = 0; } else if (p < 0) { AddBeforePosition(p, world, 0, output, o); continue; } else if (p > pathLength) { AddAfterPosition(p - pathLength, world, verticesLength - 4, output, o); continue; } // Determine curve containing position. for (;; curve++) { float length = curves[curve]; if (p > length) { continue; } if (curve == 0) { p /= length; } else { float prev = curves[curve - 1]; p = (p - prev) / (length - prev); } break; } // Curve segment lengths. if (curve != prevCurve) { prevCurve = curve; int ii = curve * 6; x1 = world[ii]; y1 = world[ii + 1]; cx1 = world[ii + 2]; cy1 = world[ii + 3]; cx2 = world[ii + 4]; cy2 = world[ii + 5]; x2 = world[ii + 6]; y2 = world[ii + 7]; tmpx = (x1 - cx1 * 2 + cx2) * 0.03f; tmpy = (y1 - cy1 * 2 + cy2) * 0.03f; dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f; dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f; ddfx = tmpx * 2 + dddfx; ddfy = tmpy * 2 + dddfy; dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f; dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f; curveLength = (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[0] = curveLength; for (ii = 1; ii < 8; ii++) { dfx += ddfx; dfy += ddfy; ddfx += dddfx; ddfy += dddfy; curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[ii] = curveLength; } dfx += ddfx; dfy += ddfy; curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[8] = curveLength; dfx += ddfx + dddfx; dfy += ddfy + dddfy; curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); segments[9] = curveLength; segment = 0; } // Weight by segment length. p *= curveLength; for (;; segment++) { float length = segments[segment]; if (p > length) { continue; } if (segment == 0) { p /= length; } else { float prev = segments[segment - 1]; p = segment + (p - prev) / (length - prev); } break; } AddCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, output, o, tangents || (i > 0 && space == 0)); } return(output); }
static Slot GetExtractionSlot () { if (extractionSlot != null) return extractionSlot; Bone bone = GetExtractionBone(); SlotData data = new SlotData(0, "temp", bone.Data); Slot slot = new Slot(data, bone); extractionSlot = slot; return extractionSlot; }
override public void Apply(Skeleton skeleton, float lastTime, float time, ExposedList <Event> firedEvents, float alpha) { Slot slot = skeleton.slots.Items[slotIndex]; if (slot.attachment != attachment) { return; } float[] frames = this.frames; if (time < frames[0]) { return; // Time is before first frame. } float[][] frameVertices = this.frameVertices; int vertexCount = frameVertices[0].Length; float[] vertices = slot.attachmentVertices; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; slot.attachmentVertices = vertices; } if (vertices.Length != vertexCount) { alpha = 1; // Don't mix from uninitialized slot vertices. } slot.attachmentVerticesCount = vertexCount; if (time >= frames[frames.Length - 1]) // Time is after last frame. { float[] lastVertices = frameVertices[frames.Length - 1]; if (alpha < 1) { for (int i = 0; i < vertexCount; i++) { float vertex = vertices[i]; vertices[i] = vertex + (lastVertices[i] - vertex) * alpha; } } else { Array.Copy(lastVertices, 0, vertices, 0, vertexCount); } return; } // Interpolate between the previous frame and the current frame. int frameIndex = Animation.binarySearch(frames, time); float frameTime = frames[frameIndex]; float percent = 1 - (time - frameTime) / (frames[frameIndex - 1] - frameTime); percent = GetCurvePercent(frameIndex - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent)); float[] prevVertices = frameVertices[frameIndex - 1]; float[] nextVertices = frameVertices[frameIndex]; if (alpha < 1) { for (int i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; float vertex = vertices[i]; vertices[i] = vertex + (prev + (nextVertices[i] - prev) * percent - vertex) * alpha; } } else { for (int i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; vertices[i] = prev + (nextVertices[i] - prev) * percent; } } }
/// <summary> /// Transforms the attachment's local <see cref="Vertices"/> to world coordinates. If the slot's <see cref="Slot.Deform"/> is /// not empty, it is used to deform the vertices. /// <para /> /// See <a href="http://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine /// Runtimes Guide. /// </summary> /// <param name="start">The index of the first <see cref="Vertices"/> value to transform. Each vertex has 2 values, x and y.</param> /// <param name="count">The number of world vertex values to output. Must be less than or equal to <see cref="WorldVerticesLength"/> - start.</param> /// <param name="worldVertices">The output world vertices. Must have a length greater than or equal to <paramref name="offset"/> + <paramref name="count"/>.</param> /// <param name="offset">The <paramref name="worldVertices"/> index to begin writing values.</param> /// <param name="stride">The number of <paramref name="worldVertices"/> entries between the value pairs written.</param> public void ComputeWorldVertices(Slot slot, int start, int count, float[] worldVertices, int offset, int stride = 2) { count = offset + (count >> 1) * stride; Skeleton skeleton = slot.bone.skeleton; var deformArray = slot.deform; float[] vertices = this.vertices; int[] bones = this.bones; if (bones == null) { if (deformArray.Count > 0) { vertices = deformArray.Items; } Bone bone = slot.bone; float x = bone.worldX, y = bone.worldY; float a = bone.a, b = bone.b, c = bone.c, d = bone.d; for (int vv = start, w = offset; w < count; vv += 2, w += stride) { float vx = vertices[vv], vy = vertices[vv + 1]; worldVertices[w] = vx * a + vy * b + x; worldVertices[w + 1] = vx * c + vy * d + y; } return; } int v = 0, skip = 0; for (int i = 0; i < start; i += 2) { int n = bones[v]; v += n + 1; skip += n; } var skeletonBones = skeleton.bones.Items; if (deformArray.Count == 0) { for (int w = offset, b = skip * 3; w < count; w += stride) { float wx = 0, wy = 0; int n = bones[v++]; n += v; for (; v < n; v++, b += 3) { Bone bone = skeletonBones[bones[v]]; float vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2]; wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; } worldVertices[w] = wx; worldVertices[w + 1] = wy; } } else { float[] deform = deformArray.Items; for (int w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { float wx = 0, wy = 0; int n = bones[v++]; n += v; for (; v < n; v++, b += 3, f += 2) { Bone bone = skeletonBones[bones[v]]; float vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2]; wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight; } worldVertices[w] = wx; worldVertices[w + 1] = wy; } } }
//virtual cocos2d::CCTextureAtlas* getTextureAtlas (RegionAttachment regionAttachment); #region SpinesCocos2d void UpdateRegionAttachmentQuad(RegionAttachment self, Slot slot, ref CCV3F_C4B_T2F_Quad quad, bool premultipliedAlpha = false) { float[] vertices = new float[8]; self.ComputeWorldVertices(slot.Skeleton.X, slot.Skeleton.Y, slot.Bone, vertices); float r = slot.Skeleton.R * slot.R * 255; float g = slot.Skeleton.G * slot.G * 255; float b = slot.Skeleton.B * slot.B * 255; float normalizedAlpha = slot.Skeleton.A * slot.A; if (premultipliedAlpha) { r *= normalizedAlpha; g *= normalizedAlpha; b *= normalizedAlpha; } float a = normalizedAlpha * 255; quad.BottomLeft.Colors.R = (byte)r; quad.BottomLeft.Colors.G = (byte)g; quad.BottomLeft.Colors.B = (byte)b; quad.BottomLeft.Colors.A = (byte)a; quad.TopLeft.Colors.R = (byte)r; quad.TopLeft.Colors.G = (byte)g; quad.TopLeft.Colors.B = (byte)b; quad.TopLeft.Colors.A = (byte)a; quad.TopRight.Colors.R = (byte)r; quad.TopRight.Colors.G = (byte)g; quad.TopRight.Colors.B = (byte)b; quad.TopRight.Colors.A = (byte)a; quad.BottomRight.Colors.R = (byte)r; quad.BottomRight.Colors.G = (byte)g; quad.BottomRight.Colors.B = (byte)b; quad.BottomRight.Colors.A = (byte)a; quad.BottomLeft.Vertices.X = vertices[RegionAttachment.X1]; quad.BottomLeft.Vertices.Y = vertices[RegionAttachment.Y1]; quad.TopLeft.Vertices.X = vertices[RegionAttachment.X2]; quad.TopLeft.Vertices.Y = vertices[RegionAttachment.Y2]; quad.TopRight.Vertices.X = vertices[RegionAttachment.X3]; quad.TopRight.Vertices.Y = vertices[RegionAttachment.Y3]; quad.BottomRight.Vertices.X = vertices[RegionAttachment.X4]; quad.BottomRight.Vertices.Y = vertices[RegionAttachment.Y4]; quad.BottomLeft.TexCoords.U = self.UVs[RegionAttachment.X1]; quad.BottomLeft.TexCoords.V = self.UVs[RegionAttachment.Y1]; quad.TopLeft.TexCoords.U = self.UVs[RegionAttachment.X2]; quad.TopLeft.TexCoords.V = self.UVs[RegionAttachment.Y2]; quad.TopRight.TexCoords.U = self.UVs[RegionAttachment.X3]; quad.TopRight.TexCoords.V = self.UVs[RegionAttachment.Y3]; quad.BottomRight.TexCoords.U = self.UVs[RegionAttachment.X4]; quad.BottomRight.TexCoords.V = self.UVs[RegionAttachment.Y4]; }
protected override void LoadContent() { skeletonRenderer = new SkeletonMeshRenderer(GraphicsDevice); skeletonRenderer.PremultipliedAlpha = true; // String name = "spineboy"; // String name = "goblins-mesh"; String name = "raptor"; bool binaryData = true; Atlas atlas = new Atlas(assetsFolder + name + ".atlas", new XnaTextureLoader(GraphicsDevice)); float scale = 1; if (name == "spineboy") { scale = 0.6f; } if (name == "raptor") { scale = 0.5f; } SkeletonData skeletonData; if (binaryData) { SkeletonBinary binary = new SkeletonBinary(atlas); binary.Scale = scale; skeletonData = binary.ReadSkeletonData(assetsFolder + name + ".skel"); } else { SkeletonJson json = new SkeletonJson(atlas); json.Scale = scale; skeletonData = json.ReadSkeletonData(assetsFolder + name + ".json"); } skeleton = new Skeleton(skeletonData); if (name == "goblins-mesh") { skeleton.SetSkin("goblin"); } // Define mixing between animations. AnimationStateData stateData = new AnimationStateData(skeleton.Data); state = new AnimationState(stateData); if (name == "spineboy") { stateData.SetMix("run", "jump", 0.2f); stateData.SetMix("jump", "run", 0.4f); // Event handling for all animations. state.Start += Start; state.End += End; state.Complete += Complete; state.Event += Event; state.SetAnimation(0, "test", false); TrackEntry entry = state.AddAnimation(0, "jump", false, 0); entry.End += End; // Event handling for queued animations. state.AddAnimation(0, "run", true, 0); } else if (name == "raptor") { state.SetAnimation(0, "walk", true); state.SetAnimation(1, "empty", false); state.AddAnimation(1, "gungrab", false, 2); } else { state.SetAnimation(0, "walk", true); } skeleton.X = 400; skeleton.Y = 580; skeleton.UpdateWorldTransform(); headSlot = skeleton.FindSlot("head"); }
override public void Apply(Skeleton skeleton, float lastTime, float time, ExposedList <Event> firedEvents, float alpha) { Slot slot = skeleton.slots.Items[slotIndex]; VertexAttachment slotAttachment = slot.attachment as VertexAttachment; if (slotAttachment == null || !slotAttachment.ApplyDeform(attachment)) { return; } float[] frames = this.frames; if (time < frames[0]) { return; // Time is before first frame. } float[][] frameVertices = this.frameVertices; int vertexCount = frameVertices[0].Length; var verticesArray = slot.attachmentVertices; if (verticesArray.Count != vertexCount) { alpha = 1; // Don't mix from uninitialized slot vertices. } // verticesArray.SetSize(vertexCount) // Ensure size and preemptively set count. if (verticesArray.Capacity < vertexCount) { verticesArray.Capacity = vertexCount; } verticesArray.Count = vertexCount; float[] vertices = verticesArray.Items; if (time >= frames[frames.Length - 1]) // Time is after last frame. { float[] lastVertices = frameVertices[frames.Length - 1]; if (alpha < 1) { for (int i = 0; i < vertexCount; i++) { float vertex = vertices[i]; vertices[i] = vertex + (lastVertices[i] - vertex) * alpha; } } else { Array.Copy(lastVertices, 0, vertices, 0, vertexCount); } return; } // Interpolate between the previous frame and the current frame. int frame = Animation.binarySearch(frames, time); float[] prevVertices = frameVertices[frame - 1]; float[] nextVertices = frameVertices[frame]; float frameTime = frames[frame]; float percent = GetCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); if (alpha < 1) { for (int i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; float vertex = vertices[i]; vertices[i] = vertex + (prev + (nextVertices[i] - prev) * percent - vertex) * alpha; } } else { for (int i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; vertices[i] = prev + (nextVertices[i] - prev) * percent; } } }
/// <summary>Sets a slot's attachment to setup pose. If you have the slotIndex, Skeleton.SetSlotAttachmentToSetupPose is faster.</summary> public static void SetAttachmentToSetupPose(this Slot slot) { var slotData = slot.data; slot.Attachment = slot.bone.skeleton.GetAttachment(slotData.name, slotData.attachmentName); }
/// <summary>Calculates world vertices and fills a Vector2 buffer.</summary> /// <param name="a">The VertexAttachment</param> /// <param name="slot">Slot where the attachment belongs.</param> /// <param name="buffer">Correctly-sized buffer. Use attachment's .WorldVerticesLength to get the correct size. If null, a new Vector2[] of the correct size will be allocated.</param> public static Vector2[] GetWorldVertices (this VertexAttachment a, Slot slot, Vector2[] buffer) { int worldVertsLength = a.worldVerticesLength; int bufferTargetSize = worldVertsLength >> 1; buffer = buffer ?? new Vector2[bufferTargetSize]; if (buffer.Length < bufferTargetSize) throw new System.ArgumentException(string.Format("Vector2 buffer too small. {0} requires an array of size {1}. Use the attachment's .WorldVerticesLength to get the correct size.", a.Name, worldVertsLength), "buffer"); var floats = new float[worldVertsLength]; a.ComputeWorldVertices(slot, floats); for (int i = 0, n = worldVertsLength >> 1; i < n; i++) { int j = i * 2; buffer[i] = new Vector2(floats[j], floats[j + 1]); } return buffer; }
/// <summary> /// Clears any previous polygons, finds all visible bounding box attachments, /// and computes the world vertices for each bounding box's polygon.</summary> /// <param name="skeleton">The skeleton.</param> /// <param name="updateAabb"> /// If true, the axis aligned bounding box containing all the polygons is computed. /// If false, the SkeletonBounds AABB methods will always return true. /// </param> public void Update(Skeleton skeleton, bool updateAabb) { ExposedList <BoundingBoxAttachment> boundingBoxes = BoundingBoxes; ExposedList <Polygon> polygons = Polygons; Slot[] slots = skeleton.slots.Items; int slotCount = skeleton.slots.Count; boundingBoxes.Clear(); for (int i = 0, n = polygons.Count; i < n; i++) { polygonPool.Add(polygons.Items[i]); } polygons.Clear(); for (int i = 0; i < slotCount; i++) { Slot slot = slots[i]; if (!slot.bone.active) { continue; } BoundingBoxAttachment boundingBox = slot.attachment as BoundingBoxAttachment; if (boundingBox == null) { continue; } boundingBoxes.Add(boundingBox); Polygon polygon = null; int poolCount = polygonPool.Count; if (poolCount > 0) { polygon = polygonPool.Items[poolCount - 1]; polygonPool.RemoveAt(poolCount - 1); } else { polygon = new Polygon(); } polygons.Add(polygon); int count = boundingBox.worldVerticesLength; polygon.Count = count; if (polygon.Vertices.Length < count) { polygon.Vertices = new float[count]; } boundingBox.ComputeWorldVertices(slot, polygon.Vertices); } if (updateAabb) { AabbCompute(); } else { minX = int.MinValue; minY = int.MinValue; maxX = int.MaxValue; maxY = int.MaxValue; } }
protected override void LoadContent () { skeletonRenderer = new SkeletonMeshRenderer(GraphicsDevice); skeletonRenderer.PremultipliedAlpha = true; // String name = "spineboy"; // String name = "goblins-mesh"; String name = "raptor"; bool binaryData = true; Atlas atlas = new Atlas(assetsFolder + name + ".atlas", new XnaTextureLoader(GraphicsDevice)); float scale = 1; if (name == "spineboy") scale = 0.6f; if (name == "raptor") scale = 0.5f; SkeletonData skeletonData; if (binaryData) { SkeletonBinary binary = new SkeletonBinary(atlas); binary.Scale = scale; skeletonData = binary.ReadSkeletonData(assetsFolder + name + ".skel"); } else { SkeletonJson json = new SkeletonJson(atlas); json.Scale = scale; skeletonData = json.ReadSkeletonData(assetsFolder + name + ".json"); } skeleton = new Skeleton(skeletonData); if (name == "goblins-mesh") skeleton.SetSkin("goblin"); // Define mixing between animations. AnimationStateData stateData = new AnimationStateData(skeleton.Data); state = new AnimationState(stateData); if (name == "spineboy") { stateData.SetMix("run", "jump", 0.2f); stateData.SetMix("jump", "run", 0.4f); // Event handling for all animations. state.Start += Start; state.End += End; state.Complete += Complete; state.Event += Event; state.SetAnimation(0, "test", false); TrackEntry entry = state.AddAnimation(0, "jump", false, 0); entry.End += End; // Event handling for queued animations. state.AddAnimation(0, "run", true, 0); } else if (name == "raptor") { state.SetAnimation(0, "walk", true); state.SetAnimation(1, "empty", false); state.AddAnimation(1, "gungrab", false, 2); } else { state.SetAnimation(0, "walk", true); } skeleton.X = 400; skeleton.Y = 590; skeleton.UpdateWorldTransform(); headSlot = skeleton.FindSlot("head"); }
public override void Apply(Skeleton skeleton, float lastTime, float time, ExposedList <Event> firedEvents, float alpha, MixPose pose, MixDirection direction) { Slot slot = skeleton.slots.Items[this.slotIndex]; float[] frames = this.frames; if (time < frames[0]) { SlotData data = slot.data; if (pose != MixPose.Setup) { if (pose != MixPose.Current) { return; } } else { slot.r = data.r; slot.g = data.g; slot.b = data.b; slot.a = data.a; return; } slot.r += (slot.r - data.r) * alpha; slot.g += (slot.g - data.g) * alpha; slot.b += (slot.b - data.b) * alpha; slot.a += (slot.a - data.a) * alpha; } else { float num; float num2; float num3; float num4; if (time >= frames[frames.Length - 5]) { int length = frames.Length; num = frames[length + -4]; num2 = frames[length + -3]; num3 = frames[length + -2]; num4 = frames[length + -1]; } else { int index = Animation.BinarySearch(frames, time, 5); num = frames[index + -4]; num2 = frames[index + -3]; num3 = frames[index + -2]; num4 = frames[index + -1]; float num7 = frames[index]; float curvePercent = base.GetCurvePercent((index / 5) - 1, 1f - ((time - num7) / (frames[index + -5] - num7))); num += (frames[index + 1] - num) * curvePercent; num2 += (frames[index + 2] - num2) * curvePercent; num3 += (frames[index + 3] - num3) * curvePercent; num4 += (frames[index + 4] - num4) * curvePercent; } if (alpha == 1f) { slot.r = num; slot.g = num2; slot.b = num3; slot.a = num4; } else { float r; float g; float b; float a; if (pose == MixPose.Setup) { r = slot.data.r; g = slot.data.g; b = slot.data.b; a = slot.data.a; } else { r = slot.r; g = slot.g; b = slot.b; a = slot.a; } slot.r = r + ((num - r) * alpha); slot.g = g + ((num2 - g) * alpha); slot.b = b + ((num3 - b) * alpha); slot.a = a + ((num4 - a) * alpha); } } }
public void ComputeWorldVertices (Slot slot, float[] worldVertices) { Skeleton skeleton = slot.bone.skeleton; ExposedList<Bone> skeletonBones = skeleton.bones; float x = skeleton.x, y = skeleton.y; float[] weights = this.weights; int[] bones = this.bones; if (slot.attachmentVerticesCount == 0) { for (int w = 0, v = 0, b = 0, n = bones.Length; v < n; w += 2) { float wx = 0, wy = 0; int nn = bones[v++] + v; for (; v < nn; v++, b += 3) { Bone bone = skeletonBones.Items[bones[v]]; float vx = weights[b], vy = weights[b + 1], weight = weights[b + 2]; wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight; wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight; } worldVertices[w] = wx + x; worldVertices[w + 1] = wy + y; } } else { float[] ffd = slot.AttachmentVertices; for (int w = 0, v = 0, b = 0, f = 0, n = bones.Length; v < n; w += 2) { float wx = 0, wy = 0; int nn = bones[v++] + v; for (; v < nn; v++, b += 3, f += 2) { Bone bone = skeletonBones.Items[bones[v]]; float vx = weights[b] + ffd[f], vy = weights[b + 1] + ffd[f + 1], weight = weights[b + 2]; wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight; wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight; } worldVertices[w] = wx + x; worldVertices[w + 1] = wy + y; } } }
public void ComputeWorldVertices (Slot slot, float[] worldVertices) { Bone bone = slot.bone; float x = bone.skeleton.x + bone.worldX, y = bone.skeleton.y + bone.worldY; float m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11; float[] vertices = this.vertices; int verticesCount = vertices.Length; if (slot.attachmentVerticesCount == verticesCount) vertices = slot.AttachmentVertices; for (int i = 0; i < verticesCount; i += 2) { float vx = vertices[i]; float vy = vertices[i + 1]; worldVertices[i] = vx * m00 + vy * m01 + x; worldVertices[i + 1] = vx * m10 + vy * m11 + y; } }
public static void SetColliderPointsLocal (PolygonCollider2D collider, Slot slot, BoundingBoxAttachment box) { if (box == null) return; if (box.IsWeighted()) Debug.LogWarning("UnityEngine.PolygonCollider2D does not support weighted or animated points. Collider points will not be animated and may have incorrect orientation. If you want to use it as a collider, please remove weights and animations from the bounding box in Spine editor."); var verts = box.GetLocalVertices(slot, null); collider.SetPath(0, verts); }
public static void DrawPath (Slot s, PathAttachment p, Transform t, bool includeName) { int worldVerticesLength = p.WorldVerticesLength; if (pathVertexBuffer == null || pathVertexBuffer.Length < worldVerticesLength) pathVertexBuffer = new float[worldVerticesLength]; float[] pv = pathVertexBuffer; p.ComputeWorldVertices(s, pv); var ocolor = Handles.color; Handles.color = SpineHandles.PathColor; Matrix4x4 m = t.localToWorldMatrix; const int step = 6; int n = worldVerticesLength - step; Vector3 p0, p1, p2, p3; for (int i = 2; i < n; i += step) { p0 = m.MultiplyPoint(new Vector3(pv[i], pv[i+1])); p1 = m.MultiplyPoint(new Vector3(pv[i+2], pv[i+3])); p2 = m.MultiplyPoint(new Vector3(pv[i+4], pv[i+5])); p3 = m.MultiplyPoint(new Vector3(pv[i+6], pv[i+7])); DrawCubicBezier(p0, p1, p2, p3); } n += step; if (p.Closed) { p0 = m.MultiplyPoint(new Vector3(pv[n - 4], pv[n - 3])); p1 = m.MultiplyPoint(new Vector3(pv[n - 2], pv[n - 1])); p2 = m.MultiplyPoint(new Vector3(pv[0], pv[1])); p3 = m.MultiplyPoint(new Vector3(pv[2], pv[3])); DrawCubicBezier(p0, p1, p2, p3); } const float endCapSize = 0.05f; Vector3 firstPoint = m.MultiplyPoint(new Vector3(pv[2], pv[3])); Handles.DotCap(0, firstPoint, Quaternion.identity, endCapSize * HandleUtility.GetHandleSize(firstPoint)); // if (!p.Closed) Handles.DotCap(0, m.MultiplyPoint(new Vector3(pv[n - 4], pv[n - 3])), q, endCapSize); if (includeName) Handles.Label(firstPoint + new Vector3(0,0.1f), p.Name, PathNameStyle); Handles.color = ocolor; }