From ed95732bf2ccbf23d90e0a39f22c2b859af22e49 Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Wed, 7 Aug 2019 14:42:00 +0200 Subject: [PATCH] [csharp] Changed Skin.Attachment type to generic OrderedDictionary. Cleaned up related code. Closes #1433. --- .../src/Collections/OrderedDictionary.cs | 636 ++++++++++++++++++ spine-csharp/src/Skin.cs | 27 +- .../Asset Types/SkeletonDataAssetInspector.cs | 39 +- .../Components/PointFollowerInspector.cs | 2 +- .../SkeletonUtilityBoneInspector.cs | 12 +- .../Editor/Windows/SkeletonBaker.cs | 22 +- .../Editor/Windows/SkeletonDebugWindow.cs | 24 +- .../spine-unity/Utility/AtlasUtilities.cs | 6 +- .../spine-unity/Utility/SkinUtilities.cs | 18 +- 9 files changed, 687 insertions(+), 99 deletions(-) create mode 100644 spine-csharp/src/Collections/OrderedDictionary.cs diff --git a/spine-csharp/src/Collections/OrderedDictionary.cs b/spine-csharp/src/Collections/OrderedDictionary.cs new file mode 100644 index 000000000..89e23417d --- /dev/null +++ b/spine-csharp/src/Collections/OrderedDictionary.cs @@ -0,0 +1,636 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated May 1, 2019. Replaces all prior versions. + * + * Copyright (c) 2013-2019, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS + * INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ +/****************************************************************************** + * Thanks to Travis Parks + * https://github.com/jehugaleahsa/truncon.collections.OrderedDictionary + *****************************************************************************/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; + +#if UNITY_EDITOR +using System.Linq; +#endif + +namespace Spine.Collections +{ + /// + /// Represents a dictionary that tracks the order that items were added. + /// + /// The type of the dictionary keys. + /// The type of the dictionary values. + /// + /// This dictionary makes it possible to get the index of a key and a key based on an index. + /// It can be costly to find the index of a key because it must be searched for linearly. + /// It can be costly to insert a key/value pair because other key's indexes must be adjusted. + /// It can be costly to remove a key/value pair because other keys' indexes must be adjusted. + /// + [DebuggerDisplay("Count = {Count}")] + [DebuggerTypeProxy(typeof(OrderedDictionaryDebugView<,>))] + public sealed class OrderedDictionary : IDictionary, IList> + { + private readonly Dictionary dictionary; + private readonly List keys; + private readonly List values; + private int version; + + private const string CollectionModifiedMessage = "Collection was modified; enumeration operation may not execute."; + private const string EditReadOnlyListMessage = "An attempt was made to edit a read-only list."; + private const string IndexOutOfRangeMessage = "The index is negative or outside the bounds of the collection."; + + /// + /// Initializes a new instance of an OrderedDictionary. + /// + public OrderedDictionary () + : this(0, null) { + } + + /// + /// Initializes a new instance of an OrderedDictionary. + /// + /// The initial capacity of the dictionary. + /// The capacity is less than zero. + public OrderedDictionary (int capacity) + : this(capacity, null) { + } + + /// + /// Initializes a new instance of an OrderedDictionary. + /// + /// The equality comparer to use to compare keys. + public OrderedDictionary (IEqualityComparer comparer) + : this(0, comparer) { + } + + /// + /// Initializes a new instance of an OrderedDictionary. + /// + /// The initial capacity of the dictionary. + /// The equality comparer to use to compare keys. + public OrderedDictionary (int capacity, IEqualityComparer comparer) { + dictionary = new Dictionary(capacity, comparer ?? EqualityComparer.Default); + keys = new List(capacity); + values = new List(capacity); + } + + /// + /// Gets the equality comparer used to compare keys. + /// + public IEqualityComparer Comparer { + get { + return dictionary.Comparer; + } + } + + /// + /// Adds the given key/value pair to the dictionary. + /// + /// The key to add to the dictionary. + /// The value to associated with the key. + /// The given key already exists in the dictionary. + /// The key is null. + public void Add (TKey key, TValue value) { + dictionary.Add(key, values.Count); + keys.Add(key); + values.Add(value); + ++version; + } + + /// + /// Inserts the given key/value pair at the specified index. + /// + /// The index to insert the key/value pair. + /// The key to insert. + /// The value to insert. + /// The given key already exists in the dictionary. + /// The key is null. + /// The index is negative -or- larger than the size of the dictionary. + public void Insert (int index, TKey key, TValue value) { + if (index < 0 || index > values.Count) { + throw new ArgumentOutOfRangeException("index", index, IndexOutOfRangeMessage); + } + dictionary.Add(key, index); + for (int keyIndex = index; keyIndex != keys.Count; ++keyIndex) { + var otherKey = keys[keyIndex]; + dictionary[otherKey] += 1; + } + keys.Insert(index, key); + values.Insert(index, value); + ++version; + } + + /// + /// Determines whether the given key exists in the dictionary. + /// + /// The key to look for. + /// True if the key exists in the dictionary; otherwise, false. + /// The key is null. + public bool ContainsKey (TKey key) { + return dictionary.ContainsKey(key); + } + + /// + /// Gets the key at the given index. + /// + /// The index of the key to get. + /// The key at the given index. + /// The index is negative -or- larger than the number of keys. + public TKey GetKey (int index) { + return keys[index]; + } + + /// + /// Gets the index of the given key. + /// + /// The key to get the index of. + /// The index of the key in the dictionary -or- -1 if the key is not found. + /// The operation runs in O(n). + public int IndexOf (TKey key) { + int index; + if (dictionary.TryGetValue(key, out index)) { + return index; + } + return -1; + } + + /// + /// Gets the keys in the dictionary in the order they were added. + /// + public KeyCollection Keys { + get { + return new KeyCollection(this.dictionary); + } + } + + /// + /// Removes the key/value pair with the given key from the dictionary. + /// + /// The key of the pair to remove. + /// True if the key was found and the pair removed; otherwise, false. + /// The key is null. + public bool Remove (TKey key) { + int index; + if (dictionary.TryGetValue(key, out index)) { + RemoveAt(index); + return true; + } + return false; + } + + /// + /// Removes the key/value pair at the given index. + /// + /// The index of the key/value pair to remove. + /// The index is negative -or- larger than the size of the dictionary. + public void RemoveAt (int index) { + var key = keys[index]; + for (int keyIndex = index + 1; keyIndex < keys.Count; ++keyIndex) { + var otherKey = keys[keyIndex]; + dictionary[otherKey] -= 1; + } + dictionary.Remove(key); + keys.RemoveAt(index); + values.RemoveAt(index); + ++version; + } + + /// + /// Tries to get the value associated with the given key. If the key is not found, + /// default(TValue) value is stored in the value. + /// + /// The key to get the value for. + /// The value used to hold the results. + /// True if the key was found; otherwise, false. + /// The key is null. + public bool TryGetValue (TKey key, out TValue value) { + int index; + if (dictionary.TryGetValue(key, out index)) { + value = values[index]; + return true; + } + value = default(TValue); + return false; + } + + /// + /// Gets the values in the dictionary. + /// + public ValueCollection Values { + get { + return new ValueCollection(values); + } + } + + /// + /// Gets or sets the value at the given index. + /// + /// The index of the value to get. + /// The value at the given index. + /// The index is negative -or- beyond the length of the dictionary. + public TValue this[int index] { + get { + return values[index]; + } + + set { + values[index] = value; + } + } + + /// + /// Gets or sets the value associated with the given key. + /// + /// The key to get the associated value by or to associate with the value. + /// The value associated with the given key. + /// The key is null. + /// The key is not in the dictionary. + public TValue this[TKey key] { + get { + return values[dictionary[key]]; + } + set { + int index; + if (dictionary.TryGetValue(key, out index)) { + values[index] = value; + } + else { + Add(key, value); + } + } + } + + /// + /// Removes all key/value pairs from the dictionary. + /// + public void Clear () { + dictionary.Clear(); + keys.Clear(); + values.Clear(); + ++version; + } + + /// + /// Gets the number of key/value pairs in the dictionary. + /// + public int Count { + get { + return dictionary.Count; + } + } + + /// + /// Gets the key/value pairs in the dictionary in the order they were added. + /// + /// An enumerator over the key/value pairs in the dictionary. + public IEnumerator> GetEnumerator () { + int startVersion = version; + for (int index = 0; index != keys.Count; ++index) { + var key = keys[index]; + var value = values[index]; + yield return new KeyValuePair(key, value); + if (version != startVersion) { + throw new InvalidOperationException(CollectionModifiedMessage); + } + } + } + + int IList>.IndexOf (KeyValuePair item) { + int index; + if (dictionary.TryGetValue(item.Key, out index) && Equals(values[index], item.Value)) { + return index; + } + return -1; + } + + void IList>.Insert (int index, KeyValuePair item) { + Insert(index, item.Key, item.Value); + } + + KeyValuePair IList>.this[int index] { + get { + TKey key = keys[index]; + TValue value = values[index]; + return new KeyValuePair(key, value); + } + set { + TKey key = keys[index]; + if (dictionary.Comparer.Equals(key, value.Key)) { + dictionary[value.Key] = index; + } + else { + dictionary.Add(value.Key, index); // will throw if key already exists + dictionary.Remove(key); + } + keys[index] = value.Key; + values[index] = value.Value; + } + } + + ICollection IDictionary.Keys { + get { + return Keys; + } + } + + ICollection IDictionary.Values { + get { + return Values; + } + } + + void ICollection>.Add (KeyValuePair item) { + Add(item.Key, item.Value); + } + + bool ICollection>.Contains (KeyValuePair item) { + int index; + if (dictionary.TryGetValue(item.Key, out index) && Equals(values[index], item.Value)) { + return true; + } + return false; + } + + void ICollection>.CopyTo (KeyValuePair[] array, int arrayIndex) { + if (array == null) { + throw new ArgumentNullException("array"); + } + if (arrayIndex < 0) { + throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex, IndexOutOfRangeMessage); + } + for (int index = 0; index != keys.Count && arrayIndex < array.Length; ++index, ++arrayIndex) { + var key = keys[index]; + var value = values[index]; + array[arrayIndex] = new KeyValuePair(key, value); + } + } + + bool ICollection>.IsReadOnly { + get { + return false; + } + } + + bool ICollection>.Remove (KeyValuePair item) { + ICollection> self = this; + if (self.Contains(item)) { + return Remove(item.Key); + } + return false; + } + + IEnumerator IEnumerable.GetEnumerator () { + return GetEnumerator(); + } + + /// + /// Wraps the keys in an OrderDictionary. + /// + public sealed class KeyCollection : ICollection + { + private readonly Dictionary dictionary; + + /// + /// Initializes a new instance of a KeyCollection. + /// + /// The OrderedDictionary whose keys to wrap. + /// The dictionary is null. + internal KeyCollection (Dictionary dictionary) { + this.dictionary = dictionary; + } + + /// + /// Copies the keys from the OrderedDictionary to the given array, starting at the given index. + /// + /// The array to copy the keys to. + /// The index into the array to start copying the keys. + /// The array is null. + /// The arrayIndex is negative. + /// The array, starting at the given index, is not large enough to contain all the keys. + public void CopyTo (TKey[] array, int arrayIndex) { + dictionary.Keys.CopyTo(array, arrayIndex); + } + + /// + /// Gets the number of keys in the OrderedDictionary. + /// + public int Count { + get { + return dictionary.Count; + } + } + + /// + /// Gets an enumerator over the keys in the OrderedDictionary. + /// + /// The enumerator. + public IEnumerator GetEnumerator () { + return dictionary.Keys.GetEnumerator(); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + bool ICollection.Contains (TKey item) { + return dictionary.ContainsKey(item); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + void ICollection.Add (TKey item) { + throw new NotSupportedException(EditReadOnlyListMessage); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + void ICollection.Clear () { + throw new NotSupportedException(EditReadOnlyListMessage); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + bool ICollection.IsReadOnly { + get { + return true; + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + bool ICollection.Remove (TKey item) { + throw new NotSupportedException(EditReadOnlyListMessage); + } + + IEnumerator IEnumerable.GetEnumerator () { + return GetEnumerator(); + } + } + + /// + /// Wraps the keys in an OrderDictionary. + /// + public sealed class ValueCollection : ICollection + { + private readonly List values; + + /// + /// Initializes a new instance of a ValueCollection. + /// + /// The OrderedDictionary whose keys to wrap. + /// The dictionary is null. + internal ValueCollection (List values) { + this.values = values; + } + + /// + /// Copies the values from the OrderedDictionary to the given array, starting at the given index. + /// + /// The array to copy the values to. + /// The index into the array to start copying the values. + /// The array is null. + /// The arrayIndex is negative. + /// The array, starting at the given index, is not large enough to contain all the values. + public void CopyTo (TValue[] array, int arrayIndex) { + values.CopyTo(array, arrayIndex); + } + + /// + /// Gets the number of values in the OrderedDictionary. + /// + public int Count { + get { + return values.Count; + } + } + + /// + /// Gets an enumerator over the values in the OrderedDictionary. + /// + /// The enumerator. + public IEnumerator GetEnumerator () { + return values.GetEnumerator(); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + bool ICollection.Contains (TValue item) { + return values.Contains(item); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + void ICollection.Add (TValue item) { + throw new NotSupportedException(EditReadOnlyListMessage); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + void ICollection.Clear () { + throw new NotSupportedException(EditReadOnlyListMessage); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + bool ICollection.IsReadOnly { + get { + return true; + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + bool ICollection.Remove (TValue item) { + throw new NotSupportedException(EditReadOnlyListMessage); + } + + IEnumerator IEnumerable.GetEnumerator () { + return GetEnumerator(); + } + } + } + + #if UNITY_EDITOR + internal class OrderedDictionaryDebugView + { + private readonly OrderedDictionary dictionary; + + public OrderedDictionaryDebugView (OrderedDictionary dictionary) { + this.dictionary = dictionary; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public KeyValuePair[] Items { + get { + return dictionary.ToArray(); + } + } + } + #endif + + /// + /// Provides extensions methods for constructing instances of . + /// + public static class CollectionExtensions + { + #region ToOrderedDictionary + + /// + /// Creates a new OrderedDictionary from the given collection, using the key selector to extract the key. + /// + /// The type of the items in the collection. + /// The type of the key. + /// The items to created the OrderedDictionary from. + /// A delegate that can extract a key from an item in the collection. + /// An OrderedDictionary mapping the extracted keys to their values. + public static OrderedDictionary ToOrderedDictionary (this IEnumerable source, Func keySelector) { + return ToOrderedDictionary(source, keySelector, null); + } + + /// + /// Creates a new OrderedDictionary from the given collection, using the key selector to extract the key. + /// The key comparer is passed to the OrderedDictionary for comparing the extracted keys. + /// + /// The type of the items in the collection. + /// The type of the key. + /// The items to created the OrderedDictionary from. + /// A delegate that can extract a key from an item in the collection. + /// The key equality comparer to use to compare keys in the dictionary. + /// An OrderedDictionary mapping the extracted keys to their values. + public static OrderedDictionary ToOrderedDictionary ( + this IEnumerable source, + Func keySelector, + IEqualityComparer comparer) { + if (source == null) { + throw new ArgumentNullException("source"); + } + if (keySelector == null) { + throw new ArgumentNullException("keySelector"); + } + var dictionary = new OrderedDictionary(comparer); + foreach (TSource item in source) { + TKey key = keySelector(item); + dictionary.Add(key, item); + } + return dictionary; + } + + #endregion + } +} diff --git a/spine-csharp/src/Skin.cs b/spine-csharp/src/Skin.cs index 0ec045a59..bbaba5cb0 100644 --- a/spine-csharp/src/Skin.cs +++ b/spine-csharp/src/Skin.cs @@ -30,7 +30,7 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.Specialized; +using Spine.Collections; namespace Spine { /// Stores attachments by slot index and attachment name. @@ -39,12 +39,12 @@ namespace Spine { /// public class Skin { internal string name; - private OrderedDictionary attachments = new OrderedDictionary(SkinEntryComparer.Instance); // contains + private OrderedDictionary attachments = new OrderedDictionary(SkinEntryComparer.Instance); internal readonly ExposedList bones = new ExposedList(); internal readonly ExposedList constraints = new ExposedList(); public string Name { get { return name; } } - public OrderedDictionary Attachments { get { return attachments; } } + public OrderedDictionary Attachments { get { return attachments; } } public ExposedList Bones { get { return bones; } } public ExposedList Constraints { get { return constraints; } } @@ -94,8 +94,9 @@ namespace Spine { /// May be null. public Attachment GetAttachment (int slotIndex, string name) { var lookup = new SkinEntry(slotIndex, name, null); - var obj = attachments[lookup]; - return (obj == null) ? null : (Attachment)obj; + Attachment attachment = null; + bool containsKey = attachments.TryGetValue(lookup, out attachment); + return containsKey ? attachment : null; } /// Removes the attachment in the skin for the specified slot index and name, if any. @@ -106,11 +107,8 @@ namespace Spine { } ///Returns all attachments contained in this skin. - public List GetAttachments () { - List entries = new List(); - foreach (SkinEntry entry in this.attachments.Keys) - entries.Add(entry); - return entries; + public ICollection GetAttachments () { + return this.attachments.Keys; } /// Returns all attachments in this skin for the specified slot index. @@ -178,19 +176,16 @@ namespace Spine { } // Avoids boxing in the dictionary and is necessary to omit entry.attachment in the comparison. - class SkinEntryComparer : IEqualityComparer { + class SkinEntryComparer : IEqualityComparer { internal static readonly SkinEntryComparer Instance = new SkinEntryComparer(); - bool IEqualityComparer.Equals (object o1, object o2) { - var e1 = (SkinEntry)o1; - var e2 = (SkinEntry)o2; + bool IEqualityComparer.Equals (SkinEntry e1, SkinEntry e2) { if (e1.SlotIndex != e2.SlotIndex) return false; if (!string.Equals(e1.Name, e2.Name, StringComparison.Ordinal)) return false; return true; } - int IEqualityComparer.GetHashCode (object o) { - var e = (SkinEntry)o; + int IEqualityComparer.GetHashCode (SkinEntry e) { return e.Name.GetHashCode() + e.SlotIndex * 37; } } diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Asset Types/SkeletonDataAssetInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Asset Types/SkeletonDataAssetInspector.cs index d708a154d..cbd2e7ed8 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Asset Types/SkeletonDataAssetInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Asset Types/SkeletonDataAssetInspector.cs @@ -484,49 +484,32 @@ namespace Spine.Unity.Editor { } } - var slotAttachments = new List(); - var slotAttachmentNames = new List(); - var defaultSkinAttachmentNames = new List(); + var slotAttachments = new List(); + var defaultSkinAttachments = new List(); var slotsItems = preview.Skeleton.Slots.Items; for (int i = preview.Skeleton.Slots.Count - 1; i >= 0; i--) { Slot slot = slotsItems[i]; EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot)); if (showAttachments) { slotAttachments.Clear(); - slotAttachmentNames.Clear(); - defaultSkinAttachmentNames.Clear(); + defaultSkinAttachments.Clear(); using (new SpineInspectorUtility.IndentScope()) { { - var skinEntries = new List(); - skin.GetAttachments(i, skinEntries); - foreach (var entry in skinEntries) { - slotAttachments.Add(entry.Attachment); - slotAttachmentNames.Add(entry.Name); - } - + skin.GetAttachments(i, slotAttachments); if (skin != defaultSkin) { - skinEntries.Clear(); - defaultSkin.GetAttachments(i, skinEntries); - foreach (var entry in skinEntries) { - slotAttachments.Add(entry.Attachment); - slotAttachmentNames.Add(entry.Name); - defaultSkinAttachmentNames.Add(entry.Name); - } - + defaultSkin.GetAttachments(i, slotAttachments); + defaultSkin.GetAttachments(i, defaultSkinAttachments); } else { - skinEntries.Clear(); - defaultSkin.GetAttachments(i, skinEntries); - foreach (var entry in skinEntries) { - defaultSkinAttachmentNames.Add(entry.Name); - } + defaultSkin.GetAttachments(i, defaultSkinAttachments); } } for (int a = 0; a < slotAttachments.Count; a++) { - Attachment attachment = slotAttachments[a]; - string attachmentName = slotAttachmentNames[a]; - bool attachmentIsFromSkin = !defaultSkinAttachmentNames.Contains(attachmentName); + var skinEntry = slotAttachments[a]; + Attachment attachment = skinEntry.Attachment; + string attachmentName = skinEntry.Name; + bool attachmentIsFromSkin = !defaultSkinAttachments.Contains(skinEntry); Texture2D attachmentTypeIcon = Icons.GetAttachmentIcon(attachment); bool initialState = slot.Attachment == attachment; diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/PointFollowerInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/PointFollowerInspector.cs index 1d5eae6b4..0dbbe8ee5 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/PointFollowerInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/PointFollowerInspector.cs @@ -111,7 +111,7 @@ namespace Spine.Unity.Editor { } static void DrawPointsInSkin (Skin skin, Skeleton skeleton, Transform transform) { - foreach (DictionaryEntry skinEntry in skin.Attachments) { + foreach (var skinEntry in skin.Attachments) { var attachment = skinEntry.Value as PointAttachment; if (attachment != null) { var skinKey = (Skin.SkinEntry)skinEntry.Key; diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonUtilityBoneInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonUtilityBoneInspector.cs index 2a52f9e58..98c2e6f2c 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonUtilityBoneInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonUtilityBoneInspector.cs @@ -80,17 +80,13 @@ namespace Spine.Unity.Editor { for(int i = 0; i < slotCount; i++){ Slot slot = skeletonUtility.skeletonRenderer.skeleton.Slots.Items[i]; if (slot.Bone == utilityBone.bone) { - var slotAttachments = new List(); - var skinEntries = new List(); + var slotAttachments = new List(); int slotIndex = skeleton.FindSlotIndex(slot.Data.Name); - skin.GetAttachments(slotIndex, skinEntries); - foreach (var entry in skinEntries) { - slotAttachments.Add(entry.Attachment); - } - + skin.GetAttachments(slotIndex, slotAttachments); + var boundingBoxes = new List(); foreach (var att in slotAttachments) { - var boundingBoxAttachment = att as BoundingBoxAttachment; + var boundingBoxAttachment = att.Attachment as BoundingBoxAttachment; if (boundingBoxAttachment != null) boundingBoxes.Add(boundingBoxAttachment); } diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs index 7d65654e7..c77be6187 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonBaker.cs @@ -339,28 +339,14 @@ namespace Spine.Unity.Editor { slotTransform.parent = prefabRoot.transform; slotTable.Add(slotData.Name, slotTransform); - List attachments = new List(); - List attachmentNames = new List(); - var skinEntries = new List(); skin.GetAttachments(slotIndex, skinEntries); - foreach (var entry in skinEntries) { - attachments.Add(entry.Attachment); - attachmentNames.Add(entry.Name); - } - - if (skin != skeletonData.DefaultSkin) { - skinEntries.Clear(); + if (skin != skeletonData.DefaultSkin) skeletonData.DefaultSkin.GetAttachments(slotIndex, skinEntries); - foreach (var entry in skinEntries) { - attachments.Add(entry.Attachment); - attachmentNames.Add(entry.Name); - } - } - for (int a = 0; a < attachments.Count; a++) { - var attachment = attachments[a]; - string attachmentName = attachmentNames[a]; + for (int a = 0; a < skinEntries.Count; a++) { + var attachment = skinEntries[a].Attachment; + string attachmentName = skinEntries[a].Name; string attachmentMeshName = "[" + slotData.Name + "] " + attachmentName; Vector3 offset = Vector3.zero; float rotation = 0; diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonDebugWindow.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonDebugWindow.cs index b4577e2cf..db0b23e70 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonDebugWindow.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Windows/SkeletonDebugWindow.cs @@ -84,7 +84,7 @@ namespace Spine.Unity.Editor { [SpineBone(dataField:"skeletonRenderer")] public string boneName; - readonly Dictionary> attachmentTable = new Dictionary>(); + readonly Dictionary> attachmentTable = new Dictionary>(); static bool staticLostValues = true; @@ -338,7 +338,7 @@ namespace Spine.Unity.Editor { } int baseIndent = EditorGUI.indentLevel; - foreach (KeyValuePair> pair in attachmentTable) { + foreach (KeyValuePair> pair in attachmentTable) { Slot slot = pair.Key; using (new EditorGUILayout.HorizontalScope()) { @@ -352,7 +352,8 @@ namespace Spine.Unity.Editor { } } - foreach (var attachment in pair.Value) { + foreach (var skinEntry in pair.Value) { + var attachment = skinEntry.Attachment; GUI.contentColor = slot.Attachment == attachment ? Color.white : Color.grey; EditorGUI.indentLevel = baseIndent + 2; var icon = Icons.GetAttachmentIcon(attachment); @@ -577,21 +578,12 @@ namespace Spine.Unity.Editor { attachmentTable.Clear(); for (int i = skeleton.Slots.Count - 1; i >= 0; i--) { - var attachments = new List(); + var attachments = new List(); attachmentTable.Add(skeleton.Slots.Items[i], attachments); // Add skin attachments. - var skinEntries = new List(); - skin.GetAttachments(i, skinEntries); - foreach (var entry in skinEntries) { - attachments.Add(entry.Attachment); - } - if (notDefaultSkin) { // Add default skin attachments. - skinEntries.Clear(); - defaultSkin.GetAttachments(i, skinEntries); - foreach (var entry in skinEntries) { - attachments.Add(entry.Attachment); - } - } + skin.GetAttachments(i, attachments); + if (notDefaultSkin) // Add default skin attachments. + defaultSkin.GetAttachments(i, attachments); } activeSkin = skeleton.Skin; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs index 31f96179e..70e55c0f7 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/AtlasUtilities.cs @@ -333,9 +333,9 @@ namespace Spine.Unity.AttachmentTools { var originalRegions = new List(); int newRegionIndex = 0; - foreach (DictionaryEntry skinEntry in skinAttachments) { - var originalKey = (Skin.SkinEntry)skinEntry.Key; - var originalAttachment = (Attachment)skinEntry.Value; + foreach (var skinEntry in skinAttachments) { + var originalKey = skinEntry.Key; + var originalAttachment = skinEntry.Value; Attachment newAttachment; if (IsRenderable(originalAttachment)) { diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkinUtilities.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkinUtilities.cs index c8b4ce92d..22f3e76f1 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkinUtilities.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Utility/SkinUtilities.cs @@ -74,7 +74,7 @@ namespace Spine.Unity.AttachmentTools { var newSkin = new Skin(original.name + " clone"); var newSkinAttachments = newSkin.Attachments; - foreach (DictionaryEntry a in original.Attachments) + foreach (var a in original.Attachments) newSkinAttachments[a.Key] = a.Value; return newSkin; @@ -129,21 +129,21 @@ namespace Spine.Unity.AttachmentTools { if (cloneAttachments) { if (overwrite) { - foreach (DictionaryEntry e in sourceAttachments) - destinationAttachments[e.Key] = ((Attachment)e.Value).GetCopy(cloneMeshesAsLinked); + foreach (var e in sourceAttachments) + destinationAttachments[e.Key] = e.Value.GetCopy(cloneMeshesAsLinked); } else { - foreach (DictionaryEntry e in sourceAttachments) { - if (destinationAttachments.Contains(e.Key)) continue; - destinationAttachments.Add(e.Key, ((Attachment)e.Value).GetCopy(cloneMeshesAsLinked)); + foreach (var e in sourceAttachments) { + if (destinationAttachments.ContainsKey(e.Key)) continue; + destinationAttachments.Add(e.Key, e.Value.GetCopy(cloneMeshesAsLinked)); } } } else { if (overwrite) { - foreach (DictionaryEntry e in sourceAttachments) + foreach (var e in sourceAttachments) destinationAttachments[e.Key] = e.Value; } else { - foreach (DictionaryEntry e in sourceAttachments) { - if (destinationAttachments.Contains(e.Key)) continue; + foreach (var e in sourceAttachments) { + if (destinationAttachments.ContainsKey(e.Key)) continue; destinationAttachments.Add(e.Key, e.Value); } }