mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +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) {
|
||||
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;
|
||||
if (time < frames[0]) return; // Time is before first frame.
|
||||
|
||||
@ -31,6 +31,6 @@
|
||||
|
||||
namespace Spine {
|
||||
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 {
|
||||
/// <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 int[] triangles;
|
||||
internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
|
||||
internal float r = 1, g = 1, b = 1, a = 1;
|
||||
internal MeshAttachment parentMesh;
|
||||
internal bool inheritFFD;
|
||||
|
||||
public int HullLength { get; set; }
|
||||
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 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.
|
||||
public int[] Edges { get; set; }
|
||||
public float Width { get; set; }
|
||||
@ -105,5 +122,9 @@ namespace Spine {
|
||||
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 {
|
||||
/// <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 float[] weights, uvs, regionUVs;
|
||||
internal int[] triangles;
|
||||
internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
|
||||
internal float r = 1, g = 1, b = 1, a = 1;
|
||||
internal WeightedMeshAttachment parentMesh;
|
||||
internal bool inheritFFD;
|
||||
|
||||
public int HullLength { get; set; }
|
||||
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 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.
|
||||
public int[] Edges { 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;
|
||||
c = pc * la + pd * lc;
|
||||
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 {
|
||||
a = la;
|
||||
b = lb;
|
||||
c = lc;
|
||||
d = ld;
|
||||
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;
|
||||
} 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) {
|
||||
float x = localX, y = localY;
|
||||
worldX = x * a + y * b + this.worldX;
|
||||
worldY = x * c + y * d + this.worldY;
|
||||
worldX = localX * a + localY * b + this.worldX;
|
||||
worldY = localX * c + localY * d + this.worldY;
|
||||
}
|
||||
|
||||
override public String ToString () {
|
||||
|
||||
@ -98,7 +98,7 @@ namespace Spine {
|
||||
/// <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) {
|
||||
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;
|
||||
if (psx < 0) {
|
||||
psx = -psx;
|
||||
@ -112,6 +112,13 @@ namespace Spine {
|
||||
psy = -psy;
|
||||
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) {
|
||||
csx = -csx;
|
||||
offset2 = 180;
|
||||
@ -135,7 +142,7 @@ namespace Spine {
|
||||
dy = (y * a - x * c) * invDet - py;
|
||||
}
|
||||
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;
|
||||
float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
|
||||
if (cos < -1) cos = -1;
|
||||
@ -144,7 +151,6 @@ namespace Spine {
|
||||
float a = l1 + l2 * cos, o = l2 * MathUtils.Sin(a2);
|
||||
a1 = MathUtils.Atan2(ty * a - tx * o, tx * a + ty * o);
|
||||
} else {
|
||||
cy = 0;
|
||||
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 c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
|
||||
@ -202,17 +208,17 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
outer:
|
||||
float offset = MathUtils.Atan2(cy, child.x) * sign2;
|
||||
a1 = (a1 - offset) * MathUtils.radDeg + offset1;
|
||||
a2 = (a2 + offset) * MathUtils.radDeg * sign2 + offset2;
|
||||
float oo = MathUtils.Atan2(cy, cx) * sign2;
|
||||
a1 = (a1 - oo) * MathUtils.radDeg + offset1;
|
||||
a2 = (a2 + oo) * MathUtils.radDeg * sign2 + offset2;
|
||||
if (a1 > 180) a1 -= 360;
|
||||
else if (a1 < -180) a1 += 360;
|
||||
if (a2 > 180) a2 -= 360;
|
||||
else if (a2 < -180) a2 += 360;
|
||||
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;
|
||||
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;
|
||||
public float Scale { get; set; }
|
||||
private char[] chars = new char[32];
|
||||
private byte[] bytes = new byte[32];
|
||||
private byte[] buffer = new byte[4];
|
||||
|
||||
private List<SkeletonJson.LinkedMesh> linkedMeshes = new List<SkeletonJson.LinkedMesh>();
|
||||
|
||||
public SkeletonBinary (params Atlas[] atlasArray)
|
||||
: this(new AtlasAttachmentLoader(atlasArray)) {
|
||||
}
|
||||
|
||||
public SkeletonBinary (AttachmentLoader attachmentLoader) {
|
||||
if (attachmentLoader == null) throw new ArgumentNullException("attachmentLoader cannot be null.");
|
||||
if (attachmentLoader == null) throw new ArgumentNullException("attachmentLoader");
|
||||
this.attachmentLoader = attachmentLoader;
|
||||
Scale = 1;
|
||||
}
|
||||
@ -97,7 +99,7 @@ namespace Spine {
|
||||
#endif // !(UNITY)
|
||||
|
||||
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;
|
||||
|
||||
var skeletonData = new SkeletonData();
|
||||
@ -116,11 +118,9 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// 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);
|
||||
BoneData parent = null;
|
||||
int parentIndex = ReadInt(input, true) - 1;
|
||||
if (parentIndex != -1) parent = skeletonData.bones.Items[parentIndex];
|
||||
BoneData parent = i == 0 ? null : skeletonData.bones.Items[ReadVarint(input, true)];
|
||||
BoneData boneData = new BoneData(name, parent);
|
||||
boneData.x = ReadFloat(input) * scale;
|
||||
boneData.y = ReadFloat(input) * scale;
|
||||
@ -135,21 +135,21 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// 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));
|
||||
for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++)
|
||||
ikConstraintData.bones.Add(skeletonData.bones.Items[ReadInt(input, true)]);
|
||||
ikConstraintData.target = skeletonData.bones.Items[ReadInt(input, true)];
|
||||
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
|
||||
ikConstraintData.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
|
||||
ikConstraintData.target = skeletonData.bones.Items[ReadVarint(input, true)];
|
||||
ikConstraintData.mix = ReadFloat(input);
|
||||
ikConstraintData.bendDirection = ReadSByte(input);
|
||||
skeletonData.ikConstraints.Add(ikConstraintData);
|
||||
}
|
||||
|
||||
// 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.bone = skeletonData.bones.Items[ReadInt(input, true)];
|
||||
transformConstraintData.target = skeletonData.bones.Items[ReadInt(input, true)];
|
||||
transformConstraintData.bone = skeletonData.bones.Items[ReadVarint(input, true)];
|
||||
transformConstraintData.target = skeletonData.bones.Items[ReadVarint(input, true)];
|
||||
transformConstraintData.translateMix = ReadFloat(input);
|
||||
transformConstraintData.x = ReadFloat(input) * scale;
|
||||
transformConstraintData.y = ReadFloat(input) * scale;
|
||||
@ -157,9 +157,9 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// 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);
|
||||
BoneData boneData = skeletonData.bones.Items[ReadInt(input, true)];
|
||||
BoneData boneData = skeletonData.bones.Items[ReadVarint(input, true)];
|
||||
SlotData slotData = new SlotData(slotName, boneData);
|
||||
int color = ReadInt(input);
|
||||
slotData.r = ((color & 0xff000000) >> 24) / 255f;
|
||||
@ -167,7 +167,7 @@ namespace Spine {
|
||||
slotData.b = ((color & 0x0000ff00) >> 8) / 255f;
|
||||
slotData.a = ((color & 0x000000ff)) / 255f;
|
||||
slotData.attachmentName = ReadString(input);
|
||||
slotData.blendMode = (BlendMode)ReadInt(input, true);
|
||||
slotData.blendMode = (BlendMode)ReadVarint(input, true);
|
||||
skeletonData.slots.Add(slotData);
|
||||
}
|
||||
|
||||
@ -179,20 +179,39 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
// 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.
|
||||
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.Int = ReadInt(input, false);
|
||||
eventData.Int = ReadVarint(input, false);
|
||||
eventData.Float = ReadFloat(input);
|
||||
eventData.String = ReadString(input);
|
||||
skeletonData.events.Add(eventData);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
skeletonData.bones.TrimExcess();
|
||||
@ -206,40 +225,49 @@ namespace Spine {
|
||||
|
||||
/** @return May be null. */
|
||||
private Skin ReadSkin (Stream input, String skinName, bool nonessential) {
|
||||
int slotCount = ReadInt(input, true);
|
||||
int slotCount = ReadVarint(input, true);
|
||||
if (slotCount == 0) return null;
|
||||
Skin skin = new Skin(skinName);
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
int slotIndex = ReadInt(input, true);
|
||||
for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
|
||||
int slotIndex = ReadVarint(input, true);
|
||||
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
String name = ReadString(input);
|
||||
if (name == null) name = attachmentName;
|
||||
|
||||
switch ((AttachmentType)input.ReadByte()) {
|
||||
AttachmentType type = (AttachmentType)input.ReadByte();
|
||||
switch (type) {
|
||||
case AttachmentType.region: {
|
||||
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;
|
||||
RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path);
|
||||
if (region == null) return null;
|
||||
region.Path = path;
|
||||
region.x = ReadFloat(input) * scale;
|
||||
region.y = ReadFloat(input) * scale;
|
||||
region.scaleX = ReadFloat(input);
|
||||
region.scaleY = ReadFloat(input);
|
||||
region.rotation = ReadFloat(input);
|
||||
region.width = ReadFloat(input) * scale;
|
||||
region.height = ReadFloat(input) * scale;
|
||||
int color = ReadInt(input);
|
||||
region.x = x * scale;
|
||||
region.y = y * scale;
|
||||
region.scaleX = scaleX;
|
||||
region.scaleY = scaleY;
|
||||
region.rotation = rotation;
|
||||
region.width = width * scale;
|
||||
region.height = height * scale;
|
||||
region.r = ((color & 0xff000000) >> 24) / 255f;
|
||||
region.g = ((color & 0x00ff0000) >> 16) / 255f;
|
||||
region.b = ((color & 0x0000ff00) >> 8) / 255f;
|
||||
@ -248,80 +276,159 @@ namespace Spine {
|
||||
return region;
|
||||
}
|
||||
case AttachmentType.boundingbox: {
|
||||
float[] vertices = ReadFloatArray(input, ReadVarint(input, true) * 2, scale);
|
||||
BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name);
|
||||
if (box == null) return null;
|
||||
box.vertices = ReadFloatArray(input, scale);
|
||||
box.vertices = vertices;
|
||||
return box;
|
||||
}
|
||||
case AttachmentType.mesh: {
|
||||
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;
|
||||
MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
|
||||
if (mesh == null) return null;
|
||||
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.g = ((color & 0x00ff0000) >> 16) / 255f;
|
||||
mesh.b = ((color & 0x0000ff00) >> 8) / 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) {
|
||||
mesh.Edges = ReadIntArray(input);
|
||||
mesh.Width = ReadFloat(input) * scale;
|
||||
mesh.Height = ReadFloat(input) * scale;
|
||||
mesh.Edges = edges;
|
||||
mesh.Width = width * scale;
|
||||
mesh.Height = height * scale;
|
||||
}
|
||||
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: {
|
||||
String path = ReadString(input);
|
||||
if (path == null) path = name;
|
||||
WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path);
|
||||
if (mesh == null) return null;
|
||||
mesh.Path = path;
|
||||
float[] uvs = ReadFloatArray(input, 1);
|
||||
int color = ReadInt(input);
|
||||
int vertexCount = ReadVarint(input, true);
|
||||
float[] uvs = ReadFloatArray(input, vertexCount * 2, 1);
|
||||
int[] triangles = ReadShortArray(input);
|
||||
|
||||
int vertexCount = ReadInt(input, true);
|
||||
var weights = new List<float>(uvs.Length * 3 * 3);
|
||||
var bones = new List<int>(uvs.Length * 3);
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
int boneCount = (int)ReadFloat(input);
|
||||
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));
|
||||
weights.Add(ReadFloat(input) * scale);
|
||||
weights.Add(ReadFloat(input) * scale);
|
||||
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.weights = weights.ToArray();
|
||||
mesh.triangles = triangles;
|
||||
mesh.regionUVs = uvs;
|
||||
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);
|
||||
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.g = ((color & 0x00ff0000) >> 16) / 255f;
|
||||
mesh.b = ((color & 0x0000ff00) >> 8) / 255f;
|
||||
mesh.a = ((color & 0x000000ff)) / 255f;
|
||||
mesh.HullLength = ReadInt(input, true) * 2;
|
||||
mesh.inheritFFD = inheritFFD;
|
||||
if (nonessential) {
|
||||
mesh.Edges = ReadIntArray(input);
|
||||
mesh.Width = ReadFloat(input) * scale;
|
||||
mesh.Height = ReadFloat(input) * scale;
|
||||
mesh.Width = width * scale;
|
||||
mesh.Height = height * scale;
|
||||
}
|
||||
linkedMeshes.Add(new SkeletonJson.LinkedMesh(mesh, skinName, slotIndex, parent));
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private float[] ReadFloatArray (Stream input, float scale) {
|
||||
int n = ReadInt(input, true);
|
||||
private float[] ReadFloatArray (Stream input, int n, float scale) {
|
||||
float[] array = new float[n];
|
||||
if (scale == 1) {
|
||||
for (int i = 0; i < n; i++)
|
||||
@ -334,18 +441,10 @@ namespace Spine {
|
||||
}
|
||||
|
||||
private int[] ReadShortArray (Stream input) {
|
||||
int n = ReadInt(input, true);
|
||||
int n = ReadVarint(input, true);
|
||||
int[] array = new int[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
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);
|
||||
for (int i = 0; i < n; i++)
|
||||
array[i] = (input.ReadByte() << 8) | input.ReadByte();
|
||||
return array;
|
||||
}
|
||||
|
||||
@ -355,11 +454,11 @@ namespace Spine {
|
||||
float duration = 0;
|
||||
|
||||
// Slot timelines.
|
||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
||||
int slotIndex = ReadInt(input, true);
|
||||
for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||
int slotIndex = ReadVarint(input, true);
|
||||
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
|
||||
int timelineType = input.ReadByte();
|
||||
int frameCount = ReadInt(input, true);
|
||||
int frameCount = ReadVarint(input, true);
|
||||
switch (timelineType) {
|
||||
case TIMELINE_COLOR: {
|
||||
ColorTimeline timeline = new ColorTimeline(frameCount);
|
||||
@ -392,11 +491,11 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// Bone timelines.
|
||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
||||
int boneIndex = ReadInt(input, true);
|
||||
for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||
int boneIndex = ReadVarint(input, true);
|
||||
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
|
||||
int timelineType = input.ReadByte();
|
||||
int frameCount = ReadInt(input, true);
|
||||
int frameCount = ReadVarint(input, true);
|
||||
switch (timelineType) {
|
||||
case TIMELINE_ROTATE: {
|
||||
RotateTimeline timeline = new RotateTimeline(frameCount);
|
||||
@ -434,9 +533,9 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// IK timelines.
|
||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
||||
IkConstraintData ikConstraint = skeletonData.ikConstraints.Items[ReadInt(input, true)];
|
||||
int frameCount = ReadInt(input, true);
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||
IkConstraintData ikConstraint = skeletonData.ikConstraints.Items[ReadVarint(input, true)];
|
||||
int frameCount = ReadVarint(input, true);
|
||||
IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount);
|
||||
timeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(ikConstraint);
|
||||
for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
|
||||
@ -448,13 +547,13 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// FFD timelines.
|
||||
for (int i = 0, n = ReadInt(input, true); i < n; i++) {
|
||||
Skin skin = skeletonData.skins.Items[ReadInt(input, true)];
|
||||
for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
|
||||
int slotIndex = ReadInt(input, true);
|
||||
for (int iii = 0, nnn = ReadInt(input, true); iii < nnn; iii++) {
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||
Skin skin = skeletonData.skins.Items[ReadVarint(input, true)];
|
||||
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
|
||||
int slotIndex = ReadVarint(input, true);
|
||||
for (int iii = 0, nnn = ReadVarint(input, true); iii < nnn; iii++) {
|
||||
Attachment attachment = skin.GetAttachment(slotIndex, ReadString(input));
|
||||
int frameCount = ReadInt(input, true);
|
||||
int frameCount = ReadVarint(input, true);
|
||||
FFDTimeline timeline = new FFDTimeline(frameCount);
|
||||
timeline.slotIndex = slotIndex;
|
||||
timeline.attachment = attachment;
|
||||
@ -468,7 +567,7 @@ namespace Spine {
|
||||
else
|
||||
vertexCount = ((WeightedMeshAttachment)attachment).weights.Length / 3 * 2;
|
||||
|
||||
int end = ReadInt(input, true);
|
||||
int end = ReadVarint(input, true);
|
||||
if (end == 0) {
|
||||
if (attachment is MeshAttachment)
|
||||
vertices = ((MeshAttachment)attachment).vertices;
|
||||
@ -476,7 +575,7 @@ namespace Spine {
|
||||
vertices = new float[vertexCount];
|
||||
} else {
|
||||
vertices = new float[vertexCount];
|
||||
int start = ReadInt(input, true);
|
||||
int start = ReadVarint(input, true);
|
||||
end += start;
|
||||
if (scale == 1) {
|
||||
for (int v = start; v < end; v++)
|
||||
@ -502,24 +601,24 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// Draw order timeline.
|
||||
int drawOrderCount = ReadInt(input, true);
|
||||
int drawOrderCount = ReadVarint(input, true);
|
||||
if (drawOrderCount > 0) {
|
||||
DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount);
|
||||
int slotCount = skeletonData.slots.Count;
|
||||
for (int i = 0; i < drawOrderCount; i++) {
|
||||
int offsetCount = ReadInt(input, true);
|
||||
int offsetCount = ReadVarint(input, true);
|
||||
int[] drawOrder = new int[slotCount];
|
||||
for (int ii = slotCount - 1; ii >= 0; ii--)
|
||||
drawOrder[ii] = -1;
|
||||
int[] unchanged = new int[slotCount - offsetCount];
|
||||
int originalIndex = 0, unchangedIndex = 0;
|
||||
for (int ii = 0; ii < offsetCount; ii++) {
|
||||
int slotIndex = ReadInt(input, true);
|
||||
int slotIndex = ReadVarint(input, true);
|
||||
// Collect unchanged items.
|
||||
while (originalIndex != slotIndex)
|
||||
unchanged[unchangedIndex++] = originalIndex++;
|
||||
// Set changed items.
|
||||
drawOrder[originalIndex + ReadInt(input, true)] = originalIndex++;
|
||||
drawOrder[originalIndex + ReadVarint(input, true)] = originalIndex++;
|
||||
}
|
||||
// Collect remaining unchanged items.
|
||||
while (originalIndex < slotCount)
|
||||
@ -534,14 +633,14 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// Event timeline.
|
||||
int eventCount = ReadInt(input, true);
|
||||
int eventCount = ReadVarint(input, true);
|
||||
if (eventCount > 0) {
|
||||
EventTimeline timeline = new EventTimeline(eventCount);
|
||||
for (int i = 0; i < eventCount; i++) {
|
||||
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);
|
||||
e.Int = ReadInt(input, false);
|
||||
e.Int = ReadVarint(input, false);
|
||||
e.Float = ReadFloat(input);
|
||||
e.String = ReadBoolean(input) ? ReadString(input) : eventData.String;
|
||||
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();
|
||||
if (value == -1) throw new EndOfStreamException();
|
||||
return (sbyte)value;
|
||||
}
|
||||
|
||||
private bool ReadBoolean (Stream input) {
|
||||
private static bool ReadBoolean (Stream input) {
|
||||
return input.ReadByte() != 0;
|
||||
}
|
||||
|
||||
@ -583,11 +682,11 @@ namespace Spine {
|
||||
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();
|
||||
}
|
||||
|
||||
private int ReadInt (Stream input, bool optimizePositive) {
|
||||
private static int ReadVarint (Stream input, bool optimizePositive) {
|
||||
int b = input.ReadByte();
|
||||
int result = b & 0x7F;
|
||||
if ((b & 0x80) != 0) {
|
||||
@ -600,8 +699,7 @@ namespace Spine {
|
||||
b = input.ReadByte();
|
||||
result |= (b & 0x7F) << 21;
|
||||
if ((b & 0x80) != 0) {
|
||||
b = input.ReadByte();
|
||||
result |= (b & 0x7F) << 28;
|
||||
result |= (input.ReadByte() & 0x7F) << 28;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -610,53 +708,28 @@ namespace Spine {
|
||||
}
|
||||
|
||||
private string ReadString (Stream input) {
|
||||
int charCount = ReadInt(input, true);
|
||||
switch (charCount) {
|
||||
int byteCount = ReadVarint(input, true);
|
||||
switch (byteCount) {
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return "";
|
||||
}
|
||||
charCount--;
|
||||
char[] chars = this.chars;
|
||||
if (chars.Length < charCount) this.chars = chars = new char[charCount];
|
||||
// Try to read 7 bit ASCII chars.
|
||||
int charIndex = 0;
|
||||
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);
|
||||
byteCount--;
|
||||
byte[] bytes = this.bytes;
|
||||
if (bytes.Length < byteCount) bytes = new byte[byteCount];
|
||||
ReadFully(input, bytes, 0, byteCount);
|
||||
return System.Text.Encoding.UTF8.GetString(bytes, 0, byteCount);
|
||||
}
|
||||
|
||||
private void ReadUtf8_slow (Stream input, int charCount, int charIndex, int b) {
|
||||
char[] chars = this.chars;
|
||||
while (true) {
|
||||
switch (b >> 4) {
|
||||
case 0:
|
||||
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;
|
||||
private static void ReadFully (Stream input, byte[] b, int off, int len) {
|
||||
while (len > 0) {
|
||||
int count = input.Read(b, off, len);
|
||||
if (count <= 0) {
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
if (++charIndex >= charCount) break;
|
||||
b = input.ReadByte() & 0xFF;
|
||||
off += count;
|
||||
len -= count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,6 +46,7 @@ namespace Spine {
|
||||
public class SkeletonJson {
|
||||
private AttachmentLoader attachmentLoader;
|
||||
public float Scale { get; set; }
|
||||
private List<LinkedMesh> linkedMeshes = new List<LinkedMesh>();
|
||||
|
||||
public SkeletonJson (params Atlas[] atlasArray)
|
||||
: this(new AtlasAttachmentLoader(atlasArray)) {
|
||||
@ -208,7 +209,7 @@ namespace Spine {
|
||||
foreach (KeyValuePair<String, Object> slotEntry in (Dictionary<String, Object>)entry.Value) {
|
||||
int slotIndex = skeletonData.FindSlotIndex(slotEntry.Key);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -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.
|
||||
if (root.ContainsKey("events")) {
|
||||
foreach (KeyValuePair<String, Object> entry in (Dictionary<String, Object>)root["events"]) {
|
||||
@ -245,7 +265,7 @@ namespace Spine {
|
||||
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"))
|
||||
name = (String)map["name"];
|
||||
|
||||
@ -285,15 +305,11 @@ namespace Spine {
|
||||
}
|
||||
|
||||
return region;
|
||||
case AttachmentType.mesh: {
|
||||
case AttachmentType.mesh:
|
||||
case AttachmentType.linkedmesh: {
|
||||
MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
|
||||
if (mesh == null) return null;
|
||||
|
||||
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")) {
|
||||
var color = (String)map["color"];
|
||||
@ -303,38 +319,31 @@ namespace Spine {
|
||||
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.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;
|
||||
}
|
||||
case AttachmentType.weightedmesh: {
|
||||
case AttachmentType.weightedmesh:
|
||||
case AttachmentType.weightedlinkedmesh: {
|
||||
WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path);
|
||||
if (mesh == null) return null;
|
||||
|
||||
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")) {
|
||||
var color = (String)map["color"];
|
||||
@ -344,11 +353,39 @@ namespace Spine {
|
||||
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.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;
|
||||
}
|
||||
case AttachmentType.boundingbox:
|
||||
@ -657,5 +694,18 @@ namespace Spine {
|
||||
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