mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-21 17:56:04 +08:00
[csharp][unity] Port of Transform constraint property mapping and cumulated 4.3 changes. Excluding import scale fixes.
This commit is contained in:
parent
0ab3a8251a
commit
90bfdba422
@ -63,7 +63,7 @@ namespace Spine {
|
|||||||
Timeline[] timelinesItems = timelines.Items;
|
Timeline[] timelinesItems = timelines.Items;
|
||||||
for (int t = 0; t < timelinesCount; ++t)
|
for (int t = 0; t < timelinesCount; ++t)
|
||||||
idCount += timelinesItems[t].PropertyIds.Length;
|
idCount += timelinesItems[t].PropertyIds.Length;
|
||||||
string[] propertyIds = new string[idCount];
|
var propertyIds = new string[idCount];
|
||||||
int currentId = 0;
|
int currentId = 0;
|
||||||
for (int t = 0; t < timelinesCount; ++t) {
|
for (int t = 0; t < timelinesCount; ++t) {
|
||||||
string[] ids = timelinesItems[t].PropertyIds;
|
string[] ids = timelinesItems[t].PropertyIds;
|
||||||
@ -320,7 +320,7 @@ namespace Spine {
|
|||||||
public void Shrink (int bezierCount) {
|
public void Shrink (int bezierCount) {
|
||||||
int size = FrameCount + bezierCount * BEZIER_SIZE;
|
int size = FrameCount + bezierCount * BEZIER_SIZE;
|
||||||
if (curves.Length > size) {
|
if (curves.Length > size) {
|
||||||
float[] newCurves = new float[size];
|
var newCurves = new float[size];
|
||||||
Array.Copy(curves, 0, newCurves, 0, size);
|
Array.Copy(curves, 0, newCurves, 0, size);
|
||||||
curves = newCurves;
|
curves = newCurves;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
* Integration of the Spine Runtimes into software or otherwise creating
|
* Integration of the Spine Runtimes into software or otherwise creating
|
||||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
* 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
|
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
* 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
|
/// Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies
|
||||||
/// multiple animations on top of each other (layering).</para>
|
/// multiple animations on top of each other (layering).</para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// See <a href='http://esotericsoftware.com/spine-applying-animations/'>Applying Animations</a> in the Spine Runtimes Guide.</para>
|
/// See <see href='https://esotericsoftware.com/spine-applying-animations/'>Applying Animations</a> in the Spine Runtimes Guide.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AnimationState {
|
public class AnimationState {
|
||||||
internal static readonly Animation EmptyAnimation = new Animation("<empty>", new ExposedList<Timeline>(), 0);
|
internal static readonly Animation EmptyAnimation = new Animation("<empty>", new ExposedList<Timeline>(), 0);
|
||||||
@ -87,7 +87,7 @@ namespace Spine {
|
|||||||
internal void OnEvent (TrackEntry entry, Event e) { if (Event != null) Event(entry, e); }
|
internal void OnEvent (TrackEntry entry, Event e) { if (Event != null) Event(entry, e); }
|
||||||
|
|
||||||
public delegate void TrackEntryDelegate (TrackEntry trackEntry);
|
public delegate void TrackEntryDelegate (TrackEntry trackEntry);
|
||||||
/// <summary>See <see href="http://esotericsoftware.com/spine-api-reference#AnimationStateListener-Methods">
|
/// <summary>See <see href="https://esotericsoftware.com/spine-api-reference#AnimationStateListener-Methods">
|
||||||
/// API Reference documentation pages here</see> for details. Usage in C# and spine-unity is explained
|
/// API Reference documentation pages here</see> for details. Usage in C# and spine-unity is explained
|
||||||
/// <see href="https://esotericsoftware.com/spine-unity-main-components#Processing-AnimationState-Events">here</see>
|
/// <see href="https://esotericsoftware.com/spine-unity-main-components#Processing-AnimationState-Events">here</see>
|
||||||
/// on the spine-unity documentation pages.</summary>
|
/// on the spine-unity documentation pages.</summary>
|
||||||
@ -726,7 +726,7 @@ namespace Spine {
|
|||||||
return AddAnimation(trackIndex, animation, loop, delay);
|
return AddAnimation(trackIndex, animation, loop, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Adds an animation to be played after the current or last queued animation for a track. If the track is empty, it is
|
/// <summary>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 <see cref="SetAnimation(int, Animation, bool)"/>.</summary>
|
/// equivalent to calling <see cref="SetAnimation(int, Animation, bool)"/>.</summary>
|
||||||
/// <param name="delay">
|
/// <param name="delay">
|
||||||
/// If > 0, sets <see cref="TrackEntry.Delay"/>. If <= 0, the delay set is the duration of the previous track entry
|
/// If > 0, sets <see cref="TrackEntry.Delay"/>. If <= 0, the delay set is the duration of the previous track entry
|
||||||
@ -774,8 +774,10 @@ namespace Spine {
|
|||||||
/// <see cref="AnimationState.AddAnimation(int, Animation, bool, float)"/> with the desired delay (an empty animation has a duration of 0) and on
|
/// <see cref="AnimationState.AddAnimation(int, Animation, bool, float)"/> with the desired delay (an empty animation has a duration of 0) and on
|
||||||
/// the returned track entry, set the <see cref="TrackEntry.SetMixDuration(float)"/>. Mixing from an empty animation causes the new
|
/// the returned track entry, set the <see cref="TrackEntry.SetMixDuration(float)"/>. 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
|
/// 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
|
/// from lower tracks or from the setup pose value if no lower tracks key the property to the value keyed in the new animation.</para>
|
||||||
/// animation.</para></summary>
|
/// <para>
|
||||||
|
/// See <see href='https://esotericsoftware.com/spine-applying-animations/#Empty-animations'>Empty animations</a> in the Spine
|
||||||
|
/// Runtimes Guide.</para></summary>
|
||||||
public TrackEntry SetEmptyAnimation (int trackIndex, float mixDuration) {
|
public TrackEntry SetEmptyAnimation (int trackIndex, float mixDuration) {
|
||||||
TrackEntry entry = SetAnimation(trackIndex, AnimationState.EmptyAnimation, false);
|
TrackEntry entry = SetAnimation(trackIndex, AnimationState.EmptyAnimation, false);
|
||||||
entry.mixDuration = mixDuration;
|
entry.mixDuration = mixDuration;
|
||||||
@ -785,7 +787,7 @@ namespace Spine {
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's
|
/// Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's
|
||||||
/// <see cref="TrackEntry.MixDuration"/>. If the track is empty, it is equivalent to calling
|
/// <see cref="TrackEntry.MixDuration"/>. If the track has no entries, this is equivalent to calling
|
||||||
/// <see cref="AnimationState.SetEmptyAnimation(int, float)"/>.</summary>
|
/// <see cref="AnimationState.SetEmptyAnimation(int, float)"/>.</summary>
|
||||||
/// <seealso cref="AnimationState.SetEmptyAnimation(int, float)"/>
|
/// <seealso cref="AnimationState.SetEmptyAnimation(int, float)"/>
|
||||||
/// <param name="trackIndex">Track number.</param>
|
/// <param name="trackIndex">Track number.</param>
|
||||||
@ -967,7 +969,7 @@ namespace Spine {
|
|||||||
public ExposedList<TrackEntry> Tracks { get { return tracks; } }
|
public ExposedList<TrackEntry> Tracks { get { return tracks; } }
|
||||||
|
|
||||||
override public string ToString () {
|
override public string ToString () {
|
||||||
System.Text.StringBuilder buffer = new System.Text.StringBuilder();
|
var buffer = new System.Text.StringBuilder();
|
||||||
TrackEntry[] tracksItems = tracks.Items;
|
TrackEntry[] tracksItems = tracks.Items;
|
||||||
for (int i = 0, n = tracks.Count; i < n; i++) {
|
for (int i = 0, n = tracks.Count; i < n; i++) {
|
||||||
TrackEntry entry = tracksItems[i];
|
TrackEntry entry = tracksItems[i];
|
||||||
@ -991,7 +993,7 @@ namespace Spine {
|
|||||||
|
|
||||||
internal TrackEntry previous, next, mixingFrom, mixingTo;
|
internal TrackEntry previous, next, mixingFrom, mixingTo;
|
||||||
// difference to libgdx reference: delegates are used for event callbacks instead of 'AnimationStateListener listener'.
|
// difference to libgdx reference: delegates are used for event callbacks instead of 'AnimationStateListener listener'.
|
||||||
/// <summary>See <see href="http://esotericsoftware.com/spine-api-reference#AnimationStateListener-Methods">
|
/// <summary>See <see href="https://esotericsoftware.com/spine-api-reference#AnimationStateListener-Methods">
|
||||||
/// API Reference documentation pages here</see> for details. Usage in C# and spine-unity is explained
|
/// API Reference documentation pages here</see> for details. Usage in C# and spine-unity is explained
|
||||||
/// <see href="https://esotericsoftware.com/spine-unity-main-components#Processing-AnimationState-Events">here</see>
|
/// <see href="https://esotericsoftware.com/spine-unity-main-components#Processing-AnimationState-Events">here</see>
|
||||||
/// on the spine-unity documentation pages.</summary>
|
/// on the spine-unity documentation pages.</summary>
|
||||||
|
|||||||
@ -64,7 +64,7 @@ namespace Spine {
|
|||||||
public void SetMix (Animation from, Animation to, float duration) {
|
public void SetMix (Animation from, Animation to, float duration) {
|
||||||
if (from == null) throw new ArgumentNullException("from", "from cannot be null.");
|
if (from == null) throw new ArgumentNullException("from", "from cannot be null.");
|
||||||
if (to == null) throw new ArgumentNullException("to", "to 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.Remove(key);
|
||||||
animationToMixTime.Add(key, duration);
|
animationToMixTime.Add(key, duration);
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ namespace Spine {
|
|||||||
public float GetMix (Animation from, Animation to) {
|
public float GetMix (Animation from, Animation to) {
|
||||||
if (from == null) throw new ArgumentNullException("from", "from cannot be null.");
|
if (from == null) throw new ArgumentNullException("from", "from cannot be null.");
|
||||||
if (to == null) throw new ArgumentNullException("to", "to 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;
|
float duration;
|
||||||
if (animationToMixTime.TryGetValue(key, out duration)) return duration;
|
if (animationToMixTime.TryGetValue(key, out duration)) return duration;
|
||||||
return defaultMix;
|
return defaultMix;
|
||||||
|
|||||||
@ -53,7 +53,7 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence) {
|
public RegionAttachment NewRegionAttachment (Skin skin, string name, string path, Sequence sequence) {
|
||||||
RegionAttachment attachment = new RegionAttachment(name);
|
var attachment = new RegionAttachment(name);
|
||||||
if (sequence != null)
|
if (sequence != null)
|
||||||
LoadSequence(name, path, sequence);
|
LoadSequence(name, path, sequence);
|
||||||
else {
|
else {
|
||||||
@ -66,7 +66,7 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence) {
|
public MeshAttachment NewMeshAttachment (Skin skin, string name, string path, Sequence sequence) {
|
||||||
MeshAttachment attachment = new MeshAttachment(name);
|
var attachment = new MeshAttachment(name);
|
||||||
if (sequence != null)
|
if (sequence != null)
|
||||||
LoadSequence(name, path, sequence);
|
LoadSequence(name, path, sequence);
|
||||||
else {
|
else {
|
||||||
|
|||||||
@ -199,7 +199,7 @@ namespace Spine {
|
|||||||
|
|
||||||
/// <summary>Returns a new mesh with this mesh set as the <see cref="ParentMesh"/>.
|
/// <summary>Returns a new mesh with this mesh set as the <see cref="ParentMesh"/>.
|
||||||
public MeshAttachment NewLinkedMesh () {
|
public MeshAttachment NewLinkedMesh () {
|
||||||
MeshAttachment mesh = new MeshAttachment(Name);
|
var mesh = new MeshAttachment(Name);
|
||||||
|
|
||||||
mesh.timelineAttachment = timelineAttachment;
|
mesh.timelineAttachment = timelineAttachment;
|
||||||
mesh.region = region;
|
mesh.region = region;
|
||||||
|
|||||||
@ -79,7 +79,7 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public string GetPath (string basePath, int index) {
|
public string GetPath (string basePath, int index) {
|
||||||
StringBuilder buffer = new StringBuilder(basePath.Length + digits);
|
var buffer = new StringBuilder(basePath.Length + digits);
|
||||||
buffer.Append(basePath);
|
buffer.Append(basePath);
|
||||||
string frame = (start + index).ToString();
|
string frame = (start + index).ToString();
|
||||||
for (int i = digits - frame.Length; i > 0; i--)
|
for (int i = digits - frame.Length; i > 0; i--)
|
||||||
|
|||||||
@ -45,7 +45,7 @@ namespace Spine {
|
|||||||
|
|
||||||
internal readonly PathConstraintData data;
|
internal readonly PathConstraintData data;
|
||||||
internal readonly ExposedList<Bone> bones;
|
internal readonly ExposedList<Bone> bones;
|
||||||
internal Slot target;
|
internal Slot slot;
|
||||||
internal float position, spacing, mixRotate, mixX, mixY;
|
internal float position, spacing, mixRotate, mixX, mixY;
|
||||||
|
|
||||||
internal bool active;
|
internal bool active;
|
||||||
@ -63,7 +63,7 @@ namespace Spine {
|
|||||||
foreach (BoneData boneData in data.bones)
|
foreach (BoneData boneData in data.bones)
|
||||||
bones.Add(skeleton.bones.Items[boneData.index]);
|
bones.Add(skeleton.bones.Items[boneData.index]);
|
||||||
|
|
||||||
target = skeleton.slots.Items[data.target.index];
|
slot = skeleton.slots.Items[data.slot.index];
|
||||||
|
|
||||||
position = data.position;
|
position = data.position;
|
||||||
spacing = data.spacing;
|
spacing = data.spacing;
|
||||||
@ -98,7 +98,7 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Update (Physics physics) {
|
public void Update (Physics physics) {
|
||||||
PathAttachment attachment = target.Attachment as PathAttachment;
|
PathAttachment attachment = slot.Attachment as PathAttachment;
|
||||||
if (attachment == null) return;
|
if (attachment == null) return;
|
||||||
|
|
||||||
float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY;
|
float mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY;
|
||||||
@ -171,7 +171,7 @@ namespace Spine {
|
|||||||
tip = data.rotateMode == RotateMode.Chain;
|
tip = data.rotateMode == RotateMode.Chain;
|
||||||
} else {
|
} else {
|
||||||
tip = false;
|
tip = false;
|
||||||
Bone p = target.bone;
|
Bone p = slot.bone;
|
||||||
offsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.DegRad : -MathUtils.DegRad;
|
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) {
|
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) {
|
float[] ComputeWorldPositions (PathAttachment path, int spacesCount, bool tangents) {
|
||||||
Slot target = this.target;
|
Slot target = this.slot;
|
||||||
float position = this.position;
|
float position = this.position;
|
||||||
float[] spaces = this.spaces.Items, output = this.positions.Resize(spacesCount * 3 + 2).Items, world;
|
float[] spaces = this.spaces.Items, output = this.positions.Resize(spacesCount * 3 + 2).Items, world;
|
||||||
bool closed = path.Closed;
|
bool closed = path.Closed;
|
||||||
@ -506,7 +506,7 @@ namespace Spine {
|
|||||||
/// <summary>The bones that will be modified by this path constraint.</summary>
|
/// <summary>The bones that will be modified by this path constraint.</summary>
|
||||||
public ExposedList<Bone> Bones { get { return bones; } }
|
public ExposedList<Bone> Bones { get { return bones; } }
|
||||||
/// <summary>The slot whose path attachment will be used to constrained the bones.</summary>
|
/// <summary>The slot whose path attachment will be used to constrained the bones.</summary>
|
||||||
public Slot Target { get { return target; } set { target = value; } }
|
public Slot Target { get { return slot; } set { slot = value; } }
|
||||||
public bool Active { get { return active; } }
|
public bool Active { get { return active; } }
|
||||||
/// <summary>The path constraint's setup pose data.</summary>
|
/// <summary>The path constraint's setup pose data.</summary>
|
||||||
public PathConstraintData Data { get { return data; } }
|
public PathConstraintData Data { get { return data; } }
|
||||||
|
|||||||
@ -32,7 +32,7 @@ using System;
|
|||||||
namespace Spine {
|
namespace Spine {
|
||||||
public class PathConstraintData : ConstraintData {
|
public class PathConstraintData : ConstraintData {
|
||||||
internal ExposedList<BoneData> bones = new ExposedList<BoneData>();
|
internal ExposedList<BoneData> bones = new ExposedList<BoneData>();
|
||||||
internal SlotData target;
|
internal SlotData slot;
|
||||||
internal PositionMode positionMode;
|
internal PositionMode positionMode;
|
||||||
internal SpacingMode spacingMode;
|
internal SpacingMode spacingMode;
|
||||||
internal RotateMode rotateMode;
|
internal RotateMode rotateMode;
|
||||||
@ -43,7 +43,7 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ExposedList<BoneData> Bones { get { return bones; } }
|
public ExposedList<BoneData> 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 PositionMode PositionMode { get { return positionMode; } set { positionMode = value; } }
|
||||||
public SpacingMode SpacingMode { get { return spacingMode; } set { spacingMode = value; } }
|
public SpacingMode SpacingMode { get { return spacingMode; } set { spacingMode = value; } }
|
||||||
public RotateMode RotateMode { get { return rotateMode; } set { rotateMode = value; } }
|
public RotateMode RotateMode { get { return rotateMode; } set { rotateMode = value; } }
|
||||||
|
|||||||
@ -39,7 +39,7 @@ namespace Spine {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PhysicsConstraint : IUpdatable {
|
public class PhysicsConstraint : IUpdatable {
|
||||||
internal readonly PhysicsConstraintData data;
|
internal readonly PhysicsConstraintData data;
|
||||||
public Bone bone;
|
internal Bone bone;
|
||||||
internal float inertia, strength, damping, massInverse, wind, gravity, mix;
|
internal float inertia, strength, damping, massInverse, wind, gravity, mix;
|
||||||
|
|
||||||
bool reset = true;
|
bool reset = true;
|
||||||
|
|||||||
@ -289,8 +289,7 @@ namespace Spine {
|
|||||||
&& (!constraint.data.skinRequired || (skin != null && skin.constraints.Contains(constraint.data)));
|
&& (!constraint.data.skinRequired || (skin != null && skin.constraints.Contains(constraint.data)));
|
||||||
if (!constraint.active) return;
|
if (!constraint.active) return;
|
||||||
|
|
||||||
Bone target = constraint.target;
|
SortBone(constraint.target);
|
||||||
SortBone(target);
|
|
||||||
|
|
||||||
ExposedList<Bone> constrained = constraint.bones;
|
ExposedList<Bone> constrained = constraint.bones;
|
||||||
Bone parent = constrained.Items[0];
|
Bone parent = constrained.Items[0];
|
||||||
@ -311,15 +310,15 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void SortTransformConstraint (TransformConstraint constraint) {
|
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)));
|
&& (!constraint.data.skinRequired || (skin != null && skin.constraints.Contains(constraint.data)));
|
||||||
if (!constraint.active) return;
|
if (!constraint.active) return;
|
||||||
|
|
||||||
SortBone(constraint.target);
|
SortBone(constraint.source);
|
||||||
|
|
||||||
Bone[] constrained = constraint.bones.Items;
|
Bone[] constrained = constraint.bones.Items;
|
||||||
int boneCount = constraint.bones.Count;
|
int boneCount = constraint.bones.Count;
|
||||||
if (constraint.data.local) {
|
if (constraint.data.localSource) {
|
||||||
for (int i = 0; i < boneCount; i++) {
|
for (int i = 0; i < boneCount; i++) {
|
||||||
Bone child = constrained[i];
|
Bone child = constrained[i];
|
||||||
SortBone(child.parent);
|
SortBone(child.parent);
|
||||||
@ -339,19 +338,18 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void SortPathConstraint (PathConstraint constraint) {
|
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)));
|
&& (!constraint.data.skinRequired || (skin != null && skin.constraints.Contains(constraint.data)));
|
||||||
if (!constraint.active) return;
|
if (!constraint.active) return;
|
||||||
|
|
||||||
Slot slot = constraint.target;
|
Slot slot = constraint.slot;
|
||||||
int slotIndex = slot.data.index;
|
int slotIndex = slot.data.index;
|
||||||
Bone slotBone = slot.bone;
|
Bone slotBone = slot.bone;
|
||||||
if (skin != null) SortPathConstraintAttachment(skin, slotIndex, slotBone);
|
if (skin != null) SortPathConstraintAttachment(skin, slotIndex, slotBone);
|
||||||
if (data.defaultSkin != null && data.defaultSkin != skin)
|
if (data.defaultSkin != null && data.defaultSkin != skin)
|
||||||
SortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
|
SortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
|
||||||
|
|
||||||
Attachment attachment = slot.attachment;
|
SortPathConstraintAttachment(slot.attachment, slotBone);
|
||||||
if (attachment is PathAttachment) SortPathConstraintAttachment(attachment, slotBone);
|
|
||||||
|
|
||||||
Bone[] constrained = constraint.bones.Items;
|
Bone[] constrained = constraint.bones.Items;
|
||||||
int boneCount = constraint.bones.Count;
|
int boneCount = constraint.bones.Count;
|
||||||
|
|||||||
@ -42,6 +42,22 @@ using Windows.Storage;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Spine {
|
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 class SkeletonBinary : SkeletonLoader {
|
||||||
public const int BONE_ROTATE = 0;
|
public const int BONE_ROTATE = 0;
|
||||||
public const int BONE_TRANSLATE = 1;
|
public const int BONE_TRANSLATE = 1;
|
||||||
@ -122,8 +138,7 @@ namespace Spine {
|
|||||||
/// <summary>Returns the version string of binary skeleton data.</summary>
|
/// <summary>Returns the version string of binary skeleton data.</summary>
|
||||||
public static string GetVersionString (Stream file) {
|
public static string GetVersionString (Stream file) {
|
||||||
if (file == null) throw new ArgumentNullException("file");
|
if (file == null) throw new ArgumentNullException("file");
|
||||||
|
var input = new SkeletonInput(file);
|
||||||
SkeletonInput input = new SkeletonInput(file);
|
|
||||||
return input.GetVersionString();
|
return input.GetVersionString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,8 +146,8 @@ namespace Spine {
|
|||||||
if (file == null) throw new ArgumentNullException("file");
|
if (file == null) throw new ArgumentNullException("file");
|
||||||
float scale = this.scale;
|
float scale = this.scale;
|
||||||
|
|
||||||
SkeletonData skeletonData = new SkeletonData();
|
var skeletonData = new SkeletonData();
|
||||||
SkeletonInput input = new SkeletonInput(file);
|
var input = new SkeletonInput(file);
|
||||||
|
|
||||||
long hash = input.ReadLong();
|
long hash = input.ReadLong();
|
||||||
skeletonData.hash = hash == 0 ? null : hash.ToString();
|
skeletonData.hash = hash == 0 ? null : hash.ToString();
|
||||||
@ -171,7 +186,7 @@ namespace Spine {
|
|||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
String name = input.ReadString();
|
String name = input.ReadString();
|
||||||
BoneData parent = i == 0 ? null : bones[input.ReadInt(true)];
|
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.rotation = input.ReadFloat();
|
||||||
data.x = input.ReadFloat() * scale;
|
data.x = input.ReadFloat() * scale;
|
||||||
data.y = input.ReadFloat() * scale;
|
data.y = input.ReadFloat() * scale;
|
||||||
@ -196,7 +211,7 @@ namespace Spine {
|
|||||||
String slotName = input.ReadString();
|
String slotName = input.ReadString();
|
||||||
|
|
||||||
BoneData boneData = bones[input.ReadInt(true)];
|
BoneData boneData = bones[input.ReadInt(true)];
|
||||||
SlotData slotData = new SlotData(i, slotName, boneData);
|
var slotData = new SlotData(i, slotName, boneData);
|
||||||
int color = input.ReadInt();
|
int color = input.ReadInt();
|
||||||
slotData.r = ((color & 0xff000000) >> 24) / 255f;
|
slotData.r = ((color & 0xff000000) >> 24) / 255f;
|
||||||
slotData.g = ((color & 0x00ff0000) >> 16) / 255f;
|
slotData.g = ((color & 0x00ff0000) >> 16) / 255f;
|
||||||
@ -222,7 +237,7 @@ namespace Spine {
|
|||||||
// IK constraints.
|
// IK constraints.
|
||||||
o = skeletonData.ikConstraints.Resize(n = input.ReadInt(true)).Items;
|
o = skeletonData.ikConstraints.Resize(n = input.ReadInt(true)).Items;
|
||||||
for (int i = 0, nn; i < n; i++) {
|
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);
|
data.order = input.ReadInt(true);
|
||||||
BoneData[] constraintBones = data.bones.Resize(nn = input.ReadInt(true)).Items;
|
BoneData[] constraintBones = data.bones.Resize(nn = input.ReadInt(true)).Items;
|
||||||
for (int ii = 0; ii < nn; ii++)
|
for (int ii = 0; ii < nn; ii++)
|
||||||
@ -242,42 +257,72 @@ namespace Spine {
|
|||||||
// Transform constraints.
|
// Transform constraints.
|
||||||
o = skeletonData.transformConstraints.Resize(n = input.ReadInt(true)).Items;
|
o = skeletonData.transformConstraints.Resize(n = input.ReadInt(true)).Items;
|
||||||
for (int i = 0, nn; i < n; i++) {
|
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);
|
data.order = input.ReadInt(true);
|
||||||
BoneData[] constraintBones = data.bones.Resize(nn = input.ReadInt(true)).Items;
|
BoneData[] constraintBones = data.bones.Resize(nn = input.ReadInt(true)).Items;
|
||||||
for (int ii = 0; ii < nn; ii++)
|
for (int ii = 0; ii < nn; ii++)
|
||||||
constraintBones[ii] = bones[input.ReadInt(true)];
|
constraintBones[ii] = bones[input.ReadInt(true)];
|
||||||
data.target = bones[input.ReadInt(true)];
|
data.source = bones[input.ReadInt(true)];
|
||||||
int flags = input.Read();
|
int flags = input.Read();
|
||||||
data.skinRequired = (flags & 1) != 0;
|
data.skinRequired = (flags & 1) != 0;
|
||||||
data.local = (flags & 2) != 0;
|
data.localSource = (flags & 2) != 0;
|
||||||
data.relative = (flags & 4) != 0;
|
data.localTarget = (flags & 4) != 0;
|
||||||
if ((flags & 8) != 0) data.offsetRotation = input.ReadFloat();
|
data.additive = (flags & 8) != 0;
|
||||||
if ((flags & 16) != 0) data.offsetX = input.ReadFloat() * scale;
|
data.clamp = (flags & 16) != 0;
|
||||||
if ((flags & 32) != 0) data.offsetY = input.ReadFloat() * scale;
|
FromProperty[] froms = data.properties.Resize(nn = flags >> 5).Items;
|
||||||
if ((flags & 64) != 0) data.offsetScaleX = input.ReadFloat();
|
for (int ii = 0, tn; ii < nn; ii++) {
|
||||||
if ((flags & 128) != 0) data.offsetScaleY = input.ReadFloat();
|
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();
|
flags = input.Read();
|
||||||
if ((flags & 1) != 0) data.offsetShearY = input.ReadFloat();
|
if ((flags & 1) != 0) data.offsetX = input.ReadFloat();
|
||||||
if ((flags & 2) != 0) data.mixRotate = input.ReadFloat();
|
if ((flags & 2) != 0) data.offsetY = input.ReadFloat();
|
||||||
if ((flags & 4) != 0) data.mixX = input.ReadFloat();
|
if ((flags & 4) != 0) data.mixRotate = input.ReadFloat();
|
||||||
if ((flags & 8) != 0) data.mixY = input.ReadFloat();
|
if ((flags & 8) != 0) data.mixX = input.ReadFloat();
|
||||||
if ((flags & 16) != 0) data.mixScaleX = input.ReadFloat();
|
if ((flags & 16) != 0) data.mixY = input.ReadFloat();
|
||||||
if ((flags & 32) != 0) data.mixScaleY = input.ReadFloat();
|
if ((flags & 32) != 0) data.mixScaleX = input.ReadFloat();
|
||||||
if ((flags & 64) != 0) data.mixShearY = input.ReadFloat();
|
if ((flags & 64) != 0) data.mixScaleY = input.ReadFloat();
|
||||||
|
if ((flags & 128) != 0) data.mixShearY = input.ReadFloat();
|
||||||
o[i] = data;
|
o[i] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path constraints
|
// Path constraints
|
||||||
o = skeletonData.pathConstraints.Resize(n = input.ReadInt(true)).Items;
|
o = skeletonData.pathConstraints.Resize(n = input.ReadInt(true)).Items;
|
||||||
for (int i = 0, nn; i < n; i++) {
|
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.order = input.ReadInt(true);
|
||||||
data.skinRequired = input.ReadBoolean();
|
data.skinRequired = input.ReadBoolean();
|
||||||
BoneData[] constraintBones = data.bones.Resize(nn = input.ReadInt(true)).Items;
|
BoneData[] constraintBones = data.bones.Resize(nn = input.ReadInt(true)).Items;
|
||||||
for (int ii = 0; ii < nn; ii++)
|
for (int ii = 0; ii < nn; ii++)
|
||||||
constraintBones[ii] = bones[input.ReadInt(true)];
|
constraintBones[ii] = bones[input.ReadInt(true)];
|
||||||
data.target = slots[input.ReadInt(true)];
|
data.slot = slots[input.ReadInt(true)];
|
||||||
int flags = input.Read();
|
int flags = input.Read();
|
||||||
data.positionMode = (PositionMode)Enum.GetValues(typeof(PositionMode)).GetValue(flags & 1);
|
data.positionMode = (PositionMode)Enum.GetValues(typeof(PositionMode)).GetValue(flags & 1);
|
||||||
data.spacingMode = (SpacingMode)Enum.GetValues(typeof(SpacingMode)).GetValue((flags >> 1) & 3);
|
data.spacingMode = (SpacingMode)Enum.GetValues(typeof(SpacingMode)).GetValue((flags >> 1) & 3);
|
||||||
@ -297,7 +342,7 @@ namespace Spine {
|
|||||||
// Physics constraints.
|
// Physics constraints.
|
||||||
o = skeletonData.physicsConstraints.Resize(n = input.ReadInt(true)).Items;
|
o = skeletonData.physicsConstraints.Resize(n = input.ReadInt(true)).Items;
|
||||||
for (int i = 0; i < n; i++) {
|
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.order = input.ReadInt(true);
|
||||||
data.bone = bones[input.ReadInt(true)];
|
data.bone = bones[input.ReadInt(true)];
|
||||||
int flags = input.Read();
|
int flags = input.Read();
|
||||||
@ -358,7 +403,7 @@ namespace Spine {
|
|||||||
// Events.
|
// Events.
|
||||||
o = skeletonData.events.Resize(n = input.ReadInt(true)).Items;
|
o = skeletonData.events.Resize(n = input.ReadInt(true)).Items;
|
||||||
for (int i = 0; i < n; i++) {
|
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.Int = input.ReadInt(false);
|
||||||
data.Float = input.ReadFloat();
|
data.Float = input.ReadFloat();
|
||||||
data.String = input.ReadString();
|
data.String = input.ReadString();
|
||||||
@ -547,7 +592,7 @@ namespace Spine {
|
|||||||
bool closed = (flags & 16) != 0;
|
bool closed = (flags & 16) != 0;
|
||||||
bool constantSpeed = (flags & 32) != 0;
|
bool constantSpeed = (flags & 32) != 0;
|
||||||
Vertices vertices = ReadVertices(input, (flags & 64) != 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++)
|
for (int i = 0, n = lengths.Length; i < n; i++)
|
||||||
lengths[i] = input.ReadFloat() * scale;
|
lengths[i] = input.ReadFloat() * scale;
|
||||||
if (nonessential) input.ReadInt(); //int color = nonessential ? input.ReadInt() : 0;
|
if (nonessential) input.ReadInt(); //int color = nonessential ? input.ReadInt() : 0;
|
||||||
@ -596,7 +641,7 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Sequence ReadSequence (SkeletonInput input) {
|
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.Start = input.ReadInt(true);
|
||||||
sequence.Digits = input.ReadInt(true);
|
sequence.Digits = input.ReadInt(true);
|
||||||
sequence.SetupIndex = input.ReadInt(true);
|
sequence.SetupIndex = input.ReadInt(true);
|
||||||
@ -606,14 +651,14 @@ namespace Spine {
|
|||||||
private Vertices ReadVertices (SkeletonInput input, bool weighted) {
|
private Vertices ReadVertices (SkeletonInput input, bool weighted) {
|
||||||
float scale = this.scale;
|
float scale = this.scale;
|
||||||
int vertexCount = input.ReadInt(true);
|
int vertexCount = input.ReadInt(true);
|
||||||
Vertices vertices = new Vertices();
|
var vertices = new Vertices();
|
||||||
vertices.length = vertexCount << 1;
|
vertices.length = vertexCount << 1;
|
||||||
if (!weighted) {
|
if (!weighted) {
|
||||||
vertices.vertices = ReadFloatArray(input, vertices.length, scale);
|
vertices.vertices = ReadFloatArray(input, vertices.length, scale);
|
||||||
return vertices;
|
return vertices;
|
||||||
}
|
}
|
||||||
ExposedList<float> weights = new ExposedList<float>(vertices.length * 3 * 3);
|
var weights = new ExposedList<float>(vertices.length * 3 * 3);
|
||||||
ExposedList<int> bonesArray = new ExposedList<int>(vertices.length * 3);
|
var bonesArray = new ExposedList<int>(vertices.length * 3);
|
||||||
for (int i = 0; i < vertexCount; i++) {
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
int boneCount = input.ReadInt(true);
|
int boneCount = input.ReadInt(true);
|
||||||
bonesArray.Add(boneCount);
|
bonesArray.Add(boneCount);
|
||||||
@ -631,7 +676,7 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private float[] ReadFloatArray (SkeletonInput input, int n, float scale) {
|
private float[] ReadFloatArray (SkeletonInput input, int n, float scale) {
|
||||||
float[] array = new float[n];
|
var array = new float[n];
|
||||||
if (scale == 1) {
|
if (scale == 1) {
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
array[i] = input.ReadFloat();
|
array[i] = input.ReadFloat();
|
||||||
@ -643,7 +688,7 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int[] ReadShortArray (SkeletonInput input, int n) {
|
private int[] ReadShortArray (SkeletonInput input, int n) {
|
||||||
int[] array = new int[n];
|
var array = new int[n];
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
array[i] = input.ReadInt(true);
|
array[i] = input.ReadInt(true);
|
||||||
return array;
|
return array;
|
||||||
@ -652,7 +697,7 @@ namespace Spine {
|
|||||||
/// <exception cref="SerializationException">SerializationException will be thrown when a Vertex attachment is not found.</exception>
|
/// <exception cref="SerializationException">SerializationException will be thrown when a Vertex attachment is not found.</exception>
|
||||||
/// <exception cref="IOException">Throws IOException when a read operation fails.</exception>
|
/// <exception cref="IOException">Throws IOException when a read operation fails.</exception>
|
||||||
private Animation ReadAnimation (String name, SkeletonInput input, SkeletonData skeletonData) {
|
private Animation ReadAnimation (String name, SkeletonInput input, SkeletonData skeletonData) {
|
||||||
ExposedList<Timeline> timelines = new ExposedList<Timeline>(input.ReadInt(true));
|
var timelines = new ExposedList<Timeline>(input.ReadInt(true));
|
||||||
float scale = this.scale;
|
float scale = this.scale;
|
||||||
|
|
||||||
// Slot timelines.
|
// Slot timelines.
|
||||||
@ -662,14 +707,14 @@ namespace Spine {
|
|||||||
int timelineType = input.ReadUByte(), frameCount = input.ReadInt(true), frameLast = frameCount - 1;
|
int timelineType = input.ReadUByte(), frameCount = input.ReadInt(true), frameLast = frameCount - 1;
|
||||||
switch (timelineType) {
|
switch (timelineType) {
|
||||||
case SLOT_ATTACHMENT: {
|
case SLOT_ATTACHMENT: {
|
||||||
AttachmentTimeline timeline = new AttachmentTimeline(frameCount, slotIndex);
|
var timeline = new AttachmentTimeline(frameCount, slotIndex);
|
||||||
for (int frame = 0; frame < frameCount; frame++)
|
for (int frame = 0; frame < frameCount; frame++)
|
||||||
timeline.SetFrame(frame, input.ReadFloat(), input.ReadStringRef());
|
timeline.SetFrame(frame, input.ReadFloat(), input.ReadStringRef());
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SLOT_RGBA: {
|
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 time = input.ReadFloat();
|
||||||
float r = input.Read() / 255f, g = input.Read() / 255f;
|
float r = input.Read() / 255f, g = input.Read() / 255f;
|
||||||
float b = input.Read() / 255f, a = input.Read() / 255f;
|
float b = input.Read() / 255f, a = input.Read() / 255f;
|
||||||
@ -700,7 +745,7 @@ namespace Spine {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SLOT_RGB: {
|
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 time = input.ReadFloat();
|
||||||
float r = input.Read() / 255f, g = input.Read() / 255f, b = input.Read() / 255f;
|
float r = input.Read() / 255f, g = input.Read() / 255f, b = input.Read() / 255f;
|
||||||
for (int frame = 0, bezier = 0; ; frame++) {
|
for (int frame = 0, bezier = 0; ; frame++) {
|
||||||
@ -727,7 +772,7 @@ namespace Spine {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SLOT_RGBA2: {
|
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 time = input.ReadFloat();
|
||||||
float r = input.Read() / 255f, g = input.Read() / 255f;
|
float r = input.Read() / 255f, g = input.Read() / 255f;
|
||||||
float b = input.Read() / 255f, a = input.Read() / 255f;
|
float b = input.Read() / 255f, a = input.Read() / 255f;
|
||||||
@ -766,7 +811,7 @@ namespace Spine {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SLOT_RGB2: {
|
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 time = input.ReadFloat();
|
||||||
float r = input.Read() / 255f, g = input.Read() / 255f, b = input.Read() / 255f;
|
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;
|
float r2 = input.Read() / 255f, g2 = input.Read() / 255f, b2 = input.Read() / 255f;
|
||||||
@ -801,7 +846,7 @@ namespace Spine {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SLOT_ALPHA: {
|
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;
|
float time = input.ReadFloat(), a = input.Read() / 255f;
|
||||||
for (int frame = 0, bezier = 0; ; frame++) {
|
for (int frame = 0, bezier = 0; ; frame++) {
|
||||||
timeline.SetFrame(frame, time, a);
|
timeline.SetFrame(frame, time, a);
|
||||||
@ -832,7 +877,7 @@ namespace Spine {
|
|||||||
for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) {
|
for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) {
|
||||||
int type = input.ReadUByte(), frameCount = input.ReadInt(true);
|
int type = input.ReadUByte(), frameCount = input.ReadInt(true);
|
||||||
if (type == BONE_INHERIT) {
|
if (type == BONE_INHERIT) {
|
||||||
InheritTimeline timeline = new InheritTimeline(frameCount, boneIndex);
|
var timeline = new InheritTimeline(frameCount, boneIndex);
|
||||||
for (int frame = 0; frame < frameCount; frame++)
|
for (int frame = 0; frame < frameCount; frame++)
|
||||||
timeline.SetFrame(frame, input.ReadFloat(), InheritEnum.Values[input.ReadUByte()]);
|
timeline.SetFrame(frame, input.ReadFloat(), InheritEnum.Values[input.ReadUByte()]);
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
@ -877,7 +922,7 @@ namespace Spine {
|
|||||||
// IK constraint timelines.
|
// IK constraint timelines.
|
||||||
for (int i = 0, n = input.ReadInt(true); i < n; i++) {
|
for (int i = 0, n = input.ReadInt(true); i < n; i++) {
|
||||||
int index = input.ReadInt(true), frameCount = input.ReadInt(true), frameLast = frameCount - 1;
|
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();
|
int flags = input.Read();
|
||||||
float time = input.ReadFloat(), mix = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.ReadFloat() : 1) : 0;
|
float time = input.ReadFloat(), mix = (flags & 1) != 0 ? ((flags & 2) != 0 ? input.ReadFloat() : 1) : 0;
|
||||||
float softness = (flags & 4) != 0 ? input.ReadFloat() * scale : 0;
|
float softness = (flags & 4) != 0 ? input.ReadFloat() * scale : 0;
|
||||||
@ -904,7 +949,7 @@ namespace Spine {
|
|||||||
// Transform constraint timelines.
|
// Transform constraint timelines.
|
||||||
for (int i = 0, n = input.ReadInt(true); i < n; i++) {
|
for (int i = 0, n = input.ReadInt(true); i < n; i++) {
|
||||||
int index = input.ReadInt(true), frameCount = input.ReadInt(true), frameLast = frameCount - 1;
|
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(),
|
float time = input.ReadFloat(), mixRotate = input.ReadFloat(), mixX = input.ReadFloat(), mixY = input.ReadFloat(),
|
||||||
mixScaleX = input.ReadFloat(), mixScaleY = input.ReadFloat(), mixShearY = input.ReadFloat();
|
mixScaleX = input.ReadFloat(), mixScaleY = input.ReadFloat(), mixShearY = input.ReadFloat();
|
||||||
for (int frame = 0, bezier = 0; ; frame++) {
|
for (int frame = 0, bezier = 0; ; frame++) {
|
||||||
@ -943,16 +988,18 @@ namespace Spine {
|
|||||||
for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) {
|
for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) {
|
||||||
int type = input.ReadUByte(), frameCount = input.ReadInt(true), bezierCount = input.ReadInt(true);
|
int type = input.ReadUByte(), frameCount = input.ReadInt(true), bezierCount = input.ReadInt(true);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PATH_POSITION:
|
case PATH_POSITION: {
|
||||||
ReadTimeline(input, timelines, new PathConstraintPositionTimeline(frameCount, bezierCount, index),
|
ReadTimeline(input, timelines, new PathConstraintPositionTimeline(frameCount, bezierCount, index),
|
||||||
data.positionMode == PositionMode.Fixed ? scale : 1);
|
data.positionMode == PositionMode.Fixed ? scale : 1);
|
||||||
break;
|
break;
|
||||||
case PATH_SPACING:
|
}
|
||||||
|
case PATH_SPACING: {
|
||||||
ReadTimeline(input, timelines, new PathConstraintSpacingTimeline(frameCount, bezierCount, index),
|
ReadTimeline(input, timelines, new PathConstraintSpacingTimeline(frameCount, bezierCount, index),
|
||||||
data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed ? scale : 1);
|
data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed ? scale : 1);
|
||||||
break;
|
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();
|
float time = input.ReadFloat(), mixRotate = input.ReadFloat(), mixX = input.ReadFloat(), mixY = input.ReadFloat();
|
||||||
for (int frame = 0, bezier = 0, frameLast = timeline.FrameCount - 1; ; frame++) {
|
for (int frame = 0, bezier = 0, frameLast = timeline.FrameCount - 1; ; frame++) {
|
||||||
timeline.SetFrame(frame, time, mixRotate, mixX, mixY);
|
timeline.SetFrame(frame, time, mixRotate, mixX, mixY);
|
||||||
@ -977,6 +1024,7 @@ namespace Spine {
|
|||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -986,36 +1034,40 @@ namespace Spine {
|
|||||||
for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) {
|
for (int ii = 0, nn = input.ReadInt(true); ii < nn; ii++) {
|
||||||
int type = input.ReadUByte(), frameCount = input.ReadInt(true);
|
int type = input.ReadUByte(), frameCount = input.ReadInt(true);
|
||||||
if (type == PHYSICS_RESET) {
|
if (type == PHYSICS_RESET) {
|
||||||
PhysicsConstraintResetTimeline timeline = new PhysicsConstraintResetTimeline(frameCount, index);
|
var timeline = new PhysicsConstraintResetTimeline(frameCount, index);
|
||||||
for (int frame = 0; frame < frameCount; frame++)
|
for (int frame = 0; frame < frameCount; frame++)
|
||||||
timeline.SetFrame(frame, input.ReadFloat());
|
timeline.SetFrame(frame, input.ReadFloat());
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int bezierCount = input.ReadInt(true);
|
int bezierCount = input.ReadInt(true);
|
||||||
|
PhysicsConstraintTimeline newTimeline;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PHYSICS_INERTIA:
|
case PHYSICS_INERTIA:
|
||||||
ReadTimeline(input, timelines, new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index), 1);
|
newTimeline = new PhysicsConstraintInertiaTimeline(frameCount, bezierCount, index);
|
||||||
break;
|
break;
|
||||||
case PHYSICS_STRENGTH:
|
case PHYSICS_STRENGTH:
|
||||||
ReadTimeline(input, timelines, new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index), 1);
|
newTimeline = new PhysicsConstraintStrengthTimeline(frameCount, bezierCount, index);
|
||||||
break;
|
break;
|
||||||
case PHYSICS_DAMPING:
|
case PHYSICS_DAMPING:
|
||||||
ReadTimeline(input, timelines, new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index), 1);
|
newTimeline = new PhysicsConstraintDampingTimeline(frameCount, bezierCount, index);
|
||||||
break;
|
break;
|
||||||
case PHYSICS_MASS:
|
case PHYSICS_MASS:
|
||||||
ReadTimeline(input, timelines, new PhysicsConstraintMassTimeline(frameCount, bezierCount, index), 1);
|
newTimeline = new PhysicsConstraintMassTimeline(frameCount, bezierCount, index);
|
||||||
break;
|
break;
|
||||||
case PHYSICS_WIND:
|
case PHYSICS_WIND:
|
||||||
ReadTimeline(input, timelines, new PhysicsConstraintWindTimeline(frameCount, bezierCount, index), 1);
|
newTimeline = new PhysicsConstraintWindTimeline(frameCount, bezierCount, index);
|
||||||
break;
|
break;
|
||||||
case PHYSICS_GRAVITY:
|
case PHYSICS_GRAVITY:
|
||||||
ReadTimeline(input, timelines, new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index), 1);
|
newTimeline = new PhysicsConstraintGravityTimeline(frameCount, bezierCount, index);
|
||||||
break;
|
break;
|
||||||
case PHYSICS_MIX:
|
case PHYSICS_MIX:
|
||||||
ReadTimeline(input, timelines, new PhysicsConstraintMixTimeline(frameCount, bezierCount, index), 1);
|
newTimeline = new PhysicsConstraintMixTimeline(frameCount, bezierCount, index);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
throw new SerializationException();
|
||||||
}
|
}
|
||||||
|
ReadTimeline(input, timelines, newTimeline, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1037,7 +1089,7 @@ namespace Spine {
|
|||||||
float[] vertices = vertexAttachment.Vertices;
|
float[] vertices = vertexAttachment.Vertices;
|
||||||
int deformLength = weighted ? (vertices.Length / 3) << 1 : vertices.Length;
|
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();
|
float time = input.ReadFloat();
|
||||||
for (int frame = 0, bezier = 0; ; frame++) {
|
for (int frame = 0, bezier = 0; ; frame++) {
|
||||||
@ -1078,7 +1130,7 @@ namespace Spine {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ATTACHMENT_SEQUENCE: {
|
case ATTACHMENT_SEQUENCE: {
|
||||||
SequenceTimeline timeline = new SequenceTimeline(frameCount, slotIndex, attachment);
|
var timeline = new SequenceTimeline(frameCount, slotIndex, attachment);
|
||||||
for (int frame = 0; frame < frameCount; frame++) {
|
for (int frame = 0; frame < frameCount; frame++) {
|
||||||
float time = input.ReadFloat();
|
float time = input.ReadFloat();
|
||||||
int modeAndIndex = input.ReadInt();
|
int modeAndIndex = input.ReadInt();
|
||||||
@ -1096,15 +1148,15 @@ namespace Spine {
|
|||||||
// Draw order timeline.
|
// Draw order timeline.
|
||||||
int drawOrderCount = input.ReadInt(true);
|
int drawOrderCount = input.ReadInt(true);
|
||||||
if (drawOrderCount > 0) {
|
if (drawOrderCount > 0) {
|
||||||
DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount);
|
var timeline = new DrawOrderTimeline(drawOrderCount);
|
||||||
int slotCount = skeletonData.slots.Count;
|
int slotCount = skeletonData.slots.Count;
|
||||||
for (int i = 0; i < drawOrderCount; i++) {
|
for (int i = 0; i < drawOrderCount; i++) {
|
||||||
float time = input.ReadFloat();
|
float time = input.ReadFloat();
|
||||||
int offsetCount = input.ReadInt(true);
|
int offsetCount = input.ReadInt(true);
|
||||||
int[] drawOrder = new int[slotCount];
|
var drawOrder = new int[slotCount];
|
||||||
for (int ii = slotCount - 1; ii >= 0; ii--)
|
for (int ii = slotCount - 1; ii >= 0; ii--)
|
||||||
drawOrder[ii] = -1;
|
drawOrder[ii] = -1;
|
||||||
int[] unchanged = new int[slotCount - offsetCount];
|
var unchanged = new int[slotCount - offsetCount];
|
||||||
int originalIndex = 0, unchangedIndex = 0;
|
int originalIndex = 0, unchangedIndex = 0;
|
||||||
for (int ii = 0; ii < offsetCount; ii++) {
|
for (int ii = 0; ii < offsetCount; ii++) {
|
||||||
int slotIndex = input.ReadInt(true);
|
int slotIndex = input.ReadInt(true);
|
||||||
@ -1128,11 +1180,11 @@ namespace Spine {
|
|||||||
// Event timeline.
|
// Event timeline.
|
||||||
int eventCount = input.ReadInt(true);
|
int eventCount = input.ReadInt(true);
|
||||||
if (eventCount > 0) {
|
if (eventCount > 0) {
|
||||||
EventTimeline timeline = new EventTimeline(eventCount);
|
var timeline = new EventTimeline(eventCount);
|
||||||
for (int i = 0; i < eventCount; i++) {
|
for (int i = 0; i < eventCount; i++) {
|
||||||
float time = input.ReadFloat();
|
float time = input.ReadFloat();
|
||||||
EventData eventData = skeletonData.events.Items[input.ReadInt(true)];
|
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.intValue = input.ReadInt(false);
|
||||||
e.floatValue = input.ReadFloat();
|
e.floatValue = input.ReadFloat();
|
||||||
e.stringValue = input.ReadString();
|
e.stringValue = input.ReadString();
|
||||||
@ -1353,7 +1405,7 @@ namespace Spine {
|
|||||||
byteCount = ReadInt(true);
|
byteCount = ReadInt(true);
|
||||||
if (byteCount > 1 && byteCount <= 13) {
|
if (byteCount > 1 && byteCount <= 13) {
|
||||||
byteCount--;
|
byteCount--;
|
||||||
byte[] buffer = new byte[byteCount];
|
var buffer = new byte[byteCount];
|
||||||
ReadFully(buffer, 0, byteCount);
|
ReadFully(buffer, 0, byteCount);
|
||||||
return System.Text.Encoding.UTF8.GetString(buffer, 0, byteCount);
|
return System.Text.Encoding.UTF8.GetString(buffer, 0, byteCount);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,21 @@ using Windows.Storage;
|
|||||||
|
|
||||||
namespace Spine {
|
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;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads skeleton data in the Spine JSON format.
|
/// Loads skeleton data in the Spine JSON format.
|
||||||
/// <para>
|
/// <para>
|
||||||
@ -94,7 +109,7 @@ namespace Spine {
|
|||||||
if (reader == null) throw new ArgumentNullException("reader", "reader cannot be null.");
|
if (reader == null) throw new ArgumentNullException("reader", "reader cannot be null.");
|
||||||
|
|
||||||
float scale = this.scale;
|
float scale = this.scale;
|
||||||
SkeletonData skeletonData = new SkeletonData();
|
var skeletonData = new SkeletonData();
|
||||||
|
|
||||||
Dictionary<string, object> root = Json.Deserialize(reader) as Dictionary<string, Object>;
|
Dictionary<string, object> root = Json.Deserialize(reader) as Dictionary<string, Object>;
|
||||||
if (root == null) throw new Exception("Invalid JSON.");
|
if (root == null) throw new Exception("Invalid JSON.");
|
||||||
@ -123,7 +138,7 @@ namespace Spine {
|
|||||||
if (parent == null)
|
if (parent == null)
|
||||||
throw new Exception("Parent bone not found: " + boneMap["parent"]);
|
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.length = GetFloat(boneMap, "length", 0) * scale;
|
||||||
data.x = GetFloat(boneMap, "x", 0) * scale;
|
data.x = GetFloat(boneMap, "x", 0) * scale;
|
||||||
data.y = GetFloat(boneMap, "y", 0) * scale;
|
data.y = GetFloat(boneMap, "y", 0) * scale;
|
||||||
@ -148,7 +163,7 @@ namespace Spine {
|
|||||||
string boneName = (string)slotMap["bone"];
|
string boneName = (string)slotMap["bone"];
|
||||||
BoneData boneData = skeletonData.FindBone(boneName);
|
BoneData boneData = skeletonData.FindBone(boneName);
|
||||||
if (boneData == null) throw new Exception("Slot bone not found: " + 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")) {
|
if (slotMap.ContainsKey("color")) {
|
||||||
string color = (string)slotMap["color"];
|
string color = (string)slotMap["color"];
|
||||||
@ -179,7 +194,7 @@ namespace Spine {
|
|||||||
// IK constraints.
|
// IK constraints.
|
||||||
if (root.ContainsKey("ik")) {
|
if (root.ContainsKey("ik")) {
|
||||||
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["ik"]) {
|
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["ik"]) {
|
||||||
IkConstraintData data = new IkConstraintData((string)constraintMap["name"]);
|
var data = new IkConstraintData((string)constraintMap["name"]);
|
||||||
data.order = GetInt(constraintMap, "order", 0);
|
data.order = GetInt(constraintMap, "order", 0);
|
||||||
data.skinRequired = GetBoolean(constraintMap, "skin", false);
|
data.skinRequired = GetBoolean(constraintMap, "skin", false);
|
||||||
|
|
||||||
@ -208,7 +223,7 @@ namespace Spine {
|
|||||||
// Transform constraints.
|
// Transform constraints.
|
||||||
if (root.ContainsKey("transform")) {
|
if (root.ContainsKey("transform")) {
|
||||||
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["transform"]) {
|
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["transform"]) {
|
||||||
TransformConstraintData data = new TransformConstraintData((string)constraintMap["name"]);
|
var data = new TransformConstraintData((string)constraintMap["name"]);
|
||||||
data.order = GetInt(constraintMap, "order", 0);
|
data.order = GetInt(constraintMap, "order", 0);
|
||||||
data.skinRequired = GetBoolean(constraintMap, "skin", false);
|
data.skinRequired = GetBoolean(constraintMap, "skin", false);
|
||||||
|
|
||||||
@ -220,26 +235,89 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string targetName = (string)constraintMap["target"];
|
string sourceName = (string)constraintMap["source"];
|
||||||
data.target = skeletonData.FindBone(targetName);
|
data.source = skeletonData.FindBone(sourceName);
|
||||||
if (data.target == null) throw new Exception("Transform constraint target bone not found: " + targetName);
|
if (data.source == null) throw new Exception("Transform constraint source bone not found: " + sourceName);
|
||||||
|
|
||||||
data.local = GetBoolean(constraintMap, "local", false);
|
data.localSource = GetBoolean(constraintMap, "localSource", false);
|
||||||
data.relative = GetBoolean(constraintMap, "relative", false);
|
data.additive = GetBoolean(constraintMap, "additive", false);
|
||||||
|
data.clamp = GetBoolean(constraintMap, "clamp", false);
|
||||||
|
|
||||||
data.offsetRotation = GetFloat(constraintMap, "rotation", 0);
|
bool rotate = false, x = false, y = false, scaleX = false, scaleY = false, shearY = false;
|
||||||
data.offsetX = GetFloat(constraintMap, "x", 0) * scale;
|
if (constraintMap.ContainsKey("properties")) {
|
||||||
data.offsetY = GetFloat(constraintMap, "y", 0) * scale;
|
foreach (KeyValuePair<string, Object> fromEntryObject in (Dictionary<string, Object>)constraintMap["properties"]) {
|
||||||
data.offsetScaleX = GetFloat(constraintMap, "scaleX", 0);
|
var fromEntry = (Dictionary<string, Object>)fromEntryObject.Value;
|
||||||
data.offsetScaleY = GetFloat(constraintMap, "scaleY", 0);
|
string fromEntryName = fromEntryObject.Key;
|
||||||
data.offsetShearY = GetFloat(constraintMap, "shearY", 0);
|
|
||||||
|
|
||||||
data.mixRotate = GetFloat(constraintMap, "mixRotate", 1);
|
FromProperty from;
|
||||||
data.mixX = GetFloat(constraintMap, "mixX", 1);
|
switch (fromEntryName) {
|
||||||
data.mixY = GetFloat(constraintMap, "mixY", data.mixX);
|
case "rotate": from = new FromRotate(); break;
|
||||||
data.mixScaleX = GetFloat(constraintMap, "mixScaleX", 1);
|
case "x": from = new FromX(); break;
|
||||||
data.mixScaleY = GetFloat(constraintMap, "mixScaleY", data.mixScaleX);
|
case "y": from = new FromY(); break;
|
||||||
data.mixShearY = GetFloat(constraintMap, "mixShearY", 1);
|
case "scaleX": from = new FromScaleX(); break;
|
||||||
|
case "scaleY": from = new FromScaleY(); break;
|
||||||
|
case "shearY": from = new FromShearY(); break;
|
||||||
|
default: throw new Exception("Invalid transform constraint from property: " + fromEntryName);
|
||||||
|
};
|
||||||
|
|
||||||
|
from.offset = GetFloat(fromEntry, "offset", 0) * scale;
|
||||||
|
if (fromEntry.ContainsKey("to")) {
|
||||||
|
foreach (KeyValuePair<string, Object> toEntryObject in (Dictionary<string, Object>)fromEntry["to"]) {
|
||||||
|
var toEntry = (Dictionary<string, Object>)toEntryObject.Value;
|
||||||
|
string toEntryName = toEntryObject.Key;
|
||||||
|
|
||||||
|
ToProperty to;
|
||||||
|
switch (toEntryName) {
|
||||||
|
case "rotate": {
|
||||||
|
rotate = true;
|
||||||
|
to = new ToRotate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "x": {
|
||||||
|
x = true;
|
||||||
|
to = new ToX();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "y": {
|
||||||
|
y = true;
|
||||||
|
to = new ToY();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "scaleX": {
|
||||||
|
scaleX = true;
|
||||||
|
to = new ToScaleX();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "scaleY": {
|
||||||
|
scaleY = true;
|
||||||
|
to = new ToScaleY();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "shearY": {
|
||||||
|
shearY = true;
|
||||||
|
to = new ToShearY();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: throw new Exception("Invalid transform constraint to property: " + toEntryName);
|
||||||
|
}
|
||||||
|
to.offset = GetFloat(toEntry, "offset", 0) * scale;
|
||||||
|
to.max = GetFloat(toEntry, "max", 1) * scale;
|
||||||
|
to.scale = GetFloat(toEntry, "scale");
|
||||||
|
from.to.Add(to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (from.to.Count != 0) data.properties.Add(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.offsetX = GetFloat(constraintMap, "x", 0);
|
||||||
|
data.offsetY = GetFloat(constraintMap, "y", 0);
|
||||||
|
if (rotate) data.mixRotate = GetFloat(constraintMap, "mixRotate", 1);
|
||||||
|
if (x) data.mixX = GetFloat(constraintMap, "mixX", 1);
|
||||||
|
if (y) data.mixY = GetFloat(constraintMap, "mixY", data.mixX);
|
||||||
|
if (scaleX) data.mixScaleX = GetFloat(constraintMap, "mixScaleX", 1);
|
||||||
|
if (scaleY) data.mixScaleY = GetFloat(constraintMap, "mixScaleY", data.mixScaleX);
|
||||||
|
if (shearY) data.mixShearY = GetFloat(constraintMap, "mixShearY", 1);
|
||||||
|
|
||||||
skeletonData.transformConstraints.Add(data);
|
skeletonData.transformConstraints.Add(data);
|
||||||
}
|
}
|
||||||
@ -248,7 +326,7 @@ namespace Spine {
|
|||||||
// Path constraints.
|
// Path constraints.
|
||||||
if (root.ContainsKey("path")) {
|
if (root.ContainsKey("path")) {
|
||||||
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["path"]) {
|
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["path"]) {
|
||||||
PathConstraintData data = new PathConstraintData((string)constraintMap["name"]);
|
var data = new PathConstraintData((string)constraintMap["name"]);
|
||||||
data.order = GetInt(constraintMap, "order", 0);
|
data.order = GetInt(constraintMap, "order", 0);
|
||||||
data.skinRequired = GetBoolean(constraintMap, "skin", false);
|
data.skinRequired = GetBoolean(constraintMap, "skin", false);
|
||||||
|
|
||||||
@ -260,9 +338,9 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string targetName = (string)constraintMap["target"];
|
string slotName = (string)constraintMap["slot"];
|
||||||
data.target = skeletonData.FindSlot(targetName);
|
data.slot = skeletonData.FindSlot(slotName);
|
||||||
if (data.target == null) throw new Exception("Path target slot not found: " + targetName);
|
if (data.slot == null) throw new Exception("Path slot not found: " + slotName);
|
||||||
|
|
||||||
data.positionMode = (PositionMode)Enum.Parse(typeof(PositionMode), GetString(constraintMap, "positionMode", "percent"), true);
|
data.positionMode = (PositionMode)Enum.Parse(typeof(PositionMode), GetString(constraintMap, "positionMode", "percent"), true);
|
||||||
data.spacingMode = (SpacingMode)Enum.Parse(typeof(SpacingMode), GetString(constraintMap, "spacingMode", "length"), true);
|
data.spacingMode = (SpacingMode)Enum.Parse(typeof(SpacingMode), GetString(constraintMap, "spacingMode", "length"), true);
|
||||||
@ -283,7 +361,7 @@ namespace Spine {
|
|||||||
// Physics constraints.
|
// Physics constraints.
|
||||||
if (root.ContainsKey("physics")) {
|
if (root.ContainsKey("physics")) {
|
||||||
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["physics"]) {
|
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["physics"]) {
|
||||||
PhysicsConstraintData data = new PhysicsConstraintData((string)constraintMap["name"]);
|
var data = new PhysicsConstraintData((string)constraintMap["name"]);
|
||||||
data.order = GetInt(constraintMap, "order", 0);
|
data.order = GetInt(constraintMap, "order", 0);
|
||||||
data.skinRequired = GetBoolean(constraintMap, "skin", false);
|
data.skinRequired = GetBoolean(constraintMap, "skin", false);
|
||||||
|
|
||||||
@ -320,7 +398,7 @@ namespace Spine {
|
|||||||
// Skins.
|
// Skins.
|
||||||
if (root.ContainsKey("skins")) {
|
if (root.ContainsKey("skins")) {
|
||||||
foreach (Dictionary<string, object> skinMap in (List<object>)root["skins"]) {
|
foreach (Dictionary<string, object> skinMap in (List<object>)root["skins"]) {
|
||||||
Skin skin = new Skin((string)skinMap["name"]);
|
var skin = new Skin((string)skinMap["name"]);
|
||||||
if (skinMap.ContainsKey("bones")) {
|
if (skinMap.ContainsKey("bones")) {
|
||||||
foreach (string entryName in (List<Object>)skinMap["bones"]) {
|
foreach (string entryName in (List<Object>)skinMap["bones"]) {
|
||||||
BoneData bone = skeletonData.FindBone(entryName);
|
BoneData bone = skeletonData.FindBone(entryName);
|
||||||
@ -393,7 +471,7 @@ namespace Spine {
|
|||||||
if (root.ContainsKey("events")) {
|
if (root.ContainsKey("events")) {
|
||||||
foreach (KeyValuePair<string, Object> entry in (Dictionary<string, Object>)root["events"]) {
|
foreach (KeyValuePair<string, Object> entry in (Dictionary<string, Object>)root["events"]) {
|
||||||
Dictionary<string, object> entryMap = (Dictionary<string, Object>)entry.Value;
|
Dictionary<string, object> entryMap = (Dictionary<string, Object>)entry.Value;
|
||||||
EventData data = new EventData(entry.Key);
|
var data = new EventData(entry.Key);
|
||||||
data.Int = GetInt(entryMap, "int", 0);
|
data.Int = GetInt(entryMap, "int", 0);
|
||||||
data.Float = GetFloat(entryMap, "float", 0);
|
data.Float = GetFloat(entryMap, "float", 0);
|
||||||
data.String = GetString(entryMap, "string", string.Empty);
|
data.String = GetString(entryMap, "string", string.Empty);
|
||||||
@ -553,7 +631,7 @@ namespace Spine {
|
|||||||
public static Sequence ReadSequence (object sequenceJson) {
|
public static Sequence ReadSequence (object sequenceJson) {
|
||||||
Dictionary<string, object> map = sequenceJson as Dictionary<string, Object>;
|
Dictionary<string, object> map = sequenceJson as Dictionary<string, Object>;
|
||||||
if (map == null) return null;
|
if (map == null) return null;
|
||||||
Sequence sequence = new Sequence(GetInt(map, "count"));
|
var sequence = new Sequence(GetInt(map, "count"));
|
||||||
sequence.start = GetInt(map, "start", 1);
|
sequence.start = GetInt(map, "start", 1);
|
||||||
sequence.digits = GetInt(map, "digits", 0);
|
sequence.digits = GetInt(map, "digits", 0);
|
||||||
sequence.setupIndex = GetInt(map, "setup", 0);
|
sequence.setupIndex = GetInt(map, "setup", 0);
|
||||||
@ -573,8 +651,8 @@ namespace Spine {
|
|||||||
attachment.vertices = vertices;
|
attachment.vertices = vertices;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ExposedList<float> weights = new ExposedList<float>(verticesLength * 3 * 3);
|
var weights = new ExposedList<float>(verticesLength * 3 * 3);
|
||||||
ExposedList<int> bones = new ExposedList<int>(verticesLength * 3);
|
var bones = new ExposedList<int>(verticesLength * 3);
|
||||||
for (int i = 0, n = vertices.Length; i < n;) {
|
for (int i = 0, n = vertices.Length; i < n;) {
|
||||||
int boneCount = (int)vertices[i++];
|
int boneCount = (int)vertices[i++];
|
||||||
bones.Add(boneCount);
|
bones.Add(boneCount);
|
||||||
@ -598,7 +676,7 @@ namespace Spine {
|
|||||||
|
|
||||||
private void ReadAnimation (Dictionary<string, Object> map, string name, SkeletonData skeletonData) {
|
private void ReadAnimation (Dictionary<string, Object> map, string name, SkeletonData skeletonData) {
|
||||||
float scale = this.scale;
|
float scale = this.scale;
|
||||||
ExposedList<Timeline> timelines = new ExposedList<Timeline>();
|
var timelines = new ExposedList<Timeline>();
|
||||||
|
|
||||||
// Slot timelines.
|
// Slot timelines.
|
||||||
if (map.ContainsKey("slots")) {
|
if (map.ContainsKey("slots")) {
|
||||||
@ -611,16 +689,18 @@ namespace Spine {
|
|||||||
int frames = values.Count;
|
int frames = values.Count;
|
||||||
if (frames == 0) continue;
|
if (frames == 0) continue;
|
||||||
string timelineName = (string)timelineEntry.Key;
|
string timelineName = (string)timelineEntry.Key;
|
||||||
if (timelineName == "attachment") {
|
switch (timelineName) {
|
||||||
AttachmentTimeline timeline = new AttachmentTimeline(frames, slotIndex);
|
case "attachment": {
|
||||||
|
var timeline = new AttachmentTimeline(frames, slotIndex);
|
||||||
int frame = 0;
|
int frame = 0;
|
||||||
foreach (Dictionary<string, Object> keyMap in values) {
|
foreach (Dictionary<string, Object> keyMap in values) {
|
||||||
timeline.SetFrame(frame++, GetFloat(keyMap, "time", 0), GetString(keyMap, "name", null));
|
timeline.SetFrame(frame++, GetFloat(keyMap, "time", 0), GetString(keyMap, "name", null));
|
||||||
}
|
}
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
|
break;
|
||||||
} else if (timelineName == "rgba") {
|
}
|
||||||
RGBATimeline timeline = new RGBATimeline(frames, frames << 2, slotIndex);
|
case "rgba": {
|
||||||
|
var timeline = new RGBATimeline(frames, frames << 2, slotIndex);
|
||||||
|
|
||||||
List<object>.Enumerator keyMapEnumerator = values.GetEnumerator();
|
List<object>.Enumerator keyMapEnumerator = values.GetEnumerator();
|
||||||
keyMapEnumerator.MoveNext();
|
keyMapEnumerator.MoveNext();
|
||||||
@ -661,9 +741,10 @@ namespace Spine {
|
|||||||
keyMap = nextMap;
|
keyMap = nextMap;
|
||||||
}
|
}
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
|
break;
|
||||||
} else if (timelineName == "rgb") {
|
}
|
||||||
RGBTimeline timeline = new RGBTimeline(frames, frames * 3, slotIndex);
|
case "rgb": {
|
||||||
|
var timeline = new RGBTimeline(frames, frames * 3, slotIndex);
|
||||||
|
|
||||||
List<object>.Enumerator keyMapEnumerator = values.GetEnumerator();
|
List<object>.Enumerator keyMapEnumerator = values.GetEnumerator();
|
||||||
keyMapEnumerator.MoveNext();
|
keyMapEnumerator.MoveNext();
|
||||||
@ -700,14 +781,16 @@ namespace Spine {
|
|||||||
keyMap = nextMap;
|
keyMap = nextMap;
|
||||||
}
|
}
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
|
break;
|
||||||
} else if (timelineName == "alpha") {
|
}
|
||||||
|
case "alpha": {
|
||||||
List<object>.Enumerator keyMapEnumerator = values.GetEnumerator();
|
List<object>.Enumerator keyMapEnumerator = values.GetEnumerator();
|
||||||
keyMapEnumerator.MoveNext();
|
keyMapEnumerator.MoveNext();
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, new AlphaTimeline(frames, frames, slotIndex), 0, 1));
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, new AlphaTimeline(frames, frames, slotIndex), 0, 1));
|
||||||
|
break;
|
||||||
} else if (timelineName == "rgba2") {
|
}
|
||||||
RGBA2Timeline timeline = new RGBA2Timeline(frames, frames * 7, slotIndex);
|
case "rgba2": {
|
||||||
|
var timeline = new RGBA2Timeline(frames, frames * 7, slotIndex);
|
||||||
|
|
||||||
List<object>.Enumerator keyMapEnumerator = values.GetEnumerator();
|
List<object>.Enumerator keyMapEnumerator = values.GetEnumerator();
|
||||||
keyMapEnumerator.MoveNext();
|
keyMapEnumerator.MoveNext();
|
||||||
@ -762,9 +845,10 @@ namespace Spine {
|
|||||||
keyMap = nextMap;
|
keyMap = nextMap;
|
||||||
}
|
}
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
|
break;
|
||||||
} else if (timelineName == "rgb2") {
|
}
|
||||||
RGB2Timeline timeline = new RGB2Timeline(frames, frames * 6, slotIndex);
|
case "rgb2": {
|
||||||
|
var timeline = new RGB2Timeline(frames, frames * 6, slotIndex);
|
||||||
|
|
||||||
List<object>.Enumerator keyMapEnumerator = values.GetEnumerator();
|
List<object>.Enumerator keyMapEnumerator = values.GetEnumerator();
|
||||||
keyMapEnumerator.MoveNext();
|
keyMapEnumerator.MoveNext();
|
||||||
@ -815,9 +899,11 @@ namespace Spine {
|
|||||||
keyMap = nextMap;
|
keyMap = nextMap;
|
||||||
}
|
}
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
|
break;
|
||||||
} else
|
}
|
||||||
|
default:
|
||||||
throw new Exception("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
|
throw new Exception("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -842,33 +928,46 @@ namespace Spine {
|
|||||||
if (!keyMapEnumerator.MoveNext()) continue;
|
if (!keyMapEnumerator.MoveNext()) continue;
|
||||||
int frames = values.Count;
|
int frames = values.Count;
|
||||||
string timelineName = (string)timelineEntry.Key;
|
string timelineName = (string)timelineEntry.Key;
|
||||||
if (timelineName == "rotate")
|
switch (timelineName) {
|
||||||
|
case "rotate":
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, new RotateTimeline(frames, frames, boneIndex), 0, 1));
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, new RotateTimeline(frames, frames, boneIndex), 0, 1));
|
||||||
else if (timelineName == "translate") {
|
break;
|
||||||
TranslateTimeline timeline = new TranslateTimeline(frames, frames << 1, boneIndex);
|
case "translate": {
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, timeline, "x", "y", 0, scale));
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, new TranslateTimeline(frames, frames << 1, boneIndex), "x", "y", 0, scale));
|
||||||
} else if (timelineName == "translatex") {
|
break;
|
||||||
|
}
|
||||||
|
case "translatex": {
|
||||||
timelines
|
timelines
|
||||||
.Add(ReadTimeline(ref keyMapEnumerator, new TranslateXTimeline(frames, frames, boneIndex), 0, scale));
|
.Add(ReadTimeline(ref keyMapEnumerator, new TranslateXTimeline(frames, frames, boneIndex), 0, scale));
|
||||||
} else if (timelineName == "translatey") {
|
break;
|
||||||
|
}
|
||||||
|
case "translatey": {
|
||||||
timelines
|
timelines
|
||||||
.Add(ReadTimeline(ref keyMapEnumerator, new TranslateYTimeline(frames, frames, boneIndex), 0, scale));
|
.Add(ReadTimeline(ref keyMapEnumerator, new TranslateYTimeline(frames, frames, boneIndex), 0, scale));
|
||||||
} else if (timelineName == "scale") {
|
break;
|
||||||
ScaleTimeline timeline = new ScaleTimeline(frames, frames << 1, boneIndex);
|
}
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, timeline, "x", "y", 1, 1));
|
case "scale": {
|
||||||
} else if (timelineName == "scalex")
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, new ScaleTimeline(frames, frames << 1, boneIndex), "x", "y", 1, 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "scalex":
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, new ScaleXTimeline(frames, frames, boneIndex), 1, 1));
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, new ScaleXTimeline(frames, frames, boneIndex), 1, 1));
|
||||||
else if (timelineName == "scaley")
|
break;
|
||||||
|
case "scaley":
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, new ScaleYTimeline(frames, frames, boneIndex), 1, 1));
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, new ScaleYTimeline(frames, frames, boneIndex), 1, 1));
|
||||||
else if (timelineName == "shear") {
|
break;
|
||||||
ShearTimeline timeline = new ShearTimeline(frames, frames << 1, boneIndex);
|
case "shear": {
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, timeline, "x", "y", 0, 1));
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, new ShearTimeline(frames, frames << 1, boneIndex), "x", "y", 0, 1));
|
||||||
} else if (timelineName == "shearx")
|
break;
|
||||||
|
}
|
||||||
|
case "shearx":
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, new ShearXTimeline(frames, frames, boneIndex), 0, 1));
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, new ShearXTimeline(frames, frames, boneIndex), 0, 1));
|
||||||
else if (timelineName == "sheary")
|
break;
|
||||||
|
case "sheary":
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, new ShearYTimeline(frames, frames, boneIndex), 0, 1));
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, new ShearYTimeline(frames, frames, boneIndex), 0, 1));
|
||||||
else if (timelineName == "inherit") {
|
break;
|
||||||
InheritTimeline timeline = new InheritTimeline(frames, boneIndex);
|
case "inherit": {
|
||||||
|
var timeline = new InheritTimeline(frames, boneIndex);
|
||||||
for (int frame = 0; ; frame++) {
|
for (int frame = 0; ; frame++) {
|
||||||
Dictionary<string, object> keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
|
Dictionary<string, object> keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
|
||||||
float time = GetFloat(keyMap, "time", 0);
|
float time = GetFloat(keyMap, "time", 0);
|
||||||
@ -879,8 +978,11 @@ namespace Spine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
} else
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
|
throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -893,7 +995,7 @@ namespace Spine {
|
|||||||
if (!keyMapEnumerator.MoveNext()) continue;
|
if (!keyMapEnumerator.MoveNext()) continue;
|
||||||
Dictionary<string, object> keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
|
Dictionary<string, object> keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
|
||||||
IkConstraintData constraint = skeletonData.FindIkConstraint(timelineMap.Key);
|
IkConstraintData constraint = skeletonData.FindIkConstraint(timelineMap.Key);
|
||||||
IkConstraintTimeline timeline = new IkConstraintTimeline(values.Count, values.Count << 1,
|
var timeline = new IkConstraintTimeline(values.Count, values.Count << 1,
|
||||||
skeletonData.IkConstraints.IndexOf(constraint));
|
skeletonData.IkConstraints.IndexOf(constraint));
|
||||||
float time = GetFloat(keyMap, "time", 0);
|
float time = GetFloat(keyMap, "time", 0);
|
||||||
float mix = GetFloat(keyMap, "mix", 1), softness = GetFloat(keyMap, "softness", 0) * scale;
|
float mix = GetFloat(keyMap, "mix", 1), softness = GetFloat(keyMap, "softness", 0) * scale;
|
||||||
@ -929,7 +1031,7 @@ namespace Spine {
|
|||||||
if (!keyMapEnumerator.MoveNext()) continue;
|
if (!keyMapEnumerator.MoveNext()) continue;
|
||||||
Dictionary<string, object> keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
|
Dictionary<string, object> keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
|
||||||
TransformConstraintData constraint = skeletonData.FindTransformConstraint(timelineMap.Key);
|
TransformConstraintData constraint = skeletonData.FindTransformConstraint(timelineMap.Key);
|
||||||
TransformConstraintTimeline timeline = new TransformConstraintTimeline(values.Count, values.Count * 6,
|
var timeline = new TransformConstraintTimeline(values.Count, values.Count * 6,
|
||||||
skeletonData.TransformConstraints.IndexOf(constraint));
|
skeletonData.TransformConstraints.IndexOf(constraint));
|
||||||
float time = GetFloat(keyMap, "time", 0);
|
float time = GetFloat(keyMap, "time", 0);
|
||||||
float mixRotate = GetFloat(keyMap, "mixRotate", 1), mixShearY = GetFloat(keyMap, "mixShearY", 1);
|
float mixRotate = GetFloat(keyMap, "mixRotate", 1), mixShearY = GetFloat(keyMap, "mixShearY", 1);
|
||||||
@ -982,15 +1084,20 @@ namespace Spine {
|
|||||||
|
|
||||||
int frames = values.Count;
|
int frames = values.Count;
|
||||||
string timelineName = (string)timelineEntry.Key;
|
string timelineName = (string)timelineEntry.Key;
|
||||||
if (timelineName == "position") {
|
switch (timelineName) {
|
||||||
|
case "position": {
|
||||||
CurveTimeline1 timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex);
|
CurveTimeline1 timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex);
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, timeline, 0, constraint.positionMode == PositionMode.Fixed ? scale : 1));
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, timeline, 0, constraint.positionMode == PositionMode.Fixed ? scale : 1));
|
||||||
} else if (timelineName == "spacing") {
|
break;
|
||||||
|
}
|
||||||
|
case "spacing": {
|
||||||
CurveTimeline1 timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex);
|
CurveTimeline1 timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex);
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, timeline, 0,
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, timeline, 0,
|
||||||
constraint.spacingMode == SpacingMode.Length || constraint.spacingMode == SpacingMode.Fixed ? scale : 1));
|
constraint.spacingMode == SpacingMode.Length || constraint.spacingMode == SpacingMode.Fixed ? scale : 1));
|
||||||
} else if (timelineName == "mix") {
|
break;
|
||||||
PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex);
|
}
|
||||||
|
case "mix": {
|
||||||
|
var timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex);
|
||||||
Dictionary<string, object> keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
|
Dictionary<string, object> keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
|
||||||
float time = GetFloat(keyMap, "time", 0);
|
float time = GetFloat(keyMap, "time", 0);
|
||||||
float mixRotate = GetFloat(keyMap, "mixRotate", 1);
|
float mixRotate = GetFloat(keyMap, "mixRotate", 1);
|
||||||
@ -1018,6 +1125,8 @@ namespace Spine {
|
|||||||
keyMap = nextMap;
|
keyMap = nextMap;
|
||||||
}
|
}
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1040,33 +1149,41 @@ namespace Spine {
|
|||||||
|
|
||||||
int frames = values.Count;
|
int frames = values.Count;
|
||||||
string timelineName = (string)timelineEntry.Key;
|
string timelineName = (string)timelineEntry.Key;
|
||||||
if (timelineName == "reset") {
|
CurveTimeline1 timeline;
|
||||||
PhysicsConstraintResetTimeline timeline1 = new PhysicsConstraintResetTimeline(frames, index);
|
switch (timelineName) {
|
||||||
|
case "reset": {
|
||||||
|
var resetTimeline = new PhysicsConstraintResetTimeline(frames, index);
|
||||||
int frame = 0;
|
int frame = 0;
|
||||||
foreach (Dictionary<string, Object> keyMap in values) {
|
foreach (Dictionary<string, Object> keyMap in values) {
|
||||||
timeline1.SetFrame(frame++, GetFloat(keyMap, "time", 0));
|
resetTimeline.SetFrame(frame++, GetFloat(keyMap, "time", 0));
|
||||||
}
|
}
|
||||||
timelines.Add(timeline1);
|
timelines.Add(resetTimeline);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
case "inertia":
|
||||||
CurveTimeline1 timeline;
|
|
||||||
if (timelineName == "inertia")
|
|
||||||
timeline = new PhysicsConstraintInertiaTimeline(frames, frames, index);
|
timeline = new PhysicsConstraintInertiaTimeline(frames, frames, index);
|
||||||
else if (timelineName == "strength")
|
break;
|
||||||
|
case "strength":
|
||||||
timeline = new PhysicsConstraintStrengthTimeline(frames, frames, index);
|
timeline = new PhysicsConstraintStrengthTimeline(frames, frames, index);
|
||||||
else if (timelineName == "damping")
|
break;
|
||||||
|
case "damping":
|
||||||
timeline = new PhysicsConstraintDampingTimeline(frames, frames, index);
|
timeline = new PhysicsConstraintDampingTimeline(frames, frames, index);
|
||||||
else if (timelineName == "mass")
|
break;
|
||||||
|
case "mass":
|
||||||
timeline = new PhysicsConstraintMassTimeline(frames, frames, index);
|
timeline = new PhysicsConstraintMassTimeline(frames, frames, index);
|
||||||
else if (timelineName == "wind")
|
break;
|
||||||
|
case "wind":
|
||||||
timeline = new PhysicsConstraintWindTimeline(frames, frames, index);
|
timeline = new PhysicsConstraintWindTimeline(frames, frames, index);
|
||||||
else if (timelineName == "gravity")
|
break;
|
||||||
|
case "gravity":
|
||||||
timeline = new PhysicsConstraintGravityTimeline(frames, frames, index);
|
timeline = new PhysicsConstraintGravityTimeline(frames, frames, index);
|
||||||
else if (timelineName == "mix") //
|
break;
|
||||||
|
case "mix":
|
||||||
timeline = new PhysicsConstraintMixTimeline(frames, frames, index);
|
timeline = new PhysicsConstraintMixTimeline(frames, frames, index);
|
||||||
else
|
break;
|
||||||
|
default:
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
timelines.Add(ReadTimeline(ref keyMapEnumerator, timeline, 0, 1));
|
timelines.Add(ReadTimeline(ref keyMapEnumerator, timeline, 0, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1089,13 +1206,14 @@ namespace Spine {
|
|||||||
Dictionary<string, object> keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
|
Dictionary<string, object> keyMap = (Dictionary<string, Object>)keyMapEnumerator.Current;
|
||||||
int frames = values.Count;
|
int frames = values.Count;
|
||||||
string timelineName = timelineMap.Key;
|
string timelineName = timelineMap.Key;
|
||||||
if (timelineName == "deform") {
|
switch (timelineName) {
|
||||||
|
case "deform": {
|
||||||
VertexAttachment vertexAttachment = (VertexAttachment)attachment;
|
VertexAttachment vertexAttachment = (VertexAttachment)attachment;
|
||||||
bool weighted = vertexAttachment.bones != null;
|
bool weighted = vertexAttachment.bones != null;
|
||||||
float[] vertices = vertexAttachment.vertices;
|
float[] vertices = vertexAttachment.vertices;
|
||||||
int deformLength = weighted ? (vertices.Length / 3) << 1 : vertices.Length;
|
int deformLength = weighted ? (vertices.Length / 3) << 1 : vertices.Length;
|
||||||
|
|
||||||
DeformTimeline timeline = new DeformTimeline(frames, frames, slot.Index, vertexAttachment);
|
var timeline = new DeformTimeline(frames, frames, slot.Index, vertexAttachment);
|
||||||
float time = GetFloat(keyMap, "time", 0);
|
float time = GetFloat(keyMap, "time", 0);
|
||||||
for (int frame = 0, bezier = 0; ; frame++) {
|
for (int frame = 0, bezier = 0; ; frame++) {
|
||||||
float[] deform;
|
float[] deform;
|
||||||
@ -1132,8 +1250,10 @@ namespace Spine {
|
|||||||
keyMap = nextMap;
|
keyMap = nextMap;
|
||||||
}
|
}
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
} else if (timelineName == "sequence") {
|
break;
|
||||||
SequenceTimeline timeline = new SequenceTimeline(frames, slot.index, attachment);
|
}
|
||||||
|
case "sequence": {
|
||||||
|
var timeline = new SequenceTimeline(frames, slot.index, attachment);
|
||||||
float lastDelay = 0;
|
float lastDelay = 0;
|
||||||
for (int frame = 0; keyMap != null; keyMap = keyMapEnumerator.MoveNext() ?
|
for (int frame = 0; keyMap != null; keyMap = keyMapEnumerator.MoveNext() ?
|
||||||
(Dictionary<string, Object>)keyMapEnumerator.Current : null, frame++) {
|
(Dictionary<string, Object>)keyMapEnumerator.Current : null, frame++) {
|
||||||
@ -1146,6 +1266,8 @@ namespace Spine {
|
|||||||
lastDelay = delay;
|
lastDelay = delay;
|
||||||
}
|
}
|
||||||
timelines.Add(timeline);
|
timelines.Add(timeline);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1156,7 +1278,7 @@ namespace Spine {
|
|||||||
// Draw order timeline.
|
// Draw order timeline.
|
||||||
if (map.ContainsKey("drawOrder")) {
|
if (map.ContainsKey("drawOrder")) {
|
||||||
List<object> values = (List<Object>)map["drawOrder"];
|
List<object> values = (List<Object>)map["drawOrder"];
|
||||||
DrawOrderTimeline timeline = new DrawOrderTimeline(values.Count);
|
var timeline = new DrawOrderTimeline(values.Count);
|
||||||
int slotCount = skeletonData.slots.Count;
|
int slotCount = skeletonData.slots.Count;
|
||||||
int frame = 0;
|
int frame = 0;
|
||||||
foreach (Dictionary<string, Object> keyMap in values) {
|
foreach (Dictionary<string, Object> keyMap in values) {
|
||||||
@ -1193,12 +1315,12 @@ namespace Spine {
|
|||||||
// Event timeline.
|
// Event timeline.
|
||||||
if (map.ContainsKey("events")) {
|
if (map.ContainsKey("events")) {
|
||||||
List<object> eventsMap = (List<Object>)map["events"];
|
List<object> eventsMap = (List<Object>)map["events"];
|
||||||
EventTimeline timeline = new EventTimeline(eventsMap.Count);
|
var timeline = new EventTimeline(eventsMap.Count);
|
||||||
int frame = 0;
|
int frame = 0;
|
||||||
foreach (Dictionary<string, Object> keyMap in eventsMap) {
|
foreach (Dictionary<string, Object> keyMap in eventsMap) {
|
||||||
EventData eventData = skeletonData.FindEvent((string)keyMap["name"]);
|
EventData eventData = skeletonData.FindEvent((string)keyMap["name"]);
|
||||||
if (eventData == null) throw new Exception("Event not found: " + keyMap["name"]);
|
if (eventData == null) throw new Exception("Event not found: " + keyMap["name"]);
|
||||||
Event e = new Event(GetFloat(keyMap, "time", 0), eventData) {
|
var e = new Event(GetFloat(keyMap, "time", 0), eventData) {
|
||||||
intValue = GetInt(keyMap, "int", eventData.Int),
|
intValue = GetInt(keyMap, "int", eventData.Int),
|
||||||
floatValue = GetFloat(keyMap, "float", eventData.Float),
|
floatValue = GetFloat(keyMap, "float", eventData.Float),
|
||||||
stringValue = GetString(keyMap, "string", eventData.String)
|
stringValue = GetString(keyMap, "string", eventData.String)
|
||||||
@ -1319,6 +1441,11 @@ namespace Spine {
|
|||||||
return (float)map[name];
|
return (float)map[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float GetFloat (Dictionary<string, Object> map, string name) {
|
||||||
|
if (!map.ContainsKey(name)) throw new ArgumentException("Named value not found: " + name);
|
||||||
|
return (float)map[name];
|
||||||
|
}
|
||||||
|
|
||||||
static int GetInt (Dictionary<string, Object> map, string name, int defaultValue) {
|
static int GetInt (Dictionary<string, Object> map, string name, int defaultValue) {
|
||||||
if (!map.ContainsKey(name)) return defaultValue;
|
if (!map.ContainsKey(name)) return defaultValue;
|
||||||
return (int)(float)map[name];
|
return (int)(float)map[name];
|
||||||
|
|||||||
@ -30,19 +30,21 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Spine {
|
namespace Spine {
|
||||||
|
using FromProperty = TransformConstraintData.FromProperty;
|
||||||
using Physics = Skeleton.Physics;
|
using Physics = Skeleton.Physics;
|
||||||
|
using ToProperty = TransformConstraintData.ToProperty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// Stores the current pose for a transform constraint. A transform constraint adjusts the world transform of the constrained
|
/// Stores the current pose for a transform constraint. A transform constraint adjusts the world transform of the constrained
|
||||||
/// bones to match that of the target bone.</para>
|
/// bones to match that of the source bone.</para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// See <a href="http://esotericsoftware.com/spine-transform-constraints">Transform constraints</a> in the Spine User Guide.</para>
|
/// See <a href="http://esotericsoftware.com/spine-transform-constraints">Transform constraints</a> in the Spine User Guide.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TransformConstraint : IUpdatable {
|
public class TransformConstraint : IUpdatable {
|
||||||
internal readonly TransformConstraintData data;
|
internal readonly TransformConstraintData data;
|
||||||
internal readonly ExposedList<Bone> bones;
|
internal readonly ExposedList<Bone> bones;
|
||||||
internal Bone target;
|
internal Bone source;
|
||||||
internal float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
|
internal float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
|
||||||
|
|
||||||
internal bool active;
|
internal bool active;
|
||||||
@ -56,7 +58,7 @@ namespace Spine {
|
|||||||
foreach (BoneData boneData in data.bones)
|
foreach (BoneData boneData in data.bones)
|
||||||
bones.Add(skeleton.bones.Items[boneData.index]);
|
bones.Add(skeleton.bones.Items[boneData.index]);
|
||||||
|
|
||||||
target = skeleton.bones.Items[data.target.index];
|
source = skeleton.bones.Items[data.source.index];
|
||||||
|
|
||||||
mixRotate = data.mixRotate;
|
mixRotate = data.mixRotate;
|
||||||
mixX = data.mixX;
|
mixX = data.mixX;
|
||||||
@ -90,205 +92,44 @@ namespace Spine {
|
|||||||
|
|
||||||
public void Update (Physics physics) {
|
public void Update (Physics physics) {
|
||||||
if (mixRotate == 0 && mixX == 0 && mixY == 0 && mixScaleX == 0 && mixScaleY == 0 && mixShearY == 0) return;
|
if (mixRotate == 0 && mixX == 0 && mixY == 0 && mixScaleX == 0 && mixScaleY == 0 && mixShearY == 0) return;
|
||||||
if (data.local) {
|
|
||||||
if (data.relative)
|
TransformConstraintData data = this.data;
|
||||||
ApplyRelativeLocal();
|
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
|
else
|
||||||
ApplyAbsoluteLocal();
|
bone.UpdateAppliedTransform();
|
||||||
} 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>The bones that will be modified by this transform constraint.</summary>
|
/// <summary>The bones that will be modified by this transform constraint.</summary>
|
||||||
public ExposedList<Bone> Bones { get { return bones; } }
|
public ExposedList<Bone> Bones { get { return bones; } }
|
||||||
/// <summary>The target bone whose world transform will be copied to the constrained bones.</summary>
|
/// <summary>The bone whose world transform will be copied to the constrained bones.</summary>
|
||||||
public Bone Target { get { return target; } set { target = value; } }
|
public Bone Source { get { return source; } set { source = value; } }
|
||||||
/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.</summary>
|
/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.</summary>
|
||||||
public float MixRotate { get { return mixRotate; } set { mixRotate = value; } }
|
public float MixRotate { get { return mixRotate; } set { mixRotate = value; } }
|
||||||
/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.</summary>
|
/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.</summary>
|
||||||
|
|||||||
@ -31,14 +31,31 @@ using System;
|
|||||||
|
|
||||||
namespace Spine {
|
namespace Spine {
|
||||||
public class TransformConstraintData : ConstraintData {
|
public class TransformConstraintData : ConstraintData {
|
||||||
internal ExposedList<BoneData> bones = new ExposedList<BoneData>();
|
internal readonly ExposedList<BoneData> bones = new ExposedList<BoneData>();
|
||||||
internal BoneData target;
|
internal BoneData source;
|
||||||
internal float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
|
internal float offsetX, offsetY, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY;
|
||||||
internal float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
|
internal bool localSource, localTarget, additive, clamp;
|
||||||
internal bool relative, local;
|
internal readonly ExposedList<FromProperty> properties = new ExposedList<FromProperty>();
|
||||||
|
|
||||||
|
public TransformConstraintData (string name) : base(name) {
|
||||||
|
}
|
||||||
|
|
||||||
public ExposedList<BoneData> Bones { get { return bones; } }
|
public ExposedList<BoneData> Bones { get { return bones; } }
|
||||||
public BoneData Target { get { return target; } set { target = value; } }
|
|
||||||
|
/// <summary>The bone whose world transform will be copied to the constrained bones.</summary>
|
||||||
|
public BoneData Source {
|
||||||
|
get { return source; }
|
||||||
|
set {
|
||||||
|
if (source == null) throw new ArgumentNullException("Source", "source cannot be null.");
|
||||||
|
source = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>The mapping of transform properties to other transform properties.</summary>
|
||||||
|
public ExposedList<FromProperty> Properties {
|
||||||
|
get { return properties; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.</summary>
|
/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.</summary>
|
||||||
public float MixRotate { get { return mixRotate; } set { mixRotate = value; } }
|
public float MixRotate { get { return mixRotate; } set { mixRotate = value; } }
|
||||||
/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.</summary>
|
/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.</summary>
|
||||||
@ -51,18 +68,222 @@ namespace Spine {
|
|||||||
public float MixScaleY { get { return mixScaleY; } set { mixScaleY = value; } }
|
public float MixScaleY { get { return mixScaleY; } set { mixScaleY = value; } }
|
||||||
/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y.</summary>
|
/// <summary>A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y.</summary>
|
||||||
public float MixShearY { get { return mixShearY; } set { mixShearY = value; } }
|
public float MixShearY { get { return mixShearY; } set { mixShearY = value; } }
|
||||||
|
/// <summary>An offset added to the constrained bone X translation.</summary>
|
||||||
public float OffsetRotation { get { return offsetRotation; } set { offsetRotation = value; } }
|
|
||||||
public float OffsetX { get { return offsetX; } set { offsetX = value; } }
|
public float OffsetX { get { return offsetX; } set { offsetX = value; } }
|
||||||
|
/// <summary>An offset added to the constrained bone Y translation.</summary>
|
||||||
public float OffsetY { get { return offsetY; } set { offsetY = value; } }
|
public float OffsetY { get { return offsetY; } set { offsetY = value; } }
|
||||||
public float OffsetScaleX { get { return offsetScaleX; } set { offsetScaleX = value; } }
|
/// <summary>Reads the source bone's local transform instead of its world transform.</summary>
|
||||||
public float OffsetScaleY { get { return offsetScaleY; } set { offsetScaleY = value; } }
|
public bool LocalSource { get { return localSource; } set { localSource = value; } }
|
||||||
public float OffsetShearY { get { return offsetShearY; } set { offsetShearY = value; } }
|
/// <summary>Sets the constrained bones' local transforms instead of their world transforms.</summary>
|
||||||
|
public bool LocalTarget { get { return localTarget; } set { localTarget = value; } }
|
||||||
|
/// <summary>Adds the source bone transform to the constrained bones instead of setting it absolutely.</summary>
|
||||||
|
public bool Additive { get { return additive; } set { additive = value; } }
|
||||||
|
/// <summary>Prevents constrained bones from exceeding the ranged defined by <see cref="ToProperty.offset"/> and
|
||||||
|
/// <see cref="ToProperty.max"/>.</summary>
|
||||||
|
public bool Clamp { get { return clamp; } set { clamp = value; } }
|
||||||
|
|
||||||
public bool Relative { get { return relative; } set { relative = value; } }
|
/// <summary>Source property for a <see cref="TransformConstraint"/>.</summary>
|
||||||
public bool Local { get { return local; } set { local = value; } }
|
abstract public class FromProperty {
|
||||||
|
/// <summary>The value of this property that corresponds to <see cref="ToProperty.offset"/>.</summary>
|
||||||
|
public float offset;
|
||||||
|
|
||||||
public TransformConstraintData (string name) : base(name) {
|
/// <summary>Constrained properties.</summary>
|
||||||
|
public readonly ExposedList<ToProperty> to = new ExposedList<ToProperty>();
|
||||||
|
|
||||||
|
/// <summary>Reads this property from the specified bone.</summary>
|
||||||
|
abstract public float Value (TransformConstraintData data, Bone source, bool local);
|
||||||
|
}
|
||||||
|
|
||||||
|
///<summary>Constrained property for a <see cref="TransformConstraint"/>.</summary>
|
||||||
|
abstract public class ToProperty {
|
||||||
|
/// <summary>The value of this property that corresponds to <see cref="FromProperty.offset"/>.</summary>
|
||||||
|
public float offset;
|
||||||
|
|
||||||
|
/// <summary>The maximum value of this property when <see cref="TransformConstraintData.clamp"/> clamped.</summary>
|
||||||
|
public float max;
|
||||||
|
|
||||||
|
/// <summary>The scale of the <see cref="FromProperty"/> value in relation to this property.</summary>
|
||||||
|
public float scale;
|
||||||
|
|
||||||
|
/// <summary>Reads the mix for this property from the specified constraint.</summary>
|
||||||
|
public abstract float Mix (TransformConstraint constraint);
|
||||||
|
|
||||||
|
/// <summary>Applies the value to this property.</summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -397,8 +397,8 @@ namespace Spine.Unity.Editor {
|
|||||||
// Transform Constraints
|
// Transform Constraints
|
||||||
handleColor = SpineHandles.TransformContraintColor;
|
handleColor = SpineHandles.TransformContraintColor;
|
||||||
foreach (TransformConstraint tc in skeleton.TransformConstraints) {
|
foreach (TransformConstraint tc in skeleton.TransformConstraints) {
|
||||||
Bone targetBone = tc.Target;
|
Bone sourceBone = tc.Source;
|
||||||
targetPos = targetBone.GetWorldPosition(transform, skeletonRenderScale, offset);
|
targetPos = sourceBone.GetWorldPosition(transform, skeletonRenderScale, offset);
|
||||||
|
|
||||||
if (tc.MixX > 0 || tc.MixY > 0) {
|
if (tc.MixX > 0 || tc.MixY > 0) {
|
||||||
if ((tc.MixX > 0 && tc.MixX != 1f) ||
|
if ((tc.MixX > 0 && tc.MixX != 1f) ||
|
||||||
@ -411,7 +411,7 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
SpineHandles.DrawBoneCircle(targetPos, handleColor, normal, 1.3f * skeletonRenderScale);
|
SpineHandles.DrawBoneCircle(targetPos, handleColor, normal, 1.3f * skeletonRenderScale);
|
||||||
Handles.color = handleColor;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -415,7 +415,7 @@ namespace Spine.Unity.Editor {
|
|||||||
foreach (TransformConstraint c in skeleton.TransformConstraints) {
|
foreach (TransformConstraint c in skeleton.TransformConstraints) {
|
||||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintTransform));
|
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintTransform));
|
||||||
EditorGUI.BeginDisabledGroup(true);
|
EditorGUI.BeginDisabledGroup(true);
|
||||||
FalseDropDown("Goal", c.Data.Target.Name, Icons.bone);
|
FalseDropDown("Source", c.Data.Source.Name, Icons.bone);
|
||||||
EditorGUI.EndDisabledGroup();
|
EditorGUI.EndDisabledGroup();
|
||||||
|
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
@ -469,7 +469,7 @@ namespace Spine.Unity.Editor {
|
|||||||
foreach (PathConstraint c in skeleton.PathConstraints) {
|
foreach (PathConstraint c in skeleton.PathConstraints) {
|
||||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintPath));
|
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintPath));
|
||||||
EditorGUI.BeginDisabledGroup(true);
|
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;
|
Attachment activeAttachment = c.Target.Attachment;
|
||||||
FalseDropDown("Active Path", activeAttachment != null ? activeAttachment.Name : "<None>", activeAttachment is PathAttachment ? Icons.path : null);
|
FalseDropDown("Active Path", activeAttachment != null ? activeAttachment.Name : "<None>", activeAttachment is PathAttachment ? Icons.path : null);
|
||||||
EditorGUILayout.LabelField("PositionMode." + c.Data.PositionMode);
|
EditorGUILayout.LabelField("PositionMode." + c.Data.PositionMode);
|
||||||
|
|||||||
@ -446,8 +446,8 @@ namespace Spine.Unity {
|
|||||||
if (useLastConstraintPos)
|
if (useLastConstraintPos)
|
||||||
constraintPos = transformConstraintLastPos[GetConstraintLastPosIndex(constraintIndex)];
|
constraintPos = transformConstraintLastPos[GetConstraintLastPosIndex(constraintIndex)];
|
||||||
else {
|
else {
|
||||||
Bone targetBone = constraint.Target;
|
Bone sourceBone = constraint.Source;
|
||||||
constraintPos = new Vector2(targetBone.X, targetBone.Y);
|
constraintPos = new Vector2(sourceBone.X, sourceBone.Y);
|
||||||
}
|
}
|
||||||
pos = new Vector2(
|
pos = new Vector2(
|
||||||
pos.x * invMixXY.x + constraintPos.x * mixXY.x,
|
pos.x * invMixXY.x + constraintPos.x * mixXY.x,
|
||||||
@ -465,8 +465,8 @@ namespace Spine.Unity {
|
|||||||
if (useLastConstraintRotation)
|
if (useLastConstraintRotation)
|
||||||
constraintRotation = transformConstraintLastRotation[GetConstraintLastPosIndex(constraintIndex)];
|
constraintRotation = transformConstraintLastRotation[GetConstraintLastPosIndex(constraintIndex)];
|
||||||
else {
|
else {
|
||||||
Bone targetBone = constraint.Target;
|
Bone sourceBone = constraint.Source;
|
||||||
constraintRotation = targetBone.Rotation;
|
constraintRotation = sourceBone.Rotation;
|
||||||
}
|
}
|
||||||
rotation = rotation * invMixRotate + constraintRotation * mixRotate;
|
rotation = rotation * invMixRotate + constraintRotation * mixRotate;
|
||||||
}
|
}
|
||||||
@ -474,16 +474,16 @@ namespace Spine.Unity {
|
|||||||
void UpdateLastConstraintPos (TransformConstraint[] transformConstraintsItems) {
|
void UpdateLastConstraintPos (TransformConstraint[] transformConstraintsItems) {
|
||||||
foreach (int constraintIndex in this.transformConstraintIndices) {
|
foreach (int constraintIndex in this.transformConstraintIndices) {
|
||||||
TransformConstraint constraint = transformConstraintsItems[constraintIndex];
|
TransformConstraint constraint = transformConstraintsItems[constraintIndex];
|
||||||
Bone targetBone = constraint.Target;
|
Bone sourceBone = constraint.Source;
|
||||||
transformConstraintLastPos[GetConstraintLastPosIndex(constraintIndex)] = new Vector2(targetBone.X, targetBone.Y);
|
transformConstraintLastPos[GetConstraintLastPosIndex(constraintIndex)] = new Vector2(sourceBone.X, sourceBone.Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateLastConstraintRotation (TransformConstraint[] transformConstraintsItems) {
|
void UpdateLastConstraintRotation (TransformConstraint[] transformConstraintsItems) {
|
||||||
foreach (int constraintIndex in this.transformConstraintIndices) {
|
foreach (int constraintIndex in this.transformConstraintIndices) {
|
||||||
TransformConstraint constraint = transformConstraintsItems[constraintIndex];
|
TransformConstraint constraint = transformConstraintsItems[constraintIndex];
|
||||||
Bone targetBone = constraint.Target;
|
Bone sourceBone = constraint.Source;
|
||||||
transformConstraintLastRotation[GetConstraintLastPosIndex(constraintIndex)] = targetBone.Rotation;
|
transformConstraintLastRotation[GetConstraintLastPosIndex(constraintIndex)] = sourceBone.Rotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,10 +524,10 @@ namespace Spine.Unity {
|
|||||||
TransformConstraint constraint = constraintsItems[i];
|
TransformConstraint constraint = constraintsItems[i];
|
||||||
if (constraint.Bones.Contains(rootMotionBone)) {
|
if (constraint.Bones.Contains(rootMotionBone)) {
|
||||||
transformConstraintIndices.Add(i);
|
transformConstraintIndices.Add(i);
|
||||||
Bone targetBone = constraint.Target;
|
Bone sourceBone = constraint.Source;
|
||||||
Vector2 constraintPos = new Vector2(targetBone.X, targetBone.Y);
|
Vector2 constraintPos = new Vector2(sourceBone.X, sourceBone.Y);
|
||||||
transformConstraintLastPos.Add(constraintPos);
|
transformConstraintLastPos.Add(constraintPos);
|
||||||
transformConstraintLastRotation.Add(targetBone.Rotation);
|
transformConstraintLastRotation.Add(sourceBone.Rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -360,7 +360,7 @@ namespace Spine.Unity {
|
|||||||
|
|
||||||
ExposedList<TransformConstraint> transformConstraints = skeleton.TransformConstraints;
|
ExposedList<TransformConstraint> transformConstraints = skeleton.TransformConstraints;
|
||||||
for (int i = 0, n = transformConstraints.Count; i < n; i++)
|
for (int i = 0, n = transformConstraints.Count; i < n; i++)
|
||||||
constraintTargets.Add(transformConstraints.Items[i].Target);
|
constraintTargets.Add(transformConstraints.Items[i].Source);
|
||||||
|
|
||||||
List<SkeletonUtilityBone> boneComponents = this.boneComponents;
|
List<SkeletonUtilityBone> boneComponents = this.boneComponents;
|
||||||
for (int i = 0, n = boneComponents.Count; i < n; i++) {
|
for (int i = 0, n = boneComponents.Count; i < n; i++) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user