mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-02 13:49:07 +08:00
Updated spine-csharp to 3.1.05: linked meshes. (#543)
* Updated spine-csharp to 3.1.00: linked meshes. * Updated SkeletonBinary.cs for 3.1.05 based on:3a06b829cc8c55aa1f62* Fixed skeleton flip when rotation and scale are disabled. Based on:b22669711d* Fixed IK when the parent has nonuniform scale and the child Y != 0. Based on:bf902936aa* Removed redundant locals.
This commit is contained in:
parent
2b27761539
commit
ba5e4073c3
@ -573,7 +573,8 @@ namespace Spine {
|
|||||||
|
|
||||||
override public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList<Event> firedEvents, float alpha) {
|
override public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList<Event> firedEvents, float alpha) {
|
||||||
Slot slot = skeleton.slots.Items[slotIndex];
|
Slot slot = skeleton.slots.Items[slotIndex];
|
||||||
if (slot.attachment != attachment) return;
|
IFfdAttachment ffdAttachment = slot.attachment as IFfdAttachment; // == null if not FfdAttachment.
|
||||||
|
if (ffdAttachment == null || !ffdAttachment.ApplyFFD(attachment)) return;
|
||||||
|
|
||||||
float[] frames = this.frames;
|
float[] frames = this.frames;
|
||||||
if (time < frames[0]) return; // Time is before first frame.
|
if (time < frames[0]) return; // Time is before first frame.
|
||||||
|
|||||||
@ -31,6 +31,6 @@
|
|||||||
|
|
||||||
namespace Spine {
|
namespace Spine {
|
||||||
public enum AttachmentType {
|
public enum AttachmentType {
|
||||||
region, boundingbox, mesh, weightedmesh
|
region, boundingbox, mesh, weightedmesh, linkedmesh, weightedlinkedmesh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
spine-csharp/src/Attachments/IFfdAttachment.cs
Normal file
5
spine-csharp/src/Attachments/IFfdAttachment.cs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
namespace Spine {
|
||||||
|
public interface IFfdAttachment {
|
||||||
|
bool ApplyFFD (Attachment sourceAttachment);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -33,11 +33,13 @@ using System;
|
|||||||
|
|
||||||
namespace Spine {
|
namespace Spine {
|
||||||
/// <summary>Attachment that displays a texture region using a mesh.</summary>
|
/// <summary>Attachment that displays a texture region using a mesh.</summary>
|
||||||
public class MeshAttachment : Attachment {
|
public class MeshAttachment : Attachment, IFfdAttachment {
|
||||||
internal float[] vertices, uvs, regionUVs;
|
internal float[] vertices, uvs, regionUVs;
|
||||||
internal int[] triangles;
|
internal int[] triangles;
|
||||||
internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
|
internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
|
||||||
internal float r = 1, g = 1, b = 1, a = 1;
|
internal float r = 1, g = 1, b = 1, a = 1;
|
||||||
|
internal MeshAttachment parentMesh;
|
||||||
|
internal bool inheritFFD;
|
||||||
|
|
||||||
public int HullLength { get; set; }
|
public int HullLength { get; set; }
|
||||||
public float[] Vertices { get { return vertices; } set { vertices = value; } }
|
public float[] Vertices { get { return vertices; } set { vertices = value; } }
|
||||||
@ -64,6 +66,21 @@ namespace Spine {
|
|||||||
public float RegionOriginalWidth { get { return regionOriginalWidth; } set { regionOriginalWidth = value; } }
|
public float RegionOriginalWidth { get { return regionOriginalWidth; } set { regionOriginalWidth = value; } }
|
||||||
public float RegionOriginalHeight { get { return regionOriginalHeight; } set { regionOriginalHeight = value; } } // Unrotated, unstripped size.
|
public float RegionOriginalHeight { get { return regionOriginalHeight; } set { regionOriginalHeight = value; } } // Unrotated, unstripped size.
|
||||||
|
|
||||||
|
public bool InheritFFD { get { return inheritFFD; } set { inheritFFD = value; } }
|
||||||
|
|
||||||
|
public MeshAttachment ParentMesh {
|
||||||
|
get { return parentMesh; }
|
||||||
|
set {
|
||||||
|
parentMesh = value;
|
||||||
|
if (value != null) {
|
||||||
|
vertices = value.vertices;
|
||||||
|
regionUVs = value.regionUVs;
|
||||||
|
triangles = value.triangles;
|
||||||
|
HullLength = value.HullLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Nonessential.
|
// Nonessential.
|
||||||
public int[] Edges { get; set; }
|
public int[] Edges { get; set; }
|
||||||
public float Width { get; set; }
|
public float Width { get; set; }
|
||||||
@ -105,5 +122,9 @@ namespace Spine {
|
|||||||
worldVertices[i + 1] = vx * m10 + vy * m11 + y;
|
worldVertices[i + 1] = vx * m10 + vy * m11 + y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ApplyFFD (Attachment sourceAttachment) {
|
||||||
|
return this == sourceAttachment || (inheritFFD && parentMesh == sourceAttachment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,12 +34,14 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace Spine {
|
namespace Spine {
|
||||||
/// <summary>Attachment that displays a texture region using a mesh which can be deformed by bones.</summary>
|
/// <summary>Attachment that displays a texture region using a mesh which can be deformed by bones.</summary>
|
||||||
public class WeightedMeshAttachment : Attachment {
|
public class WeightedMeshAttachment : Attachment, IFfdAttachment {
|
||||||
internal int[] bones;
|
internal int[] bones;
|
||||||
internal float[] weights, uvs, regionUVs;
|
internal float[] weights, uvs, regionUVs;
|
||||||
internal int[] triangles;
|
internal int[] triangles;
|
||||||
internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
|
internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
|
||||||
internal float r = 1, g = 1, b = 1, a = 1;
|
internal float r = 1, g = 1, b = 1, a = 1;
|
||||||
|
internal WeightedMeshAttachment parentMesh;
|
||||||
|
internal bool inheritFFD;
|
||||||
|
|
||||||
public int HullLength { get; set; }
|
public int HullLength { get; set; }
|
||||||
public int[] Bones { get { return bones; } set { bones = value; } }
|
public int[] Bones { get { return bones; } set { bones = value; } }
|
||||||
@ -67,6 +69,22 @@ namespace Spine {
|
|||||||
public float RegionOriginalWidth { get { return regionOriginalWidth; } set { regionOriginalWidth = value; } }
|
public float RegionOriginalWidth { get { return regionOriginalWidth; } set { regionOriginalWidth = value; } }
|
||||||
public float RegionOriginalHeight { get { return regionOriginalHeight; } set { regionOriginalHeight = value; } } // Unrotated, unstripped size.
|
public float RegionOriginalHeight { get { return regionOriginalHeight; } set { regionOriginalHeight = value; } } // Unrotated, unstripped size.
|
||||||
|
|
||||||
|
public bool InheritFFD { get { return inheritFFD; } set { inheritFFD = value; } }
|
||||||
|
|
||||||
|
public WeightedMeshAttachment ParentMesh {
|
||||||
|
get { return parentMesh; }
|
||||||
|
set {
|
||||||
|
parentMesh = value;
|
||||||
|
if (value != null) {
|
||||||
|
bones = value.bones;
|
||||||
|
weights = value.weights;
|
||||||
|
regionUVs = value.regionUVs;
|
||||||
|
triangles = value.triangles;
|
||||||
|
HullLength = value.HullLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Nonessential.
|
// Nonessential.
|
||||||
public int[] Edges { get; set; }
|
public int[] Edges { get; set; }
|
||||||
public float Width { get; set; }
|
public float Width { get; set; }
|
||||||
@ -129,5 +147,9 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ApplyFFD (Attachment sourceAttachment) {
|
||||||
|
return this == sourceAttachment || (inheritFFD && parentMesh == sourceAttachment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -139,84 +139,78 @@ namespace Spine {
|
|||||||
b = pa * lb + pb * ld;
|
b = pa * lb + pb * ld;
|
||||||
c = pc * la + pd * lc;
|
c = pc * la + pd * lc;
|
||||||
d = pc * lb + pd * ld;
|
d = pc * lb + pd * ld;
|
||||||
} else if (data.inheritRotation) { // No scale inheritance.
|
|
||||||
pa = 1;
|
|
||||||
pb = 0;
|
|
||||||
pc = 0;
|
|
||||||
pd = 1;
|
|
||||||
do {
|
|
||||||
cos = MathUtils.CosDeg(parent.appliedRotation);
|
|
||||||
sin = MathUtils.SinDeg(parent.appliedRotation);
|
|
||||||
float temp = pa * cos + pb * sin;
|
|
||||||
pb = pa * -sin + pb * cos;
|
|
||||||
pa = temp;
|
|
||||||
temp = pc * cos + pd * sin;
|
|
||||||
pd = pc * -sin + pd * cos;
|
|
||||||
pc = temp;
|
|
||||||
|
|
||||||
if (!parent.data.inheritRotation) break;
|
|
||||||
parent = parent.parent;
|
|
||||||
} while (parent != null);
|
|
||||||
a = pa * la + pb * lc;
|
|
||||||
b = pa * lb + pb * ld;
|
|
||||||
c = pc * la + pd * lc;
|
|
||||||
d = pc * lb + pd * ld;
|
|
||||||
if (skeleton.flipX) {
|
|
||||||
a = -a;
|
|
||||||
b = -b;
|
|
||||||
}
|
|
||||||
if (skeleton.flipY != yDown) {
|
|
||||||
c = -c;
|
|
||||||
d = -d;
|
|
||||||
}
|
|
||||||
} else if (data.inheritScale) { // No rotation inheritance.
|
|
||||||
pa = 1;
|
|
||||||
pb = 0;
|
|
||||||
pc = 0;
|
|
||||||
pd = 1;
|
|
||||||
do {
|
|
||||||
float r = parent.rotation;
|
|
||||||
cos = MathUtils.CosDeg(r);
|
|
||||||
sin = MathUtils.SinDeg(r);
|
|
||||||
float psx = parent.appliedScaleX, psy = parent.appliedScaleY;
|
|
||||||
float za = cos * psx, zb = -sin * psy, zc = sin * psx, zd = cos * psy;
|
|
||||||
float temp = pa * za + pb * zc;
|
|
||||||
pb = pa * zb + pb * zd;
|
|
||||||
pa = temp;
|
|
||||||
temp = pc * za + pd * zc;
|
|
||||||
pd = pc * zb + pd * zd;
|
|
||||||
pc = temp;
|
|
||||||
|
|
||||||
if (psx < 0) r = -r;
|
|
||||||
cos = MathUtils.CosDeg(-r);
|
|
||||||
sin = MathUtils.SinDeg(-r);
|
|
||||||
temp = pa * cos + pb * sin;
|
|
||||||
pb = pa * -sin + pb * cos;
|
|
||||||
pa = temp;
|
|
||||||
temp = pc * cos + pd * sin;
|
|
||||||
pd = pc * -sin + pd * cos;
|
|
||||||
pc = temp;
|
|
||||||
|
|
||||||
if (!parent.data.inheritScale) break;
|
|
||||||
parent = parent.parent;
|
|
||||||
} while (parent != null);
|
|
||||||
a = pa * la + pb * lc;
|
|
||||||
b = pa * lb + pb * ld;
|
|
||||||
c = pc * la + pd * lc;
|
|
||||||
d = pc * lb + pd * ld;
|
|
||||||
if (skeleton.flipX) {
|
|
||||||
a = -a;
|
|
||||||
b = -b;
|
|
||||||
}
|
|
||||||
if (skeleton.flipY != yDown) {
|
|
||||||
c = -c;
|
|
||||||
d = -d;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
a = la;
|
if (data.inheritRotation) { // No scale inheritance.
|
||||||
b = lb;
|
pa = 1;
|
||||||
c = lc;
|
pb = 0;
|
||||||
d = ld;
|
pc = 0;
|
||||||
|
pd = 1;
|
||||||
|
do {
|
||||||
|
cos = MathUtils.CosDeg(parent.appliedRotation);
|
||||||
|
sin = MathUtils.SinDeg(parent.appliedRotation);
|
||||||
|
float temp = pa * cos + pb * sin;
|
||||||
|
pb = pa * -sin + pb * cos;
|
||||||
|
pa = temp;
|
||||||
|
temp = pc * cos + pd * sin;
|
||||||
|
pd = pc * -sin + pd * cos;
|
||||||
|
pc = temp;
|
||||||
|
|
||||||
|
if (!parent.data.inheritRotation) break;
|
||||||
|
parent = parent.parent;
|
||||||
|
} while (parent != null);
|
||||||
|
a = pa * la + pb * lc;
|
||||||
|
b = pa * lb + pb * ld;
|
||||||
|
c = pc * la + pd * lc;
|
||||||
|
d = pc * lb + pd * ld;
|
||||||
|
} else if (data.inheritScale) { // No rotation inheritance.
|
||||||
|
pa = 1;
|
||||||
|
pb = 0;
|
||||||
|
pc = 0;
|
||||||
|
pd = 1;
|
||||||
|
do {
|
||||||
|
float r = parent.rotation;
|
||||||
|
cos = MathUtils.CosDeg(r);
|
||||||
|
sin = MathUtils.SinDeg(r);
|
||||||
|
float psx = parent.appliedScaleX, psy = parent.appliedScaleY;
|
||||||
|
float za = cos * psx, zb = -sin * psy, zc = sin * psx, zd = cos * psy;
|
||||||
|
float temp = pa * za + pb * zc;
|
||||||
|
pb = pa * zb + pb * zd;
|
||||||
|
pa = temp;
|
||||||
|
temp = pc * za + pd * zc;
|
||||||
|
pd = pc * zb + pd * zd;
|
||||||
|
pc = temp;
|
||||||
|
|
||||||
|
if (psx < 0) r = -r;
|
||||||
|
cos = MathUtils.CosDeg(-r);
|
||||||
|
sin = MathUtils.SinDeg(-r);
|
||||||
|
temp = pa * cos + pb * sin;
|
||||||
|
pb = pa * -sin + pb * cos;
|
||||||
|
pa = temp;
|
||||||
|
temp = pc * cos + pd * sin;
|
||||||
|
pd = pc * -sin + pd * cos;
|
||||||
|
pc = temp;
|
||||||
|
|
||||||
|
if (!parent.data.inheritScale) break;
|
||||||
|
parent = parent.parent;
|
||||||
|
} while (parent != null);
|
||||||
|
a = pa * la + pb * lc;
|
||||||
|
b = pa * lb + pb * ld;
|
||||||
|
c = pc * la + pd * lc;
|
||||||
|
d = pc * lb + pd * ld;
|
||||||
|
} else {
|
||||||
|
a = la;
|
||||||
|
b = lb;
|
||||||
|
c = lc;
|
||||||
|
d = ld;
|
||||||
|
}
|
||||||
|
if (skeleton.flipX) {
|
||||||
|
a = -a;
|
||||||
|
b = -b;
|
||||||
|
}
|
||||||
|
if (skeleton.flipY != yDown) {
|
||||||
|
c = -c;
|
||||||
|
d = -d;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,9 +232,8 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void LocalToWorld (float localX, float localY, out float worldX, out float worldY) {
|
public void LocalToWorld (float localX, float localY, out float worldX, out float worldY) {
|
||||||
float x = localX, y = localY;
|
worldX = localX * a + localY * b + this.worldX;
|
||||||
worldX = x * a + y * b + this.worldX;
|
worldY = localX * c + localY * d + this.worldY;
|
||||||
worldY = x * c + y * d + this.worldY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override public String ToString () {
|
override public String ToString () {
|
||||||
|
|||||||
@ -98,7 +98,7 @@ namespace Spine {
|
|||||||
/// <param name="child">A direct descendant of the parent bone.</param>
|
/// <param name="child">A direct descendant of the parent bone.</param>
|
||||||
static public void Apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) {
|
static public void Apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) {
|
||||||
if (alpha == 0) return;
|
if (alpha == 0) return;
|
||||||
float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX, cy = child.y;
|
float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY;
|
||||||
int offset1, offset2, sign2;
|
int offset1, offset2, sign2;
|
||||||
if (psx < 0) {
|
if (psx < 0) {
|
||||||
psx = -psx;
|
psx = -psx;
|
||||||
@ -112,6 +112,13 @@ namespace Spine {
|
|||||||
psy = -psy;
|
psy = -psy;
|
||||||
sign2 = -sign2;
|
sign2 = -sign2;
|
||||||
}
|
}
|
||||||
|
float cx = child.x, cy = child.y, csx = child.scaleX;
|
||||||
|
bool u = Math.Abs(psx - psy) <= 0.0001f;
|
||||||
|
if (!u && cy != 0) {
|
||||||
|
child.worldX = parent.a * cx + parent.worldX;
|
||||||
|
child.worldY = parent.c * cx + parent.worldY;
|
||||||
|
cy = 0;
|
||||||
|
}
|
||||||
if (csx < 0) {
|
if (csx < 0) {
|
||||||
csx = -csx;
|
csx = -csx;
|
||||||
offset2 = 180;
|
offset2 = 180;
|
||||||
@ -135,7 +142,7 @@ namespace Spine {
|
|||||||
dy = (y * a - x * c) * invDet - py;
|
dy = (y * a - x * c) * invDet - py;
|
||||||
}
|
}
|
||||||
float l1 = (float)Math.Sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;
|
float l1 = (float)Math.Sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;
|
||||||
if (Math.Abs(psx - psy) <= 0.0001f) {
|
if (u) {
|
||||||
l2 *= psx;
|
l2 *= psx;
|
||||||
float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
|
float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
|
||||||
if (cos < -1) cos = -1;
|
if (cos < -1) cos = -1;
|
||||||
@ -144,7 +151,6 @@ namespace Spine {
|
|||||||
float a = l1 + l2 * cos, o = l2 * MathUtils.Sin(a2);
|
float a = l1 + l2 * cos, o = l2 * MathUtils.Sin(a2);
|
||||||
a1 = MathUtils.Atan2(ty * a - tx * o, tx * a + ty * o);
|
a1 = MathUtils.Atan2(ty * a - tx * o, tx * a + ty * o);
|
||||||
} else {
|
} else {
|
||||||
cy = 0;
|
|
||||||
float a = psx * l2, b = psy * l2, ta = MathUtils.Atan2(ty, tx);
|
float a = psx * l2, b = psy * l2, ta = MathUtils.Atan2(ty, tx);
|
||||||
float aa = a * a, bb = b * b, ll = l1 * l1, dd = tx * tx + ty * ty;
|
float aa = a * a, bb = b * b, ll = l1 * l1, dd = tx * tx + ty * ty;
|
||||||
float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
|
float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
|
||||||
@ -202,17 +208,17 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
outer:
|
outer:
|
||||||
float offset = MathUtils.Atan2(cy, child.x) * sign2;
|
float oo = MathUtils.Atan2(cy, cx) * sign2;
|
||||||
a1 = (a1 - offset) * MathUtils.radDeg + offset1;
|
a1 = (a1 - oo) * MathUtils.radDeg + offset1;
|
||||||
a2 = (a2 + offset) * MathUtils.radDeg * sign2 + offset2;
|
a2 = (a2 + oo) * MathUtils.radDeg * sign2 + offset2;
|
||||||
if (a1 > 180) a1 -= 360;
|
if (a1 > 180) a1 -= 360;
|
||||||
else if (a1 < -180) a1 += 360;
|
else if (a1 < -180) a1 += 360;
|
||||||
if (a2 > 180) a2 -= 360;
|
if (a2 > 180) a2 -= 360;
|
||||||
else if (a2 < -180) a2 += 360;
|
else if (a2 < -180) a2 += 360;
|
||||||
float rotation = parent.rotation;
|
float rotation = parent.rotation;
|
||||||
parent.UpdateWorldTransform(parent.x, parent.y, rotation + (a1 - rotation) * alpha, parent.scaleX, parent.scaleY);
|
parent.UpdateWorldTransform(px, py, rotation + (a1 - rotation) * alpha, parent.appliedScaleX, parent.appliedScaleY);
|
||||||
rotation = child.rotation;
|
rotation = child.rotation;
|
||||||
child.UpdateWorldTransform(child.x, cy, rotation + (a2 - rotation) * alpha, child.scaleX, child.scaleY);
|
child.UpdateWorldTransform(cx, cy, rotation + (a2 - rotation) * alpha, child.appliedScaleX, child.appliedScaleY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,15 +52,17 @@ namespace Spine {
|
|||||||
|
|
||||||
private AttachmentLoader attachmentLoader;
|
private AttachmentLoader attachmentLoader;
|
||||||
public float Scale { get; set; }
|
public float Scale { get; set; }
|
||||||
private char[] chars = new char[32];
|
private byte[] bytes = new byte[32];
|
||||||
private byte[] buffer = new byte[4];
|
private byte[] buffer = new byte[4];
|
||||||
|
|
||||||
|
private List<SkeletonJson.LinkedMesh> linkedMeshes = new List<SkeletonJson.LinkedMesh>();
|
||||||
|
|
||||||
public SkeletonBinary (params Atlas[] atlasArray)
|
public SkeletonBinary (params Atlas[] atlasArray)
|
||||||
: this(new AtlasAttachmentLoader(atlasArray)) {
|
: this(new AtlasAttachmentLoader(atlasArray)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkeletonBinary (AttachmentLoader attachmentLoader) {
|
public SkeletonBinary (AttachmentLoader attachmentLoader) {
|
||||||
if (attachmentLoader == null) throw new ArgumentNullException("attachmentLoader cannot be null.");
|
if (attachmentLoader == null) throw new ArgumentNullException("attachmentLoader");
|
||||||
this.attachmentLoader = attachmentLoader;
|
this.attachmentLoader = attachmentLoader;
|
||||||
Scale = 1;
|
Scale = 1;
|
||||||
}
|
}
|
||||||
@ -97,7 +99,7 @@ namespace Spine {
|
|||||||
#endif // !(UNITY)
|
#endif // !(UNITY)
|
||||||
|
|
||||||
public SkeletonData ReadSkeletonData (Stream input) {
|
public SkeletonData ReadSkeletonData (Stream input) {
|
||||||
if (input == null) throw new ArgumentNullException("input cannot be null.");
|
if (input == null) throw new ArgumentNullException("input");
|
||||||
float scale = Scale;
|
float scale = Scale;
|
||||||
|
|
||||||
var skeletonData = new SkeletonData();
|
var skeletonData = new SkeletonData();
|
||||||
@ -116,11 +118,9 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bones.
|
// Bones.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||||
String name = ReadString(input);
|
String name = ReadString(input);
|
||||||
BoneData parent = null;
|
BoneData parent = i == 0 ? null : skeletonData.bones.Items[ReadVarint(input, true)];
|
||||||
int parentIndex = ReadInt(input, true) - 1;
|
|
||||||
if (parentIndex != -1) parent = skeletonData.bones.Items[parentIndex];
|
|
||||||
BoneData boneData = new BoneData(name, parent);
|
BoneData boneData = new BoneData(name, parent);
|
||||||
boneData.x = ReadFloat(input) * scale;
|
boneData.x = ReadFloat(input) * scale;
|
||||||
boneData.y = ReadFloat(input) * scale;
|
boneData.y = ReadFloat(input) * scale;
|
||||||
@ -135,21 +135,21 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IK constraints.
|
// IK constraints.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||||
IkConstraintData ikConstraintData = new IkConstraintData(ReadString(input));
|
IkConstraintData ikConstraintData = new IkConstraintData(ReadString(input));
|
||||||
for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++)
|
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
|
||||||
ikConstraintData.bones.Add(skeletonData.bones.Items[ReadInt(input, true)]);
|
ikConstraintData.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
|
||||||
ikConstraintData.target = skeletonData.bones.Items[ReadInt(input, true)];
|
ikConstraintData.target = skeletonData.bones.Items[ReadVarint(input, true)];
|
||||||
ikConstraintData.mix = ReadFloat(input);
|
ikConstraintData.mix = ReadFloat(input);
|
||||||
ikConstraintData.bendDirection = ReadSByte(input);
|
ikConstraintData.bendDirection = ReadSByte(input);
|
||||||
skeletonData.ikConstraints.Add(ikConstraintData);
|
skeletonData.ikConstraints.Add(ikConstraintData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform constraints.
|
// Transform constraints.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||||
TransformConstraintData transformConstraintData = new TransformConstraintData(ReadString(input));
|
TransformConstraintData transformConstraintData = new TransformConstraintData(ReadString(input));
|
||||||
transformConstraintData.bone = skeletonData.bones.Items[ReadInt(input, true)];
|
transformConstraintData.bone = skeletonData.bones.Items[ReadVarint(input, true)];
|
||||||
transformConstraintData.target = skeletonData.bones.Items[ReadInt(input, true)];
|
transformConstraintData.target = skeletonData.bones.Items[ReadVarint(input, true)];
|
||||||
transformConstraintData.translateMix = ReadFloat(input);
|
transformConstraintData.translateMix = ReadFloat(input);
|
||||||
transformConstraintData.x = ReadFloat(input) * scale;
|
transformConstraintData.x = ReadFloat(input) * scale;
|
||||||
transformConstraintData.y = ReadFloat(input) * scale;
|
transformConstraintData.y = ReadFloat(input) * scale;
|
||||||
@ -157,9 +157,9 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Slots.
|
// Slots.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||||
String slotName = ReadString(input);
|
String slotName = ReadString(input);
|
||||||
BoneData boneData = skeletonData.bones.Items[ReadInt(input, true)];
|
BoneData boneData = skeletonData.bones.Items[ReadVarint(input, true)];
|
||||||
SlotData slotData = new SlotData(slotName, boneData);
|
SlotData slotData = new SlotData(slotName, boneData);
|
||||||
int color = ReadInt(input);
|
int color = ReadInt(input);
|
||||||
slotData.r = ((color & 0xff000000) >> 24) / 255f;
|
slotData.r = ((color & 0xff000000) >> 24) / 255f;
|
||||||
@ -167,7 +167,7 @@ namespace Spine {
|
|||||||
slotData.b = ((color & 0x0000ff00) >> 8) / 255f;
|
slotData.b = ((color & 0x0000ff00) >> 8) / 255f;
|
||||||
slotData.a = ((color & 0x000000ff)) / 255f;
|
slotData.a = ((color & 0x000000ff)) / 255f;
|
||||||
slotData.attachmentName = ReadString(input);
|
slotData.attachmentName = ReadString(input);
|
||||||
slotData.blendMode = (BlendMode)ReadInt(input, true);
|
slotData.blendMode = (BlendMode)ReadVarint(input, true);
|
||||||
skeletonData.slots.Add(slotData);
|
skeletonData.slots.Add(slotData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,20 +179,39 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skins.
|
// Skins.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++)
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++)
|
||||||
skeletonData.skins.Add(ReadSkin(input, ReadString(input), nonessential));
|
skeletonData.skins.Add(ReadSkin(input, ReadString(input), nonessential));
|
||||||
|
|
||||||
|
// Linked meshes.
|
||||||
|
for (int i = 0, n = linkedMeshes.Count; i < n; i++) {
|
||||||
|
SkeletonJson.LinkedMesh linkedMesh = linkedMeshes[i];
|
||||||
|
Skin skin = linkedMesh.skin == null ? skeletonData.DefaultSkin : skeletonData.FindSkin(linkedMesh.skin);
|
||||||
|
if (skin == null) throw new Exception("Skin not found: " + linkedMesh.skin);
|
||||||
|
Attachment parent = skin.GetAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
||||||
|
if (parent == null) throw new Exception("Parent mesh not found: " + linkedMesh.parent);
|
||||||
|
if (linkedMesh.mesh is MeshAttachment) {
|
||||||
|
MeshAttachment mesh = (MeshAttachment)linkedMesh.mesh;
|
||||||
|
mesh.ParentMesh = (MeshAttachment)parent;
|
||||||
|
mesh.UpdateUVs();
|
||||||
|
} else {
|
||||||
|
WeightedMeshAttachment mesh = (WeightedMeshAttachment)linkedMesh.mesh;
|
||||||
|
mesh.ParentMesh = (WeightedMeshAttachment)parent;
|
||||||
|
mesh.UpdateUVs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
linkedMeshes.Clear();
|
||||||
|
|
||||||
// Events.
|
// Events.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||||
EventData eventData = new EventData(ReadString(input));
|
EventData eventData = new EventData(ReadString(input));
|
||||||
eventData.Int = ReadInt(input, false);
|
eventData.Int = ReadVarint(input, false);
|
||||||
eventData.Float = ReadFloat(input);
|
eventData.Float = ReadFloat(input);
|
||||||
eventData.String = ReadString(input);
|
eventData.String = ReadString(input);
|
||||||
skeletonData.events.Add(eventData);
|
skeletonData.events.Add(eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Animations.
|
// Animations.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++)
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++)
|
||||||
ReadAnimation(ReadString(input), input, skeletonData);
|
ReadAnimation(ReadString(input), input, skeletonData);
|
||||||
|
|
||||||
skeletonData.bones.TrimExcess();
|
skeletonData.bones.TrimExcess();
|
||||||
@ -206,40 +225,49 @@ namespace Spine {
|
|||||||
|
|
||||||
/** @return May be null. */
|
/** @return May be null. */
|
||||||
private Skin ReadSkin (Stream input, String skinName, bool nonessential) {
|
private Skin ReadSkin (Stream input, String skinName, bool nonessential) {
|
||||||
int slotCount = ReadInt(input, true);
|
int slotCount = ReadVarint(input, true);
|
||||||
if (slotCount == 0) return null;
|
if (slotCount == 0) return null;
|
||||||
Skin skin = new Skin(skinName);
|
Skin skin = new Skin(skinName);
|
||||||
for (int i = 0; i < slotCount; i++) {
|
for (int i = 0; i < slotCount; i++) {
|
||||||
int slotIndex = ReadInt(input, true);
|
int slotIndex = ReadVarint(input, true);
|
||||||
for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
|
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
|
||||||
String name = ReadString(input);
|
String name = ReadString(input);
|
||||||
skin.AddAttachment(slotIndex, name, ReadAttachment(input, skin, name, nonessential));
|
skin.AddAttachment(slotIndex, name, ReadAttachment(input, skin, slotIndex, name, nonessential));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Attachment ReadAttachment (Stream input, Skin skin, String attachmentName, bool nonessential) {
|
private Attachment ReadAttachment (Stream input, Skin skin, int slotIndex, String attachmentName, bool nonessential) {
|
||||||
float scale = Scale;
|
float scale = Scale;
|
||||||
|
|
||||||
String name = ReadString(input);
|
String name = ReadString(input);
|
||||||
if (name == null) name = attachmentName;
|
if (name == null) name = attachmentName;
|
||||||
|
|
||||||
switch ((AttachmentType)input.ReadByte()) {
|
AttachmentType type = (AttachmentType)input.ReadByte();
|
||||||
|
switch (type) {
|
||||||
case AttachmentType.region: {
|
case AttachmentType.region: {
|
||||||
String path = ReadString(input);
|
String path = ReadString(input);
|
||||||
|
float x = ReadFloat(input);
|
||||||
|
float y = ReadFloat(input);
|
||||||
|
float scaleX = ReadFloat(input);
|
||||||
|
float scaleY = ReadFloat(input);
|
||||||
|
float rotation = ReadFloat(input);
|
||||||
|
float width = ReadFloat(input);
|
||||||
|
float height = ReadFloat(input);
|
||||||
|
int color = ReadInt(input);
|
||||||
|
|
||||||
if (path == null) path = name;
|
if (path == null) path = name;
|
||||||
RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path);
|
RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path);
|
||||||
if (region == null) return null;
|
if (region == null) return null;
|
||||||
region.Path = path;
|
region.Path = path;
|
||||||
region.x = ReadFloat(input) * scale;
|
region.x = x * scale;
|
||||||
region.y = ReadFloat(input) * scale;
|
region.y = y * scale;
|
||||||
region.scaleX = ReadFloat(input);
|
region.scaleX = scaleX;
|
||||||
region.scaleY = ReadFloat(input);
|
region.scaleY = scaleY;
|
||||||
region.rotation = ReadFloat(input);
|
region.rotation = rotation;
|
||||||
region.width = ReadFloat(input) * scale;
|
region.width = width * scale;
|
||||||
region.height = ReadFloat(input) * scale;
|
region.height = height * scale;
|
||||||
int color = ReadInt(input);
|
|
||||||
region.r = ((color & 0xff000000) >> 24) / 255f;
|
region.r = ((color & 0xff000000) >> 24) / 255f;
|
||||||
region.g = ((color & 0x00ff0000) >> 16) / 255f;
|
region.g = ((color & 0x00ff0000) >> 16) / 255f;
|
||||||
region.b = ((color & 0x0000ff00) >> 8) / 255f;
|
region.b = ((color & 0x0000ff00) >> 8) / 255f;
|
||||||
@ -248,80 +276,159 @@ namespace Spine {
|
|||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
case AttachmentType.boundingbox: {
|
case AttachmentType.boundingbox: {
|
||||||
|
float[] vertices = ReadFloatArray(input, ReadVarint(input, true) * 2, scale);
|
||||||
BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name);
|
BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name);
|
||||||
if (box == null) return null;
|
if (box == null) return null;
|
||||||
box.vertices = ReadFloatArray(input, scale);
|
box.vertices = vertices;
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
case AttachmentType.mesh: {
|
case AttachmentType.mesh: {
|
||||||
String path = ReadString(input);
|
String path = ReadString(input);
|
||||||
|
int color = ReadInt(input);
|
||||||
|
int hullLength = 0;
|
||||||
|
int verticesLength = ReadVarint(input, true) * 2;
|
||||||
|
float[] uvs = ReadFloatArray(input, verticesLength, 1);
|
||||||
|
int[] triangles = ReadShortArray(input);
|
||||||
|
float[] vertices = ReadFloatArray(input, verticesLength, scale);
|
||||||
|
hullLength = ReadVarint(input, true);
|
||||||
|
int[] edges = null;
|
||||||
|
float width = 0, height = 0;
|
||||||
|
if (nonessential) {
|
||||||
|
edges = ReadShortArray(input);
|
||||||
|
width = ReadFloat(input);
|
||||||
|
height = ReadFloat(input);
|
||||||
|
}
|
||||||
|
|
||||||
if (path == null) path = name;
|
if (path == null) path = name;
|
||||||
MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
|
MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
|
||||||
if (mesh == null) return null;
|
if (mesh == null) return null;
|
||||||
mesh.Path = path;
|
mesh.Path = path;
|
||||||
mesh.regionUVs = ReadFloatArray(input, 1);
|
|
||||||
mesh.triangles = ReadShortArray(input);
|
|
||||||
mesh.vertices = ReadFloatArray(input, scale);
|
|
||||||
mesh.UpdateUVs();
|
|
||||||
int color = ReadInt(input);
|
|
||||||
mesh.r = ((color & 0xff000000) >> 24) / 255f;
|
mesh.r = ((color & 0xff000000) >> 24) / 255f;
|
||||||
mesh.g = ((color & 0x00ff0000) >> 16) / 255f;
|
mesh.g = ((color & 0x00ff0000) >> 16) / 255f;
|
||||||
mesh.b = ((color & 0x0000ff00) >> 8) / 255f;
|
mesh.b = ((color & 0x0000ff00) >> 8) / 255f;
|
||||||
mesh.a = ((color & 0x000000ff)) / 255f;
|
mesh.a = ((color & 0x000000ff)) / 255f;
|
||||||
mesh.HullLength = ReadInt(input, true) * 2;
|
mesh.vertices = vertices;
|
||||||
|
mesh.triangles = triangles;
|
||||||
|
mesh.regionUVs = uvs;
|
||||||
|
mesh.UpdateUVs();
|
||||||
|
mesh.HullLength = hullLength;
|
||||||
if (nonessential) {
|
if (nonessential) {
|
||||||
mesh.Edges = ReadIntArray(input);
|
mesh.Edges = edges;
|
||||||
mesh.Width = ReadFloat(input) * scale;
|
mesh.Width = width * scale;
|
||||||
mesh.Height = ReadFloat(input) * scale;
|
mesh.Height = height * scale;
|
||||||
}
|
}
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
case AttachmentType.linkedmesh: {
|
||||||
|
String path = ReadString(input);
|
||||||
|
int color = ReadInt(input);
|
||||||
|
String skinName = ReadString(input);
|
||||||
|
String parent = ReadString(input);
|
||||||
|
bool inheritFFD = ReadBoolean(input);
|
||||||
|
float width = 0, height = 0;
|
||||||
|
if (nonessential) {
|
||||||
|
width = ReadFloat(input);
|
||||||
|
height = ReadFloat(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path == null) path = name;
|
||||||
|
MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
|
||||||
|
if (mesh == null) return null;
|
||||||
|
mesh.Path = path;
|
||||||
|
mesh.r = ((color & 0xff000000) >> 24) / 255f;
|
||||||
|
mesh.g = ((color & 0x00ff0000) >> 16) / 255f;
|
||||||
|
mesh.b = ((color & 0x0000ff00) >> 8) / 255f;
|
||||||
|
mesh.a = ((color & 0x000000ff)) / 255f;
|
||||||
|
mesh.inheritFFD = inheritFFD;
|
||||||
|
if (nonessential) {
|
||||||
|
mesh.Width = width * scale;
|
||||||
|
mesh.Height = height * scale;
|
||||||
|
}
|
||||||
|
linkedMeshes.Add(new SkeletonJson.LinkedMesh(mesh, skinName, slotIndex, parent));
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
case AttachmentType.weightedmesh: {
|
case AttachmentType.weightedmesh: {
|
||||||
String path = ReadString(input);
|
String path = ReadString(input);
|
||||||
if (path == null) path = name;
|
int color = ReadInt(input);
|
||||||
WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path);
|
int vertexCount = ReadVarint(input, true);
|
||||||
if (mesh == null) return null;
|
float[] uvs = ReadFloatArray(input, vertexCount * 2, 1);
|
||||||
mesh.Path = path;
|
|
||||||
float[] uvs = ReadFloatArray(input, 1);
|
|
||||||
int[] triangles = ReadShortArray(input);
|
int[] triangles = ReadShortArray(input);
|
||||||
|
|
||||||
int vertexCount = ReadInt(input, true);
|
|
||||||
var weights = new List<float>(uvs.Length * 3 * 3);
|
var weights = new List<float>(uvs.Length * 3 * 3);
|
||||||
var bones = new List<int>(uvs.Length * 3);
|
var bones = new List<int>(uvs.Length * 3);
|
||||||
for (int i = 0; i < vertexCount; i++) {
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
int boneCount = (int)ReadFloat(input);
|
int boneCount = (int)ReadFloat(input);
|
||||||
bones.Add(boneCount);
|
bones.Add(boneCount);
|
||||||
for (int nn = i + boneCount * 4; i < nn; i += 4) {
|
for (int ii = 0; i < boneCount; ii++) {
|
||||||
bones.Add((int)ReadFloat(input));
|
bones.Add((int)ReadFloat(input));
|
||||||
weights.Add(ReadFloat(input) * scale);
|
weights.Add(ReadFloat(input) * scale);
|
||||||
weights.Add(ReadFloat(input) * scale);
|
weights.Add(ReadFloat(input) * scale);
|
||||||
weights.Add(ReadFloat(input));
|
weights.Add(ReadFloat(input));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int hullLength = ReadVarint(input, true);
|
||||||
|
int[] edges = null;
|
||||||
|
float width = 0, height = 0;
|
||||||
|
if (nonessential) {
|
||||||
|
edges = ReadShortArray(input);
|
||||||
|
width = ReadFloat(input);
|
||||||
|
height = ReadFloat(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path == null) path = name;
|
||||||
|
WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path);
|
||||||
|
if (mesh == null) return null;
|
||||||
|
mesh.Path = path;
|
||||||
|
mesh.r = ((color & 0xff000000) >> 24) / 255f;
|
||||||
|
mesh.g = ((color & 0x00ff0000) >> 16) / 255f;
|
||||||
|
mesh.b = ((color & 0x0000ff00) >> 8) / 255f;
|
||||||
|
mesh.a = ((color & 0x000000ff)) / 255f;
|
||||||
mesh.bones = bones.ToArray();
|
mesh.bones = bones.ToArray();
|
||||||
mesh.weights = weights.ToArray();
|
mesh.weights = weights.ToArray();
|
||||||
mesh.triangles = triangles;
|
mesh.triangles = triangles;
|
||||||
mesh.regionUVs = uvs;
|
mesh.regionUVs = uvs;
|
||||||
mesh.UpdateUVs();
|
mesh.UpdateUVs();
|
||||||
|
mesh.HullLength = hullLength * 2;
|
||||||
|
if (nonessential) {
|
||||||
|
mesh.Edges = edges;
|
||||||
|
mesh.Width = width * scale;
|
||||||
|
mesh.Height = height * scale;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
case AttachmentType.weightedlinkedmesh: {
|
||||||
|
String path = ReadString(input);
|
||||||
int color = ReadInt(input);
|
int color = ReadInt(input);
|
||||||
|
String skinName = ReadString(input);
|
||||||
|
String parent = ReadString(input);
|
||||||
|
bool inheritFFD = ReadBoolean(input);
|
||||||
|
float width = 0, height = 0;
|
||||||
|
if (nonessential) {
|
||||||
|
width = ReadFloat(input);
|
||||||
|
height = ReadFloat(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path == null) path = name;
|
||||||
|
WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path);
|
||||||
|
if (mesh == null) return null;
|
||||||
|
mesh.Path = path;
|
||||||
mesh.r = ((color & 0xff000000) >> 24) / 255f;
|
mesh.r = ((color & 0xff000000) >> 24) / 255f;
|
||||||
mesh.g = ((color & 0x00ff0000) >> 16) / 255f;
|
mesh.g = ((color & 0x00ff0000) >> 16) / 255f;
|
||||||
mesh.b = ((color & 0x0000ff00) >> 8) / 255f;
|
mesh.b = ((color & 0x0000ff00) >> 8) / 255f;
|
||||||
mesh.a = ((color & 0x000000ff)) / 255f;
|
mesh.a = ((color & 0x000000ff)) / 255f;
|
||||||
mesh.HullLength = ReadInt(input, true) * 2;
|
mesh.inheritFFD = inheritFFD;
|
||||||
if (nonessential) {
|
if (nonessential) {
|
||||||
mesh.Edges = ReadIntArray(input);
|
mesh.Width = width * scale;
|
||||||
mesh.Width = ReadFloat(input) * scale;
|
mesh.Height = height * scale;
|
||||||
mesh.Height = ReadFloat(input) * scale;
|
|
||||||
}
|
}
|
||||||
|
linkedMeshes.Add(new SkeletonJson.LinkedMesh(mesh, skinName, slotIndex, parent));
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float[] ReadFloatArray (Stream input, float scale) {
|
private float[] ReadFloatArray (Stream input, int n, float scale) {
|
||||||
int n = ReadInt(input, true);
|
|
||||||
float[] array = new float[n];
|
float[] array = new float[n];
|
||||||
if (scale == 1) {
|
if (scale == 1) {
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
@ -334,18 +441,10 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int[] ReadShortArray (Stream input) {
|
private int[] ReadShortArray (Stream input) {
|
||||||
int n = ReadInt(input, true);
|
int n = ReadVarint(input, true);
|
||||||
int[] array = new int[n];
|
int[] array = new int[n];
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
array[i] = (input.ReadByte() << 8) + input.ReadByte();
|
array[i] = (input.ReadByte() << 8) | input.ReadByte();
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int[] ReadIntArray (Stream input) {
|
|
||||||
int n = ReadInt(input, true);
|
|
||||||
int[] array = new int[n];
|
|
||||||
for (int i = 0; i < n; i++)
|
|
||||||
array[i] = ReadInt(input, true);
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,11 +454,11 @@ namespace Spine {
|
|||||||
float duration = 0;
|
float duration = 0;
|
||||||
|
|
||||||
// Slot timelines.
|
// Slot timelines.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||||
int slotIndex = ReadInt(input, true);
|
int slotIndex = ReadVarint(input, true);
|
||||||
for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
|
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
|
||||||
int timelineType = input.ReadByte();
|
int timelineType = input.ReadByte();
|
||||||
int frameCount = ReadInt(input, true);
|
int frameCount = ReadVarint(input, true);
|
||||||
switch (timelineType) {
|
switch (timelineType) {
|
||||||
case TIMELINE_COLOR: {
|
case TIMELINE_COLOR: {
|
||||||
ColorTimeline timeline = new ColorTimeline(frameCount);
|
ColorTimeline timeline = new ColorTimeline(frameCount);
|
||||||
@ -392,11 +491,11 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bone timelines.
|
// Bone timelines.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||||
int boneIndex = ReadInt(input, true);
|
int boneIndex = ReadVarint(input, true);
|
||||||
for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
|
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
|
||||||
int timelineType = input.ReadByte();
|
int timelineType = input.ReadByte();
|
||||||
int frameCount = ReadInt(input, true);
|
int frameCount = ReadVarint(input, true);
|
||||||
switch (timelineType) {
|
switch (timelineType) {
|
||||||
case TIMELINE_ROTATE: {
|
case TIMELINE_ROTATE: {
|
||||||
RotateTimeline timeline = new RotateTimeline(frameCount);
|
RotateTimeline timeline = new RotateTimeline(frameCount);
|
||||||
@ -434,9 +533,9 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IK timelines.
|
// IK timelines.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||||
IkConstraintData ikConstraint = skeletonData.ikConstraints.Items[ReadInt(input, true)];
|
IkConstraintData ikConstraint = skeletonData.ikConstraints.Items[ReadVarint(input, true)];
|
||||||
int frameCount = ReadInt(input, true);
|
int frameCount = ReadVarint(input, true);
|
||||||
IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount);
|
IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount);
|
||||||
timeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(ikConstraint);
|
timeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(ikConstraint);
|
||||||
for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
|
for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
|
||||||
@ -448,13 +547,13 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FFD timelines.
|
// FFD timelines.
|
||||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||||
Skin skin = skeletonData.skins.Items[ReadInt(input, true)];
|
Skin skin = skeletonData.skins.Items[ReadVarint(input, true)];
|
||||||
for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
|
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
|
||||||
int slotIndex = ReadInt(input, true);
|
int slotIndex = ReadVarint(input, true);
|
||||||
for (int iii = 0, nnn = ReadInt(input, true); iii < nnn; iii++) {
|
for (int iii = 0, nnn = ReadVarint(input, true); iii < nnn; iii++) {
|
||||||
Attachment attachment = skin.GetAttachment(slotIndex, ReadString(input));
|
Attachment attachment = skin.GetAttachment(slotIndex, ReadString(input));
|
||||||
int frameCount = ReadInt(input, true);
|
int frameCount = ReadVarint(input, true);
|
||||||
FFDTimeline timeline = new FFDTimeline(frameCount);
|
FFDTimeline timeline = new FFDTimeline(frameCount);
|
||||||
timeline.slotIndex = slotIndex;
|
timeline.slotIndex = slotIndex;
|
||||||
timeline.attachment = attachment;
|
timeline.attachment = attachment;
|
||||||
@ -468,7 +567,7 @@ namespace Spine {
|
|||||||
else
|
else
|
||||||
vertexCount = ((WeightedMeshAttachment)attachment).weights.Length / 3 * 2;
|
vertexCount = ((WeightedMeshAttachment)attachment).weights.Length / 3 * 2;
|
||||||
|
|
||||||
int end = ReadInt(input, true);
|
int end = ReadVarint(input, true);
|
||||||
if (end == 0) {
|
if (end == 0) {
|
||||||
if (attachment is MeshAttachment)
|
if (attachment is MeshAttachment)
|
||||||
vertices = ((MeshAttachment)attachment).vertices;
|
vertices = ((MeshAttachment)attachment).vertices;
|
||||||
@ -476,7 +575,7 @@ namespace Spine {
|
|||||||
vertices = new float[vertexCount];
|
vertices = new float[vertexCount];
|
||||||
} else {
|
} else {
|
||||||
vertices = new float[vertexCount];
|
vertices = new float[vertexCount];
|
||||||
int start = ReadInt(input, true);
|
int start = ReadVarint(input, true);
|
||||||
end += start;
|
end += start;
|
||||||
if (scale == 1) {
|
if (scale == 1) {
|
||||||
for (int v = start; v < end; v++)
|
for (int v = start; v < end; v++)
|
||||||
@ -502,24 +601,24 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw order timeline.
|
// Draw order timeline.
|
||||||
int drawOrderCount = ReadInt(input, true);
|
int drawOrderCount = ReadVarint(input, true);
|
||||||
if (drawOrderCount > 0) {
|
if (drawOrderCount > 0) {
|
||||||
DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount);
|
DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount);
|
||||||
int slotCount = skeletonData.slots.Count;
|
int slotCount = skeletonData.slots.Count;
|
||||||
for (int i = 0; i < drawOrderCount; i++) {
|
for (int i = 0; i < drawOrderCount; i++) {
|
||||||
int offsetCount = ReadInt(input, true);
|
int offsetCount = ReadVarint(input, true);
|
||||||
int[] drawOrder = new int[slotCount];
|
int[] drawOrder = new int[slotCount];
|
||||||
for (int ii = slotCount - 1; ii >= 0; ii--)
|
for (int ii = slotCount - 1; ii >= 0; ii--)
|
||||||
drawOrder[ii] = -1;
|
drawOrder[ii] = -1;
|
||||||
int[] unchanged = new int[slotCount - offsetCount];
|
int[] unchanged = new int[slotCount - offsetCount];
|
||||||
int originalIndex = 0, unchangedIndex = 0;
|
int originalIndex = 0, unchangedIndex = 0;
|
||||||
for (int ii = 0; ii < offsetCount; ii++) {
|
for (int ii = 0; ii < offsetCount; ii++) {
|
||||||
int slotIndex = ReadInt(input, true);
|
int slotIndex = ReadVarint(input, true);
|
||||||
// Collect unchanged items.
|
// Collect unchanged items.
|
||||||
while (originalIndex != slotIndex)
|
while (originalIndex != slotIndex)
|
||||||
unchanged[unchangedIndex++] = originalIndex++;
|
unchanged[unchangedIndex++] = originalIndex++;
|
||||||
// Set changed items.
|
// Set changed items.
|
||||||
drawOrder[originalIndex + ReadInt(input, true)] = originalIndex++;
|
drawOrder[originalIndex + ReadVarint(input, true)] = originalIndex++;
|
||||||
}
|
}
|
||||||
// Collect remaining unchanged items.
|
// Collect remaining unchanged items.
|
||||||
while (originalIndex < slotCount)
|
while (originalIndex < slotCount)
|
||||||
@ -534,14 +633,14 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Event timeline.
|
// Event timeline.
|
||||||
int eventCount = ReadInt(input, true);
|
int eventCount = ReadVarint(input, true);
|
||||||
if (eventCount > 0) {
|
if (eventCount > 0) {
|
||||||
EventTimeline timeline = new EventTimeline(eventCount);
|
EventTimeline timeline = new EventTimeline(eventCount);
|
||||||
for (int i = 0; i < eventCount; i++) {
|
for (int i = 0; i < eventCount; i++) {
|
||||||
float time = ReadFloat(input);
|
float time = ReadFloat(input);
|
||||||
EventData eventData = skeletonData.events.Items[ReadInt(input, true)];
|
EventData eventData = skeletonData.events.Items[ReadVarint(input, true)];
|
||||||
Event e = new Event(time, eventData);
|
Event e = new Event(time, eventData);
|
||||||
e.Int = ReadInt(input, false);
|
e.Int = ReadVarint(input, false);
|
||||||
e.Float = ReadFloat(input);
|
e.Float = ReadFloat(input);
|
||||||
e.String = ReadBoolean(input) ? ReadString(input) : eventData.String;
|
e.String = ReadBoolean(input) ? ReadString(input) : eventData.String;
|
||||||
timeline.SetFrame(i, e);
|
timeline.SetFrame(i, e);
|
||||||
@ -565,13 +664,13 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sbyte ReadSByte (Stream input) {
|
private static sbyte ReadSByte (Stream input) {
|
||||||
int value = input.ReadByte();
|
int value = input.ReadByte();
|
||||||
if (value == -1) throw new EndOfStreamException();
|
if (value == -1) throw new EndOfStreamException();
|
||||||
return (sbyte)value;
|
return (sbyte)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ReadBoolean (Stream input) {
|
private static bool ReadBoolean (Stream input) {
|
||||||
return input.ReadByte() != 0;
|
return input.ReadByte() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,11 +682,11 @@ namespace Spine {
|
|||||||
return BitConverter.ToSingle(buffer, 0);
|
return BitConverter.ToSingle(buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int ReadInt (Stream input) {
|
private static int ReadInt (Stream input) {
|
||||||
return (input.ReadByte() << 24) + (input.ReadByte() << 16) + (input.ReadByte() << 8) + input.ReadByte();
|
return (input.ReadByte() << 24) + (input.ReadByte() << 16) + (input.ReadByte() << 8) + input.ReadByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int ReadInt (Stream input, bool optimizePositive) {
|
private static int ReadVarint (Stream input, bool optimizePositive) {
|
||||||
int b = input.ReadByte();
|
int b = input.ReadByte();
|
||||||
int result = b & 0x7F;
|
int result = b & 0x7F;
|
||||||
if ((b & 0x80) != 0) {
|
if ((b & 0x80) != 0) {
|
||||||
@ -600,8 +699,7 @@ namespace Spine {
|
|||||||
b = input.ReadByte();
|
b = input.ReadByte();
|
||||||
result |= (b & 0x7F) << 21;
|
result |= (b & 0x7F) << 21;
|
||||||
if ((b & 0x80) != 0) {
|
if ((b & 0x80) != 0) {
|
||||||
b = input.ReadByte();
|
result |= (input.ReadByte() & 0x7F) << 28;
|
||||||
result |= (b & 0x7F) << 28;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -610,53 +708,28 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string ReadString (Stream input) {
|
private string ReadString (Stream input) {
|
||||||
int charCount = ReadInt(input, true);
|
int byteCount = ReadVarint(input, true);
|
||||||
switch (charCount) {
|
switch (byteCount) {
|
||||||
case 0:
|
case 0:
|
||||||
return null;
|
return null;
|
||||||
case 1:
|
case 1:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
charCount--;
|
byteCount--;
|
||||||
char[] chars = this.chars;
|
byte[] bytes = this.bytes;
|
||||||
if (chars.Length < charCount) this.chars = chars = new char[charCount];
|
if (bytes.Length < byteCount) bytes = new byte[byteCount];
|
||||||
// Try to read 7 bit ASCII chars.
|
ReadFully(input, bytes, 0, byteCount);
|
||||||
int charIndex = 0;
|
return System.Text.Encoding.UTF8.GetString(bytes, 0, byteCount);
|
||||||
int b = 0;
|
|
||||||
while (charIndex < charCount) {
|
|
||||||
b = input.ReadByte();
|
|
||||||
if (b > 127) break;
|
|
||||||
chars[charIndex++] = (char)b;
|
|
||||||
}
|
|
||||||
// If a char was not ASCII, finish with slow path.
|
|
||||||
if (charIndex < charCount) ReadUtf8_slow(input, charCount, charIndex, b);
|
|
||||||
return new String(chars, 0, charCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadUtf8_slow (Stream input, int charCount, int charIndex, int b) {
|
private static void ReadFully (Stream input, byte[] b, int off, int len) {
|
||||||
char[] chars = this.chars;
|
while (len > 0) {
|
||||||
while (true) {
|
int count = input.Read(b, off, len);
|
||||||
switch (b >> 4) {
|
if (count <= 0) {
|
||||||
case 0:
|
throw new EndOfStreamException();
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
chars[charIndex] = (char)b;
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
case 13:
|
|
||||||
chars[charIndex] = (char)((b & 0x1F) << 6 | input.ReadByte() & 0x3F);
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
chars[charIndex] = (char)((b & 0x0F) << 12 | (input.ReadByte() & 0x3F) << 6 | input.ReadByte() & 0x3F);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (++charIndex >= charCount) break;
|
off += count;
|
||||||
b = input.ReadByte() & 0xFF;
|
len -= count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,7 @@ namespace Spine {
|
|||||||
public class SkeletonJson {
|
public class SkeletonJson {
|
||||||
private AttachmentLoader attachmentLoader;
|
private AttachmentLoader attachmentLoader;
|
||||||
public float Scale { get; set; }
|
public float Scale { get; set; }
|
||||||
|
private List<LinkedMesh> linkedMeshes = new List<LinkedMesh>();
|
||||||
|
|
||||||
public SkeletonJson (params Atlas[] atlasArray)
|
public SkeletonJson (params Atlas[] atlasArray)
|
||||||
: this(new AtlasAttachmentLoader(atlasArray)) {
|
: this(new AtlasAttachmentLoader(atlasArray)) {
|
||||||
@ -208,7 +209,7 @@ namespace Spine {
|
|||||||
foreach (KeyValuePair<String, Object> slotEntry in (Dictionary<String, Object>)entry.Value) {
|
foreach (KeyValuePair<String, Object> slotEntry in (Dictionary<String, Object>)entry.Value) {
|
||||||
int slotIndex = skeletonData.FindSlotIndex(slotEntry.Key);
|
int slotIndex = skeletonData.FindSlotIndex(slotEntry.Key);
|
||||||
foreach (KeyValuePair<String, Object> attachmentEntry in ((Dictionary<String, Object>)slotEntry.Value)) {
|
foreach (KeyValuePair<String, Object> attachmentEntry in ((Dictionary<String, Object>)slotEntry.Value)) {
|
||||||
Attachment attachment = ReadAttachment(skin, attachmentEntry.Key, (Dictionary<String, Object>)attachmentEntry.Value);
|
Attachment attachment = ReadAttachment(skin, slotIndex, attachmentEntry.Key, (Dictionary<String, Object>)attachmentEntry.Value);
|
||||||
if (attachment != null) skin.AddAttachment(slotIndex, attachmentEntry.Key, attachment);
|
if (attachment != null) skin.AddAttachment(slotIndex, attachmentEntry.Key, attachment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,6 +219,25 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Linked meshes.
|
||||||
|
for (int i = 0, n = linkedMeshes.Count; i < n; i++) {
|
||||||
|
LinkedMesh linkedMesh = linkedMeshes[i];
|
||||||
|
Skin skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.FindSkin(linkedMesh.skin);
|
||||||
|
if (skin == null) throw new Exception("Slot not found: " + linkedMesh.skin);
|
||||||
|
Attachment parent = skin.GetAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
||||||
|
if (parent == null) throw new Exception("Parent mesh not found: " + linkedMesh.parent);
|
||||||
|
if (linkedMesh.mesh is MeshAttachment) {
|
||||||
|
MeshAttachment mesh = (MeshAttachment)linkedMesh.mesh;
|
||||||
|
mesh.ParentMesh = (MeshAttachment)parent;
|
||||||
|
mesh.UpdateUVs();
|
||||||
|
} else {
|
||||||
|
WeightedMeshAttachment mesh = (WeightedMeshAttachment)linkedMesh.mesh;
|
||||||
|
mesh.ParentMesh = (WeightedMeshAttachment)parent;
|
||||||
|
mesh.UpdateUVs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
linkedMeshes.Clear();
|
||||||
|
|
||||||
// Events.
|
// Events.
|
||||||
if (root.ContainsKey("events")) {
|
if (root.ContainsKey("events")) {
|
||||||
foreach (KeyValuePair<String, Object> entry in (Dictionary<String, Object>)root["events"]) {
|
foreach (KeyValuePair<String, Object> entry in (Dictionary<String, Object>)root["events"]) {
|
||||||
@ -245,7 +265,7 @@ namespace Spine {
|
|||||||
return skeletonData;
|
return skeletonData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Attachment ReadAttachment (Skin skin, String name, Dictionary<String, Object> map) {
|
private Attachment ReadAttachment (Skin skin, int slotIndex, String name, Dictionary<String, Object> map) {
|
||||||
if (map.ContainsKey("name"))
|
if (map.ContainsKey("name"))
|
||||||
name = (String)map["name"];
|
name = (String)map["name"];
|
||||||
|
|
||||||
@ -285,15 +305,11 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return region;
|
return region;
|
||||||
case AttachmentType.mesh: {
|
case AttachmentType.mesh:
|
||||||
|
case AttachmentType.linkedmesh: {
|
||||||
MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
|
MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
|
||||||
if (mesh == null) return null;
|
if (mesh == null) return null;
|
||||||
|
|
||||||
mesh.Path = path;
|
mesh.Path = path;
|
||||||
mesh.vertices = GetFloatArray(map, "vertices", scale);
|
|
||||||
mesh.triangles = GetIntArray(map, "triangles");
|
|
||||||
mesh.regionUVs = GetFloatArray(map, "uvs", 1);
|
|
||||||
mesh.UpdateUVs();
|
|
||||||
|
|
||||||
if (map.ContainsKey("color")) {
|
if (map.ContainsKey("color")) {
|
||||||
var color = (String)map["color"];
|
var color = (String)map["color"];
|
||||||
@ -303,38 +319,31 @@ namespace Spine {
|
|||||||
mesh.a = ToColor(color, 3);
|
mesh.a = ToColor(color, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh.HullLength = GetInt(map, "hull", 0) * 2;
|
|
||||||
if (map.ContainsKey("edges")) mesh.Edges = GetIntArray(map, "edges");
|
|
||||||
mesh.Width = GetInt(map, "width", 0) * scale;
|
mesh.Width = GetInt(map, "width", 0) * scale;
|
||||||
mesh.Height = GetInt(map, "height", 0) * scale;
|
mesh.Height = GetInt(map, "height", 0) * scale;
|
||||||
|
|
||||||
|
String parent = GetString(map, "parent", null);
|
||||||
|
if (parent == null) {
|
||||||
|
mesh.vertices = GetFloatArray(map, "vertices", scale);
|
||||||
|
mesh.triangles = GetIntArray(map, "triangles");
|
||||||
|
mesh.regionUVs = GetFloatArray(map, "uvs", 1);
|
||||||
|
mesh.UpdateUVs();
|
||||||
|
|
||||||
|
mesh.HullLength = GetInt(map, "hull", 0) * 2;
|
||||||
|
if (map.ContainsKey("edges")) mesh.Edges = GetIntArray(map, "edges");
|
||||||
|
} else {
|
||||||
|
mesh.InheritFFD = GetBoolean(map, "ffd", true);
|
||||||
|
linkedMeshes.Add(new LinkedMesh(mesh, GetString(map, "skin", null), slotIndex, parent));
|
||||||
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
case AttachmentType.weightedmesh: {
|
case AttachmentType.weightedmesh:
|
||||||
|
case AttachmentType.weightedlinkedmesh: {
|
||||||
WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path);
|
WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path);
|
||||||
if (mesh == null) return null;
|
if (mesh == null) return null;
|
||||||
|
|
||||||
mesh.Path = path;
|
mesh.Path = path;
|
||||||
float[] uvs = GetFloatArray(map, "uvs", 1);
|
|
||||||
float[] vertices = GetFloatArray(map, "vertices", 1);
|
|
||||||
var weights = new List<float>(uvs.Length * 3 * 3);
|
|
||||||
var bones = new List<int>(uvs.Length * 3);
|
|
||||||
for (int i = 0, n = vertices.Length; i < n; ) {
|
|
||||||
int boneCount = (int)vertices[i++];
|
|
||||||
bones.Add(boneCount);
|
|
||||||
for (int nn = i + boneCount * 4; i < nn; ) {
|
|
||||||
bones.Add((int)vertices[i]);
|
|
||||||
weights.Add(vertices[i + 1] * scale);
|
|
||||||
weights.Add(vertices[i + 2] * scale);
|
|
||||||
weights.Add(vertices[i + 3]);
|
|
||||||
i += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mesh.bones = bones.ToArray();
|
|
||||||
mesh.weights = weights.ToArray();
|
|
||||||
mesh.triangles = GetIntArray(map, "triangles");
|
|
||||||
mesh.regionUVs = uvs;
|
|
||||||
mesh.UpdateUVs();
|
|
||||||
|
|
||||||
if (map.ContainsKey("color")) {
|
if (map.ContainsKey("color")) {
|
||||||
var color = (String)map["color"];
|
var color = (String)map["color"];
|
||||||
@ -344,11 +353,39 @@ namespace Spine {
|
|||||||
mesh.a = ToColor(color, 3);
|
mesh.a = ToColor(color, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh.HullLength = GetInt(map, "hull", 0) * 2;
|
|
||||||
if (map.ContainsKey("edges")) mesh.Edges = GetIntArray(map, "edges");
|
|
||||||
mesh.Width = GetInt(map, "width", 0) * scale;
|
mesh.Width = GetInt(map, "width", 0) * scale;
|
||||||
mesh.Height = GetInt(map, "height", 0) * scale;
|
mesh.Height = GetInt(map, "height", 0) * scale;
|
||||||
|
|
||||||
|
String parent = GetString(map, "parent", null);
|
||||||
|
if (parent == null) {
|
||||||
|
float[] uvs = GetFloatArray(map, "uvs", 1);
|
||||||
|
float[] vertices = GetFloatArray(map, "vertices", 1);
|
||||||
|
var weights = new List<float>(uvs.Length * 3 * 3);
|
||||||
|
var bones = new List<int>(uvs.Length * 3);
|
||||||
|
for (int i = 0, n = vertices.Length; i < n;) {
|
||||||
|
int boneCount = (int)vertices[i++];
|
||||||
|
bones.Add(boneCount);
|
||||||
|
for (int nn = i + boneCount * 4; i < nn;) {
|
||||||
|
bones.Add((int)vertices[i]);
|
||||||
|
weights.Add(vertices[i + 1] * scale);
|
||||||
|
weights.Add(vertices[i + 2] * scale);
|
||||||
|
weights.Add(vertices[i + 3]);
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mesh.bones = bones.ToArray();
|
||||||
|
mesh.weights = weights.ToArray();
|
||||||
|
mesh.triangles = GetIntArray(map, "triangles");
|
||||||
|
mesh.regionUVs = uvs;
|
||||||
|
mesh.UpdateUVs();
|
||||||
|
|
||||||
|
mesh.HullLength = GetInt(map, "hull", 0) * 2;
|
||||||
|
if (map.ContainsKey("edges")) mesh.Edges = GetIntArray(map, "edges");
|
||||||
|
} else {
|
||||||
|
mesh.InheritFFD = GetBoolean(map, "ffd", true);
|
||||||
|
linkedMeshes.Add(new LinkedMesh(mesh, GetString(map, "skin", null), slotIndex, parent));
|
||||||
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
case AttachmentType.boundingbox:
|
case AttachmentType.boundingbox:
|
||||||
@ -657,5 +694,18 @@ namespace Spine {
|
|||||||
timeline.SetCurve(frameIndex, (float)curve[0], (float)curve[1], (float)curve[2], (float)curve[3]);
|
timeline.SetCurve(frameIndex, (float)curve[0], (float)curve[1], (float)curve[2], (float)curve[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class LinkedMesh {
|
||||||
|
internal String parent, skin;
|
||||||
|
internal int slotIndex;
|
||||||
|
internal Attachment mesh;
|
||||||
|
|
||||||
|
public LinkedMesh (Attachment mesh, String skin, int slotIndex, String parent) {
|
||||||
|
this.mesh = mesh;
|
||||||
|
this.skin = skin;
|
||||||
|
this.slotIndex = slotIndex;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user