diff --git a/spine-csharp/src/Animation.cs b/spine-csharp/src/Animation.cs
index 9989f4861..a0589396f 100644
--- a/spine-csharp/src/Animation.cs
+++ b/spine-csharp/src/Animation.cs
@@ -52,7 +52,7 @@ namespace Spine {
/// The duration of the animation in seconds, which is the highest time of all keys in the timeline.
public float Duration { get { return duration; } set { duration = value; } }
- /// The animation's name, which is unique within the skeleton.
+ /// The animation's name, which is unique across all animations in the skeleton.
public string Name { get { return name; } }
/// Applies all the animation's timelines to the specified skeleton.
diff --git a/spine-csharp/src/Attachments/RegionAttachment.cs b/spine-csharp/src/Attachments/RegionAttachment.cs
index f591de110..021069298 100644
--- a/spine-csharp/src/Attachments/RegionAttachment.cs
+++ b/spine-csharp/src/Attachments/RegionAttachment.cs
@@ -195,8 +195,8 @@ namespace Spine {
copy.rotation = rotation;
copy.width = width;
copy.height = height;
- Array.Copy(uvs, 0, copy.uvs, 0, uvs.Length);
- Array.Copy(offset, 0, copy.offset, 0, offset.Length);
+ Array.Copy(uvs, 0, copy.uvs, 0, 8);
+ Array.Copy(offset, 0, copy.offset, 0, 8);
return copy;
}
}
diff --git a/spine-csharp/src/Attachments/VertexAttachment.cs b/spine-csharp/src/Attachments/VertexAttachment.cs
index d951248b8..71bb42ea0 100644
--- a/spine-csharp/src/Attachments/VertexAttachment.cs
+++ b/spine-csharp/src/Attachments/VertexAttachment.cs
@@ -133,8 +133,7 @@ namespace Spine {
return this == sourceAttachment;
}
- ///Internal method used by VertexAttachment subclasses to copy basic data. Does not copy id (generated) and name (set on
- /// construction).
+ ///Does not copy id (generated) or name (set on construction).
internal void CopyTo (VertexAttachment attachment) {
if (bones != null) {
attachment.bones = new int[bones.Length];
diff --git a/spine-csharp/src/Bone.cs b/spine-csharp/src/Bone.cs
index 79dcdf5b3..a91d3978e 100644
--- a/spine-csharp/src/Bone.cs
+++ b/spine-csharp/src/Bone.cs
@@ -52,7 +52,7 @@ namespace Spine {
internal float a, b, worldX;
internal float c, d, worldY;
- internal bool sorted;
+ internal bool sorted, update;
public BoneData Data { get { return data; } }
public Skeleton Skeleton { get { return skeleton; } }
diff --git a/spine-csharp/src/BoneData.cs b/spine-csharp/src/BoneData.cs
index 40eef4ac1..9c80fbe74 100644
--- a/spine-csharp/src/BoneData.cs
+++ b/spine-csharp/src/BoneData.cs
@@ -37,11 +37,12 @@ namespace Spine {
internal float length;
internal float x, y, rotation, scaleX = 1, scaleY = 1, shearX, shearY;
internal TransformMode transformMode = TransformMode.Normal;
+ internal bool skinRequired;
/// The index of the bone in Skeleton.Bones
public int Index { get { return index; } }
- /// The name of the bone, which is unique within the skeleton.
+ /// The name of the bone, which is unique across all bones in the skeleton.
public string Name { get { return name; } }
/// May be null.
@@ -73,6 +74,11 @@ namespace Spine {
/// The transform mode for how parent world transforms affect this bone.
public TransformMode TransformMode { get { return transformMode; } set { transformMode = value; } }
+ ///When true, only updates this bone if the contains this
+ /// bone.
+ ///
+ public bool SkinRequired { get { return skinRequired; } set { skinRequired = value; } }
+
/// May be null.
public BoneData (int index, string name, BoneData parent) {
if (index < 0) throw new ArgumentException("index must be >= 0", "index");
diff --git a/spine-csharp/src/IConstraint.cs b/spine-csharp/src/ConstraintData.cs
similarity index 59%
rename from spine-csharp/src/IConstraint.cs
rename to spine-csharp/src/ConstraintData.cs
index 8f17c0439..7f50cc5fa 100644
--- a/spine-csharp/src/IConstraint.cs
+++ b/spine-csharp/src/ConstraintData.cs
@@ -27,13 +27,36 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
-namespace Spine {
-
- /// The interface for all constraints.
- public interface IConstraint : IUpdatable {
- /// The ordinal for the order a skeleton's constraints will be applied.
- int Order { get; }
+using System;
+using System.Collections.Generic;
+namespace Spine
+{
+ /// The base class for all constraint datas.
+ public abstract class ConstraintData {
+ internal readonly string name;
+ internal int order;
+ internal bool skinRequired;
+
+ public ConstraintData (string name) {
+ if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
+ this.name = name;
+ }
+
+ /// The constraint's name, which is unique across all constraints in the skeleton of the same type.
+ public string Name { get { return name; } }
+
+ ///The ordinal of this constraint for the order a skeleton's constraints will be applied by
+ /// .
+ public int Order { get { return order; } set { order = value; } }
+
+ ///When true, only updates this constraint if the contains
+ /// this constraint.
+ ///
+ public bool SkinRequired { get { return skinRequired; } set { skinRequired = value; } }
+
+ override public string ToString () {
+ return name;
+ }
}
-
}
diff --git a/spine-csharp/src/EventData.cs b/spine-csharp/src/EventData.cs
index 26bca7efc..2f1928d77 100644
--- a/spine-csharp/src/EventData.cs
+++ b/spine-csharp/src/EventData.cs
@@ -34,7 +34,7 @@ namespace Spine {
public class EventData {
internal string name;
- /// The name of the event, which is unique within the skeleton.
+ /// The name of the event, which is unique across all events in the skeleton.
public string Name { get { return name; } }
public int Int { get; set; }
public float Float { get; set; }
diff --git a/spine-csharp/src/IkConstraint.cs b/spine-csharp/src/IkConstraint.cs
index 8b5ba1a36..92b51f2a7 100644
--- a/spine-csharp/src/IkConstraint.cs
+++ b/spine-csharp/src/IkConstraint.cs
@@ -37,7 +37,7 @@ namespace Spine {
///
/// See IK constraints in the Spine User Guide.
///
- public class IkConstraint : IConstraint {
+ public class IkConstraint : IUpdatable {
internal IkConstraintData data;
internal ExposedList bones = new ExposedList();
internal Bone target;
@@ -93,11 +93,6 @@ namespace Spine {
}
}
-
- public int Order {
- get { return data.order; }
- }
-
/// The bones that will be modified by this IK constraint.
public ExposedList Bones {
get { return bones; }
diff --git a/spine-csharp/src/IkConstraintData.cs b/spine-csharp/src/IkConstraintData.cs
index 5a4f7fca7..de231a39e 100644
--- a/spine-csharp/src/IkConstraintData.cs
+++ b/spine-csharp/src/IkConstraintData.cs
@@ -32,23 +32,14 @@ using System.Collections.Generic;
namespace Spine {
/// Stores the setup pose for an IkConstraint.
- public class IkConstraintData {
- internal string name;
- internal int order;
+ public class IkConstraintData : ConstraintData {
internal List bones = new List();
internal BoneData target;
internal int bendDirection = 1;
internal bool compress, stretch, uniform;
internal float mix = 1;
- /// The IK constraint's name, which is unique within the skeleton.
- public string Name {
- get { return name; }
- }
-
- public int Order {
- get { return order; }
- set { order = value; }
+ public IkConstraintData (string name) : base(name) {
}
/// The bones that are constrained by this IK Constraint.
@@ -98,14 +89,5 @@ namespace Spine {
get { return uniform; }
set { uniform = value; }
}
-
- public IkConstraintData (string name) {
- if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
- this.name = name;
- }
-
- override public string ToString () {
- return name;
- }
}
}
diff --git a/spine-csharp/src/PathConstraint.cs b/spine-csharp/src/PathConstraint.cs
index 74bd08a2c..efaa29a7d 100644
--- a/spine-csharp/src/PathConstraint.cs
+++ b/spine-csharp/src/PathConstraint.cs
@@ -38,7 +38,7 @@ namespace Spine {
///
/// See Path constraints in the Spine User Guide.
///
- public class PathConstraint : IConstraint {
+ public class PathConstraint : IUpdatable {
const int NONE = -1, BEFORE = -2, AFTER = -3;
const float Epsilon = 0.00001f;
@@ -446,7 +446,6 @@ namespace Spine {
}
}
- public int Order { get { return data.order; } }
/// The position along the path.
public float Position { get { return position; } set { position = value; } }
/// The spacing between bones.
@@ -461,9 +460,5 @@ namespace Spine {
public Slot Target { get { return target; } set { target = value; } }
/// The path constraint's setup pose data.
public PathConstraintData Data { get { return data; } }
-
- override public string ToString () {
- return data.name;
- }
}
}
diff --git a/spine-csharp/src/PathConstraintData.cs b/spine-csharp/src/PathConstraintData.cs
index 924c99a06..a8f5a4e44 100644
--- a/spine-csharp/src/PathConstraintData.cs
+++ b/spine-csharp/src/PathConstraintData.cs
@@ -30,9 +30,7 @@
using System;
namespace Spine {
- public class PathConstraintData {
- internal string name;
- internal int order;
+ public class PathConstraintData : ConstraintData {
internal ExposedList bones = new ExposedList();
internal SlotData target;
internal PositionMode positionMode;
@@ -41,8 +39,9 @@ namespace Spine {
internal float offsetRotation;
internal float position, spacing, rotateMix, translateMix;
- public string Name { get { return name; } }
- public int Order { get { return order; } set { order = value; } }
+ public PathConstraintData (string name) : base(name) {
+ }
+
public ExposedList Bones { get { return bones; } }
public SlotData Target { get { return target; } set { target = value; } }
public PositionMode PositionMode { get { return positionMode; } set { positionMode = value; } }
@@ -53,15 +52,6 @@ namespace Spine {
public float Spacing { get { return spacing; } set { spacing = value; } }
public float RotateMix { get { return rotateMix; } set { rotateMix = value; } }
public float TranslateMix { get { return translateMix; } set { translateMix = value; } }
-
- public PathConstraintData (String name) {
- if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
- this.name = name;
- }
-
- public override string ToString () {
- return name;
- }
}
public enum PositionMode {
diff --git a/spine-csharp/src/Skeleton.cs b/spine-csharp/src/Skeleton.cs
index 6385fd64b..af8ddc642 100644
--- a/spine-csharp/src/Skeleton.cs
+++ b/spine-csharp/src/Skeleton.cs
@@ -55,7 +55,7 @@ namespace Spine {
public ExposedList IkConstraints { get { return ikConstraints; } }
public ExposedList PathConstraints { get { return pathConstraints; } }
public ExposedList TransformConstraints { get { return transformConstraints; } }
- public Skin Skin { get { return skin; } set { skin = value; } }
+ public Skin Skin { get { return skin; } set { SetSkin(value); } }
public float R { get { return r; } set { r = value; } }
public float G { get { return g; } set { g = value; } }
public float B { get { return b; } set { b = value; } }
@@ -118,21 +118,25 @@ namespace Spine {
UpdateWorldTransform();
}
- /// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added
- /// or removed.
+ /// Caches information about bones and constraints. Must be called if the skin is modified or if bones, constraints, or
+ /// weighted path attachments are added or removed.
public void UpdateCache () {
var updateCache = this.updateCache;
updateCache.Clear();
this.updateCacheReset.Clear();
+ int boneCount = this.bones.Items.Length;
var bones = this.bones;
- for (int i = 0, n = bones.Count; i < n; i++)
- bones.Items[i].sorted = false;
+ for (int i = 0; i < boneCount; i++) {
+ Bone bone = bones.Items[i];
+ bone.update = !bone.data.skinRequired || (skin != null && skin.bones.Contains(bone.data));
+ bone.sorted = !bone.update;
+ }
+ int ikCount = this.ikConstraints.Count, transformCount = this.transformConstraints.Count, pathCount = this.pathConstraints.Count;
var ikConstraints = this.ikConstraints;
var transformConstraints = this.transformConstraints;
var pathConstraints = this.pathConstraints;
- int ikCount = ikConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count;
int constraintCount = ikCount + transformCount + pathCount;
//outer:
for (int i = 0; i < constraintCount; i++) {
@@ -160,11 +164,13 @@ namespace Spine {
continue_outer: {}
}
- for (int i = 0, n = bones.Count; i < n; i++)
+ for (int i = 0; i < boneCount; i++)
SortBone(bones.Items[i]);
}
private void SortIkConstraint (IkConstraint constraint) {
+ if (constraint.data.skinRequired && (skin == null || !skin.constraints.Contains(constraint.data))) return;
+
Bone target = constraint.target;
SortBone(target);
@@ -185,15 +191,15 @@ namespace Spine {
}
private void SortPathConstraint (PathConstraint constraint) {
+ if (constraint.data.skinRequired && (skin == null || !skin.constraints.Contains(constraint.data))) return;
+
Slot slot = constraint.target;
int slotIndex = slot.data.index;
Bone slotBone = slot.bone;
if (skin != null) SortPathConstraintAttachment(skin, slotIndex, slotBone);
if (data.defaultSkin != null && data.defaultSkin != skin)
SortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
- for (int ii = 0, nn = data.skins.Count; ii < nn; ii++)
- SortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone);
-
+
Attachment attachment = slot.attachment;
if (attachment is PathAttachment) SortPathConstraintAttachment(attachment, slotBone);
@@ -211,6 +217,8 @@ namespace Spine {
}
private void SortTransformConstraint (TransformConstraint constraint) {
+ if (constraint.data.skinRequired && (skin == null || !skin.constraints.Contains(constraint.data))) return;
+
SortBone(constraint.target);
var constrained = constraint.bones;
@@ -269,6 +277,7 @@ namespace Spine {
var bonesItems = bones.Items;
for (int i = 0, n = bones.Count; i < n; i++) {
Bone bone = bonesItems[i];
+ if (!bone.update) continue;
if (bone.sorted) SortReset(bone.children);
bone.sorted = false;
}
@@ -295,7 +304,8 @@ namespace Spine {
}
///
- /// Updates the world transform for each bone and applies all constraints. The root bone will be temporarily parented to the specified bone.
+ /// Temporarily sets the root bone as a child of the specified bone, then updates the world transform for each bone and applies
+ /// all constraints.
///
public void UpdateWorldTransform (Bone parent) {
// This partial update avoids computing the world transform for constrained bones when 1) the bone is not updated
@@ -315,8 +325,7 @@ namespace Spine {
bone.appliedValid = true;
}
- // Apply the parent bone transform to the root bone. The root bone
- // always inherits scale, rotation and reflection.
+ // Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
Bone rootBone = this.RootBone;
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
rootBone.worldX = pa * x + pb * y + parent.worldX;
@@ -447,8 +456,12 @@ namespace Spine {
}
///
- /// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached.
- /// If there was no old skin, each slot's setup mode attachment is attached from the new skin.
+ /// Sets the skin used to look up attachments before looking in the . If the
+ /// skin is changed, is called.
+ ///
+ /// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached.
+ /// If there was no old skin, each slot's setup mode attachment is attached from the new skin.
+ ///
/// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling
/// .
/// Also, often is called before the next time the
@@ -456,6 +469,7 @@ namespace Spine {
///
/// May be null.
public void SetSkin (Skin newSkin) {
+ if (newSkin == skin) return;
if (newSkin != null) {
if (skin != null)
newSkin.AttachAll(this, skin);
@@ -472,6 +486,7 @@ namespace Spine {
}
}
skin = newSkin;
+ UpdateCache();
}
/// Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment name.
@@ -528,7 +543,7 @@ namespace Spine {
ExposedList transformConstraints = this.transformConstraints;
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
TransformConstraint transformConstraint = transformConstraints.Items[i];
- if (transformConstraint.data.name == constraintName) return transformConstraint;
+ if (transformConstraint.data.Name == constraintName) return transformConstraint;
}
return null;
}
@@ -539,7 +554,7 @@ namespace Spine {
ExposedList pathConstraints = this.pathConstraints;
for (int i = 0, n = pathConstraints.Count; i < n; i++) {
PathConstraint constraint = pathConstraints.Items[i];
- if (constraint.data.name.Equals(constraintName)) return constraint;
+ if (constraint.data.Name.Equals(constraintName)) return constraint;
}
return null;
}
diff --git a/spine-csharp/src/SkeletonBinary.cs b/spine-csharp/src/SkeletonBinary.cs
index 126149461..a660ddda4 100644
--- a/spine-csharp/src/SkeletonBinary.cs
+++ b/spine-csharp/src/SkeletonBinary.cs
@@ -174,6 +174,7 @@ namespace Spine {
data.shearY = ReadFloat(input);
data.length = ReadFloat(input) * scale;
data.transformMode = TransformModeValues[ReadVarint(input, true)];
+ data.skinRequired = ReadBoolean(input);
if (nonessential) ReadInt(input); // Skip bone color.
skeletonData.bones.Add(data);
}
@@ -206,6 +207,7 @@ namespace Spine {
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
IkConstraintData data = new IkConstraintData(ReadString(input));
data.order = ReadVarint(input, true);
+ data.skinRequired = ReadBoolean(input);
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
data.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
data.target = skeletonData.bones.Items[ReadVarint(input, true)];
@@ -221,6 +223,7 @@ namespace Spine {
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
TransformConstraintData data = new TransformConstraintData(ReadString(input));
data.order = ReadVarint(input, true);
+ data.skinRequired = ReadBoolean(input);
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
data.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
data.target = skeletonData.bones.Items[ReadVarint(input, true)];
@@ -243,6 +246,7 @@ namespace Spine {
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
PathConstraintData data = new PathConstraintData(ReadString(input));
data.order = ReadVarint(input, true);
+ data.skinRequired = ReadBoolean(input);
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
data.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
data.target = skeletonData.slots.Items[ReadVarint(input, true)];
@@ -260,7 +264,7 @@ namespace Spine {
}
// Default skin.
- Skin defaultSkin = ReadSkin(input, skeletonData, "default", nonessential);
+ Skin defaultSkin = ReadSkin(input, skeletonData, true, nonessential);
if (defaultSkin != null) {
skeletonData.defaultSkin = defaultSkin;
skeletonData.skins.Add(defaultSkin);
@@ -268,7 +272,7 @@ namespace Spine {
// Skins.
for (int i = 0, n = ReadVarint(input, true); i < n; i++)
- skeletonData.skins.Add(ReadSkin(input, skeletonData, ReadString(input), nonessential));
+ skeletonData.skins.Add(ReadSkin(input, skeletonData, false, nonessential));
// Linked meshes.
for (int i = 0, n = linkedMeshes.Count; i < n; i++) {
@@ -312,11 +316,19 @@ namespace Spine {
/// May be null.
- private Skin ReadSkin (Stream input, SkeletonData skeletonData, String skinName, bool nonessential) {
- int slotCount = ReadVarint(input, true);
- if (slotCount == 0) return null;
- Skin skin = new Skin(skinName);
- for (int i = 0; i < slotCount; i++) {
+ private Skin ReadSkin (Stream input, SkeletonData skeletonData, bool defaultSkin, bool nonessential) {
+ Skin skin = new Skin(defaultSkin ? "default" : ReadString(input));
+ if (!defaultSkin) {
+ for (int i = 0, n = ReadVarint(input, true); i < n; i++)
+ skin.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
+ for (int i = 0, n = ReadVarint(input, true); i < n; i++)
+ skin.constraints.Add(skeletonData.ikConstraints.Items[ReadVarint(input, true)]);
+ for (int i = 0, n = ReadVarint(input, true); i < n; i++)
+ skin.constraints.Add(skeletonData.transformConstraints.Items[ReadVarint(input, true)]);
+ for (int i = 0, n = ReadVarint(input, true); i < n; i++)
+ skin.constraints.Add(skeletonData.pathConstraints.Items[ReadVarint(input, true)]);
+ }
+ 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++) {
String name = ReadString(input);
diff --git a/spine-csharp/src/SkeletonJson.cs b/spine-csharp/src/SkeletonJson.cs
index 01a132995..b42d35276 100644
--- a/spine-csharp/src/SkeletonJson.cs
+++ b/spine-csharp/src/SkeletonJson.cs
@@ -109,27 +109,30 @@ namespace Spine {
}
// Bones.
- foreach (Dictionary boneMap in (List