diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7059b3183..fcedf7e5c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -331,6 +331,7 @@
- Attachment `ComputeWorldVertices()` methods now take an additional `skeleton` parameter
- Renamed timeline constraint index methods to use unified `ConstraintIndex` property
- Reorganized timeline class hierarchy with new base classes
+ - Removed `AtlasAttachmentLoader` method `AtlasRegion FindRegion(string name)` from public interface. Added `protected AtlasRegion FindRegion(string name, string path)` instead which may be overridden instead when deriving your own subclass.
### Unity
diff --git a/spine-csharp/src/Animation.cs b/spine-csharp/src/Animation.cs
index 234c037c0..c033af940 100644
--- a/spine-csharp/src/Animation.cs
+++ b/spine-csharp/src/Animation.cs
@@ -1881,12 +1881,12 @@ namespace Spine {
private const int MODE = 1, DELAY = 2;
readonly int slotIndex;
- readonly IHasTextureRegion attachment;
+ readonly IHasSequence attachment;
public SequenceTimeline (int frameCount, int slotIndex, Attachment attachment)
- : base(frameCount, (int)Property.Sequence + "|" + slotIndex + "|" + ((IHasTextureRegion)attachment).Sequence.Id) {
+ : base(frameCount, (int)Property.Sequence + "|" + slotIndex + "|" + ((IHasSequence)attachment).Sequence.Id) {
this.slotIndex = slotIndex;
- this.attachment = (IHasTextureRegion)attachment;
+ this.attachment = (IHasSequence)attachment;
}
public override int FrameEntries {
@@ -1927,8 +1927,6 @@ namespace Spine {
if ((vertexAttachment == null)
|| vertexAttachment.TimelineAttachment != attachment) return;
}
- Sequence sequence = ((IHasTextureRegion)slotAttachment).Sequence;
- if (sequence == null) return;
if (direction == MixDirection.Out) {
if (blend == MixBlend.Setup) pose.SequenceIndex = -1;
@@ -1946,7 +1944,7 @@ namespace Spine {
int modeAndIndex = (int)frames[i + MODE];
float delay = frames[i + DELAY];
- int index = modeAndIndex >> 4, count = sequence.Regions.Length;
+ int index = modeAndIndex >> 4, count = (((IHasSequence)slotAttachment).Sequence).Regions.Length;
SequenceMode mode = (SequenceMode)(modeAndIndex & 0xf);
if (mode != SequenceMode.Hold) {
index += (int)((time - before) / delay + 0.0001f);
diff --git a/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs b/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs
index c29041cd3..882d21bd4 100644
--- a/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs
+++ b/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs
@@ -49,40 +49,32 @@ namespace Spine {
this.allowMissingRegions = allowMissingRegions;
}
- private void LoadSequence (string name, string basePath, Sequence sequence) {
+ protected void FindRegions (string name, string basePath, Sequence sequence) {
TextureRegion[] regions = sequence.Regions;
for (int i = 0, n = regions.Length; i < n; i++) {
- string path = sequence.GetPath(basePath, i);
- regions[i] = FindRegion(path);
- if (regions[i] == null && !allowMissingRegions)
- throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
+ regions[i] = FindRegion(name, sequence.GetPath(basePath, i));
}
}
+ protected AtlasRegion FindRegion (string name, string path) {
+ for (int i = 0; i < atlasArray.Length; i++) {
+ AtlasRegion region = atlasArray[i].FindRegion(path);
+ if (region != null)
+ return region;
+ }
+ if (!allowMissingRegions)
+ throw new ArgumentException(string.Format("Region not found in atlas: {0} (attachment: {1})", path, name));
+ return null;
+ }
+
public RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence) {
- var attachment = new RegionAttachment(name);
- if (sequence != null)
- LoadSequence(name, path, sequence);
- else {
- AtlasRegion region = FindRegion(path);
- if (region == null && !allowMissingRegions)
- throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
- attachment.Region = region;
- }
- return attachment;
+ FindRegions(name, path, sequence);
+ return new RegionAttachment(name, sequence);
}
public MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence) {
- var attachment = new MeshAttachment(name);
- if (sequence != null)
- LoadSequence(name, path, sequence);
- else {
- AtlasRegion region = FindRegion(path);
- if (region == null && !allowMissingRegions)
- throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
- attachment.Region = region;
- }
- return attachment;
+ FindRegions(name, path, sequence);
+ return new MeshAttachment(name, sequence);
}
public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
@@ -100,17 +92,5 @@ namespace Spine {
public ClippingAttachment NewClippingAttachment (Skin skin, string name) {
return new ClippingAttachment(name);
}
-
- public AtlasRegion FindRegion (string name) {
- AtlasRegion region;
-
- for (int i = 0; i < atlasArray.Length; i++) {
- region = atlasArray[i].FindRegion(name);
- if (region != null)
- return region;
- }
-
- return null;
- }
}
}
diff --git a/spine-csharp/src/Attachments/IHasTextureRegion.cs b/spine-csharp/src/Attachments/IHasSequence.cs
similarity index 76%
rename from spine-csharp/src/Attachments/IHasTextureRegion.cs
rename to spine-csharp/src/Attachments/IHasSequence.cs
index 79629bb8b..15da803ca 100644
--- a/spine-csharp/src/Attachments/IHasTextureRegion.cs
+++ b/spine-csharp/src/Attachments/IHasSequence.cs
@@ -36,25 +36,12 @@ namespace Spine {
using Color32F = UnityEngine.Color;
#endif
- public interface IHasTextureRegion {
- /// The name used to find the
+ public interface IHasSequence {
string Path { get; set; }
- ///
- /// Sets the region used to draw the attachment. After setting the region or if the region's properties are changed,
- /// must be called.
- ///
- TextureRegion Region { get; set; }
-
- ///
- /// Updates any values the attachment calculates using the . Must be called after setting the
- /// or if the region's properties are changed.
- ///
- void UpdateRegion ();
-
Color32F GetColor ();
void SetColor (Color32F color);
void SetColor (float r, float g, float b, float a);
-
- Sequence Sequence { get; set; }
+ Sequence Sequence { get; }
+ void UpdateSequence ();
}
}
diff --git a/spine-csharp/src/Attachments/IHasTextureRegion.cs.meta b/spine-csharp/src/Attachments/IHasSequence.cs.meta
similarity index 100%
rename from spine-csharp/src/Attachments/IHasTextureRegion.cs.meta
rename to spine-csharp/src/Attachments/IHasSequence.cs.meta
diff --git a/spine-csharp/src/Attachments/MeshAttachment.cs b/spine-csharp/src/Attachments/MeshAttachment.cs
index d06ead06a..52f864287 100644
--- a/spine-csharp/src/Attachments/MeshAttachment.cs
+++ b/spine-csharp/src/Attachments/MeshAttachment.cs
@@ -39,32 +39,25 @@ namespace Spine {
#endif
/// Attachment that displays a texture region using a mesh.
- public class MeshAttachment : VertexAttachment, IHasTextureRegion {
- internal TextureRegion region;
- internal string path;
- internal float[] regionUVs, uvs;
+ public class MeshAttachment : VertexAttachment, IHasSequence {
+ internal readonly Sequence sequence;
+ internal float[] regionUVs;
internal int[] triangles;
+ internal int hullLength;
+ internal string path;
// Color is a struct, set to protected to prevent
// Color color = slot.color; color.a = 0.5;
// modifying just a copy of the struct instead of the original
// object as in reference implementation.
protected Color32F color = new Color32F(1, 1, 1, 1);
- internal int hullLength;
private MeshAttachment parentMesh;
- private Sequence sequence;
- public TextureRegion Region {
- get { return region; }
- set {
- if (value == null) throw new ArgumentNullException("region", "region cannot be null.");
- region = value;
- }
- }
public int HullLength { get { return hullLength; } set { hullLength = value; } }
+
+ /// The UV pair for each vertex, normalized within the texture region.
public float[] RegionUVs { get { return regionUVs; } set { regionUVs = value; } }
/// The UV pair for each vertex, normalized within the entire texture.
///
- public float[] UVs { get { return uvs; } set { uvs = value; } }
public int[] Triangles { get { return triangles; } set { triangles = value; } }
public Color32F GetColor () {
@@ -80,7 +73,7 @@ namespace Spine {
}
public string Path { get { return path; } set { path = value; } }
- public Sequence Sequence { get { return sequence; } set { sequence = value; } }
+ public Sequence Sequence { get { return sequence; } }
public MeshAttachment ParentMesh {
get { return parentMesh; }
@@ -101,12 +94,18 @@ namespace Spine {
}
// Nonessential.
+ ///
+ /// Vertex index pairs describing edges for controlling triangulation, or be null if nonessential data was not exported. Mesh
+ /// triangles never cross edges. Triangulation is not performed at runtime.
+ ///
public int[] Edges { get; set; }
public float Width { get; set; }
public float Height { get; set; }
- public MeshAttachment (string name)
+ public MeshAttachment (string name, Sequence sequence)
: base(name) {
+ if (sequence == null) throw new ArgumentException("sequence cannot be null.", "sequence");
+ this.sequence = sequence;
}
/// Copy constructor. Use if the other mesh is a linked mesh.
@@ -115,21 +114,17 @@ namespace Spine {
if (parentMesh != null) throw new ArgumentException("Use newLinkedMesh to copy a linked mesh.");
- region = other.region;
path = other.path;
color = other.color;
regionUVs = new float[other.regionUVs.Length];
Array.Copy(other.regionUVs, 0, regionUVs, 0, regionUVs.Length);
- uvs = new float[other.uvs.Length];
- Array.Copy(other.uvs, 0, uvs, 0, uvs.Length);
-
triangles = new int[other.triangles.Length];
Array.Copy(other.triangles, 0, triangles, 0, triangles.Length);
hullLength = other.hullLength;
- sequence = other.sequence == null ? null : new Sequence(other.sequence);
+ sequence = new Sequence(other.sequence);
// Nonessential.
if (other.Edges != null) {
@@ -140,58 +135,81 @@ namespace Spine {
Height = other.Height;
}
+ public void UpdateSequence () {
+ sequence.Update(this);
+ }
- public void UpdateRegion () {
- float[] regionUVs = this.regionUVs;
- if (this.uvs == null || this.uvs.Length != regionUVs.Length) this.uvs = new float[regionUVs.Length];
- float[] uvs = this.uvs;
+ /// Returns a new mesh with this mesh set as the .
+ public MeshAttachment NewLinkedMesh () {
+ var mesh = new MeshAttachment(Name, new Sequence(sequence));
+
+ mesh.timelineAttachment = timelineAttachment;
+ mesh.path = path;
+ mesh.color = color;
+ mesh.ParentMesh = parentMesh != null ? parentMesh : this;
+ mesh.UpdateSequence();
+ return mesh;
+ }
+
+ public override Attachment Copy () {
+ return parentMesh != null ? NewLinkedMesh() : new MeshAttachment(this);
+ }
+
+ ///
+ /// Computes UVs for a mesh attachment.
+ ///
+ /// Output array for the computed UVs, same length as regionUVs.
+ internal static void ComputeUVs (TextureRegion region, float[] regionUVs, float[] uvs) {
int n = uvs.Length;
float u, v, width, height;
-
- if (region is AtlasRegion) {
- u = this.region.u;
- v = this.region.v;
- AtlasRegion region = (AtlasRegion)this.region;
- // Note: difference from reference implementation.
- // Covers rotation since region.width and height are already setup accordingly.
- float textureWidth = this.region.width / (region.u2 - region.u);
- float textureHeight = this.region.height / (region.v2 - region.v);
- switch (region.degrees) {
- case 90:
- u -= (region.originalHeight - region.offsetY - region.packedWidth) / textureWidth;
- v -= (region.originalWidth - region.offsetX - region.packedHeight) / textureHeight;
- width = region.originalHeight / textureWidth;
- height = region.originalWidth / textureHeight;
+ AtlasRegion r = region as AtlasRegion;
+ if (r != null) {
+ u = r.u;
+ v = r.v;
+ float textureWidth = region.width / (region.u2 - region.u);
+ float textureHeight = region.height / (region.v2 - region.v);
+ switch (r.degrees) {
+ case 90: {
+ u -= (r.originalHeight - r.offsetY - r.packedWidth) / textureWidth;
+ v -= (r.originalWidth - r.offsetX - r.packedHeight) / textureHeight;
+ width = r.originalHeight / textureWidth;
+ height = r.originalWidth / textureHeight;
for (int i = 0; i < n; i += 2) {
uvs[i] = u + regionUVs[i + 1] * width;
uvs[i + 1] = v + (1 - regionUVs[i]) * height;
}
return;
- case 180:
- u -= (region.originalWidth - region.offsetX - region.packedWidth) / textureWidth;
- v -= region.offsetY / textureHeight;
- width = region.originalWidth / textureWidth;
- height = region.originalHeight / textureHeight;
+ }
+ case 180: {
+ u -= (r.originalWidth - r.offsetX - r.packedWidth) / textureWidth;
+ v -= r.offsetY / textureHeight;
+ width = r.originalWidth / textureWidth;
+ height = r.originalHeight / textureHeight;
for (int i = 0; i < n; i += 2) {
uvs[i] = u + (1 - regionUVs[i]) * width;
uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height;
}
return;
- case 270:
- u -= region.offsetY / textureWidth;
- v -= region.offsetX / textureHeight;
- width = region.originalHeight / textureWidth;
- height = region.originalWidth / textureHeight;
+ }
+ case 270: {
+ u -= r.offsetY / textureWidth;
+ v -= r.offsetX / textureHeight;
+ width = r.originalHeight / textureWidth;
+ height = r.originalWidth / textureHeight;
for (int i = 0; i < n; i += 2) {
uvs[i] = u + (1 - regionUVs[i + 1]) * width;
uvs[i + 1] = v + regionUVs[i] * height;
}
return;
}
- u -= region.offsetX / textureWidth;
- v -= (region.originalHeight - region.offsetY - region.packedHeight) / textureHeight;
- width = region.originalWidth / textureWidth;
- height = region.originalHeight / textureHeight;
+ default: {
+ u -= r.offsetX / textureWidth;
+ v -= (r.originalHeight - r.offsetY - r.packedHeight) / textureHeight;
+ width = r.originalWidth / textureWidth;
+ height = r.originalHeight / textureHeight;
+ break;
+ }
+ }
} else if (region == null) {
u = v = 0;
width = height = 1;
@@ -206,29 +224,5 @@ namespace Spine {
uvs[i + 1] = v + regionUVs[i + 1] * height;
}
}
-
- /// If the attachment has a , the region may be changed.
- override public void ComputeWorldVertices (Skeleton skeleton, Slot slot, int start, int count, float[] worldVertices, int offset,
- int stride = 2) {
- if (sequence != null) sequence.Apply(slot.AppliedPose, this);
- base.ComputeWorldVertices(skeleton, slot, start, count, worldVertices, offset, stride);
- }
-
- /// Returns a new mesh with this mesh set as the .
- public MeshAttachment NewLinkedMesh () {
- var mesh = new MeshAttachment(Name);
-
- mesh.timelineAttachment = timelineAttachment;
- mesh.region = region;
- mesh.path = path;
- mesh.color = color;
- mesh.ParentMesh = parentMesh != null ? parentMesh : this;
- if (mesh.Region != null) mesh.UpdateRegion();
- return mesh;
- }
-
- public override Attachment Copy () {
- return parentMesh != null ? NewLinkedMesh() : new MeshAttachment(this);
- }
}
}
diff --git a/spine-csharp/src/Attachments/RegionAttachment.cs b/spine-csharp/src/Attachments/RegionAttachment.cs
index 27877eeb6..09bf19f1c 100644
--- a/spine-csharp/src/Attachments/RegionAttachment.cs
+++ b/spine-csharp/src/Attachments/RegionAttachment.cs
@@ -39,21 +39,19 @@ namespace Spine {
#endif
/// Attachment that displays a texture region.
- public class RegionAttachment : Attachment, IHasTextureRegion {
+ public class RegionAttachment : Attachment, IHasSequence {
public const int BLX = 0, BLY = 1;
public const int ULX = 2, ULY = 3;
public const int URX = 4, URY = 5;
public const int BRX = 6, BRY = 7;
- internal TextureRegion region;
+ internal readonly Sequence sequence;
internal float x, y, rotation, scaleX = 1, scaleY = 1, width, height;
- internal float[] offset = new float[8], uvs = new float[8];
// Color is a struct, set to protected to prevent
// Color color = slot.color; color.a = 0.5;
// modifying just a copy of the struct instead of the original
// object as in reference implementation.
protected Color32F color = new Color32F(1, 1, 1, 1);
- internal Sequence sequence;
public float X { get { return x; } set { x = value; } }
public float Y { get { return y; } set { y = value; } }
@@ -76,22 +74,17 @@ namespace Spine {
}
public string Path { get; set; }
- public TextureRegion Region { get { return region; } set { region = value; } }
+ public Sequence Sequence { get { return sequence; } }
- /// For each of the 4 vertices, a pair of x,y values that is the local position of the vertex.
- ///
- public float[] Offset { get { return offset; } }
- public float[] UVs { get { return uvs; } }
- public Sequence Sequence { get { return sequence; } set { sequence = value; } }
-
- public RegionAttachment (string name)
+ public RegionAttachment (string name, Sequence sequence)
: base(name) {
+ if (sequence == null) throw new ArgumentException("sequence cannot be null.", "sequence");
+ this.sequence = sequence;
}
/// Copy constructor.
public RegionAttachment (RegionAttachment other)
: base(other) {
- region = other.region;
Path = other.Path;
x = other.x;
y = other.y;
@@ -100,41 +93,94 @@ namespace Spine {
rotation = other.rotation;
width = other.width;
height = other.height;
- Array.Copy(other.uvs, 0, uvs, 0, 8);
- Array.Copy(other.offset, 0, offset, 0, 8);
color = other.color;
- sequence = other.sequence == null ? null : new Sequence(other.sequence);
+ sequence = new Sequence(other.sequence);
}
- /// Calculates the and using the region and the attachment's transform. Must be called if the
- /// region, the region's properties, or the transform are changed.
- public void UpdateRegion () {
- float width = Width, height = Height;
- float localX2 = width / 2;
- float localY2 = height / 2;
- float localX = -localX2;
- float localY = -localY2;
+ ///
+ /// Transforms the attachment's four vertices to world coordinates. If the attachment has a the region may
+ /// be changed.
+ ///
+ /// See World transforms in the Spine
+ /// Runtimes Guide.
+ /// The output world vertices. Must have a length greater than or equal to offset + 8.
+ /// The vertex offsets.
+ /// The worldVertices index to begin writing values.
+ /// The number of worldVertices entries between the value pairs written.
+ public void ComputeWorldVertices (Slot slot, float[] vertexOffsets, float[] worldVertices, int offset, int stride = 2) {
+ BonePose bone = slot.Bone.AppliedPose;
+ float bwx = bone.worldX, bwy = bone.worldY;
+ float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
+
+ // Vertex order is different from RegionAttachment.java
+ float offsetX = vertexOffsets[BRX]; // 0
+ float offsetY = vertexOffsets[BRY]; // 1
+ worldVertices[offset] = offsetX * a + offsetY * b + bwx; // bl
+ worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
+ offset += stride;
+
+ offsetX = vertexOffsets[BLX]; // 2
+ offsetY = vertexOffsets[BLY]; // 3
+ worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ul
+ worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
+ offset += stride;
+
+ offsetX = vertexOffsets[ULX]; // 4
+ offsetY = vertexOffsets[ULY]; // 5
+ worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ur
+ worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
+ offset += stride;
+
+ offsetX = vertexOffsets[URX]; // 6
+ offsetY = vertexOffsets[URY]; // 7
+ worldVertices[offset] = offsetX * a + offsetY * b + bwx; // br
+ worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
+ //offset += stride;
+ }
+
+ ///
+ /// Returns the vertex offsets for the specified slot pose.
+ ///
+ public float[] GetOffsets (SlotPose pose) {
+ return sequence.GetOffsets(sequence.ResolveIndex(pose));
+ }
+
+ public void UpdateSequence () {
+ sequence.Update(this);
+ }
+
+ public override Attachment Copy () {
+ return new RegionAttachment(this);
+ }
+
+ ///
+ /// Computes UVs and offsets for a region attachment.
+ ///
+ /// Output array for the computed UVs, length of 8.
+ /// Output array for the computed vertex offsets, length of 8.
+ internal static void ComputeUVs (TextureRegion region, float x, float y, float scaleX, float scaleY, float rotation, float width,
+ float height, float[] offset, float[] uvs) {
+ float localX2 = width / 2, localY2 = height / 2;
+ float localX = -localX2, localY = -localY2;
bool rotated = false;
- if (region is AtlasRegion) {
- AtlasRegion region = (AtlasRegion)this.region;
- localX += region.offsetX / region.originalWidth * width;
- localY += region.offsetY / region.originalHeight * height;
- if (region.degrees == 90) {
+ AtlasRegion r = region as AtlasRegion;
+ if (r != null) {
+ localX += r.offsetX / r.originalWidth * width;
+ localY += r.offsetY / r.originalHeight * height;
+ if (r.degrees == 90) {
rotated = true;
- localX2 -= (region.originalWidth - region.offsetX - region.packedHeight) / region.originalWidth * width;
- localY2 -= (region.originalHeight - region.offsetY - region.packedWidth) / region.originalHeight * height;
+ localX2 -= (r.originalWidth - r.offsetX - r.packedHeight) / r.originalWidth * width;
+ localY2 -= (r.originalHeight - r.offsetY - r.packedWidth) / r.originalHeight * height;
} else {
- localX2 -= (region.originalWidth - region.offsetX - region.packedWidth) / region.originalWidth * width;
- localY2 -= (region.originalHeight - region.offsetY - region.packedHeight) / region.originalHeight * height;
+ localX2 -= (r.originalWidth - r.offsetX - r.packedWidth) / r.originalWidth * width;
+ localY2 -= (r.originalHeight - r.offsetY - r.packedHeight) / r.originalHeight * height;
}
}
- float scaleX = ScaleX, scaleY = ScaleY;
localX *= scaleX;
localY *= scaleY;
localX2 *= scaleX;
localY2 *= scaleY;
- float r = Rotation * MathUtils.DegRad, cos = (float)Math.Cos(r), sin = (float)Math.Sin(r);
- float x = X, y = Y;
+ float rot = rotation * MathUtils.DegRad, cos = (float)Math.Cos(rot), sin = (float)Math.Sin(rot);
float localXCos = localX * cos + x;
float localXSin = localX * sin;
float localYCos = localY * cos + y;
@@ -143,7 +189,6 @@ namespace Spine {
float localX2Sin = localX2 * sin;
float localY2Cos = localY2 * cos + y;
float localY2Sin = localY2 * sin;
- float[] offset = this.offset;
offset[BLX] = localXCos - localYSin;
offset[BLY] = localYCos + localXSin;
offset[ULX] = localXCos - localY2Sin;
@@ -152,8 +197,6 @@ namespace Spine {
offset[URY] = localY2Cos + localX2Sin;
offset[BRX] = localX2Cos - localYSin;
offset[BRY] = localYCos + localX2Sin;
-
- float[] uvs = this.uvs;
if (region == null) {
uvs[BLX] = 0;
uvs[BLY] = 0;
@@ -163,71 +206,23 @@ namespace Spine {
uvs[URY] = 1;
uvs[BRX] = 1;
uvs[BRY] = 0;
- } else if (rotated) {
- uvs[BLX] = region.u2;
- uvs[BLY] = region.v;
- uvs[ULX] = region.u2;
- uvs[ULY] = region.v2;
- uvs[URX] = region.u;
- uvs[URY] = region.v2;
- uvs[BRX] = region.u;
- uvs[BRY] = region.v;
} else {
uvs[BLX] = region.u2;
- uvs[BLY] = region.v2;
- uvs[ULX] = region.u;
uvs[ULY] = region.v2;
uvs[URX] = region.u;
- uvs[URY] = region.v;
- uvs[BRX] = region.u2;
uvs[BRY] = region.v;
+ if (rotated) {
+ uvs[BLY] = region.v;
+ uvs[ULX] = region.u2;
+ uvs[URY] = region.v2;
+ uvs[BRX] = region.u;
+ } else {
+ uvs[BLY] = region.v2;
+ uvs[ULX] = region.u;
+ uvs[URY] = region.v;
+ uvs[BRX] = region.u2;
+ }
}
}
-
- ///
- /// Transforms the attachment's four vertices to world coordinates. If the attachment has a the region may
- /// be changed.
- /// The parent bone.
- /// The output world vertices. Must have a length greater than or equal to offset + 8.
- /// The worldVertices index to begin writing values.
- /// The number of worldVertices entries between the value pairs written.
- public void ComputeWorldVertices (Slot slot, float[] worldVertices, int offset, int stride = 2) {
- if (sequence != null) sequence.Apply(slot.AppliedPose, this);
-
- float[] vertexOffset = this.offset;
- BonePose bone = slot.Bone.AppliedPose;
- float bwx = bone.worldX, bwy = bone.worldY;
- float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
- float offsetX, offsetY;
-
- // Vertex order is different from RegionAttachment.java
- offsetX = vertexOffset[BRX]; // 0
- offsetY = vertexOffset[BRY]; // 1
- worldVertices[offset] = offsetX * a + offsetY * b + bwx; // bl
- worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
- offset += stride;
-
- offsetX = vertexOffset[BLX]; // 2
- offsetY = vertexOffset[BLY]; // 3
- worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ul
- worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
- offset += stride;
-
- offsetX = vertexOffset[ULX]; // 4
- offsetY = vertexOffset[ULY]; // 5
- worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ur
- worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
- offset += stride;
-
- offsetX = vertexOffset[URX]; // 6
- offsetY = vertexOffset[URY]; // 7
- worldVertices[offset] = offsetX * a + offsetY * b + bwx; // br
- worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
- //offset += stride;
- }
-
- public override Attachment Copy () {
- return new RegionAttachment(this);
- }
}
}
diff --git a/spine-csharp/src/Attachments/Sequence.cs b/spine-csharp/src/Attachments/Sequence.cs
index 42f523a22..4d4ae6dca 100644
--- a/spine-csharp/src/Attachments/Sequence.cs
+++ b/spine-csharp/src/Attachments/Sequence.cs
@@ -31,12 +31,18 @@ using System;
using System.Text;
namespace Spine {
+ ///
+ /// Holds texture regions, UVs, and vertex offsets for rendering a region or mesh attachment. must
+ /// be populated and called before use.
+ ///
public class Sequence {
static int nextID = 0;
static readonly Object nextIdLock = new Object();
internal readonly int id;
internal readonly TextureRegion[] regions;
+ internal readonly bool pathSuffix;
+ internal float[][] uvs, offsets;
internal int start, digits, setupIndex;
public int Start { get { return start; } set { start = value; } }
@@ -44,14 +50,16 @@ namespace Spine {
/// The index of the region to show for the setup pose.
public int SetupIndex { get { return setupIndex; } set { setupIndex = value; } }
public TextureRegion[] Regions { get { return regions; } }
+ public bool PathSuffix { get { return pathSuffix; } }
/// Returns a unique ID for this attachment.
public int Id { get { return id; } }
- public Sequence (int count) {
+ public Sequence (int count, bool pathSuffix) {
lock (Sequence.nextIdLock) {
id = Sequence.nextID++;
}
regions = new TextureRegion[count];
+ this.pathSuffix = pathSuffix;
}
/// Copy constructor.
@@ -59,26 +67,82 @@ namespace Spine {
lock (Sequence.nextIdLock) {
id = Sequence.nextID++;
}
- regions = new TextureRegion[other.regions.Length];
- Array.Copy(other.regions, 0, regions, 0, regions.Length);
+ int regionCount = other.regions.Length;
+ regions = new TextureRegion[regionCount];
+ Array.Copy(other.regions, 0, regions, 0, regionCount);
start = other.start;
digits = other.digits;
setupIndex = other.setupIndex;
- }
+ pathSuffix = other.pathSuffix;
- public void Apply (SlotPose slot, IHasTextureRegion attachment) {
- int index = slot.SequenceIndex;
- if (index == -1) index = setupIndex;
- if (index >= regions.Length) index = regions.Length - 1;
- TextureRegion region = regions[index];
- if (attachment.Region != region) {
- attachment.Region = region;
- attachment.UpdateRegion();
+ if (other.uvs != null) {
+ int length = other.uvs[0].Length;
+ uvs = new float[regionCount][];
+ for (int i = 0; i < regionCount; i++) {
+ uvs[i] = new float[length];
+ Array.Copy(other.uvs[i], 0, uvs[i], 0, length);
+ }
+ }
+ if (other.offsets != null) {
+ offsets = new float[regionCount][];
+ for (int i = 0; i < regionCount; i++) {
+ offsets[i] = new float[8];
+ Array.Copy(other.offsets[i], 0, offsets[i], 0, 8);
+ }
}
}
+ public void Update (IHasSequence attachment) {
+ int regionCount = regions.Length;
+ RegionAttachment region = attachment as RegionAttachment;
+ if (region != null) {
+ uvs = new float[regionCount][];
+ offsets = new float[regionCount][];
+ for (int i = 0; i < regionCount; i++) {
+ uvs[i] = new float[8];
+ offsets[i] = new float[8];
+ RegionAttachment.ComputeUVs(regions[i], region.x, region.y, region.scaleX, region.scaleY, region.rotation,
+ region.width, region.height, offsets[i], uvs[i]);
+ }
+ } else {
+ MeshAttachment mesh = attachment as MeshAttachment;
+ if (mesh != null) {
+ float[] regionUVs = mesh.regionUVs;
+ uvs = new float[regionCount][];
+ offsets = null;
+ for (int i = 0; i < regionCount; i++) {
+ uvs[i] = new float[regionUVs.Length];
+ MeshAttachment.ComputeUVs(regions[i], regionUVs, uvs[i]);
+ }
+ }
+ }
+ }
+
+ public int ResolveIndex (SlotPose pose) {
+ int index = pose.SequenceIndex;
+ if (index == -1) index = setupIndex;
+ if (index >= regions.Length) index = regions.Length - 1;
+ return index;
+ }
+
+ public TextureRegion GetRegion (int index) {
+ return regions[index];
+ }
+
+ public float[] GetUVs (int index) {
+ return uvs[index];
+ }
+
+ ///
+ /// Returns vertex offsets from the center of a . Invalid to call for a .
+ ///
+ public float[] GetOffsets (int index) {
+ return offsets[index];
+ }
+
public string GetPath (string basePath, int index) {
+ if (!pathSuffix) return basePath;
var buffer = new StringBuilder(basePath.Length + digits);
buffer.Append(basePath);
string frame = (start + index).ToString();
diff --git a/spine-csharp/src/Skeleton.cs b/spine-csharp/src/Skeleton.cs
index d341ad41a..79719c75d 100644
--- a/spine-csharp/src/Skeleton.cs
+++ b/spine-csharp/src/Skeleton.cs
@@ -459,7 +459,7 @@ namespace Spine {
verticesLength = 8;
vertices = temp;
if (vertices.Length < 8) vertices = temp = new float[8];
- region.ComputeWorldVertices(slot, vertices, 0, 2);
+ region.ComputeWorldVertices(slot, region.GetOffsets(slot.applied), vertices, 0, 2);
triangles = quadTriangles;
} else {
MeshAttachment mesh = attachment as MeshAttachment;
diff --git a/spine-csharp/src/SkeletonBinary.cs b/spine-csharp/src/SkeletonBinary.cs
index 04e97fbe8..c4016867c 100644
--- a/spine-csharp/src/SkeletonBinary.cs
+++ b/spine-csharp/src/SkeletonBinary.cs
@@ -461,7 +461,7 @@ namespace Spine {
if (parent == null) throw new Exception("Parent mesh not found: " + linkedMesh.parent);
linkedMesh.mesh.TimelineAttachment = linkedMesh.inheritTimelines ? (VertexAttachment)parent : linkedMesh.mesh;
linkedMesh.mesh.ParentMesh = (MeshAttachment)parent;
- if (linkedMesh.mesh.Region != null) linkedMesh.mesh.UpdateRegion();
+ linkedMesh.mesh.UpdateSequence();
}
linkedMeshes.Clear();
@@ -546,7 +546,7 @@ namespace Spine {
case AttachmentType.Region: {
string path = (flags & 16) != 0 ? input.ReadStringRef() : null;
uint color = (flags & 32) != 0 ? (uint)input.ReadInt() : 0xffffffff;
- Sequence sequence = (flags & 64) != 0 ? ReadSequence(input) : null;
+ Sequence sequence = ReadSequence(input, (flags & 64) != 0);
float rotation = (flags & 128) != 0 ? input.ReadFloat() : 0;
float x = input.ReadFloat();
float y = input.ReadFloat();
@@ -567,8 +567,7 @@ namespace Spine {
region.width = width * scale;
region.height = height * scale;
region.SetColor(color.RGBA8888ToColor());
- region.sequence = sequence;
- if (region.Region != null) region.UpdateRegion();
+ region.UpdateSequence();
return region;
}
case AttachmentType.Boundingbox: {
@@ -586,7 +585,7 @@ namespace Spine {
case AttachmentType.Mesh: {
string path = (flags & 16) != 0 ? input.ReadStringRef() : name;
uint color = (flags & 32) != 0 ? (uint)input.ReadInt() : 0xffffffff;
- Sequence sequence = (flags & 64) != 0 ? ReadSequence(input) : null;
+ Sequence sequence = ReadSequence(input, (flags & 64) != 0);
int hullLength = input.ReadInt(true);
Vertices vertices = ReadVertices(input, (flags & 128) != 0);
float[] uvs = ReadFloatArray(input, vertices.length, 1);
@@ -604,25 +603,24 @@ namespace Spine {
if (mesh == null) return null;
mesh.Path = path;
mesh.SetColor(color.RGBA8888ToColor());
+ mesh.HullLength = hullLength << 1;
mesh.bones = vertices.bones;
mesh.vertices = vertices.vertices;
mesh.WorldVerticesLength = vertices.length;
- mesh.triangles = triangles;
mesh.regionUVs = uvs;
- if (mesh.Region != null) mesh.UpdateRegion();
- mesh.HullLength = hullLength << 1;
- mesh.Sequence = sequence;
+ mesh.triangles = triangles;
if (nonessential) {
mesh.Edges = edges;
mesh.Width = width * scale;
mesh.Height = height * scale;
}
+ mesh.UpdateSequence();
return mesh;
}
case AttachmentType.Linkedmesh: {
string path = (flags & 16) != 0 ? input.ReadStringRef() : name;
uint color = (flags & 32) != 0 ? (uint)input.ReadInt() : 0xffffffff;
- Sequence sequence = (flags & 64) != 0 ? ReadSequence(input) : null;
+ Sequence sequence = ReadSequence(input, (flags & 64) != 0);
bool inheritTimelines = (flags & 128) != 0;
int skinIndex = input.ReadInt(true);
string parent = input.ReadStringRef();
@@ -636,7 +634,6 @@ namespace Spine {
if (mesh == null) return null;
mesh.Path = path;
mesh.SetColor(color.RGBA8888ToColor());
- mesh.Sequence = sequence;
if (nonessential) {
mesh.Width = width * scale;
mesh.Height = height * scale;
@@ -696,8 +693,9 @@ namespace Spine {
return null;
}
- private Sequence ReadSequence (SkeletonInput input) {
- var sequence = new Sequence(input.ReadInt(true));
+ private Sequence ReadSequence (SkeletonInput input, bool hasPathSuffix) {
+ if (!hasPathSuffix) return new Sequence(1, false);
+ var sequence = new Sequence(input.ReadInt(true), true);
sequence.Start = input.ReadInt(true);
sequence.Digits = input.ReadInt(true);
sequence.SetupIndex = input.ReadInt(true);
diff --git a/spine-csharp/src/SkeletonJson.cs b/spine-csharp/src/SkeletonJson.cs
index 6428b4342..2b2b67240 100644
--- a/spine-csharp/src/SkeletonJson.cs
+++ b/spine-csharp/src/SkeletonJson.cs
@@ -494,7 +494,7 @@ namespace Spine {
if (parent == null) throw new Exception("Parent mesh not found: " + linkedMesh.parent);
linkedMesh.mesh.TimelineAttachment = linkedMesh.inheritTimelines ? (VertexAttachment)parent : linkedMesh.mesh;
linkedMesh.mesh.ParentMesh = (MeshAttachment)parent;
- if (linkedMesh.mesh.Region != null) linkedMesh.mesh.UpdateRegion();
+ linkedMesh.mesh.UpdateSequence();
}
linkedMeshes.Clear();
@@ -596,14 +596,13 @@ namespace Spine {
region.rotation = GetFloat(map, "rotation", 0);
region.width = GetFloat(map, "width") * scale;
region.height = GetFloat(map, "height") * scale;
- region.sequence = sequence;
if (map.ContainsKey("color")) {
string color = (string)map["color"];
region.SetColor(ToColor32(color, 8));
}
- if (region.Region != null) region.UpdateRegion();
+ region.UpdateSequence();
return region;
}
case AttachmentType.Boundingbox:
@@ -628,7 +627,6 @@ namespace Spine {
mesh.Width = GetFloat(map, "width", 0) * scale;
mesh.Height = GetFloat(map, "height", 0) * scale;
- mesh.Sequence = sequence;
string parent = GetString(map, "parent", null);
if (parent != null) {
@@ -640,10 +638,10 @@ namespace Spine {
ReadVertices(map, mesh, uvs.Length);
mesh.triangles = GetIntArray(map, "triangles");
mesh.regionUVs = uvs;
- if (mesh.Region != null) mesh.UpdateRegion();
-
+
if (map.ContainsKey("hull")) mesh.HullLength = GetInt(map, "hull", 0) << 1;
if (map.ContainsKey("edges")) mesh.Edges = GetIntArray(map, "edges");
+ mesh.UpdateSequence();
return mesh;
}
case AttachmentType.Path: {
@@ -693,8 +691,8 @@ namespace Spine {
public static Sequence ReadSequence (object sequenceJson) {
Dictionary map = sequenceJson as Dictionary;
- if (map == null) return null;
- var sequence = new Sequence(GetInt(map, "count"));
+ if (map == null) return new Sequence(1, false);
+ var sequence = new Sequence(GetInt(map, "count"), true);
sequence.start = GetInt(map, "start", 1);
sequence.digits = GetInt(map, "digits", 0);
sequence.setupIndex = GetInt(map, "setup", 0);
diff --git a/spine-csharp/src/package.json b/spine-csharp/src/package.json
index 9959001ff..0c0ea0376 100644
--- a/spine-csharp/src/package.json
+++ b/spine-csharp/src/package.json
@@ -2,7 +2,7 @@
"name": "com.esotericsoftware.spine.spine-csharp",
"displayName": "spine-csharp Runtime",
"description": "This plugin provides the spine-csharp core runtime.",
- "version": "4.3.12",
+ "version": "4.3.13",
"unity": "2018.3",
"author": {
"name": "Esoteric Software",
diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs
index ef9d1841f..11516abb0 100644
--- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs
+++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/AssetUtility.cs
@@ -300,24 +300,14 @@ namespace Spine.Unity.Editor {
}
public RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence) {
- RegionAttachment regionAttachment = new RegionAttachment(name);
- if (sequence != null)
- LoadSequence(path, sequence);
- else {
- requirementList.Add(path);
- AssignDummyRegion(regionAttachment);
- }
+ RegionAttachment regionAttachment = new RegionAttachment(name, sequence);
+ LoadSequence(path, sequence);
return regionAttachment;
}
public MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence) {
- MeshAttachment meshAttachment = new MeshAttachment(name);
- if (sequence != null)
- LoadSequence(path, sequence);
- else {
- requirementList.Add(path);
- AssignDummyRegion(meshAttachment);
- }
+ MeshAttachment meshAttachment = new MeshAttachment(name, sequence);
+ LoadSequence(path, sequence);
return meshAttachment;
}
@@ -344,10 +334,6 @@ namespace Spine.Unity.Editor {
requirementList.Add(path);
}
}
-
- private static void AssignDummyRegion (IHasTextureRegion attachment) {
- attachment.Region = new AtlasRegion();
- }
}
#endregion
diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs
index 8948f3479..31a0764b9 100644
--- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs
+++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs
@@ -520,8 +520,10 @@ namespace Spine.Unity.Editor {
bone.AppliedPose.UpdateWorldTransform(skeleton);
float[] floatVerts = new float[8];
- attachment.ComputeWorldVertices(slot, floatVerts, 0);
- Vector2[] uvs = ExtractUV(attachment.UVs);
+ Sequence sequence = attachment.Sequence;
+ int sequenceIndex = 0;
+ attachment.ComputeWorldVertices(slot, sequence.GetOffsets(sequenceIndex), floatVerts, 0);
+ Vector2[] uvs = ExtractUV(sequence.GetUVs(sequenceIndex));
Vector3[] verts = ExtractVerts(floatVerts);
//unrotate verts now that they're centered
@@ -559,7 +561,10 @@ namespace Spine.Unity.Editor {
float[] floatVerts = new float[attachment.WorldVerticesLength];
attachment.ComputeWorldVertices(skeleton, slot, floatVerts);
- Vector2[] uvs = ExtractUV(attachment.UVs);
+
+ Sequence sequence = attachment.Sequence;
+ int sequenceIndex = 0;
+ Vector2[] uvs = ExtractUV(sequence.GetUVs(sequenceIndex));
Vector3[] verts = ExtractVerts(floatVerts);
int[] triangles = attachment.Triangles;
@@ -624,7 +629,10 @@ namespace Spine.Unity.Editor {
float[] floatVerts = new float[attachment.WorldVerticesLength];
attachment.ComputeWorldVertices(skeleton, skeleton.Slots.Items[slotIndex], floatVerts);
- Vector2[] uvs = ExtractUV(attachment.UVs);
+
+ Sequence sequence = attachment.Sequence;
+ int sequenceIndex = 0;
+ Vector2[] uvs = ExtractUV(sequence.GetUVs(sequenceIndex));
Vector3[] verts = ExtractVerts(floatVerts);
int[] triangles = attachment.Triangles;
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/BlendModeMaterials.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/BlendModeMaterials.cs
index 58fd28116..feb1299fa 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/BlendModeMaterials.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/BlendModeMaterials.cs
@@ -88,7 +88,7 @@ namespace Spine.Unity {
skin.GetAttachments(slotIndex, skinEntries);
foreach (Skin.SkinEntry entry in skinEntries) {
- if (entry.Attachment is IHasTextureRegion) {
+ if (entry.Attachment is IHasSequence) {
requiresBlendModeMaterials = true;
return true;
}
@@ -165,22 +165,15 @@ namespace Spine.Unity {
skin.GetAttachments(slotIndex, skinEntries);
foreach (Skin.SkinEntry entry in skinEntries) {
- IHasTextureRegion renderableAttachment = entry.Attachment as IHasTextureRegion;
+ IHasSequence renderableAttachment = entry.Attachment as IHasSequence;
if (renderableAttachment != null) {
- AtlasRegion originalRegion = (AtlasRegion)renderableAttachment.Region;
- if (originalRegion != null) {
- anyCreationFailed |= createForRegionFunc(
- ref replacementMaterials, ref anyReplacementMaterialsChanged,
- originalRegion, materialTemplate, materialSuffix, skeletonDataAsset);
- } else {
- Sequence sequence = renderableAttachment.Sequence;
- if (sequence != null && sequence.Regions != null) {
- for (int i = 0, count = sequence.Regions.Length; i < count; ++i) {
- originalRegion = (AtlasRegion)sequence.Regions[i];
- anyCreationFailed |= createForRegionFunc(
- ref replacementMaterials, ref anyReplacementMaterialsChanged,
- originalRegion, materialTemplate, materialSuffix, skeletonDataAsset);
- }
+ Sequence sequence = renderableAttachment.Sequence;
+ if (sequence != null && sequence.Regions != null) {
+ for (int i = 0, count = sequence.Regions.Length; i < count; ++i) {
+ AtlasRegion originalRegion = (AtlasRegion)sequence.Regions[i];
+ anyCreationFailed |= createForRegionFunc(
+ ref replacementMaterials, ref anyReplacementMaterialsChanged,
+ originalRegion, materialTemplate, materialSuffix, skeletonDataAsset);
}
}
}
@@ -268,20 +261,12 @@ namespace Spine.Unity {
skin.GetAttachments(slotIndex, skinEntries);
foreach (Skin.SkinEntry entry in skinEntries) {
- IHasTextureRegion renderableAttachment = entry.Attachment as IHasTextureRegion;
+ IHasSequence renderableAttachment = entry.Attachment as IHasSequence;
if (renderableAttachment != null) {
- if (renderableAttachment.Sequence != null) {
- TextureRegion[] regions = renderableAttachment.Sequence.Regions;
- for (int i = 0; i < regions.Length; ++i) {
- regions[i] = CloneAtlasRegionWithMaterial(
- (AtlasRegion)regions[i], replacementMaterials);
- }
- if (regions.Length > 0) {
- renderableAttachment.Region = regions[0];
- }
- } else if (renderableAttachment.Region != null) {
- renderableAttachment.Region = CloneAtlasRegionWithMaterial(
- (AtlasRegion)renderableAttachment.Region, replacementMaterials);
+ TextureRegion[] regions = renderableAttachment.Sequence.Regions;
+ for (int i = 0; i < regions.Length; ++i) {
+ regions[i] = CloneAtlasRegionWithMaterial(
+ (AtlasRegion)regions[i], replacementMaterials);
}
}
}
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/RegionlessAttachmentLoader.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/RegionlessAttachmentLoader.cs
index 974606098..9a765d53b 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/RegionlessAttachmentLoader.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/RegionlessAttachmentLoader.cs
@@ -57,16 +57,12 @@ namespace Spine.Unity {
}
public RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence) {
- RegionAttachment attachment = new RegionAttachment(name) {
- Region = EmptyRegion
- };
+ RegionAttachment attachment = new RegionAttachment(name, new Sequence(1, false));
return attachment;
}
public MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence) {
- MeshAttachment attachment = new MeshAttachment(name) {
- Region = EmptyRegion
- };
+ MeshAttachment attachment = new MeshAttachment(name, new Sequence(1, false));
return attachment;
}
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs
index d68965fed..f098781a2 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Mesh Generation/MeshGenerator.cs
@@ -254,15 +254,17 @@ namespace Spine.Unity {
RegionAttachment regionAttachment = attachment as RegionAttachment;
if (regionAttachment != null) {
- if (regionAttachment.Sequence != null) regionAttachment.Sequence.Apply(slot.AppliedPose, regionAttachment);
- rendererObject = regionAttachment.Region;
+ Sequence sequence = regionAttachment.Sequence;
+ int sequenceIndex = sequence.ResolveIndex(slot.AppliedPose);
+ rendererObject = sequence.GetRegion(sequenceIndex);
attachmentVertexCount = 4;
attachmentTriangleCount = 6;
} else {
MeshAttachment meshAttachment = attachment as MeshAttachment;
if (meshAttachment != null) {
- if (meshAttachment.Sequence != null) meshAttachment.Sequence.Apply(slot.AppliedPose, meshAttachment);
- rendererObject = meshAttachment.Region;
+ Sequence sequence = meshAttachment.Sequence;
+ int sequenceIndex = sequence.ResolveIndex(slot.AppliedPose);
+ rendererObject = sequence.GetRegion(sequenceIndex);
attachmentVertexCount = meshAttachment.WorldVerticesLength >> 1;
attachmentTriangleCount = meshAttachment.Triangles.Length;
} else {
@@ -323,10 +325,11 @@ namespace Spine.Unity {
#endif
) continue;
Attachment attachment = slot.AppliedPose.Attachment;
- IHasTextureRegion rendererAttachment = attachment as IHasTextureRegion;
+ IHasSequence rendererAttachment = attachment as IHasSequence;
if (rendererAttachment != null) {
- if (rendererAttachment.Sequence != null) rendererAttachment.Sequence.Apply(slot.AppliedPose, rendererAttachment);
- AtlasRegion atlasRegion = (AtlasRegion)rendererAttachment.Region;
+ Sequence sequence = rendererAttachment.Sequence;
+ int sequenceIndex = sequence.ResolveIndex(slot.AppliedPose);
+ AtlasRegion atlasRegion = (AtlasRegion)sequence.GetRegion(sequenceIndex);
Material material = (Material)atlasRegion.page.rendererObject;
if (lastRendererMaterial != material) {
if (lastRendererMaterial != null)
@@ -399,8 +402,9 @@ namespace Spine.Unity {
RegionAttachment regionAttachment = attachment as RegionAttachment;
if (regionAttachment != null) {
- if (regionAttachment.Sequence != null) regionAttachment.Sequence.Apply(slot.AppliedPose, regionAttachment);
- region = regionAttachment.Region;
+ Sequence sequence = regionAttachment.Sequence;
+ int sequenceIndex = sequence.ResolveIndex(slot.AppliedPose);
+ region = sequence.GetRegion(sequenceIndex);
#if SPINE_TRIANGLECHECK
attachmentVertexCount = 4;
attachmentTriangleCount = 6;
@@ -408,8 +412,9 @@ namespace Spine.Unity {
} else {
MeshAttachment meshAttachment = attachment as MeshAttachment;
if (meshAttachment != null) {
- if (meshAttachment.Sequence != null) meshAttachment.Sequence.Apply(slot.AppliedPose, meshAttachment);
- region = meshAttachment.Region;
+ Sequence sequence = meshAttachment.Sequence;
+ int sequenceIndex = sequence.ResolveIndex(slot.AppliedPose);
+ region = sequence.GetRegion(sequenceIndex);
#if SPINE_TRIANGLECHECK
attachmentVertexCount = meshAttachment.WorldVerticesLength >> 1;
attachmentTriangleCount = meshAttachment.Triangles.Length;
@@ -620,8 +625,10 @@ namespace Spine.Unity {
// Identify and prepare values.
RegionAttachment region = attachment as RegionAttachment;
if (region != null) {
- region.ComputeWorldVertices(slot, workingVerts, 0);
- uvs = region.UVs;
+ Sequence sequence = region.Sequence;
+ int sequenceIndex = sequence.ResolveIndex(slotPose);
+ region.ComputeWorldVertices(slot, sequence.GetOffsets(sequenceIndex), workingVerts, 0);
+ uvs = sequence.GetUVs(sequenceIndex);
attachmentTriangleIndices = regionTriangles;
regionC = region.GetColor();
attachmentVertexCount = 4;
@@ -634,8 +641,10 @@ namespace Spine.Unity {
workingVerts = new float[meshVerticesLength];
this.tempVerts = workingVerts;
}
- mesh.ComputeWorldVertices(skeleton, slot, 0, meshVerticesLength, workingVerts, 0); //meshAttachment.ComputeWorldVertices(slot, tempVerts);
- uvs = mesh.UVs;
+ Sequence sequence = mesh.Sequence;
+ int sequenceIndex = sequence.ResolveIndex(slotPose);
+ mesh.ComputeWorldVertices(skeleton, slot, 0, meshVerticesLength, workingVerts, 0);
+ uvs = sequence.GetUVs(sequenceIndex);
attachmentTriangleIndices = mesh.Triangles;
regionC = mesh.GetColor();
attachmentVertexCount = meshVerticesLength >> 1; // meshVertexCount / 2;
@@ -942,7 +951,10 @@ namespace Spine.Unity {
RegionAttachment regionAttachment = attachment as RegionAttachment;
if (regionAttachment != null) {
- regionAttachment.ComputeWorldVertices(slot, tempVerts, 0);
+ Sequence sequence = regionAttachment.Sequence;
+ int sequenceIndex = sequence.ResolveIndex(slotPose);
+ regionAttachment.ComputeWorldVertices(slot, sequence.GetOffsets(sequenceIndex), tempVerts, 0);
+
Color regionC = regionAttachment.GetColor();
Color combinedC = skeletonC * slotC * regionC;
@@ -978,7 +990,7 @@ namespace Spine.Unity {
cbi[vertexIndex] = color; cbi[vertexIndex + 1] = color; cbi[vertexIndex + 2] = color; cbi[vertexIndex + 3] = color;
- float[] regionUVs = regionAttachment.UVs;
+ float[] regionUVs = sequence.GetUVs(sequenceIndex);
ubi[vertexIndex] = new Vector2(regionUVs[RegionAttachment.BLX], regionUVs[RegionAttachment.BLY]);
ubi[vertexIndex + 1] = new Vector2(regionUVs[RegionAttachment.BRX], regionUVs[RegionAttachment.BRY]);
ubi[vertexIndex + 2] = new Vector2(regionUVs[RegionAttachment.ULX], regionUVs[RegionAttachment.ULY]);
@@ -1032,7 +1044,9 @@ namespace Spine.Unity {
color.b = (byte)(combinedC.b * 255);
}
- float[] attachmentUVs = meshAttachment.UVs;
+ Sequence sequence = meshAttachment.Sequence;
+ int sequenceIndex = sequence.ResolveIndex(slotPose);
+ float[] attachmentUVs = sequence.GetUVs(sequenceIndex);
// Potential first attachment bounds initialization. See conditions in RegionAttachment logic.
if (vertexIndex == 0) {
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/TK2D/SpriteCollectionAttachmentLoader.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/TK2D/SpriteCollectionAttachmentLoader.cs
index 6b9ed0b76..7a9bea0a1 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/TK2D/SpriteCollectionAttachmentLoader.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Modules/TK2D/SpriteCollectionAttachmentLoader.cs
@@ -134,31 +134,13 @@ namespace Spine.Unity.TK2D {
}
public RegionAttachment NewRegionAttachment (Skin skin, String name, String path, Sequence sequence) {
- RegionAttachment attachment = new RegionAttachment(name);
- if (sequence != null)
- LoadSequence(name, path, sequence);
- else {
- AtlasRegion region = ProcessSpriteDefinition(path);
- if (region == null)
- throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
- attachment.Region = region;
- attachment.Path = path;
- }
- return attachment;
+ LoadSequence(name, path, sequence);
+ return new RegionAttachment(name, sequence);
}
public MeshAttachment NewMeshAttachment (Skin skin, String name, String path, Sequence sequence) {
- MeshAttachment attachment = new MeshAttachment(name);
- if (sequence != null)
- LoadSequence(name, path, sequence);
- else {
- AtlasRegion region = ProcessSpriteDefinition(path);
- if (region == null)
- throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
- attachment.Region = region;
- attachment.Path = path;
- }
- return attachment;
+ LoadSequence(name, path, sequence);
+ return new MeshAttachment(name, sequence);
}
public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name) {
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonDataModifierAssets/BlendModeMaterials/BlendModeMaterialsAsset.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonDataModifierAssets/BlendModeMaterials/BlendModeMaterialsAsset.cs
index 3e34b7d9f..5239cafb7 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonDataModifierAssets/BlendModeMaterials/BlendModeMaterialsAsset.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonDataModifierAssets/BlendModeMaterials/BlendModeMaterialsAsset.cs
@@ -77,10 +77,12 @@ namespace Spine.Unity {
if (templateMaterial == null) continue;
foreach (Skin.SkinEntry entry in entryBuffer) {
- IHasTextureRegion renderableAttachment = entry.Attachment as IHasTextureRegion;
- if (renderableAttachment != null) {
- renderableAttachment.Region = materialCache.CloneAtlasRegionWithMaterial(
- (AtlasRegion)renderableAttachment.Region, templateMaterial);
+ IHasSequence renderableAttachment = entry.Attachment as IHasSequence;
+ if (renderableAttachment == null) continue;
+ TextureRegion[] regions = renderableAttachment.Sequence.Regions;
+ for (int i = 0; i < regions.Length; ++i) {
+ regions[i] = materialCache.CloneAtlasRegionWithMaterial(
+ (AtlasRegion)regions[i], templateMaterial);
}
}
}
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs
index 5123317b3..9285fef0f 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs
@@ -498,7 +498,8 @@ namespace Spine.Unity.AttachmentTools {
}
originalRegions.Clear();
- if (!object.ReferenceEquals(sourceAttachments, outputAttachments)) {
+ bool isInPlaceOperation = object.ReferenceEquals(sourceAttachments, outputAttachments);
+ if (!isInPlaceOperation) {
outputAttachments.Clear();
outputAttachments.AddRange(sourceAttachments);
}
@@ -507,40 +508,22 @@ namespace Spine.Unity.AttachmentTools {
for (int attachmentIndex = 0, n = sourceAttachments.Count; attachmentIndex < n; attachmentIndex++) {
Attachment originalAttachment = sourceAttachments[attachmentIndex];
- if (originalAttachment is IHasTextureRegion) {
- MeshAttachment originalMeshAttachment = originalAttachment as MeshAttachment;
- IHasTextureRegion originalTextureAttachment = (IHasTextureRegion)originalAttachment;
-
- Attachment newAttachment = (originalTextureAttachment.Sequence != null) ? originalAttachment :
- (originalMeshAttachment != null) ? originalMeshAttachment.NewLinkedMesh() :
- originalAttachment.Copy();
- IHasTextureRegion newTextureAttachment = (IHasTextureRegion)newAttachment;
- AtlasRegion region = newTextureAttachment.Region as AtlasRegion;
- if (region == null && originalTextureAttachment.Sequence != null)
- region = (AtlasRegion)originalTextureAttachment.Sequence.Regions[0];
-
+ if (originalAttachment is IHasSequence) {
+ IHasSequence originalTextureAttachment = (IHasSequence)originalAttachment;
+ Attachment newAttachment = originalAttachment.Copy();
+ AtlasRegion firstRegion = (AtlasRegion)originalTextureAttachment.Sequence.Regions[0];
int existingIndex;
- if (existingRegions.TryGetValue(region, out existingIndex)) {
+ if (existingRegions.TryGetValue(firstRegion, out existingIndex)) {
regionIndices.Add(existingIndex);
} else {
- existingRegions.Add(region, newRegionIndex);
+ existingRegions.Add(firstRegion, newRegionIndex);
Sequence originalSequence = originalTextureAttachment.Sequence;
- if (originalSequence != null) {
- newTextureAttachment.Sequence = new Sequence(originalSequence);
- for (int i = 0, regionCount = originalSequence.Regions.Length; i < regionCount; ++i) {
- AtlasRegion sequenceRegion = (AtlasRegion)originalSequence.Regions[i];
- AddRegionTexturesToPack(numTextureParamsToRepack, sequenceRegion,
- settings.textureFormat, settings.mipmaps, settings.additionalTextureFormats,
- settings.additionalTexturePropertyIDsToCopy, settings.additionalTextureIsLinear);
- originalRegions.Add(sequenceRegion);
- regionIndices.Add(newRegionIndex);
- newRegionIndex++;
- }
- } else {
- AddRegionTexturesToPack(numTextureParamsToRepack, region,
+ for (int i = 0, regionCount = originalSequence.Regions.Length; i < regionCount; ++i) {
+ AtlasRegion sequenceRegion = (AtlasRegion)originalSequence.Regions[i];
+ AddRegionTexturesToPack(numTextureParamsToRepack, sequenceRegion,
settings.textureFormat, settings.mipmaps, settings.additionalTextureFormats,
settings.additionalTexturePropertyIDsToCopy, settings.additionalTextureIsLinear);
- originalRegions.Add(region);
+ originalRegions.Add(sequenceRegion);
regionIndices.Add(newRegionIndex);
newRegionIndex++;
}
@@ -616,32 +599,24 @@ namespace Spine.Unity.AttachmentTools {
// Map the cloned attachments to the repacked atlas.
for (int attachmentIndex = 0, repackedIndex = 0, n = outputAttachments.Count;
- attachmentIndex < n;
- ++attachmentIndex, ++repackedIndex) {
+ attachmentIndex < n; ++attachmentIndex, ++repackedIndex) {
Attachment attachment = outputAttachments[attachmentIndex];
- IHasTextureRegion textureAttachment = attachment as IHasTextureRegion;
+ IHasSequence textureAttachment = attachment as IHasSequence;
if (textureAttachment != null) {
- if (textureAttachment.Sequence != null) {
- TextureRegion[] regions = textureAttachment.Sequence.Regions;
- for (int r = 0, regionCount = regions.Length; r < regionCount; ++r) {
- TextureRegion originalRegion = regions[r];
- TextureRegion repackedRegion = repackedRegions[regionIndices[repackedIndex++]];
+ TextureRegion[] regions = textureAttachment.Sequence.Regions;
+ for (int r = 0, regionCount = regions.Length; r < regionCount; ++r) {
+ TextureRegion originalRegion = regions[r];
+ TextureRegion repackedRegion = repackedRegions[regionIndices[repackedIndex++]];
+ if (enableBlendModes) {
AssignBlendMode(ref repackedRegion, originalRegion, normalShader, ref blendModePages,
additiveMaterialSource, multiplyMaterialSource, screenMaterialSource);
- regions[r] = repackedRegion;
}
- textureAttachment.Region = regions[0];
- --repackedIndex;
- } else {
- TextureRegion originalRegion = textureAttachment.Region;
- TextureRegion repackedRegion = repackedRegions[regionIndices[repackedIndex]];
- if (enableBlendModes)
- AssignBlendMode(ref repackedRegion, originalRegion, normalShader, ref blendModePages,
- additiveMaterialSource, multiplyMaterialSource, screenMaterialSource);
- textureAttachment.Region = repackedRegion;
+ regions[r] = repackedRegion;
}
- textureAttachment.UpdateRegion();
+ --repackedIndex;
+
+ textureAttachment.UpdateSequence();
}
}
@@ -1075,7 +1050,7 @@ namespace Spine.Unity.AttachmentTools {
}
static bool IsRenderable (Attachment a) {
- return a is IHasTextureRegion;
+ return a is IHasSequence;
}
///
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentRegionExtensions.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentRegionExtensions.cs
index b86bfb8f3..b895c6880 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentRegionExtensions.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AttachmentRegionExtensions.cs
@@ -74,9 +74,10 @@ namespace Spine.Unity.AttachmentTools {
if (region == null) throw new System.ArgumentNullException("region");
// (AtlasAttachmentLoader.cs)
- RegionAttachment attachment = new RegionAttachment(attachmentName);
+ Sequence sequence = new Sequence(1, false);
+ sequence.Regions[0] = region;
+ RegionAttachment attachment = new RegionAttachment(attachmentName, sequence);
- attachment.Region = region;
attachment.Path = region.name;
attachment.ScaleX = 1;
attachment.ScaleY = 1;
@@ -84,15 +85,11 @@ namespace Spine.Unity.AttachmentTools {
attachment.SetColor(Color.white);
// pass OriginalWidth and OriginalHeight because UpdateOffset uses it in its calculation.
- TextureRegion textreRegion = attachment.Region;
- AtlasRegion atlasRegion = textreRegion as AtlasRegion;
- float originalWidth = atlasRegion != null ? atlasRegion.originalWidth : textreRegion.width;
- float originalHeight = atlasRegion != null ? atlasRegion.originalHeight : textreRegion.height;
- attachment.Width = originalWidth * scale;
- attachment.Height = originalHeight * scale;
+ attachment.Width = region.originalWidth * scale;
+ attachment.Height = region.originalHeight * scale;
attachment.SetColor(Color.white);
- attachment.UpdateRegion();
+ attachment.UpdateSequence();
return attachment;
}
@@ -166,8 +163,10 @@ namespace Spine.Unity.AttachmentTools {
float scale = 1f / sprite.pixelsPerUnit;
if (useOriginalRegionScale) {
RegionAttachment regionAttachment = attachment as RegionAttachment;
- if (regionAttachment != null)
- scale = regionAttachment.Width / regionAttachment.Region.OriginalWidth;
+ if (regionAttachment != null) {
+ var firstRegion = regionAttachment.Sequence.GetRegion(0);
+ scale = regionAttachment.Width / firstRegion.OriginalWidth;
+ }
}
attachment.SetRegion(atlasRegion, useOriginalRegionSize, scale);
}
@@ -181,17 +180,18 @@ namespace Spine.Unity.AttachmentTools {
public static void SetRegion (this Attachment attachment, AtlasRegion atlasRegion, bool useOriginalRegionSize = false, float scale = 0.01f) {
RegionAttachment regionAttachment = attachment as RegionAttachment;
if (regionAttachment != null) {
- regionAttachment.Region = atlasRegion;
+
+ regionAttachment.Sequence.Regions[0] = atlasRegion;
if (!useOriginalRegionSize) {
regionAttachment.Width = atlasRegion.width * scale;
regionAttachment.Height = atlasRegion.height * scale;
}
- regionAttachment.UpdateRegion();
+ regionAttachment.UpdateSequence();
} else {
MeshAttachment meshAttachment = attachment as MeshAttachment;
if (meshAttachment != null) {
- meshAttachment.Region = atlasRegion;
- meshAttachment.UpdateRegion();
+ meshAttachment.Sequence.Regions[0] = atlasRegion;
+ meshAttachment.UpdateSequence();
}
}
}
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkeletonExtensions.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkeletonExtensions.cs
index deb62c3b7..65ada4075 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkeletonExtensions.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkeletonExtensions.cs
@@ -229,9 +229,10 @@ namespace Spine.Unity {
#region Attachments
public static Material GetMaterial (this Attachment a) {
object rendererObject = null;
- IHasTextureRegion renderableAttachment = a as IHasTextureRegion;
- if (renderableAttachment != null)
- rendererObject = renderableAttachment.Region;
+ IHasSequence renderableAttachment = a as IHasSequence;
+ if (renderableAttachment != null) {
+ rendererObject = renderableAttachment.Sequence.Regions[0];
+ }
if (rendererObject == null)
return null;
diff --git a/spine-unity/Assets/Spine/package.json b/spine-unity/Assets/Spine/package.json
index 139e04bab..b39b5c6ce 100644
--- a/spine-unity/Assets/Spine/package.json
+++ b/spine-unity/Assets/Spine/package.json
@@ -2,7 +2,7 @@
"name": "com.esotericsoftware.spine.spine-unity",
"displayName": "spine-unity Runtime",
"description": "This plugin provides the spine-unity runtime core and examples. Spine Examples can be installed via the Samples tab.",
- "version": "4.3.53",
+ "version": "4.3.54",
"unity": "2018.3",
"author": {
"name": "Esoteric Software",