diff --git a/spine-csharp/src/Animation.cs b/spine-csharp/src/Animation.cs
index cbc6b0f2f..d64474de0 100644
--- a/spine-csharp/src/Animation.cs
+++ b/spine-csharp/src/Animation.cs
@@ -63,7 +63,7 @@ namespace Spine {
Timeline[] timelinesItems = timelines.Items;
for (int t = 0; t < timelinesCount; ++t)
idCount += timelinesItems[t].PropertyIds.Length;
- string[] propertyIds = new string[idCount];
+ var propertyIds = new string[idCount];
int currentId = 0;
for (int t = 0; t < timelinesCount; ++t) {
string[] ids = timelinesItems[t].PropertyIds;
@@ -320,7 +320,7 @@ namespace Spine {
public void Shrink (int bezierCount) {
int size = FrameCount + bezierCount * BEZIER_SIZE;
if (curves.Length > size) {
- float[] newCurves = new float[size];
+ var newCurves = new float[size];
Array.Copy(curves, 0, newCurves, 0, size);
curves = newCurves;
}
diff --git a/spine-csharp/src/AnimationState.cs b/spine-csharp/src/AnimationState.cs
index 98221fa9c..ebe2a20b3 100644
--- a/spine-csharp/src/AnimationState.cs
+++ b/spine-csharp/src/AnimationState.cs
@@ -7,7 +7,7 @@
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
- * http://esotericsoftware.com/spine-editor-license
+ * https://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
@@ -37,7 +37,7 @@ namespace Spine {
/// Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies
/// multiple animations on top of each other (layering).
///
- /// See Applying Animations in the Spine Runtimes Guide.
+ /// See Applying Animations in the Spine Runtimes Guide.
///
public class AnimationState {
internal static readonly Animation EmptyAnimation = new Animation("", new ExposedList(), 0);
@@ -87,7 +87,7 @@ namespace Spine {
internal void OnEvent (TrackEntry entry, Event e) { if (Event != null) Event(entry, e); }
public delegate void TrackEntryDelegate (TrackEntry trackEntry);
- /// See
+ /// See
/// API Reference documentation pages here for details. Usage in C# and spine-unity is explained
/// here
/// on the spine-unity documentation pages.
@@ -726,7 +726,7 @@ namespace Spine {
return AddAnimation(trackIndex, animation, loop, delay);
}
- /// Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is
+ /// Adds an animation to be played after the current or last queued animation for a track. If the track has no entries, this is
/// equivalent to calling .
///
/// If > 0, sets . If <= 0, the delay set is the duration of the previous track entry
@@ -774,8 +774,10 @@ namespace Spine {
/// with the desired delay (an empty animation has a duration of 0) and on
/// the returned track entry, set the . Mixing from an empty animation causes the new
/// animation to be applied more and more over the mix duration. Properties keyed in the new animation transition from the value
- /// from lower tracks or from the setup pose value if no lower tracks key the property to the value keyed in the new
- /// animation.
+ /// from lower tracks or from the setup pose value if no lower tracks key the property to the value keyed in the new animation.
+ ///
+ /// See Empty animations in the Spine
+ /// Runtimes Guide.
public TrackEntry SetEmptyAnimation (int trackIndex, float mixDuration) {
TrackEntry entry = SetAnimation(trackIndex, AnimationState.EmptyAnimation, false);
entry.mixDuration = mixDuration;
@@ -785,7 +787,7 @@ namespace Spine {
///
/// Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's
- /// . If the track is empty, it is equivalent to calling
+ /// . If the track has no entries, this is equivalent to calling
/// .
///
/// Track number.
@@ -967,7 +969,7 @@ namespace Spine {
public ExposedList Tracks { get { return tracks; } }
override public string ToString () {
- System.Text.StringBuilder buffer = new System.Text.StringBuilder();
+ var buffer = new System.Text.StringBuilder();
TrackEntry[] tracksItems = tracks.Items;
for (int i = 0, n = tracks.Count; i < n; i++) {
TrackEntry entry = tracksItems[i];
@@ -991,7 +993,7 @@ namespace Spine {
internal TrackEntry previous, next, mixingFrom, mixingTo;
// difference to libgdx reference: delegates are used for event callbacks instead of 'AnimationStateListener listener'.
- /// See
+ /// See
/// API Reference documentation pages here for details. Usage in C# and spine-unity is explained
/// here
/// on the spine-unity documentation pages.
diff --git a/spine-csharp/src/AnimationStateData.cs b/spine-csharp/src/AnimationStateData.cs
index 88079cff4..38dfa4a33 100644
--- a/spine-csharp/src/AnimationStateData.cs
+++ b/spine-csharp/src/AnimationStateData.cs
@@ -64,7 +64,7 @@ namespace Spine {
public void SetMix (Animation from, Animation to, float duration) {
if (from == null) throw new ArgumentNullException("from", "from cannot be null.");
if (to == null) throw new ArgumentNullException("to", "to cannot be null.");
- AnimationPair key = new AnimationPair(from, to);
+ var key = new AnimationPair(from, to);
animationToMixTime.Remove(key);
animationToMixTime.Add(key, duration);
}
@@ -76,7 +76,7 @@ namespace Spine {
public float GetMix (Animation from, Animation to) {
if (from == null) throw new ArgumentNullException("from", "from cannot be null.");
if (to == null) throw new ArgumentNullException("to", "to cannot be null.");
- AnimationPair key = new AnimationPair(from, to);
+ var key = new AnimationPair(from, to);
float duration;
if (animationToMixTime.TryGetValue(key, out duration)) return duration;
return defaultMix;
diff --git a/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs b/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs
index 92a2fafae..65c41cfd9 100644
--- a/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs
+++ b/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs
@@ -53,7 +53,7 @@ namespace Spine {
}
public RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence) {
- RegionAttachment attachment = new RegionAttachment(name);
+ var attachment = new RegionAttachment(name);
if (sequence != null)
LoadSequence(name, path, sequence);
else {
@@ -66,7 +66,7 @@ namespace Spine {
}
public MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence) {
- MeshAttachment attachment = new MeshAttachment(name);
+ var attachment = new MeshAttachment(name);
if (sequence != null)
LoadSequence(name, path, sequence);
else {
diff --git a/spine-csharp/src/Attachments/MeshAttachment.cs b/spine-csharp/src/Attachments/MeshAttachment.cs
index cf55ee748..85a9685f8 100644
--- a/spine-csharp/src/Attachments/MeshAttachment.cs
+++ b/spine-csharp/src/Attachments/MeshAttachment.cs
@@ -199,7 +199,7 @@ namespace Spine {
/// Returns a new mesh with this mesh set as the .
public MeshAttachment NewLinkedMesh () {
- MeshAttachment mesh = new MeshAttachment(Name);
+ var mesh = new MeshAttachment(Name);
mesh.timelineAttachment = timelineAttachment;
mesh.region = region;
diff --git a/spine-csharp/src/Attachments/Sequence.cs b/spine-csharp/src/Attachments/Sequence.cs
index ac78ee07c..81d148588 100644
--- a/spine-csharp/src/Attachments/Sequence.cs
+++ b/spine-csharp/src/Attachments/Sequence.cs
@@ -79,7 +79,7 @@ namespace Spine {
}
public string GetPath (string basePath, int index) {
- StringBuilder buffer = new StringBuilder(basePath.Length + digits);
+ var buffer = new StringBuilder(basePath.Length + digits);
buffer.Append(basePath);
string frame = (start + index).ToString();
for (int i = digits - frame.Length; i > 0; i--)
diff --git a/spine-csharp/src/PathConstraint.cs b/spine-csharp/src/PathConstraint.cs
index 3af363fa6..1f21c3fbb 100644
--- a/spine-csharp/src/PathConstraint.cs
+++ b/spine-csharp/src/PathConstraint.cs
@@ -45,7 +45,7 @@ namespace Spine {
internal readonly PathConstraintData data;
internal readonly ExposedList bones;
- internal Slot target;
+ internal Slot slot;
internal float position, spacing, mixRotate, mixX, mixY;
internal bool active;
@@ -63,7 +63,7 @@ namespace Spine {
foreach (BoneData boneData in data.bones)
bones.Add(skeleton.bones.Items[boneData.index]);
- target = skeleton.slots.Items[data.target.index];
+ slot = skeleton.slots.Items[data.slot.index];
position = data.position;
spacing = data.spacing;
@@ -98,7 +98,7 @@ namespace Spine {
}
public void Update (Physics physics) {
- PathAttachment attachment = target.Attachment as PathAttachment;
+ PathAttachment attachment = slot.Attachment as PathAttachment;
if (attachment == null) return;
float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY;
@@ -171,7 +171,7 @@ namespace Spine {
tip = data.rotateMode == RotateMode.Chain;
} else {
tip = false;
- Bone p = target.bone;
+ Bone p = slot.bone;
offsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.DegRad : -MathUtils.DegRad;
}
for (int i = 0, p = 3; i < boneCount; i++, p += 3) {
@@ -223,7 +223,7 @@ namespace Spine {
}
float[] ComputeWorldPositions (PathAttachment path, int spacesCount, bool tangents) {
- Slot target = this.target;
+ Slot target = this.slot;
float position = this.position;
float[] spaces = this.spaces.Items, output = this.positions.Resize(spacesCount * 3 + 2).Items, world;
bool closed = path.Closed;
@@ -506,7 +506,7 @@ namespace Spine {
/// The bones that will be modified by this path constraint.
public ExposedList Bones { get { return bones; } }
/// The slot whose path attachment will be used to constrained the bones.
- public Slot Target { get { return target; } set { target = value; } }
+ public Slot Target { get { return slot; } set { slot = value; } }
public bool Active { get { return active; } }
/// The path constraint's setup pose data.
public PathConstraintData Data { get { return data; } }
diff --git a/spine-csharp/src/PathConstraintData.cs b/spine-csharp/src/PathConstraintData.cs
index 89f6e4627..5025d53d8 100644
--- a/spine-csharp/src/PathConstraintData.cs
+++ b/spine-csharp/src/PathConstraintData.cs
@@ -32,7 +32,7 @@ using System;
namespace Spine {
public class PathConstraintData : ConstraintData {
internal ExposedList bones = new ExposedList();
- internal SlotData target;
+ internal SlotData slot;
internal PositionMode positionMode;
internal SpacingMode spacingMode;
internal RotateMode rotateMode;
@@ -43,7 +43,7 @@ namespace Spine {
}
public ExposedList Bones { get { return bones; } }
- public SlotData Target { get { return target; } set { target = value; } }
+ public SlotData Slot { get { return slot; } set { slot = value; } }
public PositionMode PositionMode { get { return positionMode; } set { positionMode = value; } }
public SpacingMode SpacingMode { get { return spacingMode; } set { spacingMode = value; } }
public RotateMode RotateMode { get { return rotateMode; } set { rotateMode = value; } }
diff --git a/spine-csharp/src/PhysicsConstraint.cs b/spine-csharp/src/PhysicsConstraint.cs
index d3dc00528..0c751947e 100644
--- a/spine-csharp/src/PhysicsConstraint.cs
+++ b/spine-csharp/src/PhysicsConstraint.cs
@@ -39,7 +39,7 @@ namespace Spine {
///
public class PhysicsConstraint : IUpdatable {
internal readonly PhysicsConstraintData data;
- public Bone bone;
+ internal Bone bone;
internal float inertia, strength, damping, massInverse, wind, gravity, mix;
bool reset = true;
diff --git a/spine-csharp/src/Skeleton.cs b/spine-csharp/src/Skeleton.cs
index ac3b6a98f..44bfa4f1f 100644
--- a/spine-csharp/src/Skeleton.cs
+++ b/spine-csharp/src/Skeleton.cs
@@ -289,8 +289,7 @@ namespace Spine {
&& (!constraint.data.skinRequired || (skin != null && skin.constraints.Contains(constraint.data)));
if (!constraint.active) return;
- Bone target = constraint.target;
- SortBone(target);
+ SortBone(constraint.target);
ExposedList constrained = constraint.bones;
Bone parent = constrained.Items[0];
@@ -311,15 +310,15 @@ namespace Spine {
}
private void SortTransformConstraint (TransformConstraint constraint) {
- constraint.active = constraint.target.active
+ constraint.active = constraint.source.active
&& (!constraint.data.skinRequired || (skin != null && skin.constraints.Contains(constraint.data)));
if (!constraint.active) return;
- SortBone(constraint.target);
+ SortBone(constraint.source);
Bone[] constrained = constraint.bones.Items;
int boneCount = constraint.bones.Count;
- if (constraint.data.local) {
+ if (constraint.data.localSource) {
for (int i = 0; i < boneCount; i++) {
Bone child = constrained[i];
SortBone(child.parent);
@@ -339,19 +338,18 @@ namespace Spine {
}
private void SortPathConstraint (PathConstraint constraint) {
- constraint.active = constraint.target.bone.active
+ constraint.active = constraint.slot.bone.active
&& (!constraint.data.skinRequired || (skin != null && skin.constraints.Contains(constraint.data)));
if (!constraint.active) return;
- Slot slot = constraint.target;
+ Slot slot = constraint.slot;
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);
- Attachment attachment = slot.attachment;
- if (attachment is PathAttachment) SortPathConstraintAttachment(attachment, slotBone);
+ SortPathConstraintAttachment(slot.attachment, slotBone);
Bone[] constrained = constraint.bones.Items;
int boneCount = constraint.bones.Count;
diff --git a/spine-csharp/src/SkeletonBinary.cs b/spine-csharp/src/SkeletonBinary.cs
index df365dda2..08c32d0b3 100644
--- a/spine-csharp/src/SkeletonBinary.cs
+++ b/spine-csharp/src/SkeletonBinary.cs
@@ -42,6 +42,22 @@ using Windows.Storage;
#endif
namespace Spine {
+
+ using FromProperty = TransformConstraintData.FromProperty;
+ using FromRotate = TransformConstraintData.FromRotate;
+ using FromScaleX = TransformConstraintData.FromScaleX;
+ using FromScaleY = TransformConstraintData.FromScaleY;
+ using FromShearY = TransformConstraintData.FromShearY;
+ using FromX = TransformConstraintData.FromX;
+ using FromY = TransformConstraintData.FromY;
+ using ToProperty = TransformConstraintData.ToProperty;
+ using ToRotate = TransformConstraintData.ToRotate;
+ using ToScaleX = TransformConstraintData.ToScaleX;
+ using ToScaleY = TransformConstraintData.ToScaleY;
+ using ToShearY = TransformConstraintData.ToShearY;
+ using ToX = TransformConstraintData.ToX;
+ using ToY = TransformConstraintData.ToY;
+
public class SkeletonBinary : SkeletonLoader {
public const int BONE_ROTATE = 0;
public const int BONE_TRANSLATE = 1;
@@ -122,8 +138,7 @@ namespace Spine {
/// Returns the version string of binary skeleton data.
public static string GetVersionString (Stream file) {
if (file == null) throw new ArgumentNullException("file");
-
- SkeletonInput input = new SkeletonInput(file);
+ var input = new SkeletonInput(file);
return input.GetVersionString();
}
@@ -131,8 +146,8 @@ namespace Spine {
if (file == null) throw new ArgumentNullException("file");
float scale = this.scale;
- SkeletonData skeletonData = new SkeletonData();
- SkeletonInput input = new SkeletonInput(file);
+ var skeletonData = new SkeletonData();
+ var input = new SkeletonInput(file);
long hash = input.ReadLong();
skeletonData.hash = hash == 0 ? null : hash.ToString();
@@ -171,7 +186,7 @@ namespace Spine {
for (int i = 0; i < n; i++) {
String name = input.ReadString();
BoneData parent = i == 0 ? null : bones[input.ReadInt(true)];
- BoneData data = new BoneData(i, name, parent);
+ var data = new BoneData(i, name, parent);
data.rotation = input.ReadFloat();
data.x = input.ReadFloat() * scale;
data.y = input.ReadFloat() * scale;
@@ -196,7 +211,7 @@ namespace Spine {
String slotName = input.ReadString();
BoneData boneData = bones[input.ReadInt(true)];
- SlotData slotData = new SlotData(i, slotName, boneData);
+ var slotData = new SlotData(i, slotName, boneData);
int color = input.ReadInt();
slotData.r = ((color & 0xff000000) >> 24) / 255f;
slotData.g = ((color & 0x00ff0000) >> 16) / 255f;
@@ -222,7 +237,7 @@ namespace Spine {
// IK constraints.
o = skeletonData.ikConstraints.Resize(n = input.ReadInt(true)).Items;
for (int i = 0, nn; i < n; i++) {
- IkConstraintData data = new IkConstraintData(input.ReadString());
+ var data = new IkConstraintData(input.ReadString());
data.order = input.ReadInt(true);
BoneData[] constraintBones = data.bones.Resize(nn = input.ReadInt(true)).Items;
for (int ii = 0; ii < nn; ii++)
@@ -242,42 +257,72 @@ namespace Spine {
// Transform constraints.
o = skeletonData.transformConstraints.Resize(n = input.ReadInt(true)).Items;
for (int i = 0, nn; i < n; i++) {
- TransformConstraintData data = new TransformConstraintData(input.ReadString());
+ var data = new TransformConstraintData(input.ReadString());
data.order = input.ReadInt(true);
BoneData[] constraintBones = data.bones.Resize(nn = input.ReadInt(true)).Items;
for (int ii = 0; ii < nn; ii++)
constraintBones[ii] = bones[input.ReadInt(true)];
- data.target = bones[input.ReadInt(true)];
+ data.source = bones[input.ReadInt(true)];
int flags = input.Read();
data.skinRequired = (flags & 1) != 0;
- data.local = (flags & 2) != 0;
- data.relative = (flags & 4) != 0;
- if ((flags & 8) != 0) data.offsetRotation = input.ReadFloat();
- if ((flags & 16) != 0) data.offsetX = input.ReadFloat() * scale;
- if ((flags & 32) != 0) data.offsetY = input.ReadFloat() * scale;
- if ((flags & 64) != 0) data.offsetScaleX = input.ReadFloat();
- if ((flags & 128) != 0) data.offsetScaleY = input.ReadFloat();
+ data.localSource = (flags & 2) != 0;
+ data.localTarget = (flags & 4) != 0;
+ data.additive = (flags & 8) != 0;
+ data.clamp = (flags & 16) != 0;
+ FromProperty[] froms = data.properties.Resize(nn = flags >> 5).Items;
+ for (int ii = 0, tn; ii < nn; ii++) {
+ FromProperty from;
+ switch (input.ReadSByte()) {
+ case 0: from = new FromRotate(); break;
+ case 1: from = new FromX(); break;
+ case 2: from = new FromY(); break;
+ case 3: from = new FromScaleX(); break;
+ case 4: from = new FromScaleY(); break;
+ case 5: from = new FromShearY(); break;
+ default: from = null; break;
+ };
+ from.offset = input.ReadFloat() * scale;
+ ToProperty[] tos = from.to.Resize(tn = input.ReadSByte()).Items;
+ for (int t = 0; t < tn; t++) {
+ ToProperty to;
+ switch (input.ReadSByte()) {
+ case 0: to = new ToRotate(); break;
+ case 1: to = new ToX(); break;
+ case 2: to = new ToY(); break;
+ case 3: to = new ToScaleX(); break;
+ case 4: to = new ToScaleY(); break;
+ case 5: to = new ToShearY(); break;
+ default: to = null; break;
+ };
+ to.offset = input.ReadFloat() * scale;
+ to.max = input.ReadFloat() * scale;
+ to.scale = input.ReadFloat();
+ tos[t] = to;
+ }
+ froms[ii] = from;
+ }
flags = input.Read();
- if ((flags & 1) != 0) data.offsetShearY = input.ReadFloat();
- if ((flags & 2) != 0) data.mixRotate = input.ReadFloat();
- if ((flags & 4) != 0) data.mixX = input.ReadFloat();
- if ((flags & 8) != 0) data.mixY = input.ReadFloat();
- if ((flags & 16) != 0) data.mixScaleX = input.ReadFloat();
- if ((flags & 32) != 0) data.mixScaleY = input.ReadFloat();
- if ((flags & 64) != 0) data.mixShearY = input.ReadFloat();
+ if ((flags & 1) != 0) data.offsetX = input.ReadFloat();
+ if ((flags & 2) != 0) data.offsetY = input.ReadFloat();
+ if ((flags & 4) != 0) data.mixRotate = input.ReadFloat();
+ if ((flags & 8) != 0) data.mixX = input.ReadFloat();
+ if ((flags & 16) != 0) data.mixY = input.ReadFloat();
+ if ((flags & 32) != 0) data.mixScaleX = input.ReadFloat();
+ if ((flags & 64) != 0) data.mixScaleY = input.ReadFloat();
+ if ((flags & 128) != 0) data.mixShearY = input.ReadFloat();
o[i] = data;
}
// Path constraints
o = skeletonData.pathConstraints.Resize(n = input.ReadInt(true)).Items;
for (int i = 0, nn; i < n; i++) {
- PathConstraintData data = new PathConstraintData(input.ReadString());
+ var data = new PathConstraintData(input.ReadString());
data.order = input.ReadInt(true);
data.skinRequired = input.ReadBoolean();
BoneData[] constraintBones = data.bones.Resize(nn = input.ReadInt(true)).Items;
for (int ii = 0; ii < nn; ii++)
constraintBones[ii] = bones[input.ReadInt(true)];
- data.target = slots[input.ReadInt(true)];
+ data.slot = slots[input.ReadInt(true)];
int flags = input.Read();
data.positionMode = (PositionMode)Enum.GetValues(typeof(PositionMode)).GetValue(flags & 1);
data.spacingMode = (SpacingMode)Enum.GetValues(typeof(SpacingMode)).GetValue((flags >> 1) & 3);
@@ -297,7 +342,7 @@ namespace Spine {
// Physics constraints.
o = skeletonData.physicsConstraints.Resize(n = input.ReadInt(true)).Items;
for (int i = 0; i < n; i++) {
- PhysicsConstraintData data = new PhysicsConstraintData(input.ReadString());
+ var data = new PhysicsConstraintData(input.ReadString());
data.order = input.ReadInt(true);
data.bone = bones[input.ReadInt(true)];
int flags = input.Read();
@@ -358,7 +403,7 @@ namespace Spine {
// Events.
o = skeletonData.events.Resize(n = input.ReadInt(true)).Items;
for (int i = 0; i < n; i++) {
- EventData data = new EventData(input.ReadString());
+ var data = new EventData(input.ReadString());
data.Int = input.ReadInt(false);
data.Float = input.ReadFloat();
data.String = input.ReadString();
@@ -547,7 +592,7 @@ namespace Spine {
bool closed = (flags & 16) != 0;
bool constantSpeed = (flags & 32) != 0;
Vertices vertices = ReadVertices(input, (flags & 64) != 0);
- float[] lengths = new float[vertices.length / 6];
+ var lengths = new float[vertices.length / 6];
for (int i = 0, n = lengths.Length; i < n; i++)
lengths[i] = input.ReadFloat() * scale;
if (nonessential) input.ReadInt(); //int color = nonessential ? input.ReadInt() : 0;
@@ -596,7 +641,7 @@ namespace Spine {
}
private Sequence ReadSequence (SkeletonInput input) {
- Sequence sequence = new Sequence(input.ReadInt(true));
+ var sequence = new Sequence(input.ReadInt(true));
sequence.Start = input.ReadInt(true);
sequence.Digits = input.ReadInt(true);
sequence.SetupIndex = input.ReadInt(true);
@@ -606,14 +651,14 @@ namespace Spine {
private Vertices ReadVertices (SkeletonInput input, bool weighted) {
float scale = this.scale;
int vertexCount = input.ReadInt(true);
- Vertices vertices = new Vertices();
+ var vertices = new Vertices();
vertices.length = vertexCount << 1;
if (!weighted) {
vertices.vertices = ReadFloatArray(input, vertices.length, scale);
return vertices;
}
- ExposedList weights = new ExposedList(vertices.length * 3 * 3);
- ExposedList bonesArray = new ExposedList(vertices.length * 3);
+ var weights = new ExposedList(vertices.length * 3 * 3);
+ var bonesArray = new ExposedList(vertices.length * 3);
for (int i = 0; i < vertexCount; i++) {
int boneCount = input.ReadInt(true);
bonesArray.Add(boneCount);
@@ -631,7 +676,7 @@ namespace Spine {
}
private float[] ReadFloatArray (SkeletonInput input, int n, float scale) {
- float[] array = new float[n];
+ var array = new float[n];
if (scale == 1) {
for (int i = 0; i < n; i++)
array[i] = input.ReadFloat();
@@ -643,7 +688,7 @@ namespace Spine {
}
private int[] ReadShortArray (SkeletonInput input, int n) {
- int[] array = new int[n];
+ var array = new int[n];
for (int i = 0; i < n; i++)
array[i] = input.ReadInt(true);
return array;
@@ -652,7 +697,7 @@ namespace Spine {
/// SerializationException will be thrown when a Vertex attachment is not found.
/// Throws IOException when a read operation fails.
private Animation ReadAnimation (String name, SkeletonInput input, SkeletonData skeletonData) {
- ExposedList timelines = new ExposedList(input.ReadInt(true));
+ var timelines = new ExposedList(input.ReadInt(true));
float scale = this.scale;
// Slot timelines.
@@ -662,14 +707,14 @@ namespace Spine {
int timelineType = input.ReadUByte(), frameCount = input.ReadInt(true), frameLast = frameCount - 1;
switch (timelineType) {
case SLOT_ATTACHMENT: {
- AttachmentTimeline timeline = new AttachmentTimeline(frameCount, slotIndex);
+ var timeline = new AttachmentTimeline(frameCount, slotIndex);
for (int frame = 0; frame < frameCount; frame++)
timeline.SetFrame(frame, input.ReadFloat(), input.ReadStringRef());
timelines.Add(timeline);
break;
}
case SLOT_RGBA: {
- RGBATimeline timeline = new RGBATimeline(frameCount, input.ReadInt(true), slotIndex);
+ var timeline = new RGBATimeline(frameCount, input.ReadInt(true), slotIndex);
float time = input.ReadFloat();
float r = input.Read() / 255f, g = input.Read() / 255f;
float b = input.Read() / 255f, a = input.Read() / 255f;
@@ -700,7 +745,7 @@ namespace Spine {
break;
}
case SLOT_RGB: {
- RGBTimeline timeline = new RGBTimeline(frameCount, input.ReadInt(true), slotIndex);
+ var timeline = new RGBTimeline(frameCount, input.ReadInt(true), slotIndex);
float time = input.ReadFloat();
float r = input.Read() / 255f, g = input.Read() / 255f, b = input.Read() / 255f;
for (int frame = 0, bezier = 0; ; frame++) {
@@ -727,7 +772,7 @@ namespace Spine {
break;
}
case SLOT_RGBA2: {
- RGBA2Timeline timeline = new RGBA2Timeline(frameCount, input.ReadInt(true), slotIndex);
+ var timeline = new RGBA2Timeline(frameCount, input.ReadInt(true), slotIndex);
float time = input.ReadFloat();
float r = input.Read() / 255f, g = input.Read() / 255f;
float b = input.Read() / 255f, a = input.Read() / 255f;
@@ -766,7 +811,7 @@ namespace Spine {
break;
}
case SLOT_RGB2: {
- RGB2Timeline timeline = new RGB2Timeline(frameCount, input.ReadInt(true), slotIndex);
+ var timeline = new RGB2Timeline(frameCount, input.ReadInt(true), slotIndex);
float time = input.ReadFloat();
float r = input.Read() / 255f, g = input.Read() / 255f, b = input.Read() / 255f;
float r2 = input.Read() / 255f, g2 = input.Read() / 255f, b2 = input.Read() / 255f;
@@ -801,7 +846,7 @@ namespace Spine {
break;
}
case SLOT_ALPHA: {
- AlphaTimeline timeline = new AlphaTimeline(frameCount, input.ReadInt(true), slotIndex);
+ var timeline = new AlphaTimeline(frameCount, input.ReadInt(true), slotIndex);
float time = input.ReadFloat(), a = input.Read() / 255f;
for (int frame = 0, bezier = 0; ; frame++) {
timeline.SetFrame(frame, time, a);
@@ -832,7 +877,7 @@ namespace Spine {
for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) {
int type = input.ReadUByte(), frameCount = input.ReadInt(true);
if (type == BONE_INHERIT) {
- InheritTimeline timeline = new InheritTimeline(frameCount, boneIndex);
+ var timeline = new InheritTimeline(frameCount, boneIndex);
for (int frame = 0; frame < frameCount; frame++)
timeline.SetFrame(frame, input.ReadFloat(), InheritEnum.Values[input.ReadUByte()]);
timelines.Add(timeline);
@@ -877,7 +922,7 @@ namespace Spine {
// IK constraint timelines.
for (int i = 0, n = input.ReadInt(true); i < n; i++) {
int index = input.ReadInt(true), frameCount = input.ReadInt(true), frameLast = frameCount - 1;
- IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount, input.ReadInt(true), index);
+ var timeline = new IkConstraintTimeline(frameCount, input.ReadInt(true), index);
int flags = input.Read();
float time = input.ReadFloat(), mix = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.ReadFloat() : 1) : 0;
float softness = (flags & 4) != 0 ? input.ReadFloat() * scale : 0;
@@ -904,7 +949,7 @@ namespace Spine {
// Transform constraint timelines.
for (int i = 0, n = input.ReadInt(true); i < n; i++) {
int index = input.ReadInt(true), frameCount = input.ReadInt(true), frameLast = frameCount - 1;
- TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount, input.ReadInt(true), index);
+ var timeline = new TransformConstraintTimeline(frameCount, input.ReadInt(true), index);
float time = input.ReadFloat(), mixRotate = input.ReadFloat(), mixX = input.ReadFloat(), mixY = input.ReadFloat(),
mixScaleX = input.ReadFloat(), mixScaleY = input.ReadFloat(), mixShearY = input.ReadFloat();
for (int frame = 0, bezier = 0; ; frame++) {
@@ -943,16 +988,18 @@ namespace Spine {
for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) {
int type = input.ReadUByte(), frameCount = input.ReadInt(true), bezierCount = input.ReadInt(true);
switch (type) {
- case PATH_POSITION:
+ case PATH_POSITION: {
ReadTimeline(input, timelines, new PathConstraintPositionTimeline(frameCount, bezierCount, index),
data.positionMode == PositionMode.Fixed ? scale : 1);
break;
- case PATH_SPACING:
+ }
+ case PATH_SPACING: {
ReadTimeline(input, timelines, new PathConstraintSpacingTimeline(frameCount, bezierCount, index),
data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed ? scale : 1);
break;
- case PATH_MIX:
- PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index);
+ }
+ case PATH_MIX: {
+ var timeline = new PathConstraintMixTimeline(frameCount, bezierCount, index);
float time = input.ReadFloat(), mixRotate = input.ReadFloat(), mixX = input.ReadFloat(), mixY = input.ReadFloat();
for (int frame = 0, bezier = 0, frameLast = timeline.FrameCount - 1; ; frame++) {
timeline.SetFrame(frame, time, mixRotate, mixX, mixY);
@@ -977,6 +1024,7 @@ namespace Spine {
timelines.Add(timeline);
break;
}
+ }
}
}
@@ -986,36 +1034,40 @@ namespace Spine {
for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) {
int type = input.ReadUByte(), frameCount = input.ReadInt(true);
if (type == PHYSICS_RESET) {
- PhysicsConstraintResetTimeline timeline = new PhysicsConstraintResetTimeline(frameCount, index);
+ var timeline = new PhysicsConstraintResetTimeline(frameCount, index);
for (int frame = 0; frame < frameCount; frame++)
timeline.SetFrame(frame, input.ReadFloat());
timelines.Add(timeline);
continue;
}
int bezierCount = input.ReadInt(true);
+ PhysicsConstraintTimeline newTimeline;
switch (type) {
case PHYSICS_INERTIA:
- ReadTimeline(input, timelines, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1);
+ newTimeline = new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index);
break;
case PHYSICS_STRENGTH:
- ReadTimeline(input, timelines, new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index), 1);
+ newTimeline = new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index);
break;
case PHYSICS_DAMPING:
- ReadTimeline(input, timelines, new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index), 1);
+ newTimeline = new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index);
break;
case PHYSICS_MASS:
- ReadTimeline(input, timelines, new PhysicsConstraintMassTimeline(frameCount, bezierCount, index), 1);
+ newTimeline = new PhysicsConstraintMassTimeline(frameCount, bezierCount, index);
break;
case PHYSICS_WIND:
- ReadTimeline(input, timelines, new PhysicsConstraintWindTimeline(frameCount, bezierCount, index), 1);
+ newTimeline = new PhysicsConstraintWindTimeline(frameCount, bezierCount, index);
break;
case PHYSICS_GRAVITY:
- ReadTimeline(input, timelines, new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index), 1);
+ newTimeline = new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index);
break;
case PHYSICS_MIX:
- ReadTimeline(input, timelines, new PhysicsConstraintMixTimeline(frameCount, bezierCount, index), 1);
+ newTimeline = new PhysicsConstraintMixTimeline(frameCount, bezierCount, index);
break;
+ default:
+ throw new SerializationException();
}
+ ReadTimeline(input, timelines, newTimeline, 1);
}
}
@@ -1037,7 +1089,7 @@ namespace Spine {
float[] vertices = vertexAttachment.Vertices;
int deformLength = weighted ? (vertices.Length / 3) << 1 : vertices.Length;
- DeformTimeline timeline = new DeformTimeline(frameCount, input.ReadInt(true), slotIndex, vertexAttachment);
+ var timeline = new DeformTimeline(frameCount, input.ReadInt(true), slotIndex, vertexAttachment);
float time = input.ReadFloat();
for (int frame = 0, bezier = 0; ; frame++) {
@@ -1078,7 +1130,7 @@ namespace Spine {
break;
}
case ATTACHMENT_SEQUENCE: {
- SequenceTimeline timeline = new SequenceTimeline(frameCount, slotIndex, attachment);
+ var timeline = new SequenceTimeline(frameCount, slotIndex, attachment);
for (int frame = 0; frame < frameCount; frame++) {
float time = input.ReadFloat();
int modeAndIndex = input.ReadInt();
@@ -1096,15 +1148,15 @@ namespace Spine {
// Draw order timeline.
int drawOrderCount = input.ReadInt(true);
if (drawOrderCount > 0) {
- DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount);
+ var timeline = new DrawOrderTimeline(drawOrderCount);
int slotCount = skeletonData.slots.Count;
for (int i = 0; i < drawOrderCount; i++) {
float time = input.ReadFloat();
int offsetCount = input.ReadInt(true);
- int[] drawOrder = new int[slotCount];
+ var drawOrder = new int[slotCount];
for (int ii = slotCount - 1; ii >= 0; ii--)
drawOrder[ii] = -1;
- int[] unchanged = new int[slotCount - offsetCount];
+ var unchanged = new int[slotCount - offsetCount];
int originalIndex = 0, unchangedIndex = 0;
for (int ii = 0; ii < offsetCount; ii++) {
int slotIndex = input.ReadInt(true);
@@ -1128,11 +1180,11 @@ namespace Spine {
// Event timeline.
int eventCount = input.ReadInt(true);
if (eventCount > 0) {
- EventTimeline timeline = new EventTimeline(eventCount);
+ var timeline = new EventTimeline(eventCount);
for (int i = 0; i < eventCount; i++) {
float time = input.ReadFloat();
EventData eventData = skeletonData.events.Items[input.ReadInt(true)];
- Event e = new Event(time, eventData);
+ var e = new Event(time, eventData);
e.intValue = input.ReadInt(false);
e.floatValue = input.ReadFloat();
e.stringValue = input.ReadString();
@@ -1353,7 +1405,7 @@ namespace Spine {
byteCount = ReadInt(true);
if (byteCount > 1 && byteCount <= 13) {
byteCount--;
- byte[] buffer = new byte[byteCount];
+ var buffer = new byte[byteCount];
ReadFully(buffer, 0, byteCount);
return System.Text.Encoding.UTF8.GetString(buffer, 0, byteCount);
}
diff --git a/spine-csharp/src/SkeletonJson.cs b/spine-csharp/src/SkeletonJson.cs
index 6a1b31119..593170bbd 100644
--- a/spine-csharp/src/SkeletonJson.cs
+++ b/spine-csharp/src/SkeletonJson.cs
@@ -42,6 +42,21 @@ using Windows.Storage;
namespace Spine {
+ using FromProperty = TransformConstraintData.FromProperty;
+ using FromRotate = TransformConstraintData.FromRotate;
+ using FromScaleX = TransformConstraintData.FromScaleX;
+ using FromScaleY = TransformConstraintData.FromScaleY;
+ using FromShearY = TransformConstraintData.FromShearY;
+ using FromX = TransformConstraintData.FromX;
+ using FromY = TransformConstraintData.FromY;
+ using ToProperty = TransformConstraintData.ToProperty;
+ using ToRotate = TransformConstraintData.ToRotate;
+ using ToScaleX = TransformConstraintData.ToScaleX;
+ using ToScaleY = TransformConstraintData.ToScaleY;
+ using ToShearY = TransformConstraintData.ToShearY;
+ using ToX = TransformConstraintData.ToX;
+ using ToY = TransformConstraintData.ToY;
+
///
/// Loads skeleton data in the Spine JSON format.
///
@@ -94,7 +109,7 @@ namespace Spine {
if (reader == null) throw new ArgumentNullException("reader", "reader cannot be null.");
float scale = this.scale;
- SkeletonData skeletonData = new SkeletonData();
+ var skeletonData = new SkeletonData();
Dictionary root = Json.Deserialize(reader) as Dictionary;
if (root == null) throw new Exception("Invalid JSON.");
@@ -123,7 +138,7 @@ namespace Spine {
if (parent == null)
throw new Exception("Parent bone not found: " + boneMap["parent"]);
}
- BoneData data = new BoneData(skeletonData.Bones.Count, (string)boneMap["name"], parent);
+ var data = new BoneData(skeletonData.Bones.Count, (string)boneMap["name"], parent);
data.length = GetFloat(boneMap, "length", 0) * scale;
data.x = GetFloat(boneMap, "x", 0) * scale;
data.y = GetFloat(boneMap, "y", 0) * scale;
@@ -148,7 +163,7 @@ namespace Spine {
string boneName = (string)slotMap["bone"];
BoneData boneData = skeletonData.FindBone(boneName);
if (boneData == null) throw new Exception("Slot bone not found: " + boneName);
- SlotData data = new SlotData(skeletonData.Slots.Count, slotName, boneData);
+ var data = new SlotData(skeletonData.Slots.Count, slotName, boneData);
if (slotMap.ContainsKey("color")) {
string color = (string)slotMap["color"];
@@ -179,7 +194,7 @@ namespace Spine {
// IK constraints.
if (root.ContainsKey("ik")) {
foreach (Dictionary constraintMap in (List
///
/// See Transform constraints in the Spine User Guide.
///
public class TransformConstraint : IUpdatable {
internal readonly TransformConstraintData data;
internal readonly ExposedList bones;
- internal Bone target;
+ internal Bone source;
internal float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
internal bool active;
@@ -56,7 +58,7 @@ namespace Spine {
foreach (BoneData boneData in data.bones)
bones.Add(skeleton.bones.Items[boneData.index]);
- target = skeleton.bones.Items[data.target.index];
+ source = skeleton.bones.Items[data.source.index];
mixRotate = data.mixRotate;
mixX = data.mixX;
@@ -90,205 +92,44 @@ namespace Spine {
public void Update (Physics physics) {
if (mixRotate == 0 && mixX == 0 && mixY == 0 && mixScaleX == 0 && mixScaleY == 0 && mixShearY == 0) return;
- if (data.local) {
- if (data.relative)
- ApplyRelativeLocal();
+
+ TransformConstraintData data = this.data;
+ bool localFrom = data.localSource, localTarget = data.localTarget, additive = data.additive, clamp = data.clamp;
+ Bone source = this.source;
+ FromProperty[] fromItems = data.properties.Items;
+ int fn = data.properties.Count;
+ Bone[] bones = this.bones.Items;
+ for (int i = 0, n = this.bones.Count; i < n; i++) {
+ var bone = bones[i];
+ for (int f = 0; f < fn; f++) {
+ FromProperty from = fromItems[f];
+ float value = from.Value(data, source, localFrom) - from.offset;
+ ToProperty[] toItems = from.to.Items;
+ for (int t = 0, tn = from.to.Count; t < tn; t++) {
+ var to = (ToProperty)toItems[t];
+ if (to.Mix(this) != 0) {
+ float clamped = to.offset + value * to.scale;
+ if (clamp) {
+ if (to.offset < to.max)
+ clamped = MathUtils.Clamp(clamped, to.offset, to.max);
+ else
+ clamped = MathUtils.Clamp(clamped, to.max, to.offset);
+ }
+ to.Apply(this, bone, clamped, localTarget, additive);
+ }
+ }
+ }
+ if (localTarget)
+ bone.Update(Skeleton.Physics.None); // note: reference implementation passes null, ignored parameter
else
- ApplyAbsoluteLocal();
- } else {
- if (data.relative)
- ApplyRelativeWorld();
- else
- ApplyAbsoluteWorld();
- }
- }
-
- void ApplyAbsoluteWorld () {
- float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,
- mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
- bool translate = mixX != 0 || mixY != 0;
-
- Bone target = this.target;
- float ta = target.a, tb = target.b, tc = target.c, td = target.d;
- float degRadReflect = ta * td - tb * tc > 0 ? MathUtils.DegRad : -MathUtils.DegRad;
- float offsetRotation = data.offsetRotation * degRadReflect, offsetShearY = data.offsetShearY * degRadReflect;
-
- Bone[] bones = this.bones.Items;
- for (int i = 0, n = this.bones.Count; i < n; i++) {
- Bone bone = bones[i];
-
- if (mixRotate != 0) {
- float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
- float r = MathUtils.Atan2(tc, ta) - MathUtils.Atan2(c, a) + offsetRotation;
- if (r > MathUtils.PI)
- r -= MathUtils.PI2;
- else if (r < -MathUtils.PI) //
- r += MathUtils.PI2;
- r *= mixRotate;
- float cos = MathUtils.Cos(r), sin = MathUtils.Sin(r);
- bone.a = cos * a - sin * c;
- bone.b = cos * b - sin * d;
- bone.c = sin * a + cos * c;
- bone.d = sin * b + cos * d;
- }
-
- if (translate) {
- float tx, ty; //Vector2 temp = this.temp;
- target.LocalToWorld(data.offsetX, data.offsetY, out tx, out ty); //target.localToWorld(temp.set(data.offsetX, data.offsetY));
- bone.worldX += (tx - bone.worldX) * mixX;
- bone.worldY += (ty - bone.worldY) * mixY;
- }
-
- if (mixScaleX != 0) {
- float s = (float)Math.Sqrt(bone.a * bone.a + bone.c * bone.c);
- if (s != 0) s = (s + ((float)Math.Sqrt(ta * ta + tc * tc) - s + data.offsetScaleX) * mixScaleX) / s;
- bone.a *= s;
- bone.c *= s;
- }
- if (mixScaleY != 0) {
- float s = (float)Math.Sqrt(bone.b * bone.b + bone.d * bone.d);
- if (s != 0) s = (s + ((float)Math.Sqrt(tb * tb + td * td) - s + data.offsetScaleY) * mixScaleY) / s;
- bone.b *= s;
- bone.d *= s;
- }
-
- if (mixShearY > 0) {
- float b = bone.b, d = bone.d;
- float by = MathUtils.Atan2(d, b);
- float r = MathUtils.Atan2(td, tb) - MathUtils.Atan2(tc, ta) - (by - MathUtils.Atan2(bone.c, bone.a));
- if (r > MathUtils.PI)
- r -= MathUtils.PI2;
- else if (r < -MathUtils.PI) //
- r += MathUtils.PI2;
- r = by + (r + offsetShearY) * mixShearY;
- float s = (float)Math.Sqrt(b * b + d * d);
- bone.b = MathUtils.Cos(r) * s;
- bone.d = MathUtils.Sin(r) * s;
- }
-
- bone.UpdateAppliedTransform();
- }
- }
-
- void ApplyRelativeWorld () {
- float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,
- mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
- bool translate = mixX != 0 || mixY != 0;
-
- Bone target = this.target;
- float ta = target.a, tb = target.b, tc = target.c, td = target.d;
- float degRadReflect = ta * td - tb * tc > 0 ? MathUtils.DegRad : -MathUtils.DegRad;
- float offsetRotation = data.offsetRotation * degRadReflect, offsetShearY = data.offsetShearY * degRadReflect;
-
- Bone[] bones = this.bones.Items;
- for (int i = 0, n = this.bones.Count; i < n; i++) {
- Bone bone = bones[i];
-
- if (mixRotate != 0) {
- float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
- float r = MathUtils.Atan2(tc, ta) + offsetRotation;
- if (r > MathUtils.PI)
- r -= MathUtils.PI2;
- else if (r < -MathUtils.PI) //
- r += MathUtils.PI2;
- r *= mixRotate;
- float cos = MathUtils.Cos(r), sin = MathUtils.Sin(r);
- bone.a = cos * a - sin * c;
- bone.b = cos * b - sin * d;
- bone.c = sin * a + cos * c;
- bone.d = sin * b + cos * d;
- }
-
- if (translate) {
- float tx, ty; //Vector2 temp = this.temp;
- target.LocalToWorld(data.offsetX, data.offsetY, out tx, out ty); //target.localToWorld(temp.set(data.offsetX, data.offsetY));
- bone.worldX += tx * mixX;
- bone.worldY += ty * mixY;
- }
-
- if (mixScaleX != 0) {
- float s = ((float)Math.Sqrt(ta * ta + tc * tc) - 1 + data.offsetScaleX) * mixScaleX + 1;
- bone.a *= s;
- bone.c *= s;
- }
- if (mixScaleY != 0) {
- float s = ((float)Math.Sqrt(tb * tb + td * td) - 1 + data.offsetScaleY) * mixScaleY + 1;
- bone.b *= s;
- bone.d *= s;
- }
-
- if (mixShearY > 0) {
- float r = MathUtils.Atan2(td, tb) - MathUtils.Atan2(tc, ta);
- if (r > MathUtils.PI)
- r -= MathUtils.PI2;
- else if (r < -MathUtils.PI) //
- r += MathUtils.PI2;
- float b = bone.b, d = bone.d;
- r = MathUtils.Atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * mixShearY;
- float s = (float)Math.Sqrt(b * b + d * d);
- bone.b = MathUtils.Cos(r) * s;
- bone.d = MathUtils.Sin(r) * s;
- }
-
- bone.UpdateAppliedTransform();
- }
- }
-
- void ApplyAbsoluteLocal () {
- float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,
- mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
-
- Bone target = this.target;
-
- Bone[] bones = this.bones.Items;
- for (int i = 0, n = this.bones.Count; i < n; i++) {
- Bone bone = bones[i];
-
- float rotation = bone.arotation;
- if (mixRotate != 0) rotation += (target.arotation - rotation + data.offsetRotation) * mixRotate;
-
- float x = bone.ax, y = bone.ay;
- x += (target.ax - x + data.offsetX) * mixX;
- y += (target.ay - y + data.offsetY) * mixY;
-
- float scaleX = bone.ascaleX, scaleY = bone.ascaleY;
- if (mixScaleX != 0 && scaleX != 0)
- scaleX = (scaleX + (target.ascaleX - scaleX + data.offsetScaleX) * mixScaleX) / scaleX;
- if (mixScaleY != 0 && scaleY != 0)
- scaleY = (scaleY + (target.ascaleY - scaleY + data.offsetScaleY) * mixScaleY) / scaleY;
-
- float shearY = bone.ashearY;
- if (mixShearY != 0) shearY += (target.ashearY - shearY + data.offsetShearY) * mixShearY;
-
- bone.UpdateWorldTransform(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
- }
- }
-
- void ApplyRelativeLocal () {
- float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX,
- mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
-
- Bone target = this.target;
-
- Bone[] bones = this.bones.Items;
- for (int i = 0, n = this.bones.Count; i < n; i++) {
- Bone bone = bones[i];
-
- float rotation = bone.arotation + (target.arotation + data.offsetRotation) * mixRotate;
- float x = bone.ax + (target.ax + data.offsetX) * mixX;
- float y = bone.ay + (target.ay + data.offsetY) * mixY;
- float scaleX = bone.ascaleX * (((target.ascaleX - 1 + data.offsetScaleX) * mixScaleX) + 1);
- float scaleY = bone.ascaleY * (((target.ascaleY - 1 + data.offsetScaleY) * mixScaleY) + 1);
- float shearY = bone.ashearY + (target.ashearY + data.offsetShearY) * mixShearY;
-
- bone.UpdateWorldTransform(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
+ bone.UpdateAppliedTransform();
}
}
/// The bones that will be modified by this transform constraint.
public ExposedList Bones { get { return bones; } }
- /// The target bone whose world transform will be copied to the constrained bones.
- public Bone Target { get { return target; } set { target = value; } }
+ /// The bone whose world transform will be copied to the constrained bones.
+ public Bone Source { get { return source; } set { source = value; } }
/// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
public float MixRotate { get { return mixRotate; } set { mixRotate = value; } }
/// A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.
diff --git a/spine-csharp/src/TransformConstraintData.cs b/spine-csharp/src/TransformConstraintData.cs
index b15ce4b5e..342c35c7d 100644
--- a/spine-csharp/src/TransformConstraintData.cs
+++ b/spine-csharp/src/TransformConstraintData.cs
@@ -31,14 +31,31 @@ using System;
namespace Spine {
public class TransformConstraintData : ConstraintData {
- internal ExposedList bones = new ExposedList();
- internal BoneData target;
- internal float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
- internal float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
- internal bool relative, local;
+ internal readonly ExposedList bones = new ExposedList();
+ internal BoneData source;
+ internal float offsetX, offsetY, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
+ internal bool localSource, localTarget, additive, clamp;
+ internal readonly ExposedList properties = new ExposedList();
+
+ public TransformConstraintData (string name) : base(name) {
+ }
public ExposedList Bones { get { return bones; } }
- public BoneData Target { get { return target; } set { target = value; } }
+
+ /// The bone whose world transform will be copied to the constrained bones.
+ public BoneData Source {
+ get { return source; }
+ set {
+ if (source == null) throw new ArgumentNullException("Source", "source cannot be null.");
+ source = value;
+ }
+ }
+
+ /// The mapping of transform properties to other transform properties.
+ public ExposedList Properties {
+ get { return properties; }
+ }
+
/// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
public float MixRotate { get { return mixRotate; } set { mixRotate = value; } }
/// A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.
@@ -51,18 +68,222 @@ namespace Spine {
public float MixScaleY { get { return mixScaleY; } set { mixScaleY = value; } }
/// A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y.
public float MixShearY { get { return mixShearY; } set { mixShearY = value; } }
-
- public float OffsetRotation { get { return offsetRotation; } set { offsetRotation = value; } }
+ /// An offset added to the constrained bone X translation.
public float OffsetX { get { return offsetX; } set { offsetX = value; } }
+ /// An offset added to the constrained bone Y translation.
public float OffsetY { get { return offsetY; } set { offsetY = value; } }
- public float OffsetScaleX { get { return offsetScaleX; } set { offsetScaleX = value; } }
- public float OffsetScaleY { get { return offsetScaleY; } set { offsetScaleY = value; } }
- public float OffsetShearY { get { return offsetShearY; } set { offsetShearY = value; } }
+ /// Reads the source bone's local transform instead of its world transform.
+ public bool LocalSource { get { return localSource; } set { localSource = value; } }
+ /// Sets the constrained bones' local transforms instead of their world transforms.
+ public bool LocalTarget { get { return localTarget; } set { localTarget = value; } }
+ /// Adds the source bone transform to the constrained bones instead of setting it absolutely.
+ public bool Additive { get { return additive; } set { additive = value; } }
+ /// Prevents constrained bones from exceeding the ranged defined by and
+ /// .
+ public bool Clamp { get { return clamp; } set { clamp = value; } }
- public bool Relative { get { return relative; } set { relative = value; } }
- public bool Local { get { return local; } set { local = value; } }
+ /// Source property for a .
+ abstract public class FromProperty {
+ /// The value of this property that corresponds to .
+ public float offset;
- public TransformConstraintData (string name) : base(name) {
+ /// Constrained properties.
+ public readonly ExposedList to = new ExposedList();
+
+ /// Reads this property from the specified bone.
+ abstract public float Value (TransformConstraintData data, Bone source, bool local);
+ }
+
+ ///Constrained property for a .
+ abstract public class ToProperty {
+ /// The value of this property that corresponds to .
+ public float offset;
+
+ /// The maximum value of this property when clamped.
+ public float max;
+
+ /// The scale of the value in relation to this property.
+ public float scale;
+
+ /// Reads the mix for this property from the specified constraint.
+ public abstract float Mix (TransformConstraint constraint);
+
+ /// Applies the value to this property.
+ public abstract void Apply (TransformConstraint constraint, Bone bone, float value, bool local, bool additive);
+ }
+
+ public class FromRotate : FromProperty {
+ public override float Value (TransformConstraintData data, Bone source, bool local) {
+ return local ? source.arotation : MathUtils.Atan2(source.c, source.a) * MathUtils.RadDeg;
+ }
+ }
+
+ public class ToRotate : ToProperty {
+ public override float Mix (TransformConstraint constraint) {
+ return constraint.mixRotate;
+ }
+
+ public override void Apply (TransformConstraint constraint, Bone bone, float value, bool local, bool additive) {
+ if (local) {
+ if (!additive) value -= bone.arotation;
+ bone.arotation += value * constraint.mixRotate;
+ } else {
+ float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
+ value *= MathUtils.DegRad;
+ if (!additive) value -= MathUtils.Atan2(c, a);
+ if (value > MathUtils.PI)
+ value -= MathUtils.PI2;
+ else if (value < -MathUtils.PI) //
+ value += MathUtils.PI2;
+ value *= constraint.mixRotate;
+ float cos = MathUtils.Cos(value), sin = MathUtils.Sin(value);
+ bone.a = cos * a - sin * c;
+ bone.b = cos * b - sin * d;
+ bone.c = sin * a + cos * c;
+ bone.d = sin * b + cos * d;
+ }
+ }
+ }
+
+ public class FromX : FromProperty {
+ public override float Value (TransformConstraintData data, Bone source, bool local) {
+ return local ? source.ax + data.offsetX : data.offsetX * source.a + data.offsetY * source.b + source.worldX;
+ }
+ }
+
+ public class ToX : ToProperty {
+ public override float Mix (TransformConstraint constraint) {
+ return constraint.mixX;
+ }
+
+ public override void Apply (TransformConstraint constraint, Bone bone, float value, bool local, bool additive) {
+ if (local) {
+ if (!additive) value -= bone.ax;
+ bone.ax += value * constraint.mixX;
+ } else {
+ if (!additive) value -= bone.worldX;
+ bone.worldX += value * constraint.mixX;
+ }
+ }
+ }
+
+ public class FromY : FromProperty {
+ public override float Value (TransformConstraintData data, Bone source, bool local) {
+ return local ? source.ay + data.offsetY : data.offsetX * source.c + data.offsetY * source.d + source.worldY;
+ }
+ }
+
+ public class ToY : ToProperty {
+ public override float Mix (TransformConstraint constraint) {
+ return constraint.mixY;
+ }
+
+ public override void Apply (TransformConstraint constraint, Bone bone, float value, bool local, bool additive) {
+ if (local) {
+ if (!additive) value -= bone.ay;
+ bone.ay += value * constraint.mixY;
+ } else {
+ if (!additive) value -= bone.worldY;
+ bone.worldY += value * constraint.mixY;
+ }
+ }
+ }
+
+ public class FromScaleX : FromProperty {
+ public override float Value (TransformConstraintData data, Bone source, bool local) {
+ return local ? source.ascaleX : (float)Math.Sqrt(source.a * source.a + source.c * source.c);
+ }
+ }
+
+ public class ToScaleX : ToProperty {
+ public override float Mix (TransformConstraint constraint) {
+ return constraint.mixScaleX;
+ }
+
+ public override void Apply (TransformConstraint constraint, Bone bone, float value, bool local, bool additive) {
+ if (local) {
+ if (additive)
+ bone.ascaleX *= 1 + ((value - 1) * constraint.mixScaleX);
+ else if (bone.ascaleX != 0) //
+ bone.ascaleX = 1 + (value / bone.ascaleX - 1) * constraint.mixScaleX;
+ } else {
+ float s;
+ if (additive)
+ s = 1 + (value - 1) * constraint.mixScaleX;
+ else {
+ s = (float)Math.Sqrt(bone.a * bone.a + bone.c * bone.c);
+ if (s != 0) s = 1 + (value / s - 1) * constraint.mixScaleX;
+ }
+ bone.a *= s;
+ bone.c *= s;
+ }
+ }
+ }
+
+ public class FromScaleY : FromProperty {
+ public override float Value (TransformConstraintData data, Bone source, bool local) {
+ return local ? source.ascaleY : (float)Math.Sqrt(source.b * source.b + source.d * source.d);
+ }
+ }
+
+ public class ToScaleY : ToProperty {
+ public override float Mix (TransformConstraint constraint) {
+ return constraint.mixScaleY;
+ }
+
+ public override void Apply (TransformConstraint constraint, Bone bone, float value, bool local, bool additive) {
+ if (local) {
+ if (additive)
+ bone.ascaleY *= 1 + ((value - 1) * constraint.mixScaleY);
+ else if (bone.ascaleY != 0) //
+ bone.ascaleY = 1 + (value / bone.ascaleY - 1) * constraint.mixScaleY;
+ } else {
+ float s;
+ if (additive)
+ s = 1 + (value - 1) * constraint.mixScaleY;
+ else {
+ s = (float)Math.Sqrt(bone.b * bone.b + bone.d * bone.d);
+ if (s != 0) s = 1 + (value / s - 1) * constraint.mixScaleY;
+ }
+ bone.b *= s;
+ bone.d *= s;
+ }
+ }
+ }
+
+ public class FromShearY : FromProperty {
+ public override float Value (TransformConstraintData data, Bone source, bool local) {
+ return local ? source.ashearY : (MathUtils.Atan2(source.d, source.b) - MathUtils.Atan2(source.c, source.a)) * MathUtils.RadDeg - 90;
+ }
+ }
+
+ public class ToShearY : ToProperty {
+ public override float Mix (TransformConstraint constraint) {
+ return constraint.mixShearY;
+ }
+
+ public override void Apply (TransformConstraint constraint, Bone bone, float value, bool local, bool additive) {
+ if (local) {
+ if (!additive) value -= bone.ashearY;
+ bone.ashearY += value * constraint.mixShearY;
+ } else {
+ float b = bone.b, d = bone.d, by = MathUtils.Atan2(d, b);
+ value = (value + 90) * MathUtils.DegRad;
+ if (additive)
+ value -= MathUtils.PI / 2;
+ else {
+ value -= by - MathUtils.Atan2(bone.c, bone.a);
+ if (value > MathUtils.PI)
+ value -= MathUtils.PI2;
+ else if (value < -MathUtils.PI) //
+ value += MathUtils.PI2;
+ }
+ value = by + value * constraint.mixShearY;
+ float s = (float)Math.Sqrt(b * b + d * d);
+ bone.b = MathUtils.Cos(value) * s;
+ bone.d = MathUtils.Sin(value) * s;
+ }
+ }
}
}
}
diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineHandles.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineHandles.cs
index 6a5b0b761..6b7064fc8 100644
--- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineHandles.cs
+++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineHandles.cs
@@ -397,8 +397,8 @@ namespace Spine.Unity.Editor {
// Transform Constraints
handleColor = SpineHandles.TransformContraintColor;
foreach (TransformConstraint tc in skeleton.TransformConstraints) {
- Bone targetBone = tc.Target;
- targetPos = targetBone.GetWorldPosition(transform, skeletonRenderScale, offset);
+ Bone sourceBone = tc.Source;
+ targetPos = sourceBone.GetWorldPosition(transform, skeletonRenderScale, offset);
if (tc.MixX > 0 || tc.MixY > 0) {
if ((tc.MixX > 0 && tc.MixX != 1f) ||
@@ -411,7 +411,7 @@ namespace Spine.Unity.Editor {
}
SpineHandles.DrawBoneCircle(targetPos, handleColor, normal, 1.3f * skeletonRenderScale);
Handles.color = handleColor;
- SpineHandles.DrawCrosshairs(targetPos, 0.2f, targetBone.A, targetBone.B, targetBone.C, targetBone.D, transform, skeletonRenderScale);
+ SpineHandles.DrawCrosshairs(targetPos, 0.2f, sourceBone.A, sourceBone.B, sourceBone.C, sourceBone.D, transform, skeletonRenderScale);
}
}
diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonDebugWindow.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonDebugWindow.cs
index 2af4e2a3c..5547bc5dc 100644
--- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonDebugWindow.cs
+++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonDebugWindow.cs
@@ -415,7 +415,7 @@ namespace Spine.Unity.Editor {
foreach (TransformConstraint c in skeleton.TransformConstraints) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintTransform));
EditorGUI.BeginDisabledGroup(true);
- FalseDropDown("Goal", c.Data.Target.Name, Icons.bone);
+ FalseDropDown("Source", c.Data.Source.Name, Icons.bone);
EditorGUI.EndDisabledGroup();
EditorGUI.BeginChangeCheck();
@@ -469,7 +469,7 @@ namespace Spine.Unity.Editor {
foreach (PathConstraint c in skeleton.PathConstraints) {
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintPath));
EditorGUI.BeginDisabledGroup(true);
- FalseDropDown("Path Slot", c.Data.Target.Name, Icons.slot);
+ FalseDropDown("Path Slot", c.Data.Slot.Name, Icons.slot);
Attachment activeAttachment = c.Target.Attachment;
FalseDropDown("Active Path", activeAttachment != null ? activeAttachment.Name : "", activeAttachment is PathAttachment ? Icons.path : null);
EditorGUILayout.LabelField("PositionMode." + c.Data.PositionMode);
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/RootMotion/SkeletonRootMotionBase.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/RootMotion/SkeletonRootMotionBase.cs
index 81fc288b8..e34d4104c 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/RootMotion/SkeletonRootMotionBase.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/RootMotion/SkeletonRootMotionBase.cs
@@ -446,8 +446,8 @@ namespace Spine.Unity {
if (useLastConstraintPos)
constraintPos = transformConstraintLastPos[GetConstraintLastPosIndex(constraintIndex)];
else {
- Bone targetBone = constraint.Target;
- constraintPos = new Vector2(targetBone.X, targetBone.Y);
+ Bone sourceBone = constraint.Source;
+ constraintPos = new Vector2(sourceBone.X, sourceBone.Y);
}
pos = new Vector2(
pos.x * invMixXY.x + constraintPos.x * mixXY.x,
@@ -465,8 +465,8 @@ namespace Spine.Unity {
if (useLastConstraintRotation)
constraintRotation = transformConstraintLastRotation[GetConstraintLastPosIndex(constraintIndex)];
else {
- Bone targetBone = constraint.Target;
- constraintRotation = targetBone.Rotation;
+ Bone sourceBone = constraint.Source;
+ constraintRotation = sourceBone.Rotation;
}
rotation = rotation * invMixRotate + constraintRotation * mixRotate;
}
@@ -474,16 +474,16 @@ namespace Spine.Unity {
void UpdateLastConstraintPos (TransformConstraint[] transformConstraintsItems) {
foreach (int constraintIndex in this.transformConstraintIndices) {
TransformConstraint constraint = transformConstraintsItems[constraintIndex];
- Bone targetBone = constraint.Target;
- transformConstraintLastPos[GetConstraintLastPosIndex(constraintIndex)] = new Vector2(targetBone.X, targetBone.Y);
+ Bone sourceBone = constraint.Source;
+ transformConstraintLastPos[GetConstraintLastPosIndex(constraintIndex)] = new Vector2(sourceBone.X, sourceBone.Y);
}
}
void UpdateLastConstraintRotation (TransformConstraint[] transformConstraintsItems) {
foreach (int constraintIndex in this.transformConstraintIndices) {
TransformConstraint constraint = transformConstraintsItems[constraintIndex];
- Bone targetBone = constraint.Target;
- transformConstraintLastRotation[GetConstraintLastPosIndex(constraintIndex)] = targetBone.Rotation;
+ Bone sourceBone = constraint.Source;
+ transformConstraintLastRotation[GetConstraintLastPosIndex(constraintIndex)] = sourceBone.Rotation;
}
}
@@ -524,10 +524,10 @@ namespace Spine.Unity {
TransformConstraint constraint = constraintsItems[i];
if (constraint.Bones.Contains(rootMotionBone)) {
transformConstraintIndices.Add(i);
- Bone targetBone = constraint.Target;
- Vector2 constraintPos = new Vector2(targetBone.X, targetBone.Y);
+ Bone sourceBone = constraint.Source;
+ Vector2 constraintPos = new Vector2(sourceBone.X, sourceBone.Y);
transformConstraintLastPos.Add(constraintPos);
- transformConstraintLastRotation.Add(targetBone.Rotation);
+ transformConstraintLastRotation.Add(sourceBone.Rotation);
}
}
}
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonUtility/SkeletonUtility.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonUtility/SkeletonUtility.cs
index b37f56ad1..95a842c4b 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonUtility/SkeletonUtility.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonUtility/SkeletonUtility.cs
@@ -360,7 +360,7 @@ namespace Spine.Unity {
ExposedList transformConstraints = skeleton.TransformConstraints;
for (int i = 0, n = transformConstraints.Count; i < n; i++)
- constraintTargets.Add(transformConstraints.Items[i].Target);
+ constraintTargets.Add(transformConstraints.Items[i].Source);
List boneComponents = this.boneComponents;
for (int i = 0, n = boneComponents.Count; i < n; i++) {