mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-21 09:46:02 +08:00
[csharp] See #1346: Port bone/constraint association with skins. Also contains second (and final) partial port of commit ff5b854. Adapted spine-unity for skin changes. Fixed a bug in Skin setter property.
This commit is contained in:
parent
1eea0c24c9
commit
c63bc7b88f
@ -52,7 +52,7 @@ namespace Spine {
|
||||
/// <summary>The duration of the animation in seconds, which is the highest time of all keys in the timeline.</summary>
|
||||
public float Duration { get { return duration; } set { duration = value; } }
|
||||
|
||||
/// <summary>The animation's name, which is unique within the skeleton.</summary>
|
||||
/// <summary>The animation's name, which is unique across all animations in the skeleton.</summary>
|
||||
public string Name { get { return name; } }
|
||||
|
||||
/// <summary>Applies all the animation's timelines to the specified skeleton.</summary>
|
||||
|
||||
@ -195,8 +195,8 @@ namespace Spine {
|
||||
copy.rotation = rotation;
|
||||
copy.width = width;
|
||||
copy.height = height;
|
||||
Array.Copy(uvs, 0, copy.uvs, 0, uvs.Length);
|
||||
Array.Copy(offset, 0, copy.offset, 0, offset.Length);
|
||||
Array.Copy(uvs, 0, copy.uvs, 0, 8);
|
||||
Array.Copy(offset, 0, copy.offset, 0, 8);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,8 +133,7 @@ namespace Spine {
|
||||
return this == sourceAttachment;
|
||||
}
|
||||
|
||||
///<summary>Internal method used by VertexAttachment subclasses to copy basic data. Does not copy id (generated) and name (set on
|
||||
/// construction).</summary>
|
||||
///<summary>Does not copy id (generated) or name (set on construction).</summary>
|
||||
internal void CopyTo (VertexAttachment attachment) {
|
||||
if (bones != null) {
|
||||
attachment.bones = new int[bones.Length];
|
||||
|
||||
@ -52,7 +52,7 @@ namespace Spine {
|
||||
internal float a, b, worldX;
|
||||
internal float c, d, worldY;
|
||||
|
||||
internal bool sorted;
|
||||
internal bool sorted, update;
|
||||
|
||||
public BoneData Data { get { return data; } }
|
||||
public Skeleton Skeleton { get { return skeleton; } }
|
||||
|
||||
@ -37,11 +37,12 @@ namespace Spine {
|
||||
internal float length;
|
||||
internal float x, y, rotation, scaleX = 1, scaleY = 1, shearX, shearY;
|
||||
internal TransformMode transformMode = TransformMode.Normal;
|
||||
internal bool skinRequired;
|
||||
|
||||
/// <summary>The index of the bone in Skeleton.Bones</summary>
|
||||
public int Index { get { return index; } }
|
||||
|
||||
/// <summary>The name of the bone, which is unique within the skeleton.</summary>
|
||||
/// <summary>The name of the bone, which is unique across all bones in the skeleton.</summary>
|
||||
public string Name { get { return name; } }
|
||||
|
||||
/// <summary>May be null.</summary>
|
||||
@ -73,6 +74,11 @@ namespace Spine {
|
||||
/// <summary>The transform mode for how parent world transforms affect this bone.</summary>
|
||||
public TransformMode TransformMode { get { return transformMode; } set { transformMode = value; } }
|
||||
|
||||
///<summary>When true, <see cref="Skeleton.UpdateWorldTransform()"/> only updates this bone if the <see cref="Skeleton.Skin"/> contains this
|
||||
/// bone.</summary>
|
||||
/// <seealso cref="Skin.Bones"/>
|
||||
public bool SkinRequired { get { return skinRequired; } set { skinRequired = value; } }
|
||||
|
||||
/// <param name="parent">May be null.</param>
|
||||
public BoneData (int index, string name, BoneData parent) {
|
||||
if (index < 0) throw new ArgumentException("index must be >= 0", "index");
|
||||
|
||||
@ -27,13 +27,36 @@
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
namespace Spine {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>The interface for all constraints.</summary>
|
||||
public interface IConstraint : IUpdatable {
|
||||
/// <summary>The ordinal for the order a skeleton's constraints will be applied.</summary>
|
||||
int Order { get; }
|
||||
namespace Spine
|
||||
{
|
||||
/// <summary>The base class for all constraint datas.</summary>
|
||||
public abstract class ConstraintData {
|
||||
internal readonly string name;
|
||||
internal int order;
|
||||
internal bool skinRequired;
|
||||
|
||||
public ConstraintData (string name) {
|
||||
if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/// <summary> The constraint's name, which is unique across all constraints in the skeleton of the same type.</summary>
|
||||
public string Name { get { return name; } }
|
||||
|
||||
///<summary>The ordinal of this constraint for the order a skeleton's constraints will be applied by
|
||||
/// <see cref="Skeleton.UpdateWorldTransform()"/>.</summary>
|
||||
public int Order { get { return order; } set { order = value; } }
|
||||
|
||||
///<summary>When true, <see cref="Skeleton.UpdateWorldTransform()"/> only updates this constraint if the <see cref="Skeleton.Skin"/> contains
|
||||
/// this constraint.</summary>
|
||||
///<seealso cref="Skin.Constraints"/>
|
||||
public bool SkinRequired { get { return skinRequired; } set { skinRequired = value; } }
|
||||
|
||||
override public string ToString () {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,7 +34,7 @@ namespace Spine {
|
||||
public class EventData {
|
||||
internal string name;
|
||||
|
||||
/// <summary>The name of the event, which is unique within the skeleton.</summary>
|
||||
/// <summary>The name of the event, which is unique across all events in the skeleton.</summary>
|
||||
public string Name { get { return name; } }
|
||||
public int Int { get; set; }
|
||||
public float Float { get; set; }
|
||||
|
||||
@ -37,7 +37,7 @@ namespace Spine {
|
||||
/// <para>
|
||||
/// See <a href="http://esotericsoftware.com/spine-ik-constraints">IK constraints</a> in the Spine User Guide.</para>
|
||||
/// </summary>
|
||||
public class IkConstraint : IConstraint {
|
||||
public class IkConstraint : IUpdatable {
|
||||
internal IkConstraintData data;
|
||||
internal ExposedList<Bone> bones = new ExposedList<Bone>();
|
||||
internal Bone target;
|
||||
@ -93,11 +93,6 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int Order {
|
||||
get { return data.order; }
|
||||
}
|
||||
|
||||
/// <summary>The bones that will be modified by this IK constraint.</summary>
|
||||
public ExposedList<Bone> Bones {
|
||||
get { return bones; }
|
||||
|
||||
@ -32,23 +32,14 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Spine {
|
||||
/// <summary>Stores the setup pose for an IkConstraint.</summary>
|
||||
public class IkConstraintData {
|
||||
internal string name;
|
||||
internal int order;
|
||||
public class IkConstraintData : ConstraintData {
|
||||
internal List<BoneData> bones = new List<BoneData>();
|
||||
internal BoneData target;
|
||||
internal int bendDirection = 1;
|
||||
internal bool compress, stretch, uniform;
|
||||
internal float mix = 1;
|
||||
|
||||
/// <summary>The IK constraint's name, which is unique within the skeleton.</summary>
|
||||
public string Name {
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
public int Order {
|
||||
get { return order; }
|
||||
set { order = value; }
|
||||
public IkConstraintData (string name) : base(name) {
|
||||
}
|
||||
|
||||
/// <summary>The bones that are constrained by this IK Constraint.</summary>
|
||||
@ -98,14 +89,5 @@ namespace Spine {
|
||||
get { return uniform; }
|
||||
set { uniform = value; }
|
||||
}
|
||||
|
||||
public IkConstraintData (string name) {
|
||||
if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
override public string ToString () {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ namespace Spine {
|
||||
/// <para>
|
||||
/// See <a href="http://esotericsoftware.com/spine-path-constraints">Path constraints</a> in the Spine User Guide.</para>
|
||||
/// </summary>
|
||||
public class PathConstraint : IConstraint {
|
||||
public class PathConstraint : IUpdatable {
|
||||
const int NONE = -1, BEFORE = -2, AFTER = -3;
|
||||
const float Epsilon = 0.00001f;
|
||||
|
||||
@ -446,7 +446,6 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
|
||||
public int Order { get { return data.order; } }
|
||||
/// <summary>The position along the path.</summary>
|
||||
public float Position { get { return position; } set { position = value; } }
|
||||
/// <summary>The spacing between bones.</summary>
|
||||
@ -461,9 +460,5 @@ namespace Spine {
|
||||
public Slot Target { get { return target; } set { target = value; } }
|
||||
/// <summary>The path constraint's setup pose data.</summary>
|
||||
public PathConstraintData Data { get { return data; } }
|
||||
|
||||
override public string ToString () {
|
||||
return data.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,9 +30,7 @@
|
||||
using System;
|
||||
|
||||
namespace Spine {
|
||||
public class PathConstraintData {
|
||||
internal string name;
|
||||
internal int order;
|
||||
public class PathConstraintData : ConstraintData {
|
||||
internal ExposedList<BoneData> bones = new ExposedList<BoneData>();
|
||||
internal SlotData target;
|
||||
internal PositionMode positionMode;
|
||||
@ -41,8 +39,9 @@ namespace Spine {
|
||||
internal float offsetRotation;
|
||||
internal float position, spacing, rotateMix, translateMix;
|
||||
|
||||
public string Name { get { return name; } }
|
||||
public int Order { get { return order; } set { order = value; } }
|
||||
public PathConstraintData (string name) : base(name) {
|
||||
}
|
||||
|
||||
public ExposedList<BoneData> Bones { get { return bones; } }
|
||||
public SlotData Target { get { return target; } set { target = value; } }
|
||||
public PositionMode PositionMode { get { return positionMode; } set { positionMode = value; } }
|
||||
@ -53,15 +52,6 @@ namespace Spine {
|
||||
public float Spacing { get { return spacing; } set { spacing = value; } }
|
||||
public float RotateMix { get { return rotateMix; } set { rotateMix = value; } }
|
||||
public float TranslateMix { get { return translateMix; } set { translateMix = value; } }
|
||||
|
||||
public PathConstraintData (String name) {
|
||||
if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public override string ToString () {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public enum PositionMode {
|
||||
|
||||
@ -55,7 +55,7 @@ namespace Spine {
|
||||
public ExposedList<IkConstraint> IkConstraints { get { return ikConstraints; } }
|
||||
public ExposedList<PathConstraint> PathConstraints { get { return pathConstraints; } }
|
||||
public ExposedList<TransformConstraint> TransformConstraints { get { return transformConstraints; } }
|
||||
public Skin Skin { get { return skin; } set { skin = value; } }
|
||||
public Skin Skin { get { return skin; } set { SetSkin(value); } }
|
||||
public float R { get { return r; } set { r = value; } }
|
||||
public float G { get { return g; } set { g = value; } }
|
||||
public float B { get { return b; } set { b = value; } }
|
||||
@ -118,21 +118,25 @@ namespace Spine {
|
||||
UpdateWorldTransform();
|
||||
}
|
||||
|
||||
/// <summary>Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added
|
||||
/// or removed.</summary>
|
||||
/// <summary>Caches information about bones and constraints. Must be called if the skin is modified or if bones, constraints, or
|
||||
/// weighted path attachments are added or removed.</summary>
|
||||
public void UpdateCache () {
|
||||
var updateCache = this.updateCache;
|
||||
updateCache.Clear();
|
||||
this.updateCacheReset.Clear();
|
||||
|
||||
int boneCount = this.bones.Items.Length;
|
||||
var bones = this.bones;
|
||||
for (int i = 0, n = bones.Count; i < n; i++)
|
||||
bones.Items[i].sorted = false;
|
||||
for (int i = 0; i < boneCount; i++) {
|
||||
Bone bone = bones.Items[i];
|
||||
bone.update = !bone.data.skinRequired || (skin != null && skin.bones.Contains(bone.data));
|
||||
bone.sorted = !bone.update;
|
||||
}
|
||||
|
||||
int ikCount = this.ikConstraints.Count, transformCount = this.transformConstraints.Count, pathCount = this.pathConstraints.Count;
|
||||
var ikConstraints = this.ikConstraints;
|
||||
var transformConstraints = this.transformConstraints;
|
||||
var pathConstraints = this.pathConstraints;
|
||||
int ikCount = ikConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count;
|
||||
int constraintCount = ikCount + transformCount + pathCount;
|
||||
//outer:
|
||||
for (int i = 0; i < constraintCount; i++) {
|
||||
@ -160,11 +164,13 @@ namespace Spine {
|
||||
continue_outer: {}
|
||||
}
|
||||
|
||||
for (int i = 0, n = bones.Count; i < n; i++)
|
||||
for (int i = 0; i < boneCount; i++)
|
||||
SortBone(bones.Items[i]);
|
||||
}
|
||||
|
||||
private void SortIkConstraint (IkConstraint constraint) {
|
||||
if (constraint.data.skinRequired && (skin == null || !skin.constraints.Contains(constraint.data))) return;
|
||||
|
||||
Bone target = constraint.target;
|
||||
SortBone(target);
|
||||
|
||||
@ -185,14 +191,14 @@ namespace Spine {
|
||||
}
|
||||
|
||||
private void SortPathConstraint (PathConstraint constraint) {
|
||||
if (constraint.data.skinRequired && (skin == null || !skin.constraints.Contains(constraint.data))) return;
|
||||
|
||||
Slot slot = constraint.target;
|
||||
int slotIndex = slot.data.index;
|
||||
Bone slotBone = slot.bone;
|
||||
if (skin != null) SortPathConstraintAttachment(skin, slotIndex, slotBone);
|
||||
if (data.defaultSkin != null && data.defaultSkin != skin)
|
||||
SortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
|
||||
for (int ii = 0, nn = data.skins.Count; ii < nn; ii++)
|
||||
SortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone);
|
||||
|
||||
Attachment attachment = slot.attachment;
|
||||
if (attachment is PathAttachment) SortPathConstraintAttachment(attachment, slotBone);
|
||||
@ -211,6 +217,8 @@ namespace Spine {
|
||||
}
|
||||
|
||||
private void SortTransformConstraint (TransformConstraint constraint) {
|
||||
if (constraint.data.skinRequired && (skin == null || !skin.constraints.Contains(constraint.data))) return;
|
||||
|
||||
SortBone(constraint.target);
|
||||
|
||||
var constrained = constraint.bones;
|
||||
@ -269,6 +277,7 @@ namespace Spine {
|
||||
var bonesItems = bones.Items;
|
||||
for (int i = 0, n = bones.Count; i < n; i++) {
|
||||
Bone bone = bonesItems[i];
|
||||
if (!bone.update) continue;
|
||||
if (bone.sorted) SortReset(bone.children);
|
||||
bone.sorted = false;
|
||||
}
|
||||
@ -295,7 +304,8 @@ namespace Spine {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the world transform for each bone and applies all constraints. The root bone will be temporarily parented to the specified bone.
|
||||
/// Temporarily sets the root bone as a child of the specified bone, then updates the world transform for each bone and applies
|
||||
/// all constraints.
|
||||
/// </summary>
|
||||
public void UpdateWorldTransform (Bone parent) {
|
||||
// This partial update avoids computing the world transform for constrained bones when 1) the bone is not updated
|
||||
@ -315,8 +325,7 @@ namespace Spine {
|
||||
bone.appliedValid = true;
|
||||
}
|
||||
|
||||
// Apply the parent bone transform to the root bone. The root bone
|
||||
// always inherits scale, rotation and reflection.
|
||||
// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
|
||||
Bone rootBone = this.RootBone;
|
||||
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
||||
rootBone.worldX = pa * x + pb * y + parent.worldX;
|
||||
@ -447,8 +456,12 @@ namespace Spine {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>Sets the skin used to look up attachments before looking in the <see cref="SkeletonData.DefaultSkin"/>. If the
|
||||
/// skin is changed, <see cref="UpdateCache()"/> is called.
|
||||
/// </para>
|
||||
/// <para>Attachments from the new skin are attached if the corresponding attachment from the old skin was attached.
|
||||
/// If there was no old skin, each slot's setup mode attachment is attached from the new skin.</para>
|
||||
/// If there was no old skin, each slot's setup mode attachment is attached from the new skin.
|
||||
/// </para>
|
||||
/// <para>After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling
|
||||
/// <see cref="Skeleton.SetSlotsToSetupPose()"/>.
|
||||
/// Also, often <see cref="AnimationState.Apply(Skeleton)"/> is called before the next time the
|
||||
@ -456,6 +469,7 @@ namespace Spine {
|
||||
/// </summary>
|
||||
/// <param name="newSkin">May be null.</param>
|
||||
public void SetSkin (Skin newSkin) {
|
||||
if (newSkin == skin) return;
|
||||
if (newSkin != null) {
|
||||
if (skin != null)
|
||||
newSkin.AttachAll(this, skin);
|
||||
@ -472,6 +486,7 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
skin = newSkin;
|
||||
UpdateCache();
|
||||
}
|
||||
|
||||
/// <summary>Finds an attachment by looking in the {@link #skin} and {@link SkeletonData#defaultSkin} using the slot name and attachment name.</summary>
|
||||
@ -528,7 +543,7 @@ namespace Spine {
|
||||
ExposedList<TransformConstraint> transformConstraints = this.transformConstraints;
|
||||
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
|
||||
TransformConstraint transformConstraint = transformConstraints.Items[i];
|
||||
if (transformConstraint.data.name == constraintName) return transformConstraint;
|
||||
if (transformConstraint.data.Name == constraintName) return transformConstraint;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -539,7 +554,7 @@ namespace Spine {
|
||||
ExposedList<PathConstraint> pathConstraints = this.pathConstraints;
|
||||
for (int i = 0, n = pathConstraints.Count; i < n; i++) {
|
||||
PathConstraint constraint = pathConstraints.Items[i];
|
||||
if (constraint.data.name.Equals(constraintName)) return constraint;
|
||||
if (constraint.data.Name.Equals(constraintName)) return constraint;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -174,6 +174,7 @@ namespace Spine {
|
||||
data.shearY = ReadFloat(input);
|
||||
data.length = ReadFloat(input) * scale;
|
||||
data.transformMode = TransformModeValues[ReadVarint(input, true)];
|
||||
data.skinRequired = ReadBoolean(input);
|
||||
if (nonessential) ReadInt(input); // Skip bone color.
|
||||
skeletonData.bones.Add(data);
|
||||
}
|
||||
@ -206,6 +207,7 @@ namespace Spine {
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||
IkConstraintData data = new IkConstraintData(ReadString(input));
|
||||
data.order = ReadVarint(input, true);
|
||||
data.skinRequired = ReadBoolean(input);
|
||||
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
|
||||
data.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
|
||||
data.target = skeletonData.bones.Items[ReadVarint(input, true)];
|
||||
@ -221,6 +223,7 @@ namespace Spine {
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||
TransformConstraintData data = new TransformConstraintData(ReadString(input));
|
||||
data.order = ReadVarint(input, true);
|
||||
data.skinRequired = ReadBoolean(input);
|
||||
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
|
||||
data.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
|
||||
data.target = skeletonData.bones.Items[ReadVarint(input, true)];
|
||||
@ -243,6 +246,7 @@ namespace Spine {
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||
PathConstraintData data = new PathConstraintData(ReadString(input));
|
||||
data.order = ReadVarint(input, true);
|
||||
data.skinRequired = ReadBoolean(input);
|
||||
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
|
||||
data.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
|
||||
data.target = skeletonData.slots.Items[ReadVarint(input, true)];
|
||||
@ -260,7 +264,7 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// Default skin.
|
||||
Skin defaultSkin = ReadSkin(input, skeletonData, "default", nonessential);
|
||||
Skin defaultSkin = ReadSkin(input, skeletonData, true, nonessential);
|
||||
if (defaultSkin != null) {
|
||||
skeletonData.defaultSkin = defaultSkin;
|
||||
skeletonData.skins.Add(defaultSkin);
|
||||
@ -268,7 +272,7 @@ namespace Spine {
|
||||
|
||||
// Skins.
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++)
|
||||
skeletonData.skins.Add(ReadSkin(input, skeletonData, ReadString(input), nonessential));
|
||||
skeletonData.skins.Add(ReadSkin(input, skeletonData, false, nonessential));
|
||||
|
||||
// Linked meshes.
|
||||
for (int i = 0, n = linkedMeshes.Count; i < n; i++) {
|
||||
@ -312,11 +316,19 @@ namespace Spine {
|
||||
|
||||
|
||||
/// <returns>May be null.</returns>
|
||||
private Skin ReadSkin (Stream input, SkeletonData skeletonData, String skinName, bool nonessential) {
|
||||
int slotCount = ReadVarint(input, true);
|
||||
if (slotCount == 0) return null;
|
||||
Skin skin = new Skin(skinName);
|
||||
for (int i = 0; i < slotCount; i++) {
|
||||
private Skin ReadSkin (Stream input, SkeletonData skeletonData, bool defaultSkin, bool nonessential) {
|
||||
Skin skin = new Skin(defaultSkin ? "default" : ReadString(input));
|
||||
if (!defaultSkin) {
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++)
|
||||
skin.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]);
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++)
|
||||
skin.constraints.Add(skeletonData.ikConstraints.Items[ReadVarint(input, true)]);
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++)
|
||||
skin.constraints.Add(skeletonData.transformConstraints.Items[ReadVarint(input, true)]);
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++)
|
||||
skin.constraints.Add(skeletonData.pathConstraints.Items[ReadVarint(input, true)]);
|
||||
}
|
||||
for (int i = 0, n = ReadVarint(input, true); i < n; i++) {
|
||||
int slotIndex = ReadVarint(input, true);
|
||||
for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
|
||||
String name = ReadString(input);
|
||||
|
||||
@ -109,6 +109,7 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// Bones.
|
||||
if (root.ContainsKey("bones")) {
|
||||
foreach (Dictionary<string, Object> boneMap in (List<Object>)root["bones"]) {
|
||||
BoneData parent = null;
|
||||
if (boneMap.ContainsKey("parent")) {
|
||||
@ -128,9 +129,11 @@ namespace Spine {
|
||||
|
||||
string tm = GetString(boneMap, "transform", TransformMode.Normal.ToString());
|
||||
data.transformMode = (TransformMode)Enum.Parse(typeof(TransformMode), tm, true);
|
||||
data.skinRequired = GetBoolean(boneMap, "skin", false);
|
||||
|
||||
skeletonData.bones.Add(data);
|
||||
}
|
||||
}
|
||||
|
||||
// Slots.
|
||||
if (root.ContainsKey("slots")) {
|
||||
@ -171,16 +174,19 @@ namespace Spine {
|
||||
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["ik"]) {
|
||||
IkConstraintData data = new IkConstraintData((string)constraintMap["name"]);
|
||||
data.order = GetInt(constraintMap, "order", 0);
|
||||
data.skinRequired = GetBoolean(constraintMap,"skin", false);
|
||||
|
||||
if (constraintMap.ContainsKey("bones")) {
|
||||
foreach (string boneName in (List<Object>)constraintMap["bones"]) {
|
||||
BoneData bone = skeletonData.FindBone(boneName);
|
||||
if (bone == null) throw new Exception("IK constraint bone not found: " + boneName);
|
||||
if (bone == null) throw new Exception("IK bone not found: " + boneName);
|
||||
data.bones.Add(bone);
|
||||
}
|
||||
}
|
||||
|
||||
string targetName = (string)constraintMap["target"];
|
||||
data.target = skeletonData.FindBone(targetName);
|
||||
if (data.target == null) throw new Exception("Target bone not found: " + targetName);
|
||||
if (data.target == null) throw new Exception("IK target bone not found: " + targetName);
|
||||
data.mix = GetFloat(constraintMap, "mix", 1);
|
||||
data.bendDirection = GetBoolean(constraintMap, "bendPositive", true) ? 1 : -1;
|
||||
data.compress = GetBoolean(constraintMap, "compress", false);
|
||||
@ -196,16 +202,19 @@ namespace Spine {
|
||||
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["transform"]) {
|
||||
TransformConstraintData data = new TransformConstraintData((string)constraintMap["name"]);
|
||||
data.order = GetInt(constraintMap, "order", 0);
|
||||
data.skinRequired = GetBoolean(constraintMap,"skin", false);
|
||||
|
||||
if (constraintMap.ContainsKey("bones")) {
|
||||
foreach (string boneName in (List<Object>)constraintMap["bones"]) {
|
||||
BoneData bone = skeletonData.FindBone(boneName);
|
||||
if (bone == null) throw new Exception("Transform constraint bone not found: " + boneName);
|
||||
data.bones.Add(bone);
|
||||
}
|
||||
}
|
||||
|
||||
string targetName = (string)constraintMap["target"];
|
||||
data.target = skeletonData.FindBone(targetName);
|
||||
if (data.target == null) throw new Exception("Target bone not found: " + targetName);
|
||||
if (data.target == null) throw new Exception("Transform constraint target bone not found: " + targetName);
|
||||
|
||||
data.local = GetBoolean(constraintMap, "local", false);
|
||||
data.relative = GetBoolean(constraintMap, "relative", false);
|
||||
@ -231,16 +240,19 @@ namespace Spine {
|
||||
foreach (Dictionary<string, Object> constraintMap in (List<Object>)root["path"]) {
|
||||
PathConstraintData data = new PathConstraintData((string)constraintMap["name"]);
|
||||
data.order = GetInt(constraintMap, "order", 0);
|
||||
data.skinRequired = GetBoolean(constraintMap,"skin", false);
|
||||
|
||||
if (constraintMap.ContainsKey("bones")) {
|
||||
foreach (string boneName in (List<Object>)constraintMap["bones"]) {
|
||||
BoneData bone = skeletonData.FindBone(boneName);
|
||||
if (bone == null) throw new Exception("Path bone not found: " + boneName);
|
||||
data.bones.Add(bone);
|
||||
}
|
||||
}
|
||||
|
||||
string targetName = (string)constraintMap["target"];
|
||||
data.target = skeletonData.FindSlot(targetName);
|
||||
if (data.target == null) throw new Exception("Target slot not found: " + targetName);
|
||||
if (data.target == null) throw new Exception("Path target slot not found: " + targetName);
|
||||
|
||||
data.positionMode = (PositionMode)Enum.Parse(typeof(PositionMode), GetString(constraintMap, "positionMode", "percent"), true);
|
||||
data.spacingMode = (SpacingMode)Enum.Parse(typeof(SpacingMode), GetString(constraintMap, "spacingMode", "length"), true);
|
||||
@ -259,9 +271,38 @@ namespace Spine {
|
||||
|
||||
// Skins.
|
||||
if (root.ContainsKey("skins")) {
|
||||
foreach (KeyValuePair<string, Object> skinMap in (Dictionary<string, Object>)root["skins"]) {
|
||||
var skin = new Skin(skinMap.Key);
|
||||
foreach (KeyValuePair<string, Object> slotEntry in (Dictionary<string, Object>)skinMap.Value) {
|
||||
foreach (Dictionary<string, object> skinMap in (List<object>)root["skins"]) {
|
||||
Skin skin = new Skin((string)skinMap["name"]);
|
||||
if (skinMap.ContainsKey("bones")) {
|
||||
foreach (string entryName in (List<Object>)skinMap["bones"]) {
|
||||
BoneData bone = skeletonData.FindBone(entryName);
|
||||
if (bone == null) throw new Exception("Skin bone not found: " + entryName);
|
||||
skin.bones.Add(bone);
|
||||
}
|
||||
}
|
||||
if (skinMap.ContainsKey("ik")) {
|
||||
foreach (string entryName in (List<Object>)skinMap["ik"]) {
|
||||
IkConstraintData constraint = skeletonData.FindIkConstraint(entryName);
|
||||
if (constraint == null) throw new Exception("Skin IK constraint not found: " + entryName);
|
||||
skin.constraints.Add(constraint);
|
||||
}
|
||||
}
|
||||
if (skinMap.ContainsKey("transform")) {
|
||||
foreach (string entryName in (List<Object>)skinMap["transform"]) {
|
||||
TransformConstraintData constraint = skeletonData.FindTransformConstraint(entryName);
|
||||
if (constraint == null) throw new Exception("Skin transform constraint not found: " + entryName);
|
||||
skin.constraints.Add(constraint);
|
||||
}
|
||||
}
|
||||
if (skinMap.ContainsKey("path")) {
|
||||
foreach (string entryName in (List<Object>)skinMap["path"]) {
|
||||
PathConstraintData constraint = skeletonData.FindPathConstraint(entryName);
|
||||
if (constraint == null) throw new Exception("Skin path constraint not found: " + entryName);
|
||||
skin.constraints.Add(constraint);
|
||||
}
|
||||
}
|
||||
if (skinMap.ContainsKey("attachments")) {
|
||||
foreach (KeyValuePair<string, Object> slotEntry in (Dictionary<string, Object>)skinMap["attachments"]) {
|
||||
int slotIndex = skeletonData.FindSlotIndex(slotEntry.Key);
|
||||
foreach (KeyValuePair<string, Object> entry in ((Dictionary<string, Object>)slotEntry.Value)) {
|
||||
try {
|
||||
@ -272,6 +313,7 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
skeletonData.skins.Add(skin);
|
||||
if (skin.name == "default") skeletonData.defaultSkin = skin;
|
||||
}
|
||||
@ -494,7 +536,7 @@ namespace Spine {
|
||||
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<string, Object> valueMap in values) {
|
||||
float time = (float)valueMap["time"];
|
||||
float time = GetFloat(valueMap, "time", 0);
|
||||
timeline.SetFrame(frameIndex++, time, (string)valueMap["name"]);
|
||||
}
|
||||
timelines.Add(timeline);
|
||||
@ -506,7 +548,7 @@ namespace Spine {
|
||||
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<string, Object> valueMap in values) {
|
||||
float time = (float)valueMap["time"];
|
||||
float time = GetFloat(valueMap, "time", 0);
|
||||
string c = (string)valueMap["color"];
|
||||
timeline.SetFrame(frameIndex, time, ToColor(c, 0), ToColor(c, 1), ToColor(c, 2), ToColor(c, 3));
|
||||
ReadCurve(valueMap, timeline, frameIndex);
|
||||
@ -521,7 +563,7 @@ namespace Spine {
|
||||
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<string, Object> valueMap in values) {
|
||||
float time = (float)valueMap["time"];
|
||||
float time = GetFloat(valueMap, "time", 0);
|
||||
string light = (string)valueMap["light"];
|
||||
string dark = (string)valueMap["dark"];
|
||||
timeline.SetFrame(frameIndex, time, ToColor(light, 0), ToColor(light, 1), ToColor(light, 2), ToColor(light, 3),
|
||||
@ -554,7 +596,7 @@ namespace Spine {
|
||||
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<string, Object> valueMap in values) {
|
||||
timeline.SetFrame(frameIndex, (float)valueMap["time"], (float)valueMap["angle"]);
|
||||
timeline.SetFrame(frameIndex, GetFloat(valueMap, "time", 0), GetFloat(valueMap, "angle", 0));
|
||||
ReadCurve(valueMap, timeline, frameIndex);
|
||||
frameIndex++;
|
||||
}
|
||||
@ -563,9 +605,11 @@ namespace Spine {
|
||||
|
||||
} else if (timelineName == "translate" || timelineName == "scale" || timelineName == "shear") {
|
||||
TranslateTimeline timeline;
|
||||
float timelineScale = 1;
|
||||
if (timelineName == "scale")
|
||||
float timelineScale = 1, defaultValue = 0;
|
||||
if (timelineName == "scale") {
|
||||
timeline = new ScaleTimeline(values.Count);
|
||||
defaultValue = 1;
|
||||
}
|
||||
else if (timelineName == "shear")
|
||||
timeline = new ShearTimeline(values.Count);
|
||||
else {
|
||||
@ -576,9 +620,9 @@ namespace Spine {
|
||||
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<string, Object> valueMap in values) {
|
||||
float time = (float)valueMap["time"];
|
||||
float x = GetFloat(valueMap, "x", 0);
|
||||
float y = GetFloat(valueMap, "y", 0);
|
||||
float time = GetFloat(valueMap, "time", 0);
|
||||
float x = GetFloat(valueMap, "x", defaultValue);
|
||||
float y = GetFloat(valueMap, "y", defaultValue);
|
||||
timeline.SetFrame(frameIndex, time, x * timelineScale, y * timelineScale);
|
||||
ReadCurve(valueMap, timeline, frameIndex);
|
||||
frameIndex++;
|
||||
@ -603,7 +647,7 @@ namespace Spine {
|
||||
foreach (Dictionary<string, Object> valueMap in values) {
|
||||
timeline.SetFrame(
|
||||
frameIndex,
|
||||
(float)valueMap["time"],
|
||||
GetFloat(valueMap, "time", 0),
|
||||
GetFloat(valueMap, "mix", 1),
|
||||
GetBoolean(valueMap, "bendPositive", true) ? 1 : -1,
|
||||
GetBoolean(valueMap, "compress", true),
|
||||
@ -626,7 +670,7 @@ namespace Spine {
|
||||
timeline.transformConstraintIndex = skeletonData.transformConstraints.IndexOf(constraint);
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<string, Object> valueMap in values) {
|
||||
float time = (float)valueMap["time"];
|
||||
float time = GetFloat(valueMap, "time", 0);
|
||||
float rotateMix = GetFloat(valueMap, "rotateMix", 1);
|
||||
float translateMix = GetFloat(valueMap, "translateMix", 1);
|
||||
float scaleMix = GetFloat(valueMap, "scaleMix", 1);
|
||||
@ -641,8 +685,8 @@ namespace Spine {
|
||||
}
|
||||
|
||||
// Path constraint timelines.
|
||||
if (map.ContainsKey("paths")) {
|
||||
foreach (KeyValuePair<string, Object> constraintMap in (Dictionary<string, Object>)map["paths"]) {
|
||||
if (map.ContainsKey("path")) {
|
||||
foreach (KeyValuePair<string, Object> constraintMap in (Dictionary<string, Object>)map["path"]) {
|
||||
int index = skeletonData.FindPathConstraintIndex(constraintMap.Key);
|
||||
if (index == -1) throw new Exception("Path constraint not found: " + constraintMap.Key);
|
||||
PathConstraintData data = skeletonData.pathConstraints.Items[index];
|
||||
@ -664,7 +708,7 @@ namespace Spine {
|
||||
timeline.pathConstraintIndex = index;
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<string, Object> valueMap in values) {
|
||||
timeline.SetFrame(frameIndex, (float)valueMap["time"], GetFloat(valueMap, timelineName, 0) * timelineScale);
|
||||
timeline.SetFrame(frameIndex, GetFloat(valueMap, "time", 0), GetFloat(valueMap, timelineName, 0) * timelineScale);
|
||||
ReadCurve(valueMap, timeline, frameIndex);
|
||||
frameIndex++;
|
||||
}
|
||||
@ -676,7 +720,7 @@ namespace Spine {
|
||||
timeline.pathConstraintIndex = index;
|
||||
int frameIndex = 0;
|
||||
foreach (Dictionary<string, Object> valueMap in values) {
|
||||
timeline.SetFrame(frameIndex, (float)valueMap["time"], GetFloat(valueMap, "rotateMix", 1), GetFloat(valueMap, "translateMix", 1));
|
||||
timeline.SetFrame(frameIndex, GetFloat(valueMap, "time", 0), GetFloat(valueMap, "rotateMix", 1), GetFloat(valueMap, "translateMix", 1));
|
||||
ReadCurve(valueMap, timeline, frameIndex);
|
||||
frameIndex++;
|
||||
}
|
||||
@ -727,7 +771,7 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
|
||||
timeline.SetFrame(frameIndex, (float)valueMap["time"], deform);
|
||||
timeline.SetFrame(frameIndex, GetFloat(valueMap, "time", 0), deform);
|
||||
ReadCurve(valueMap, timeline, frameIndex);
|
||||
frameIndex++;
|
||||
}
|
||||
@ -770,7 +814,7 @@ namespace Spine {
|
||||
for (int i = slotCount - 1; i >= 0; i--)
|
||||
if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex];
|
||||
}
|
||||
timeline.SetFrame(frameIndex++, (float)drawOrderMap["time"], drawOrder);
|
||||
timeline.SetFrame(frameIndex++, GetFloat(drawOrderMap, "time", 0), drawOrder);
|
||||
}
|
||||
timelines.Add(timeline);
|
||||
duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]);
|
||||
@ -784,7 +828,7 @@ namespace Spine {
|
||||
foreach (Dictionary<string, Object> eventMap in eventsMap) {
|
||||
EventData eventData = skeletonData.FindEvent((string)eventMap["name"]);
|
||||
if (eventData == null) throw new Exception("Event not found: " + eventMap["name"]);
|
||||
var e = new Event((float)eventMap["time"], eventData) {
|
||||
var e = new Event(GetFloat(eventMap, "time", 0), eventData) {
|
||||
intValue = GetInt(eventMap, "int", eventData.Int),
|
||||
floatValue = GetFloat(eventMap, "float", eventData.Float),
|
||||
stringValue = GetString(eventMap, "string", eventData.String)
|
||||
@ -807,12 +851,12 @@ namespace Spine {
|
||||
if (!valueMap.ContainsKey("curve"))
|
||||
return;
|
||||
Object curveObject = valueMap["curve"];
|
||||
if (curveObject.Equals("stepped"))
|
||||
if (curveObject is string)
|
||||
timeline.SetStepped(frameIndex);
|
||||
else {
|
||||
var curve = curveObject as List<Object>;
|
||||
if (curve != null)
|
||||
timeline.SetCurve(frameIndex, (float)curve[0], (float)curve[1], (float)curve[2], (float)curve[3]);
|
||||
timeline.SetCurve(frameIndex, (float)curveObject, GetFloat(valueMap, "c2", 0), GetFloat(valueMap, "c3", 1), GetFloat(valueMap, "c4", 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -40,9 +40,13 @@ namespace Spine {
|
||||
public class Skin {
|
||||
internal string name;
|
||||
private OrderedDictionary attachments = new OrderedDictionary(SkinEntryComparer.Instance); // contains <SkinEntry, Attachment>
|
||||
internal readonly ExposedList<BoneData> bones = new ExposedList<BoneData>();
|
||||
internal readonly ExposedList<ConstraintData> constraints = new ExposedList<ConstraintData>();
|
||||
|
||||
public string Name { get { return name; } }
|
||||
public OrderedDictionary Attachments { get { return attachments; } }
|
||||
public ExposedList<BoneData> Bones { get { return bones; } }
|
||||
public ExposedList<ConstraintData> Constraints { get { return constraints; } }
|
||||
|
||||
public Skin (string name) {
|
||||
if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
|
||||
@ -59,13 +63,23 @@ namespace Spine {
|
||||
|
||||
///<summary>Adds all attachments, bones, and constraints from the specified skin to this skin.</summary>
|
||||
public void AddSkin (Skin skin) {
|
||||
foreach (BoneData data in skin.bones)
|
||||
if (!bones.Contains(data)) bones.Add(data);
|
||||
|
||||
foreach (ConstraintData data in skin.constraints)
|
||||
if (!constraints.Contains(data)) constraints.Add(data);
|
||||
|
||||
foreach (SkinEntry entry in skin.attachments.Keys)
|
||||
SetAttachment(entry.SlotIndex, entry.Name, entry.Attachment);
|
||||
}
|
||||
|
||||
///<summary>Adds all attachments from the specified skin to this skin. Attachments are deep copied.</summary>
|
||||
public void CopySkin (Skin skin) {
|
||||
// note: bones and constraints are added in a separate commit.
|
||||
foreach (BoneData data in skin.bones)
|
||||
if (!bones.Contains(data)) bones.Add(data);
|
||||
|
||||
foreach (ConstraintData data in skin.constraints)
|
||||
if (!constraints.Contains(data)) constraints.Add(data);
|
||||
|
||||
foreach (SkinEntry entry in skin.attachments.Keys) {
|
||||
Attachment attachment = entry.Attachment.Copy();
|
||||
@ -98,13 +112,20 @@ namespace Spine {
|
||||
return entries;
|
||||
}
|
||||
|
||||
/// <summary>Returns all attachments for the given slot in this skin.</summary>
|
||||
/// <summary>Returns all attachments in this skin for the specified slot index.</summary>
|
||||
/// <param name="slotIndex">The target slotIndex. To find the slot index, use <see cref="Spine.Skeleton.FindSlotIndex"/> or <see cref="Spine.SkeletonData.FindSlotIndex"/>
|
||||
public void GetAttachments (int slotIndex, List<SkinEntry> attachments) {
|
||||
foreach (SkinEntry entry in this.attachments.Keys)
|
||||
if (entry.SlotIndex == slotIndex) attachments.Add(entry);
|
||||
}
|
||||
|
||||
///<summary>Clears all attachments, bones, and constraints.</summary>
|
||||
public void Clear () {
|
||||
attachments.Clear();
|
||||
bones.Clear();
|
||||
constraints.Clear();
|
||||
}
|
||||
|
||||
override public string ToString () {
|
||||
return name;
|
||||
}
|
||||
@ -141,6 +162,7 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The name the attachment is associated with, equivalent to the skin placeholder name in the Spine editor.</summary>
|
||||
public String Name {
|
||||
get {
|
||||
return name;
|
||||
|
||||
@ -40,8 +40,11 @@ namespace Spine {
|
||||
internal string attachmentName;
|
||||
internal BlendMode blendMode;
|
||||
|
||||
/// <summary>The index of the slot in <see cref="Skeleton.Slots"/>.</summary>
|
||||
public int Index { get { return index; } }
|
||||
/// <summary>The name of the slot, which is unique across all slots in the skeleton.</summary>
|
||||
public string Name { get { return name; } }
|
||||
/// <summary>The bone this slot belongs to.</summary>
|
||||
public BoneData BoneData { get { return boneData; } }
|
||||
public float R { get { return r; } set { r = value; } }
|
||||
public float G { get { return g; } set { g = value; } }
|
||||
@ -53,8 +56,9 @@ namespace Spine {
|
||||
public float B2 { get { return b2; } set { b2 = value; } }
|
||||
public bool HasSecondColor { get { return hasSecondColor; } set { hasSecondColor = value; } }
|
||||
|
||||
/// <summary>May be null.</summary>
|
||||
/// <summary>The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible.</summary>
|
||||
public String AttachmentName { get { return attachmentName; } set { attachmentName = value; } }
|
||||
/// <summary>The blend mode for drawing the slot's attachment.</summary>
|
||||
public BlendMode BlendMode { get { return blendMode; } set { blendMode = value; } }
|
||||
|
||||
public SlotData (int index, String name, BoneData boneData) {
|
||||
|
||||
@ -37,7 +37,7 @@ namespace Spine {
|
||||
/// <para>
|
||||
/// See <a href="http://esotericsoftware.com/spine-transform-constraints">Transform constraints</a> in the Spine User Guide.</para>
|
||||
/// </summary>
|
||||
public class TransformConstraint : IConstraint {
|
||||
public class TransformConstraint : IUpdatable {
|
||||
internal TransformConstraintData data;
|
||||
internal ExposedList<Bone> bones;
|
||||
internal Bone target;
|
||||
@ -288,7 +288,6 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
|
||||
public int Order { get { return data.order; } }
|
||||
/// <summary>The bones that will be modified by this transform constraint.</summary>
|
||||
public ExposedList<Bone> Bones { get { return bones; } }
|
||||
/// <summary>The target bone whose world transform will be copied to the constrained bones.</summary>
|
||||
|
||||
@ -30,17 +30,13 @@
|
||||
using System;
|
||||
|
||||
namespace Spine {
|
||||
public class TransformConstraintData {
|
||||
internal string name;
|
||||
internal int order;
|
||||
public class TransformConstraintData : ConstraintData {
|
||||
internal ExposedList<BoneData> bones = new ExposedList<BoneData>();
|
||||
internal BoneData target;
|
||||
internal float rotateMix, translateMix, scaleMix, shearMix;
|
||||
internal float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
|
||||
internal bool relative, local;
|
||||
|
||||
public string Name { get { return name; } }
|
||||
public int Order { get { return order; } set { order = value; } }
|
||||
public ExposedList<BoneData> Bones { get { return bones; } }
|
||||
public BoneData Target { get { return target; } set { target = value; } }
|
||||
public float RotateMix { get { return rotateMix; } set { rotateMix = value; } }
|
||||
@ -58,13 +54,7 @@ namespace Spine {
|
||||
public bool Relative { get { return relative; } set { relative = value; } }
|
||||
public bool Local { get { return local; } set { local = value; } }
|
||||
|
||||
public TransformConstraintData (string name) {
|
||||
if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
override public string ToString () {
|
||||
return name;
|
||||
public TransformConstraintData (string name) : base(name) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,8 +504,17 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
if (!fieldMatchesSkin) {
|
||||
Skin skinToSet = string.IsNullOrEmpty(componentSkinName) ? null : skeletonRenderer.Skeleton.Data.FindSkin(componentSkinName);
|
||||
skeletonRenderer.Skeleton.Skin = skinToSet;
|
||||
skeletonRenderer.Skeleton.SetSkin(skinToSet);
|
||||
skeletonRenderer.Skeleton.SetSlotsToSetupPose();
|
||||
|
||||
// Note: the UpdateIfSkinMismatch concept shall be replaced with e.g. an OnValidate based
|
||||
// solution or in a separate commit. The current solution does not repaint the Game view because
|
||||
// it is first applying values and in the next editor pass is calling this skin-changing method.
|
||||
if (skeletonRenderer is SkeletonAnimation)
|
||||
((SkeletonAnimation) skeletonRenderer).Update(0f);
|
||||
else if (skeletonRenderer is SkeletonMecanim)
|
||||
((SkeletonMecanim) skeletonRenderer).Update();
|
||||
|
||||
skeletonRenderer.LateUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -707,9 +707,10 @@ namespace Spine.Unity.Editor {
|
||||
if (root == null || !root.ContainsKey("skins"))
|
||||
return requiredPaths;
|
||||
|
||||
foreach (var skin in (Dictionary<string, object>)root["skins"]) {
|
||||
foreach (var slot in (Dictionary<string, object>)skin.Value) {
|
||||
|
||||
foreach (Dictionary<string, object> skinMap in (List<object>)root["skins"]) {
|
||||
if (!skinMap.ContainsKey("attachments"))
|
||||
continue;
|
||||
foreach (var slot in (Dictionary<string, object>)skinMap["attachments"]) {
|
||||
foreach (var attachment in ((Dictionary<string, object>)slot.Value)) {
|
||||
var data = ((Dictionary<string, object>)attachment.Value);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user