Browse Source

[csharp] Ported skin API changes, see #841.

Harald Csaszar 6 years ago
parent
commit
a009c35b82
26 changed files with 278 additions and 95 deletions
  1. 3 0
      spine-csharp/src/Attachments/Attachment.cs
  2. 6 0
      spine-csharp/src/Attachments/BoundingBoxAttachment.cs
  3. 8 1
      spine-csharp/src/Attachments/ClippingAttachment.cs
  4. 37 0
      spine-csharp/src/Attachments/MeshAttachment.cs
  5. 11 1
      spine-csharp/src/Attachments/PathAttachment.cs
  6. 8 0
      spine-csharp/src/Attachments/PointAttachment.cs
  7. 21 0
      spine-csharp/src/Attachments/RegionAttachment.cs
  8. 22 2
      spine-csharp/src/Attachments/VertexAttachment.cs
  9. 2 2
      spine-csharp/src/Skeleton.cs
  10. 1 1
      spine-csharp/src/SkeletonBinary.cs
  11. 1 1
      spine-csharp/src/SkeletonJson.cs
  12. 71 39
      spine-csharp/src/Skin.cs
  13. 1 1
      spine-unity/Assets/Spine Examples/Scripts/Mix and Match Character Customize/EquipsVisualsComponentExample.cs
  14. 1 1
      spine-unity/Assets/Spine Examples/Scripts/Sample Components/Legacy/SpriteAttacher.cs
  15. 1 1
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/PointFollowerEditor.cs
  16. 13 5
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs
  17. 16 6
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDataAssetInspector.cs
  18. 11 2
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDebugWindow.cs
  19. 18 5
      spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAttributeDrawers.cs
  20. 5 1
      spine-unity/Assets/Spine/Editor/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs
  21. 7 4
      spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/BlendModeMaterialsAsset.cs
  22. 4 4
      spine-unity/Assets/Spine/Runtime/spine-unity/Modules/AttachmentTools/AttachmentTools.cs
  23. 3 1
      spine-unity/Assets/Spine/Runtime/spine-unity/Modules/BoundingBoxFollower/BoundingBoxFollower.cs
  24. 4 1
      spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs
  25. 3 1
      spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs
  26. 0 15
      spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs

+ 3 - 0
spine-csharp/src/Attachments/Attachment.cs

@@ -41,6 +41,9 @@ namespace Spine {
 		override public string ToString () {
 			return Name;
 		}
+
+		///<summary>Returns a copy of the attachment.</summary>
+		public abstract Attachment Copy ();
 	}
 
 	public interface IHasRendererObject {

+ 6 - 0
spine-csharp/src/Attachments/BoundingBoxAttachment.cs

@@ -35,5 +35,11 @@ namespace Spine {
 		public BoundingBoxAttachment (string name)
 			: base(name) {
 		}
+
+		public override Attachment Copy () {
+			BoundingBoxAttachment copy = new BoundingBoxAttachment(this.Name);
+			CopyTo(copy);
+			return copy;
+		}
 	}
 }

+ 8 - 1
spine-csharp/src/Attachments/ClippingAttachment.cs

@@ -37,5 +37,12 @@ namespace Spine {
 
         public ClippingAttachment(string name) : base(name) {
         }
-    }
+
+		public override Attachment Copy () {
+			ClippingAttachment copy = new ClippingAttachment(this.Name);
+			CopyTo(copy);
+			copy.endSlot = endSlot;
+			return copy;
+		}
+	}
 }

+ 37 - 0
spine-csharp/src/Attachments/MeshAttachment.cs

@@ -155,5 +155,42 @@ namespace Spine {
 		override public bool ApplyDeform (VertexAttachment sourceAttachment) {
 			return this == sourceAttachment || (inheritDeform && parentMesh == sourceAttachment);
 		}
+
+		public override Attachment Copy () {
+			MeshAttachment copy = new MeshAttachment(this.Name);
+			copy.regionOffsetX = regionOffsetX;
+			copy.regionOffsetY = regionOffsetY;
+			copy.regionWidth = regionWidth;
+			copy.regionHeight = regionHeight;
+			copy.regionOriginalWidth = regionOriginalWidth;
+			copy.regionOriginalHeight = regionOriginalHeight;
+
+			copy.Path = Path;
+			
+			if (parentMesh == null) {
+				CopyTo(copy);
+				copy.regionUVs = new float[regionUVs.Length];
+				Array.Copy(regionUVs, 0, copy.regionUVs, 0, regionUVs.Length);
+				copy.uvs = new float[uvs.Length];
+				Array.Copy(uvs, 0, copy.uvs, 0, uvs.Length);
+				copy.triangles = new int[triangles.Length];
+				Array.Copy(triangles, 0, copy.triangles, 0, triangles.Length);
+				copy.HullLength = HullLength;
+				
+				copy.inheritDeform = inheritDeform;
+				
+				// Nonessential.
+				if (Edges != null) {
+					copy.Edges = new int[Edges.Length];
+					Array.Copy(Edges, 0, copy.Edges, 0, Edges.Length);
+				}
+				copy.Width = Width;
+				copy.Height = Height;
+			}
+			else
+				copy.ParentMesh = parentMesh;
+			
+			return copy;
+		}
 	}
 }

+ 11 - 1
spine-csharp/src/Attachments/PathAttachment.cs

@@ -42,6 +42,16 @@ namespace Spine {
 
 		public PathAttachment (String name)
 			: base(name) {
-		}			
+		}
+
+		public override Attachment Copy () {
+			PathAttachment copy = new PathAttachment(this.Name);
+			CopyTo(copy);
+			copy.lengths = new float[lengths.Length];
+			Array.Copy(lengths, 0, copy.lengths, 0, lengths.Length);
+			copy.closed = closed;
+			copy.constantSpeed = constantSpeed;
+			       return copy;
+		}
 	}
 }

+ 8 - 0
spine-csharp/src/Attachments/PointAttachment.cs

@@ -55,5 +55,13 @@ namespace Spine {
 			float iy = cos * bone.c + sin * bone.d;
 			return MathUtils.Atan2(iy, ix) * MathUtils.RadDeg;
 		}
+
+		public override Attachment Copy () {
+			PointAttachment copy = new PointAttachment(this.Name);
+			copy.x = x;
+			copy.y = y;
+			copy.rotation = rotation;
+			return copy;
+		}
 	}
 }

+ 21 - 0
spine-csharp/src/Attachments/RegionAttachment.cs

@@ -178,5 +178,26 @@ namespace Spine {
 			worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy;
 			//offset += stride;
 		}
+
+		public override Attachment Copy () {
+			RegionAttachment copy = new RegionAttachment(this.Name);
+			copy.regionOffsetX = regionOffsetX;
+			copy.regionOffsetY = regionOffsetY;
+			copy.regionWidth = regionWidth;
+			copy.regionHeight = regionHeight;
+			copy.regionOriginalWidth = regionOriginalWidth;
+			copy.regionOriginalHeight = regionOriginalHeight;
+			copy.Path = Path;
+			copy.x = x;
+			copy.y = y;
+			copy.scaleX = scaleX;
+			copy.scaleY = scaleY;
+			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);
+			return copy;
+		}
 	}
 }

+ 22 - 2
spine-csharp/src/Attachments/VertexAttachment.cs

@@ -32,7 +32,7 @@ using System;
 namespace Spine {
 	/// <summary>>An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's
 	/// <see cref="Slot.Deform"/>.</summary> 
-	public class VertexAttachment : Attachment {
+	public abstract class VertexAttachment : Attachment {
 		static int nextID = 0;
 		static readonly Object nextIdLock = new Object();
 
@@ -131,6 +131,26 @@ namespace Spine {
 		/// <summary>Returns true if a deform originally applied to the specified attachment should be applied to this attachment.</summary>
 		virtual public bool ApplyDeform (VertexAttachment sourceAttachment) {
 			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>
+		internal void CopyTo (VertexAttachment attachment) {
+			if (bones != null) {
+				attachment.bones = new int[bones.Length];
+				Array.Copy(bones, 0, attachment.bones, 0, bones.Length);
+			}
+			else
+				attachment.bones = null;
+			
+			if (vertices != null) {
+				attachment.vertices = new float[vertices.Length];
+				Array.Copy(vertices, 0, attachment.vertices, 0, vertices.Length);
+			}
+			else
+				attachment.vertices = null;
+			
+			attachment.worldVerticesLength = worldVerticesLength;
+		}
 	}
 }

+ 2 - 2
spine-csharp/src/Skeleton.cs

@@ -235,8 +235,8 @@ namespace Spine {
 		}
 
 		private void SortPathConstraintAttachment (Skin skin, int slotIndex, Bone slotBone) {
-			foreach (var entry in skin.Attachments)
-				if (entry.Key.slotIndex == slotIndex) SortPathConstraintAttachment(entry.Value, slotBone);
+			foreach (var entry in skin.Attachments.Keys)
+				if (entry.SlotIndex == slotIndex) SortPathConstraintAttachment(entry.Attachment, slotBone);
 		}
 
 		private void SortPathConstraintAttachment (Attachment attachment, Bone slotBone) {

+ 1 - 1
spine-csharp/src/SkeletonBinary.cs

@@ -321,7 +321,7 @@ namespace Spine {
 				for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) {
 					String name = ReadString(input);
 					Attachment attachment = ReadAttachment(input, skeletonData, skin, slotIndex, name, nonessential);
-					if (attachment != null) skin.AddAttachment(slotIndex, name, attachment);
+					if (attachment != null) skin.SetAttachment(slotIndex, name, attachment);
 				}
 			}
 			return skin;

+ 1 - 1
spine-csharp/src/SkeletonJson.cs

@@ -266,7 +266,7 @@ namespace Spine {
 						foreach (KeyValuePair<string, Object> entry in ((Dictionary<string, Object>)slotEntry.Value)) {
 							try {
 								Attachment attachment = ReadAttachment((Dictionary<string, Object>)entry.Value, skin, slotIndex, entry.Key, skeletonData);
-								if (attachment != null) skin.AddAttachment(slotIndex, entry.Key, attachment);
+								if (attachment != null) skin.SetAttachment(slotIndex, entry.Key, attachment);
 							} catch (Exception e) {
 								throw new Exception("Error reading attachment: " + entry.Key + ", skin: " + skin, e);
 							}

+ 71 - 39
spine-csharp/src/Skin.cs

@@ -37,53 +37,62 @@ namespace Spine {
 	/// </summary>
 	public class Skin {
 		internal string name;
-		private Dictionary<AttachmentKeyTuple, Attachment> attachments =
-			new Dictionary<AttachmentKeyTuple, Attachment>(AttachmentKeyTupleComparer.Instance);
-
+		private Dictionary<SkinEntry, Attachment> attachments =
+			new Dictionary<SkinEntry, Attachment>(SkinEntryComparer.Instance);
+		
 		public string Name { get { return name; } }
-		public Dictionary<AttachmentKeyTuple, Attachment> Attachments { get { return attachments; } }
+		public Dictionary<SkinEntry, Attachment> Attachments { get { return attachments; } }
 
 		public Skin (string name) {
 			if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
 			this.name = name;
 		}
 
-		/// <summary>Adds an attachment to the skin for the specified slot index and name. If the name already exists for the slot, the previous value is replaced.</summary>
-		public void AddAttachment (int slotIndex, string name, Attachment attachment) {
+		/// <summary>Adds an attachment to the skin for the specified slot index and name.
+		/// If the name already exists for the slot, the previous value is replaced.</summary>
+		public void SetAttachment (int slotIndex, string name, Attachment attachment) {
 			if (attachment == null) throw new ArgumentNullException("attachment", "attachment cannot be null.");
-			attachments[new AttachmentKeyTuple(slotIndex, name)] = attachment;
+			if (slotIndex < 0) throw new ArgumentNullException("slotIndex", "slotIndex must be >= 0.");
+			attachments[new SkinEntry(slotIndex, name, attachment)] = attachment;
+		}
+
+		///<summary>Adds all attachments from the specified skin to this skin.</summary>
+		public void AddSkin (Skin skin) {
+			foreach (SkinEntry entry in skin.attachments.Keys)
+				SetAttachment(entry.SlotIndex, entry.Name, entry.Attachment);
 		}
 
 		/// <summary>Returns the attachment for the specified slot index and name, or null.</summary>
 		/// <returns>May be null.</returns>
 		public Attachment GetAttachment (int slotIndex, string name) {
 			Attachment attachment;
-			attachments.TryGetValue(new AttachmentKeyTuple(slotIndex, name), out attachment);
+			var lookup = new SkinEntry(slotIndex, name, null);
+			attachments.TryGetValue(lookup, out attachment);
 			return attachment;
 		}
 
 		/// <summary> Removes the attachment in the skin for the specified slot index and name, if any.</summary>
 		public void RemoveAttachment (int slotIndex, string name) {
 			if (slotIndex < 0) throw new ArgumentOutOfRangeException("slotIndex", "slotIndex must be >= 0");
-			attachments.Remove(new AttachmentKeyTuple(slotIndex, name));
+			var lookup = new SkinEntry(slotIndex, name, null);
+			attachments.Remove(lookup);
 		}
 
-		/// <summary>Finds the skin keys for a given slot. The results are added to the passed List(names).</summary>
-		/// <param name="slotIndex">The target slotIndex. To find the slot index, use <see cref="Spine.Skeleton.FindSlotIndex"/> or <see cref="Spine.SkeletonData.FindSlotIndex"/>
-		/// <param name="names">Found skin key names will be added to this list.</param>
-		public void FindNamesForSlot (int slotIndex, List<string> names) {
-			if (names == null) throw new ArgumentNullException("names", "names cannot be null.");
-			foreach (AttachmentKeyTuple key in attachments.Keys)
-				if (key.slotIndex == slotIndex) names.Add(key.name);
+		///<summary>Returns all attachments contained in this skin.</summary>
+		public List<SkinEntry> GetAttachments () {
+			List<SkinEntry> entries = new List<SkinEntry>();
+			foreach (SkinEntry entry in this.attachments.Keys)
+				entries.Add(entry);
+			return entries;
 		}
 
-		/// <summary>Finds the attachments for a given slot. The results are added to the passed List(Attachment).</summary>
+		/// <summary>Returns all <see cref="SkinEntry"/> instances for the given slot contained in this skin.</summary>
 		/// <param name="slotIndex">The target slotIndex. To find the slot index, use <see cref="Spine.Skeleton.FindSlotIndex"/> or <see cref="Spine.SkeletonData.FindSlotIndex"/>
-		/// <param name="attachments">Found Attachments will be added to this list.</param>
-		public void FindAttachmentsForSlot (int slotIndex, List<Attachment> attachments) {
-			if (attachments == null) throw new ArgumentNullException("attachments", "attachments cannot be null.");
-			foreach (KeyValuePair<AttachmentKeyTuple, Attachment> entry in this.attachments)
-				if (entry.Key.slotIndex == slotIndex) attachments.Add(entry.Value);
+		public List<SkinEntry> GetEntries (int slotIndex) { 
+			List<SkinEntry> entries = new List<SkinEntry>();
+			foreach (SkinEntry entry in this.attachments.Keys)
+				if (entry.SlotIndex == slotIndex) entries.Add(entry);
+			return entries;
 		}
 
 		override public string ToString () {
@@ -92,38 +101,61 @@ namespace Spine {
 
 		/// <summary>Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached.</summary>
 		internal void AttachAll (Skeleton skeleton, Skin oldSkin) {
-			foreach (KeyValuePair<AttachmentKeyTuple, Attachment> entry in oldSkin.attachments) {
-				int slotIndex = entry.Key.slotIndex;
+			foreach (SkinEntry entry in oldSkin.attachments.Keys) {
+				int slotIndex = entry.SlotIndex;
 				Slot slot = skeleton.slots.Items[slotIndex];
-				if (slot.Attachment == entry.Value) {
-					Attachment attachment = GetAttachment(slotIndex, entry.Key.name);
+				if (slot.Attachment == entry.Attachment) {
+					Attachment attachment = GetAttachment(slotIndex, entry.Name);
 					if (attachment != null) slot.Attachment = attachment;
 				}
 			}
 		}
 
-		public struct AttachmentKeyTuple {
-			public readonly int slotIndex;
-			public readonly string name;
-			internal readonly int nameHashCode;
+		/// <summary>Stores an entry in the skin consisting of the slot index, name, and attachment.</summary>
+		public struct SkinEntry {
+			private readonly int slotIndex;
+			private readonly string name;
+			private readonly Attachment attachment;
+			internal readonly int hashCode;
 
-			public AttachmentKeyTuple (int slotIndex, string name) {
+			public SkinEntry (int slotIndex, string name, Attachment attachment) {
 				this.slotIndex = slotIndex;
 				this.name = name;
-				nameHashCode = this.name.GetHashCode();
+				this.attachment = attachment;
+				this.hashCode = this.name.GetHashCode() + this.slotIndex * 37;
+			}
+
+			public int SlotIndex {
+				get {
+					return slotIndex;
+				}
+			}
+
+			public String Name {
+				get {
+					return name;
+				}
 			}
-		}
 
+			public Attachment Attachment {
+				get {
+					return attachment;
+				}
+			}
+		}
+	
 		// Avoids boxing in the dictionary.
-		class AttachmentKeyTupleComparer : IEqualityComparer<AttachmentKeyTuple> {
-			internal static readonly AttachmentKeyTupleComparer Instance = new AttachmentKeyTupleComparer();
+		class SkinEntryComparer : IEqualityComparer<SkinEntry> {
+			internal static readonly SkinEntryComparer Instance = new SkinEntryComparer();
 
-			bool IEqualityComparer<AttachmentKeyTuple>.Equals (AttachmentKeyTuple o1, AttachmentKeyTuple o2) {
-				return o1.slotIndex == o2.slotIndex && o1.nameHashCode == o2.nameHashCode && string.Equals(o1.name, o2.name, StringComparison.Ordinal);
+			bool IEqualityComparer<SkinEntry>.Equals (SkinEntry o1, SkinEntry o2) {
+				if (o1.SlotIndex != o2.SlotIndex) return false;
+				if (!string.Equals(o1.Name, o2.Name, StringComparison.Ordinal)) return false;
+				return true;
 			}
 
-			int IEqualityComparer<AttachmentKeyTuple>.GetHashCode (AttachmentKeyTuple o) {
-				return o.slotIndex;
+			int IEqualityComparer<SkinEntry>.GetHashCode (SkinEntry o) {
+				return o.Name.GetHashCode() + o.SlotIndex * 37;
 			}
 		}
 	}

+ 1 - 1
spine-unity/Assets/Spine Examples/Scripts/Mix and Match Character Customize/EquipsVisualsComponentExample.cs

@@ -60,7 +60,7 @@ namespace Spine.Unity.Examples {
 		}
 
 		public void Equip (int slotIndex, string attachmentName, Attachment attachment) {
-			equipsSkin.AddAttachment(slotIndex, attachmentName, attachment);
+			equipsSkin.SetAttachment(slotIndex, attachmentName, attachment);
 			skeletonAnimation.Skeleton.SetSkin(equipsSkin);
 			RefreshSkeletonAttachments();
 		}

+ 1 - 1
spine-unity/Assets/Spine Examples/Scripts/Sample Components/Legacy/SpriteAttacher.cs

@@ -170,7 +170,7 @@ namespace Spine.Unity.Examples {
 			if (skinName != "")
 				skin = skeletonData.FindSkin(skinName);
 
-			skin.AddAttachment(slotIndex, att.Name, att);
+			skin.SetAttachment(slotIndex, att.Name, att);
 
 			return att;
 		}

+ 1 - 1
spine-unity/Assets/Spine/Editor/spine-unity/Editor/PointFollowerEditor.cs

@@ -114,7 +114,7 @@ namespace Spine.Unity.Editor {
 				var attachment = skinEntry.Value as PointAttachment;
 				if (attachment != null) {
 					var skinKey = skinEntry.Key;
-					var slot = skeleton.Slots.Items[skinKey.slotIndex];
+					var slot = skeleton.Slots.Items[skinKey.SlotIndex];
 					DrawPointAttachmentWithLabel(attachment, slot.Bone, transform);
 				}
 			}

+ 13 - 5
spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonBaker.cs

@@ -229,7 +229,9 @@ namespace Spine.Unity.Editor {
 					for (int i = 0; i < skinCount; i++) {
 						var skin = skins.Items[i];
 						List<string> temp = new List<string>();
-						skin.FindNamesForSlot(s, temp);
+						var entries = skin.GetEntries(s);
+						foreach (var entry in entries)
+							temp.Add(entry.Name);
 						foreach (string str in temp) {
 							if (!attachmentNames.Contains(str))
 								attachmentNames.Add(str);
@@ -342,12 +344,18 @@ namespace Spine.Unity.Editor {
 					List<Attachment> attachments = new List<Attachment>();
 					List<string> attachmentNames = new List<string>();
 
-					skin.FindAttachmentsForSlot(i, attachments);
-					skin.FindNamesForSlot(i, attachmentNames);
+					var entries = skin.GetEntries(i);
+					foreach (var entry in entries) {
+						attachments.Add(entry.Attachment);
+						attachmentNames.Add(entry.Name);
+					}
 
 					if (skin != skeletonData.DefaultSkin) {
-						skeletonData.DefaultSkin.FindAttachmentsForSlot(i, attachments);
-						skeletonData.DefaultSkin.FindNamesForSlot(i, attachmentNames);
+						entries = skeletonData.DefaultSkin.GetEntries(i);
+						foreach (var entry in entries) {
+							attachments.Add(entry.Attachment);
+							attachmentNames.Add(entry.Name);
+						}
 					}
 
 					for (int a = 0; a < attachments.Count; a++) {

+ 16 - 6
spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDataAssetInspector.cs

@@ -498,15 +498,25 @@ namespace Spine.Unity.Editor {
 
 						using (new SpineInspectorUtility.IndentScope()) {
 							{
-								skin.FindNamesForSlot(i, slotAttachmentNames);
-								skin.FindAttachmentsForSlot(i, slotAttachments);
+								var entries = skin.GetEntries(i);
+								foreach (var entry in entries) {
+									slotAttachments.Add(entry.Attachment);
+									slotAttachmentNames.Add(entry.Name);
+								}
 
 								if (skin != defaultSkin) {
-									defaultSkin.FindNamesForSlot(i, defaultSkinAttachmentNames);
-									defaultSkin.FindNamesForSlot(i, slotAttachmentNames);
-									defaultSkin.FindAttachmentsForSlot(i, slotAttachments);
+									entries = defaultSkin.GetEntries(i);
+									foreach (var entry in entries) {
+										slotAttachments.Add(entry.Attachment);
+										slotAttachmentNames.Add(entry.Name);
+										defaultSkinAttachmentNames.Add(entry.Name);
+									}
+
 								} else {
-									defaultSkin.FindNamesForSlot(i, defaultSkinAttachmentNames);
+									entries = defaultSkin.GetEntries(i);
+									foreach (var entry in entries) {
+										defaultSkinAttachmentNames.Add(entry.Name);
+									}
 								}
 							}
 

+ 11 - 2
spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDebugWindow.cs

@@ -574,8 +574,17 @@ namespace Spine.Unity.Editor {
 			for (int i = skeleton.Slots.Count - 1; i >= 0; i--) {
 				var attachments = new List<Attachment>();
 				attachmentTable.Add(skeleton.Slots.Items[i], attachments);
-				skin.FindAttachmentsForSlot(i, attachments); // Add skin attachments.
-				if (notDefaultSkin) defaultSkin.FindAttachmentsForSlot(i, attachments); // Add default skin attachments.
+				// Add skin attachments.
+				var entries = skin.GetEntries(i);
+				foreach (var entry in entries) {
+					attachments.Add(entry.Attachment);
+				}
+				if (notDefaultSkin) { // Add default skin attachments.
+					entries = defaultSkin.GetEntries(i);
+					foreach (var entry in entries) {
+						attachments.Add(entry.Attachment);
+					}
+				}
 			}
 
 			activeSkin = skeleton.Skin;

+ 18 - 5
spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAttributeDrawers.cs

@@ -184,8 +184,12 @@ namespace Spine.Unity.Editor {
 					if (targetAttribute.containsBoundingBoxes) {
 						int slotIndex = i;
 						var attachments = new List<Attachment>();
-						foreach (var skin in data.Skins)
-							skin.FindAttachmentsForSlot(slotIndex, attachments);
+						foreach (var skin in data.Skins) {
+							var entries = skin.GetEntries(slotIndex);
+							foreach (var entry in entries) {
+								attachments.Add(entry.Attachment);
+							}
+						}
 
 						bool hasBoundingBox = false;
 						foreach (var attachment in attachments) {
@@ -470,10 +474,19 @@ namespace Spine.Unity.Editor {
 					attachmentNames.Clear();
 					placeholderNames.Clear();
 
-					skin.FindNamesForSlot(i, attachmentNames);
+					var entries = skin.GetEntries(i);
+					foreach (var entry in entries) {
+						attachmentNames.Add(entry.Name);
+					}
+
 					if (skin != defaultSkin) {
-						defaultSkin.FindNamesForSlot(i, attachmentNames);
-						skin.FindNamesForSlot(i, placeholderNames);
+						foreach (var entry in entries) {
+							placeholderNames.Add(entry.Name);
+						}
+						entries = defaultSkin.GetEntries(i);
+						foreach (var entry in entries) {
+							attachmentNames.Add(entry.Name);
+						}
 					}
 
 					for (int a = 0; a < attachmentNames.Count; a++) {

+ 5 - 1
spine-unity/Assets/Spine/Editor/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs

@@ -81,7 +81,11 @@ namespace Spine.Unity.Editor {
 				Slot slot = skeletonUtility.skeletonRenderer.skeleton.Slots.Items[i];
 				if (slot.Bone == utilityBone.bone) {
 					var slotAttachments = new List<Attachment>();
-					skin.FindAttachmentsForSlot(skeleton.FindSlotIndex(slot.Data.Name), slotAttachments);
+					var entries = skin.GetEntries(skeleton.FindSlotIndex(slot.Data.Name));
+					foreach (var entry in entries) {
+						slotAttachments.Add(entry.Attachment);
+					}
+
 					var boundingBoxes = new List<BoundingBoxAttachment>();
 					foreach (var att in slotAttachments) {
 						var boundingBoxAttachment = att as BoundingBoxAttachment;

+ 7 - 4
spine-unity/Assets/Spine/Runtime/spine-unity/Asset Types/BlendModeMaterialsAsset.cs

@@ -54,14 +54,17 @@ namespace Spine.Unity {
 			using (var materialCache = new AtlasMaterialCache()) {
 				var attachmentBuffer = new List<Attachment>();
 				var slotsItems = skeletonData.Slots.Items;
-				for (int i = 0, slotCount = skeletonData.Slots.Count; i < slotCount; i++) {
-					var slot = slotsItems[i];
+				for (int slotIndex = 0, slotCount = skeletonData.Slots.Count; slotIndex < slotCount; slotIndex++) {
+					var slot = slotsItems[slotIndex];
 					if (slot.blendMode == BlendMode.Normal) continue;
 					if (!includeAdditiveSlots && slot.blendMode == BlendMode.Additive) continue;
 
 					attachmentBuffer.Clear();
-					foreach (var skin in skeletonData.Skins)
-						skin.FindAttachmentsForSlot(i, attachmentBuffer);
+					foreach (var skin in skeletonData.Skins) {
+						var entries = skin.GetEntries(slotIndex);
+						foreach (var entry in entries)
+							attachmentBuffer.Add(entry.Attachment);
+					}
 
 					Material templateMaterial = null;
 					switch (slot.blendMode) {

+ 4 - 4
spine-unity/Assets/Spine/Runtime/spine-unity/Modules/AttachmentTools/AttachmentTools.cs

@@ -523,9 +523,9 @@ namespace Spine.Unity.Modules.AttachmentTools {
 					}
 
 					repackedAttachments.Add(newAttachment);
-					newSkin.AddAttachment(originalKey.slotIndex, originalKey.name, newAttachment);
+					newSkin.SetAttachment(originalKey.SlotIndex, originalKey.Name, newAttachment);
 				} else {
-					newSkin.AddAttachment(originalKey.slotIndex, originalKey.name, useOriginalNonrenderables ? originalAttachment : originalAttachment.GetClone(true));
+					newSkin.SetAttachment(originalKey.SlotIndex, originalKey.Name, useOriginalNonrenderables ? originalAttachment : originalAttachment.GetClone(true));
 				}	
 			}
 
@@ -804,7 +804,7 @@ namespace Spine.Unity.Modules.AttachmentTools {
 			int slotIndex = skeleton.FindSlotIndex(slotName);
 			if (skeleton == null) throw new System.ArgumentNullException("skeleton", "skeleton cannot be null.");
 			if (slotIndex == -1) throw new System.ArgumentException(string.Format("Slot '{0}' does not exist in skeleton.", slotName), "slotName");
-			skin.AddAttachment(slotIndex, keyName, attachment);
+			skin.SetAttachment(slotIndex, keyName, attachment);
 		}
 
 		/// <summary>Adds skin items from another skin. For items that already exist, the previous values are replaced.</summary>
@@ -823,7 +823,7 @@ namespace Spine.Unity.Modules.AttachmentTools {
 
 		/// <summary>Adds an attachment to the skin for the specified slot index and name. If the name already exists for the slot, the previous value is replaced.</summary>
 		public static void SetAttachment (this Skin skin, int slotIndex, string keyName, Attachment attachment) {
-			skin.AddAttachment(slotIndex, keyName, attachment);
+			skin.SetAttachment(slotIndex, keyName, attachment);
 		}
 		
 		public static void RemoveAttachment (this Skin skin, string slotName, string keyName, SkeletonData skeletonData) {

+ 3 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/Modules/BoundingBoxFollower/BoundingBoxFollower.cs

@@ -140,7 +140,9 @@ namespace Spine.Unity {
 		void AddSkin (Skin skin, int slotIndex) {
 			if (skin == null) return;
 			var attachmentNames = new List<string>();
-			skin.FindNamesForSlot(slotIndex, attachmentNames);
+			var entries = skin.GetEntries(slotIndex);
+			foreach (var entry in entries)
+				attachmentNames.Add(entry.Name);
 
 			foreach (var skinKey in attachmentNames) {
 				var attachment = skin.GetAttachment(slotIndex, skinKey);

+ 4 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs

@@ -368,7 +368,10 @@ namespace Spine.Unity.Modules {
 			var attachments = new List<Attachment>();
 			foreach (Slot s in skeleton.Slots) {
 				if (s.Bone == b) {
-					skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
+					var entries = skin.GetEntries(skeleton.Slots.IndexOf(s));
+					foreach (var entry in entries)
+						attachments.Add(entry.Attachment);
+
 					foreach (var a in attachments) {
 						var bbAttachment = a as BoundingBoxAttachment;
 						if (bbAttachment != null) {

+ 3 - 1
spine-unity/Assets/Spine/Runtime/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs

@@ -363,7 +363,9 @@ namespace Spine.Unity.Modules {
 			var attachments = new List<Attachment>();
 			foreach (Slot slot in skeleton.Slots) {
 				if (slot.bone == b) {
-					skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(slot), attachments);
+					var entries = skin.GetEntries(skeleton.Slots.IndexOf(slot));
+					foreach (var entry in entries)
+						attachments.Add(entry.Attachment);
 
 					bool bbAttachmentAdded = false;
 					foreach (var a in attachments) {

+ 0 - 15
spine-unity/Assets/Spine/Runtime/spine-unity/SkeletonExtensions.cs

@@ -608,21 +608,6 @@ namespace Spine {
 		public static void AllowImmediateQueue (this TrackEntry trackEntry) {
 			if (trackEntry.nextTrackLast < 0) trackEntry.nextTrackLast = 0;
 		}
-
-		#endregion
-
-		#region Skins
-		/// <summary><see cref="Spine.Skin.FindNamesForSlot(int,List)"/></summary>
-		public static void FindNamesForSlot (this Skin skin, string slotName, SkeletonData skeletonData, List<string> results) {
-			int slotIndex = skeletonData.FindSlotIndex(slotName);
-			skin.FindNamesForSlot(slotIndex, results);
-		}
-
-		/// <summary><see cref="Spine.Skin.FindAttachmentsForSlot(int,List)"/></summary>
-		public static void FindAttachmentsForSlot (this Skin skin, string slotName, SkeletonData skeletonData, List<Attachment> results) {
-			int slotIndex = skeletonData.FindSlotIndex(slotName);
-			skin.FindAttachmentsForSlot(slotIndex, results);
-		}
 		#endregion
 	}
 }