From 9ae48c2aac7beae57717eeaccf0fb99a567674c8 Mon Sep 17 00:00:00 2001 From: ZimM Date: Thu, 26 Feb 2015 05:00:44 +0200 Subject: [PATCH 01/24] replaced List with ExposedList to avoid indexer overhead --- spine-csharp/src/Animation.cs | 25 +- .../src/Attachments/SkinnedMeshAttachment.cs | 6 +- spine-csharp/src/Bone.cs | 4 +- spine-csharp/src/ExposedList.cs | 667 ++++++++++++++++++ spine-csharp/src/ExposedList.cs.meta | 8 + spine-csharp/src/IkConstraint.cs | 12 +- spine-csharp/src/Skeleton.cs | 112 +-- spine-csharp/src/SkeletonBounds.cs | 38 +- spine-csharp/src/Skin.cs | 2 +- .../spine-unity/Editor/SkeletonBaker.cs | 50 +- .../Editor/SkeletonDataAssetInspector.cs | 2 +- .../Assets/spine-unity/SkeletonRenderer.cs | 10 +- .../Editor/SkeletonUtilityBoneInspector.cs | 4 +- .../Editor/SkeletonUtilityInspector.cs | 2 +- .../SkeletonUtility/SkeletonUtility.cs | 10 +- 15 files changed, 816 insertions(+), 136 deletions(-) create mode 100644 spine-csharp/src/ExposedList.cs create mode 100644 spine-csharp/src/ExposedList.cs.meta diff --git a/spine-csharp/src/Animation.cs b/spine-csharp/src/Animation.cs index 672126e43..a31b12c10 100644 --- a/spine-csharp/src/Animation.cs +++ b/spine-csharp/src/Animation.cs @@ -233,7 +233,7 @@ namespace Spine { float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - Bone bone = skeleton.bones[boneIndex]; + Bone bone = skeleton.bones.Items[boneIndex]; float amount; @@ -296,7 +296,7 @@ namespace Spine { float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - Bone bone = skeleton.bones[boneIndex]; + Bone bone = skeleton.bones.Items[boneIndex]; if (time >= frames[frames.Length - 3]) { // Time is after last frame. bone.x += (bone.data.x + frames[frames.Length - 2] - bone.x) * alpha; @@ -326,7 +326,7 @@ namespace Spine { float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - Bone bone = skeleton.bones[boneIndex]; + Bone bone = skeleton.bones.Items[boneIndex]; if (time >= frames[frames.Length - 3]) { // Time is after last frame. bone.scaleX += (bone.data.scaleX * frames[frames.Length - 2] - bone.scaleX) * alpha; bone.scaleY += (bone.data.scaleY * frames[frames.Length - 1] - bone.scaleY) * alpha; @@ -402,7 +402,7 @@ namespace Spine { b = prevFrameB + (frames[frameIndex + FRAME_B] - prevFrameB) * percent; a = prevFrameA + (frames[frameIndex + FRAME_A] - prevFrameA) * percent; } - Slot slot = skeleton.slots[slotIndex]; + Slot slot = skeleton.slots.Items[slotIndex]; if (alpha < 1) { slot.r += (r - slot.r) * alpha; slot.g += (g - slot.g) * alpha; @@ -450,7 +450,7 @@ namespace Spine { if (frames[frameIndex] < lastTime) return; String attachmentName = attachmentNames[frameIndex]; - skeleton.slots[slotIndex].Attachment = + skeleton.slots.Items[slotIndex].Attachment = attachmentName == null ? null : skeleton.GetAttachment(slotIndex, attachmentName); } } @@ -533,15 +533,16 @@ namespace Spine { else frameIndex = Animation.binarySearch(frames, time) - 1; - List drawOrder = skeleton.drawOrder; - List slots = skeleton.slots; + ExposedList drawOrder = skeleton.drawOrder; + ExposedList slots = skeleton.slots; int[] drawOrderToSetupIndex = drawOrders[frameIndex]; if (drawOrderToSetupIndex == null) { drawOrder.Clear(); - drawOrder.AddRange(slots); + for (int i = 0, n = slots.Count; i < n; i++) + drawOrder.Add(slots.Items[i]); } else { for (int i = 0, n = drawOrderToSetupIndex.Length; i < n; i++) - drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + drawOrder.Items[i] = slots.Items[drawOrderToSetupIndex[i]]; } } } @@ -570,7 +571,7 @@ namespace Spine { } override public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { - Slot slot = skeleton.slots[slotIndex]; + Slot slot = skeleton.slots.Items[slotIndex]; if (slot.attachment != attachment) return; float[] frames = this.frames; @@ -652,7 +653,7 @@ namespace Spine { float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. - IkConstraint ikConstraint = skeleton.ikConstraints[ikConstraintIndex]; + IkConstraint ikConstraint = skeleton.ikConstraints.Items[ikConstraintIndex]; if (time >= frames[frames.Length - 3]) { // Time is after last frame. ikConstraint.mix += (frames[frames.Length - 2] - ikConstraint.mix) * alpha; @@ -703,7 +704,7 @@ namespace Spine { int frameIndex = (time >= frames[frames.Length - 2] ? frames.Length : Animation.binarySearch(frames, time, 2)) - 2; if (frames[frameIndex] < lastTime) return; - SetFlip(skeleton.bones[boneIndex], frames[frameIndex + 1] != 0); + SetFlip(skeleton.bones.Items[boneIndex], frames[frameIndex + 1] != 0); } virtual protected void SetFlip (Bone bone, bool flip) { diff --git a/spine-csharp/src/Attachments/SkinnedMeshAttachment.cs b/spine-csharp/src/Attachments/SkinnedMeshAttachment.cs index fc7de7e00..1ef38d72c 100644 --- a/spine-csharp/src/Attachments/SkinnedMeshAttachment.cs +++ b/spine-csharp/src/Attachments/SkinnedMeshAttachment.cs @@ -95,7 +95,7 @@ namespace Spine { public void ComputeWorldVertices (Slot slot, float[] worldVertices) { Skeleton skeleton = slot.bone.skeleton; - List skeletonBones = skeleton.bones; + ExposedList skeletonBones = skeleton.bones; float x = skeleton.x, y = skeleton.y; float[] weights = this.weights; int[] bones = this.bones; @@ -104,7 +104,7 @@ namespace Spine { float wx = 0, wy = 0; int nn = bones[v++] + v; for (; v < nn; v++, b += 3) { - Bone bone = skeletonBones[bones[v]]; + Bone bone = skeletonBones.Items[bones[v]]; float vx = weights[b], vy = weights[b + 1], weight = weights[b + 2]; wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight; wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight; @@ -118,7 +118,7 @@ namespace Spine { float wx = 0, wy = 0; int nn = bones[v++] + v; for (; v < nn; v++, b += 3, f += 2) { - Bone bone = skeletonBones[bones[v]]; + Bone bone = skeletonBones.Items[bones[v]]; float vx = weights[b] + ffd[f], vy = weights[b + 1] + ffd[f + 1], weight = weights[b + 2]; wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight; wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight; diff --git a/spine-csharp/src/Bone.cs b/spine-csharp/src/Bone.cs index 86546b2cd..9199697f8 100644 --- a/spine-csharp/src/Bone.cs +++ b/spine-csharp/src/Bone.cs @@ -38,7 +38,7 @@ namespace Spine { internal BoneData data; internal Skeleton skeleton; internal Bone parent; - internal List children = new List(); + internal ExposedList children = new ExposedList(); internal float x, y, rotation, rotationIK, scaleX, scaleY; internal bool flipX, flipY; internal float m00, m01, m10, m11; @@ -48,7 +48,7 @@ namespace Spine { public BoneData Data { get { return data; } } public Skeleton Skeleton { get { return skeleton; } } public Bone Parent { get { return parent; } } - public List Children { get { return children; } } + public ExposedList Children { get { return children; } } public float X { get { return x; } set { x = value; } } public float Y { get { return y; } set { y = value; } } /// The forward kinetics rotation. diff --git a/spine-csharp/src/ExposedList.cs b/spine-csharp/src/ExposedList.cs new file mode 100644 index 000000000..7d4469bf6 --- /dev/null +++ b/spine-csharp/src/ExposedList.cs @@ -0,0 +1,667 @@ +using System; +using System.Collections.Generic; + +namespace Spine { + /// + /// Represents a strongly typed list of objects that can be accessed by index. Provides methods to search and manipulate lists. + /// + /// The type of elements in the list. + public class ExposedList : IEnumerable { + private const int _defaultCapacity = 4; + private static readonly T[] _emptyArray = new T[0]; + public T[] Items; + + private int _size; + + /// + /// Initializes a new instance of the class that is empty and has the default initial capacity. + /// + public ExposedList() { + Items = _emptyArray; + } + + /// + /// Initializes a new instance of the class that is empty and has the specified initial capacity. + /// + /// The number of elements that the new list can initially store. + /// + /// is less than 0. + /// + public ExposedList(int capacity) { + if (capacity < 0) { + throw new ArgumentOutOfRangeException("capacity"); + } + Items = new T[capacity]; + } + + /// + /// Gets or sets the total number of elements the internal data structure can hold without resizing. + /// + /// + /// The number of elements that the can contain before resizing is required. + /// + /// + /// is set to a value that is less than + /// + /// . + /// + /// There is not enough memory available on the system. + public int Capacity { + get { + return Items.Length; + } + set { + if (value == Items.Length) { + return; + } + if (value < _size) { + throw new ArgumentOutOfRangeException("value"); + } + if (value > 0) { + var objArray = new T[value]; + if (_size > 0) { + Array.Copy(Items, 0, objArray, 0, _size); + } + Items = objArray; + } else { + Items = _emptyArray; + } + } + } + + /// + /// Gets the number of elements actually contained in the . + /// + /// + /// The number of elements actually contained in the . + /// + public int Count { + get { + return _size; + } + } + + /// + /// Adds an object to the end of the . + /// + /// + /// The object to be added to the end of the . The value can be null for reference types. + /// + public void Add(T item) { + if (_size == Items.Length) { + EnsureCapacity(_size + 1); + } + Items[_size++] = item; + } + + /// + /// Removes all elements from the . + /// + public void Clear() { + if (_size > 0) { + Array.Clear(Items, 0, _size); + _size = 0; + } + } + + /// + /// Determines whether an element is in the . + /// + /// + /// true if is found in the ; otherwise, false. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + public bool Contains(T item) { + if (item == null) { + for (int index = 0; index < _size; ++index) { + if (Items[index] == null) { + return true; + } + } + return false; + } else { + EqualityComparer @default = EqualityComparer.Default; + for (int index = 0; index < _size; ++index) { + if (@default.Equals(Items[index], item)) { + return true; + } + } + return false; + } + } + + /// + /// Copies the entire to a compatible one-dimensional array, starting at the specified index of the target array. + /// + /// + /// The one-dimensional that is the destination of the elements copied from + /// + /// . The must have zero-based indexing. + /// + /// + /// The zero-based index in at which copying begins. + /// + /// + /// is null. + /// + /// + /// is less than 0. + /// + /// + /// The number of elements in the source is greater than the available space from + /// + /// to the end of the destination . + /// + public void CopyTo(T[] array, int arrayIndex) { + Array.Copy(Items, 0, array, arrayIndex, _size); + } + + /// + /// Searches for the specified object and returns the zero-based index of the first occurrence within the entire + /// + /// . + /// + /// + /// The zero-based index of the first occurrence of within the entire + /// + /// , if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + public int IndexOf(T item) { + return Array.IndexOf(Items, item, 0, _size); + } + + /// + /// Inserts an element into the at the specified index. + /// + /// + /// The zero-based index at which should be inserted. + /// + /// The object to insert. The value can be null for reference types. + /// + /// is less than 0.-or- is greater than + /// + /// . + /// + public void Insert(int index, T item) { + if ((uint) index > (uint) _size) { + throw new ArgumentOutOfRangeException("index"); + } + if (_size == Items.Length) { + EnsureCapacity(_size + 1); + } + if (index < _size) { + Array.Copy(Items, index, Items, index + 1, _size - index); + } + Items[index] = item; + ++_size; + } + + /// + /// Removes the first occurrence of a specific object from the . + /// + /// + /// true if is successfully removed; otherwise, false. This method also returns false if + /// + /// was not found in the . + /// + /// + /// The object to remove from the . The value can be null for reference types. + /// + public bool Remove(T item) { + int index = IndexOf(item); + if (index < 0) { + return false; + } + RemoveAt(index); + return true; + } + + /// + /// Removes the element at the specified index of the . + /// + /// The zero-based index of the element to remove. + /// + /// is less than 0.-or- is equal to or greater than + /// + /// . + /// + public void RemoveAt(int index) { + if ((uint) index >= (uint) _size) { + throw new ArgumentOutOfRangeException(); + } + --_size; + if (index < _size) { + Array.Copy(Items, index + 1, Items, index, _size - index); + } + Items[_size] = default (T); + } + + /// + /// Copies the entire to a compatible one-dimensional array, starting at the beginning of the target array. + /// + /// + /// The one-dimensional that is the destination of the elements copied from + /// + /// . The must have zero-based indexing. + /// + /// + /// is null. + /// + /// + /// The number of elements in the source is greater than the number of elements that the destination + /// + /// can contain. + /// + public void CopyTo(T[] array) { + CopyTo(array, 0); + } + + /// + /// Copies a range of elements from the to a compatible one-dimensional array, starting at the specified index of the target array. + /// + /// + /// The zero-based index in the source at which copying begins. + /// + /// + /// The one-dimensional that is the destination of the elements copied from + /// + /// . The must have zero-based indexing. + /// + /// + /// The zero-based index in at which copying begins. + /// + /// The number of elements to copy. + /// + /// is null. + /// + /// + /// is less than 0.-or- is less than 0.-or- + /// + /// is less than 0. + /// + /// + /// is equal to or greater than the of the source + /// + /// .-or-The number of elements from to the end of the source + /// + /// is greater than the available space from + /// + /// to the end of the destination . + /// + public void CopyTo(int index, T[] array, int arrayIndex, int count) { + if (_size - index < count) { + throw new ArgumentException("Invalid length"); + } + Array.Copy(Items, index, array, arrayIndex, count); + } + + private void EnsureCapacity(int min) { + if (Items.Length >= min) { + return; + } + int num = Items.Length == 0 ? 4 : Items.Length * 2; + if (num < min) { + num = min; + } + Capacity = num; + } + + /// + /// Creates a shallow copy of a range of elements in the source . + /// + /// + /// A shallow copy of a range of elements in the source . + /// + /// + /// The zero-based index at which the range starts. + /// + /// The number of elements in the range. + /// + /// is less than 0.-or- is less than 0. + /// + /// + /// and do not denote a valid range of elements in the + /// + /// . + /// + public ExposedList GetRange(int index, int count) { + if (index < 0 || count < 0) { + throw new ArgumentOutOfRangeException("index || count"); + } + if (_size - index < count) { + throw new ArgumentException("Invalid length"); + } + var list = new ExposedList(count); + Array.Copy(Items, index, list.Items, 0, count); + list._size = count; + return list; + } + + /// + /// Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the + /// + /// that extends from the specified index to the last element. + /// + /// + /// The zero-based index of the first occurrence of within the range of elements in the + /// + /// that extends from to the last element, if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + /// The zero-based starting index of the search. 0 (zero) is valid in an empty list. + /// + /// is outside the range of valid indexes for the + /// + /// . + /// + public int IndexOf(T item, int index) { + if (index > _size) { + throw new ArgumentOutOfRangeException("index"); + } + return Array.IndexOf(Items, item, index, _size - index); + } + + /// + /// Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the + /// + /// that starts at the specified index and contains the specified number of elements. + /// + /// + /// The zero-based index of the first occurrence of within the range of elements in the + /// + /// that starts at and contains + /// + /// number of elements, if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + /// The zero-based starting index of the search. 0 (zero) is valid in an empty list. + /// The number of elements in the section to search. + /// + /// is outside the range of valid indexes for the + /// + /// .-or- is less than 0.-or- + /// + /// and do not specify a valid section in the + /// + /// . + /// + public int IndexOf(T item, int index, int count) { + if (index > _size) { + throw new ArgumentOutOfRangeException("index"); + } + if (count < 0 || index > _size - count) { + throw new ArgumentOutOfRangeException("count"); + } + return Array.IndexOf(Items, item, index, count); + } + + /// + /// Searches for the specified object and returns the zero-based index of the last occurrence within the entire + /// + /// . + /// + /// + /// The zero-based index of the last occurrence of within the entire the + /// + /// , if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + public int LastIndexOf(T item) { + return LastIndexOf(item, _size - 1, _size); + } + + /// + /// Searches for the specified object and returns the zero-based index of the last occurrence within the range of elements in the + /// + /// that extends from the first element to the specified index. + /// + /// + /// The zero-based index of the last occurrence of within the range of elements in the + /// + /// that extends from the first element to , if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + /// The zero-based starting index of the backward search. + /// + /// is outside the range of valid indexes for the + /// + /// . + /// + public int LastIndexOf(T item, int index) { + if (index >= _size) { + throw new ArgumentOutOfRangeException("index"); + } + return LastIndexOf(item, index, index + 1); + } + + /// + /// Searches for the specified object and returns the zero-based index of the last occurrence within the range of elements in the + /// + /// that contains the specified number of elements and ends at the specified index. + /// + /// + /// The zero-based index of the last occurrence of within the range of elements in the + /// + /// that contains number of elements and ends at + /// + /// , if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + /// The zero-based starting index of the backward search. + /// The number of elements in the section to search. + /// + /// is outside the range of valid indexes for the + /// + /// .-or- is less than 0.-or- + /// + /// and do not specify a valid section in the + /// + /// . + /// + public int LastIndexOf(T item, int index, int count) { + if (_size == 0) { + return -1; + } + if (index < 0 || count < 0) { + throw new ArgumentOutOfRangeException("index || count"); + } + if (index >= _size || count > index + 1) { + throw new ArgumentOutOfRangeException("size || count"); + } + return Array.LastIndexOf(Items, item, index, count); + } + + /// + /// Removes a range of elements from the . + /// + /// The zero-based starting index of the range of elements to remove. + /// The number of elements to remove. + /// + /// is less than 0.-or- is less than 0. + /// + /// + /// and do not denote a valid range of elements in the + /// + /// . + /// + public void RemoveRange(int index, int count) { + if (index < 0 || count < 0) { + throw new ArgumentOutOfRangeException("index || count"); + } + if (_size - index < count) { + throw new ArgumentException("Invalid length"); + } + if (count <= 0) { + return; + } + _size -= count; + if (index < _size) { + Array.Copy(Items, index + count, Items, index, _size - index); + } + Array.Clear(Items, _size, count); + } + + //public void Sort(Comparison comparison) + //{ + // if (comparison == null) + // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + // if (this._size <= 0) + // return; + // Array.Sort(this._items, 0, this._size, (IComparer) new Array.FunctorComparer(comparison)); + //} + /// + /// Sorts the elements in the entire using the specified + /// + /// . + /// + /// + /// The to use when comparing elements. + /// + /// + /// is null. + /// + /// + /// The implementation of caused an error during the sort. For example, + /// + /// might not return 0 when comparing an item with itself. + /// + /// + /// Copies the elements of the to a new array. + /// + /// + /// An array containing copies of the elements of the . + /// + public T[] ToArray() { + var objArray = new T[_size]; + Array.Copy(Items, 0, objArray, 0, _size); + return objArray; + } + + // Returns an enumerator for this list with the given + // permission for removal of elements. If modifications made to the list + // while an enumeration is in progress, the MoveNext and + // GetObject methods of the enumerator will throw an exception. + // + public Enumerator GetEnumerator() { + return new Enumerator(this); + } + + /// + IEnumerator IEnumerable.GetEnumerator() { + return new Enumerator(this); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { + return new Enumerator(this); + } + + [Serializable()] + public struct Enumerator : IEnumerator, System.Collections.IEnumerator + { + private readonly ExposedList _list; + private int _index; + private T _current; + + internal Enumerator(ExposedList list) { + _list = list; + _index = 0; + _current = default(T); + } + + public void Dispose() { + } + + public bool MoveNext() { + ExposedList localList = _list; + + if (((uint)_index < (uint)localList._size)) { + _current = localList.Items[_index]; + _index++; + return true; + } + return MoveNextRare(); + } + + private bool MoveNextRare() + { + _index = _list._size + 1; + _current = default(T); + return false; + } + + public T Current { + get { + return _current; + } + } + + Object System.Collections.IEnumerator.Current { + get { + if( _index == 0 || _index == _list._size + 1) + throw new InvalidOperationException(); + return Current; + } + } + + void System.Collections.IEnumerator.Reset() { + _index = 0; + _current = default(T); + } + + } + } +} \ No newline at end of file diff --git a/spine-csharp/src/ExposedList.cs.meta b/spine-csharp/src/ExposedList.cs.meta new file mode 100644 index 000000000..e12f21463 --- /dev/null +++ b/spine-csharp/src/ExposedList.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 540cf6a03c85e284e83831880e3f25a8 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/spine-csharp/src/IkConstraint.cs b/spine-csharp/src/IkConstraint.cs index a2816e796..a49e5d40e 100644 --- a/spine-csharp/src/IkConstraint.cs +++ b/spine-csharp/src/IkConstraint.cs @@ -36,13 +36,13 @@ namespace Spine { private const float radDeg = 180 / (float)Math.PI; internal IkConstraintData data; - internal List bones = new List(); + internal ExposedList bones = new ExposedList(); internal Bone target; internal int bendDirection; internal float mix; public IkConstraintData Data { get { return data; } } - public List Bones { get { return bones; } } + public ExposedList Bones { get { return bones; } } public Bone Target { get { return target; } set { target = value; } } public int BendDirection { get { return bendDirection; } set { bendDirection = value; } } public float Mix { get { return mix; } set { mix = value; } } @@ -54,7 +54,7 @@ namespace Spine { mix = data.mix; bendDirection = data.bendDirection; - bones = new List(data.bones.Count); + bones = new ExposedList(data.bones.Count); foreach (BoneData boneData in data.bones) bones.Add(skeleton.FindBone(boneData.name)); target = skeleton.FindBone(data.target.name); @@ -62,13 +62,13 @@ namespace Spine { public void apply () { Bone target = this.target; - List bones = this.bones; + ExposedList bones = this.bones; switch (bones.Count) { case 1: - apply(bones[0], target.worldX, target.worldY, mix); + apply(bones.Items[0], target.worldX, target.worldY, mix); break; case 2: - apply(bones[0], bones[1], target.worldX, target.worldY, bendDirection, mix); + apply(bones.Items[0], bones.Items[1], target.worldX, target.worldY, bendDirection, mix); break; } } diff --git a/spine-csharp/src/Skeleton.cs b/spine-csharp/src/Skeleton.cs index 0e032dba5..56f1c421b 100644 --- a/spine-csharp/src/Skeleton.cs +++ b/spine-csharp/src/Skeleton.cs @@ -34,11 +34,11 @@ using System.Collections.Generic; namespace Spine { public class Skeleton { internal SkeletonData data; - internal List bones; - internal List slots; - internal List drawOrder; - internal List ikConstraints; - private List> boneCache = new List>(); + internal ExposedList bones; + internal ExposedList slots; + internal ExposedList drawOrder; + internal ExposedList ikConstraints; + private ExposedList> boneCache = new ExposedList>(); internal Skin skin; internal float r = 1, g = 1, b = 1, a = 1; internal float time; @@ -46,10 +46,10 @@ namespace Spine { internal float x, y; public SkeletonData Data { get { return data; } } - public List Bones { get { return bones; } } - public List Slots { get { return slots; } } - public List DrawOrder { get { return drawOrder; } } - public List IkConstraints { get { return ikConstraints; } set { ikConstraints = value; } } + public ExposedList Bones { get { return bones; } } + public ExposedList Slots { get { return slots; } } + public ExposedList DrawOrder { get { return drawOrder; } } + public ExposedList IkConstraints { get { return ikConstraints; } set { ikConstraints = value; } } public Skin Skin { get { return skin; } set { skin = value; } } public float R { get { return r; } set { r = value; } } public float G { get { return g; } set { g = value; } } @@ -63,7 +63,7 @@ namespace Spine { public Bone RootBone { get { - return bones.Count == 0 ? null : bones[0]; + return bones.Count == 0 ? null : bones.Items[0]; } } @@ -71,24 +71,24 @@ namespace Spine { if (data == null) throw new ArgumentNullException("data cannot be null."); this.data = data; - bones = new List(data.bones.Count); + bones = new ExposedList(data.bones.Count); foreach (BoneData boneData in data.bones) { - Bone parent = boneData.parent == null ? null : bones[data.bones.IndexOf(boneData.parent)]; + Bone parent = boneData.parent == null ? null : bones.Items[data.bones.IndexOf(boneData.parent)]; Bone bone = new Bone(boneData, this, parent); if (parent != null) parent.children.Add(bone); bones.Add(bone); } - slots = new List(data.slots.Count); - drawOrder = new List(data.slots.Count); + slots = new ExposedList(data.slots.Count); + drawOrder = new ExposedList(data.slots.Count); foreach (SlotData slotData in data.slots) { - Bone bone = bones[data.bones.IndexOf(slotData.boneData)]; + Bone bone = bones.Items[data.bones.IndexOf(slotData.boneData)]; Slot slot = new Slot(slotData, bone); slots.Add(slot); drawOrder.Add(slot); } - ikConstraints = new List(data.ikConstraints.Count); + ikConstraints = new ExposedList(data.ikConstraints.Count); foreach (IkConstraintData ikConstraintData in data.ikConstraints) ikConstraints.Add(new IkConstraint(ikConstraintData, this)); @@ -98,31 +98,31 @@ namespace Spine { /// Caches information about bones and IK constraints. Must be called if bones or IK constraints are added or /// removed. public void UpdateCache () { - List> boneCache = this.boneCache; - List ikConstraints = this.ikConstraints; + ExposedList> boneCache = this.boneCache; + ExposedList ikConstraints = this.ikConstraints; int ikConstraintsCount = ikConstraints.Count; int arrayCount = ikConstraintsCount + 1; if (boneCache.Count > arrayCount) boneCache.RemoveRange(arrayCount, boneCache.Count - arrayCount); for (int i = 0, n = boneCache.Count; i < n; i++) - boneCache[i].Clear(); + boneCache.Items[i].Clear(); while (boneCache.Count < arrayCount) - boneCache.Add(new List()); + boneCache.Add(new ExposedList()); - List nonIkBones = boneCache[0]; + ExposedList nonIkBones = boneCache.Items[0]; for (int i = 0, n = bones.Count; i < n; i++) { - Bone bone = bones[i]; + Bone bone = bones.Items[i]; Bone current = bone; do { for (int ii = 0; ii < ikConstraintsCount; ii++) { - IkConstraint ikConstraint = ikConstraints[ii]; - Bone parent = ikConstraint.bones[0]; - Bone child = ikConstraint.bones[ikConstraint.bones.Count - 1]; + IkConstraint ikConstraint = ikConstraints.Items[ii]; + Bone parent = ikConstraint.bones.Items[0]; + Bone child = ikConstraint.bones.Items[ikConstraint.bones.Count - 1]; while (true) { if (current == child) { - boneCache[ii].Add(bone); - boneCache[ii + 1].Add(bone); + boneCache.Items[ii].Add(bone); + boneCache.Items[ii + 1].Add(bone); goto outer; } if (child == parent) break; @@ -138,20 +138,20 @@ namespace Spine { /// Updates the world transform for each bone and applies IK constraints. public void UpdateWorldTransform () { - List bones = this.bones; + ExposedList bones = this.bones; for (int ii = 0, nn = bones.Count; ii < nn; ii++) { - Bone bone = bones[ii]; + Bone bone = bones.Items[ii]; bone.rotationIK = bone.rotation; } - List> boneCache = this.boneCache; - List ikConstraints = this.ikConstraints; + ExposedList> boneCache = this.boneCache; + ExposedList ikConstraints = this.ikConstraints; int i = 0, last = boneCache.Count - 1; while (true) { - List updateBones = boneCache[i]; + ExposedList updateBones = boneCache.Items[i]; for (int ii = 0, nn = updateBones.Count; ii < nn; ii++) - updateBones[ii].UpdateWorldTransform(); + updateBones.Items[ii].UpdateWorldTransform(); if (i == last) break; - ikConstraints[i].apply(); + ikConstraints.Items[i].apply(); i++; } } @@ -163,32 +163,34 @@ namespace Spine { } public void SetBonesToSetupPose () { - List bones = this.bones; + ExposedList bones = this.bones; for (int i = 0, n = bones.Count; i < n; i++) - bones[i].SetToSetupPose(); + bones.Items[i].SetToSetupPose(); - List ikConstraints = this.ikConstraints; + ExposedList ikConstraints = this.ikConstraints; for (int i = 0, n = ikConstraints.Count; i < n; i++) { - IkConstraint ikConstraint = ikConstraints[i]; + IkConstraint ikConstraint = ikConstraints.Items[i]; ikConstraint.bendDirection = ikConstraint.data.bendDirection; ikConstraint.mix = ikConstraint.data.mix; } } public void SetSlotsToSetupPose () { - List slots = this.slots; + ExposedList slots = this.slots; drawOrder.Clear(); - drawOrder.AddRange(slots); + for (int i = 0, n = slots.Count; i < n; i++) + drawOrder.Add(slots.Items[i]); + for (int i = 0, n = slots.Count; i < n; i++) - slots[i].SetToSetupPose(i); + slots.Items[i].SetToSetupPose(i); } /// May be null. public Bone FindBone (String boneName) { if (boneName == null) throw new ArgumentNullException("boneName cannot be null."); - List bones = this.bones; + ExposedList bones = this.bones; for (int i = 0, n = bones.Count; i < n; i++) { - Bone bone = bones[i]; + Bone bone = bones.Items[i]; if (bone.data.name == boneName) return bone; } return null; @@ -197,18 +199,18 @@ namespace Spine { /// -1 if the bone was not found. public int FindBoneIndex (String boneName) { if (boneName == null) throw new ArgumentNullException("boneName cannot be null."); - List bones = this.bones; + ExposedList bones = this.bones; for (int i = 0, n = bones.Count; i < n; i++) - if (bones[i].data.name == boneName) return i; + if (bones.Items[i].data.name == boneName) return i; return -1; } /// May be null. public Slot FindSlot (String slotName) { if (slotName == null) throw new ArgumentNullException("slotName cannot be null."); - List slots = this.slots; + ExposedList slots = this.slots; for (int i = 0, n = slots.Count; i < n; i++) { - Slot slot = slots[i]; + Slot slot = slots.Items[i]; if (slot.data.name == slotName) return slot; } return null; @@ -217,9 +219,9 @@ namespace Spine { /// -1 if the bone was not found. public int FindSlotIndex (String slotName) { if (slotName == null) throw new ArgumentNullException("slotName cannot be null."); - List slots = this.slots; + ExposedList slots = this.slots; for (int i = 0, n = slots.Count; i < n; i++) - if (slots[i].data.name.Equals(slotName)) return i; + if (slots.Items[i].data.name.Equals(slotName)) return i; return -1; } @@ -239,9 +241,9 @@ namespace Spine { if (skin != null) newSkin.AttachAll(this, skin); else { - List slots = this.slots; + ExposedList slots = this.slots; for (int i = 0, n = slots.Count; i < n; i++) { - Slot slot = slots[i]; + Slot slot = slots.Items[i]; String name = slot.data.attachmentName; if (name != null) { Attachment attachment = newSkin.GetAttachment(i, name); @@ -272,9 +274,9 @@ namespace Spine { /// May be null. public void SetAttachment (String slotName, String attachmentName) { if (slotName == null) throw new ArgumentNullException("slotName cannot be null."); - List slots = this.slots; + ExposedList slots = this.slots; for (int i = 0, n = slots.Count; i < n; i++) { - Slot slot = slots[i]; + Slot slot = slots.Items[i]; if (slot.data.name == slotName) { Attachment attachment = null; if (attachmentName != null) { @@ -291,9 +293,9 @@ namespace Spine { /** @return May be null. */ public IkConstraint FindIkConstraint (String ikConstraintName) { if (ikConstraintName == null) throw new ArgumentNullException("ikConstraintName cannot be null."); - List ikConstraints = this.ikConstraints; + ExposedList ikConstraints = this.ikConstraints; for (int i = 0, n = ikConstraints.Count; i < n; i++) { - IkConstraint ikConstraint = ikConstraints[i]; + IkConstraint ikConstraint = ikConstraints.Items[i]; if (ikConstraint.data.name == ikConstraintName) return ikConstraint; } return null; diff --git a/spine-csharp/src/SkeletonBounds.cs b/spine-csharp/src/SkeletonBounds.cs index 4c546d76c..0c1a146f2 100644 --- a/spine-csharp/src/SkeletonBounds.cs +++ b/spine-csharp/src/SkeletonBounds.cs @@ -33,11 +33,11 @@ using System.Collections.Generic; namespace Spine { public class SkeletonBounds { - private List polygonPool = new List(); + private ExposedList polygonPool = new ExposedList(); private float minX, minY, maxX, maxY; - public List BoundingBoxes { get; private set; } - public List Polygons { get; private set; } + public ExposedList BoundingBoxes { get; private set; } + public ExposedList Polygons { get; private set; } public float MinX { get { return minX; } set { minX = value; } } public float MinY { get { return minY; } set { minY = value; } } public float MaxX { get { return maxX; } set { maxX = value; } } @@ -46,23 +46,23 @@ namespace Spine { public float Height { get { return maxY - minY; } } public SkeletonBounds () { - BoundingBoxes = new List(); - Polygons = new List(); + BoundingBoxes = new ExposedList(); + Polygons = new ExposedList(); } public void Update (Skeleton skeleton, bool updateAabb) { - List boundingBoxes = BoundingBoxes; - List polygons = Polygons; - List slots = skeleton.slots; + ExposedList boundingBoxes = BoundingBoxes; + ExposedList polygons = Polygons; + ExposedList slots = skeleton.slots; int slotCount = slots.Count; boundingBoxes.Clear(); - foreach (Polygon polygon in polygons) - polygonPool.Add(polygon); + for (int i = 0, n = polygons.Count; i < n; i++) + polygonPool.Add(polygons.Items[n]); polygons.Clear(); for (int i = 0; i < slotCount; i++) { - Slot slot = slots[i]; + Slot slot = slots.Items[i]; BoundingBoxAttachment boundingBox = slot.attachment as BoundingBoxAttachment; if (boundingBox == null) continue; boundingBoxes.Add(boundingBox); @@ -70,7 +70,7 @@ namespace Spine { Polygon polygon = null; int poolCount = polygonPool.Count; if (poolCount > 0) { - polygon = polygonPool[poolCount - 1]; + polygon = polygonPool.Items[poolCount - 1]; polygonPool.RemoveAt(poolCount - 1); } else polygon = new Polygon(); @@ -87,9 +87,9 @@ namespace Spine { private void aabbCompute () { float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue; - List polygons = Polygons; + ExposedList polygons = Polygons; for (int i = 0, n = polygons.Count; i < n; i++) { - Polygon polygon = polygons[i]; + Polygon polygon = polygons.Items[i]; float[] vertices = polygon.Vertices; for (int ii = 0, nn = polygon.Count; ii < nn; ii += 2) { float x = vertices[ii]; @@ -159,18 +159,18 @@ namespace Spine { /// Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more /// efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. public BoundingBoxAttachment ContainsPoint (float x, float y) { - List polygons = Polygons; + ExposedList polygons = Polygons; for (int i = 0, n = polygons.Count; i < n; i++) - if (ContainsPoint(polygons[i], x, y)) return BoundingBoxes[i]; + if (ContainsPoint(polygons.Items[i], x, y)) return BoundingBoxes.Items[i]; return null; } /// Returns the first bounding box attachment that contains the line segment, or null. When doing many checks, it is usually /// more efficient to only call this method if {@link #aabbIntersectsSegment(float, float, float, float)} returns true. public BoundingBoxAttachment IntersectsSegment (float x1, float y1, float x2, float y2) { - List polygons = Polygons; + ExposedList polygons = Polygons; for (int i = 0, n = polygons.Count; i < n; i++) - if (IntersectsSegment(polygons[i], x1, y1, x2, y2)) return BoundingBoxes[i]; + if (IntersectsSegment(polygons.Items[i], x1, y1, x2, y2)) return BoundingBoxes.Items[i]; return null; } @@ -200,7 +200,7 @@ namespace Spine { public Polygon getPolygon (BoundingBoxAttachment attachment) { int index = BoundingBoxes.IndexOf(attachment); - return index == -1 ? null : Polygons[index]; + return index == -1 ? null : Polygons.Items[index]; } } diff --git a/spine-csharp/src/Skin.cs b/spine-csharp/src/Skin.cs index e8e68d3dc..7b4c57b15 100644 --- a/spine-csharp/src/Skin.cs +++ b/spine-csharp/src/Skin.cs @@ -77,7 +77,7 @@ namespace Spine { internal void AttachAll (Skeleton skeleton, Skin oldSkin) { foreach (KeyValuePair, Attachment> entry in oldSkin.attachments) { int slotIndex = entry.Key.Key; - Slot slot = skeleton.slots[slotIndex]; + Slot slot = skeleton.slots.Items[slotIndex]; if (slot.attachment == entry.Value) { Attachment attachment = GetAttachment(slotIndex, entry.Key.Value); if (attachment != null) slot.Attachment = attachment; diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs index 74fcc2899..4fa1a0161 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs @@ -640,7 +640,7 @@ public static class SkeletonBaker { skeleton.UpdateWorldTransform(); float[] floatVerts = new float[attachment.UVs.Length]; - attachment.ComputeWorldVertices(skeleton.Slots[slotIndex], floatVerts); + attachment.ComputeWorldVertices(skeleton.Slots.Items[slotIndex], floatVerts); Vector2[] uvs = ExtractUV(attachment.UVs); Vector3[] verts = ExtractVerts(floatVerts); @@ -807,26 +807,26 @@ public static class SkeletonBaker { List ignoreRotateTimelineIndexes = new List(); - if (bakeIK) { - foreach (IkConstraint i in skeleton.IkConstraints) { - foreach (Bone b in i.Bones) { - int index = skeleton.FindBoneIndex(b.Data.Name); - ignoreRotateTimelineIndexes.Add(index); - BakeBone(b, animation, clip); - } - } - } + //if (bakeIK) { + // foreach (IkConstraint i in skeleton.IkConstraints) { + // foreach (Bone b in i.Bones) { + // int index = skeleton.FindBoneIndex(b.Data.Name); + // ignoreRotateTimelineIndexes.Add(index); + // BakeBone(b, animation, clip); + // } + // } + //} - foreach (Bone b in skeleton.Bones) { - if (b.Data.InheritRotation == false) { - int index = skeleton.FindBoneIndex(b.Data.Name); + //foreach (Bone b in skeleton.Bones) { + // if (b.Data.InheritRotation == false) { + // int index = skeleton.FindBoneIndex(b.Data.Name); - if (ignoreRotateTimelineIndexes.Contains(index) == false) { - ignoreRotateTimelineIndexes.Add(index); - BakeBone(b, animation, clip); - } - } - } + // if (ignoreRotateTimelineIndexes.Contains(index) == false) { + // ignoreRotateTimelineIndexes.Add(index); + // BakeBone(b, animation, clip); + // } + // } + //} foreach (Timeline t in timelines) { skeleton.SetToSetupPose(); @@ -911,8 +911,8 @@ public static class SkeletonBaker { static void ParseAttachmentTimeline (Skeleton skeleton, AttachmentTimeline timeline, Dictionary> slotLookup, AnimationClip clip) { var attachmentNames = slotLookup[timeline.SlotIndex]; - string bonePath = GetPath(skeleton.Slots[timeline.SlotIndex].Bone.Data); - string slotPath = bonePath + "/" + skeleton.Slots[timeline.SlotIndex].Data.Name; + string bonePath = GetPath(skeleton.Slots.Items[timeline.SlotIndex].Bone.Data); + string slotPath = bonePath + "/" + skeleton.Slots.Items[timeline.SlotIndex].Data.Name; Dictionary curveTable = new Dictionary(); @@ -923,7 +923,7 @@ public static class SkeletonBaker { float[] frames = timeline.Frames; if (frames[0] != 0) { - string startingName = skeleton.Slots[timeline.SlotIndex].Data.AttachmentName; + string startingName = skeleton.Slots.Items[timeline.SlotIndex].Data.AttachmentName; foreach (var pair in curveTable) { if (startingName == "" || startingName == null) { pair.Value.AddKey(new Keyframe(0, 0, float.PositiveInfinity, float.PositiveInfinity)); @@ -1062,7 +1062,7 @@ public static class SkeletonBaker { static void ParseTranslateTimeline (Skeleton skeleton, TranslateTimeline timeline, AnimationClip clip) { var boneData = skeleton.Data.Bones[timeline.BoneIndex]; - var bone = skeleton.Bones[timeline.BoneIndex]; + var bone = skeleton.Bones.Items[timeline.BoneIndex]; AnimationCurve xCurve = new AnimationCurve(); AnimationCurve yCurve = new AnimationCurve(); @@ -1208,7 +1208,7 @@ public static class SkeletonBaker { static void ParseScaleTimeline (Skeleton skeleton, ScaleTimeline timeline, AnimationClip clip) { var boneData = skeleton.Data.Bones[timeline.BoneIndex]; - var bone = skeleton.Bones[timeline.BoneIndex]; + var bone = skeleton.Bones.Items[timeline.BoneIndex]; AnimationCurve xCurve = new AnimationCurve(); AnimationCurve yCurve = new AnimationCurve(); @@ -1341,7 +1341,7 @@ public static class SkeletonBaker { static void ParseRotateTimeline (Skeleton skeleton, RotateTimeline timeline, AnimationClip clip) { var boneData = skeleton.Data.Bones[timeline.BoneIndex]; - var bone = skeleton.Bones[timeline.BoneIndex]; + var bone = skeleton.Bones.Items[timeline.BoneIndex]; AnimationCurve curve = new AnimationCurve(); diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs index 83bbef004..81d2c37a0 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs @@ -357,7 +357,7 @@ public class SkeletonDataAssetInspector : Editor { } for (int i = m_skeletonAnimation.skeleton.Slots.Count - 1; i >= 0; i--) { - Slot slot = m_skeletonAnimation.skeleton.Slots[i]; + Slot slot = m_skeletonAnimation.skeleton.Slots.Items[i]; EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, SpineEditorUtilities.Icons.slot)); if (showAttachments) { diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index 48b2c745e..450e7b50b 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -173,11 +173,11 @@ public class SkeletonRenderer : MonoBehaviour { int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; Material lastMaterial = null; submeshMaterials.Clear(); - List drawOrder = skeleton.DrawOrder; + ExposedList drawOrder = skeleton.DrawOrder; int drawOrderCount = drawOrder.Count; bool renderMeshes = this.renderMeshes; for (int i = 0; i < drawOrderCount; i++) { - Slot slot = drawOrder[i]; + Slot slot = drawOrder.Items[i]; Attachment attachment = slot.attachment; object rendererObject; @@ -254,7 +254,7 @@ public class SkeletonRenderer : MonoBehaviour { float zSpacing = this.zSpacing; float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b; for (int i = 0; i < drawOrderCount; i++) { - Slot slot = drawOrder[i]; + Slot slot = drawOrder.Items[i]; Attachment attachment = slot.attachment; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; @@ -413,9 +413,9 @@ public class SkeletonRenderer : MonoBehaviour { } // Store triangles. - List drawOrder = skeleton.DrawOrder; + ExposedList drawOrder = skeleton.DrawOrder; for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) { - Slot slot = drawOrder[i]; + Slot slot = drawOrder.Items[i]; Attachment attachment = slot.attachment; Bone bone = slot.bone; bool flip = frontFacing && ((bone.WorldFlipX != bone.WorldFlipY) != (Mathf.Sign(bone.WorldScaleX) != Mathf.Sign(bone.WorldScaleY))); diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs index f8d6d7340..52f3f71b3 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs @@ -190,14 +190,14 @@ public class SkeletonUtilityBoneInspector : Editor { } } - void BoneSelectorContextMenu (string current, List bones, string topValue, GenericMenu.MenuFunction2 callback) { + void BoneSelectorContextMenu (string current, ExposedList bones, string topValue, GenericMenu.MenuFunction2 callback) { GenericMenu menu = new GenericMenu(); if (topValue != "") menu.AddItem(new GUIContent(topValue), current == topValue, callback, null); for (int i = 0; i < bones.Count; i++) { - menu.AddItem(new GUIContent(bones[i].Data.Name), bones[i].Data.Name == current, callback, bones[i]); + menu.AddItem(new GUIContent(bones.Items[i].Data.Name), bones.Items[i].Data.Name == current, callback, bones.Items[i]); } menu.ShowAsContext(); diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs index 4c6d02d09..e955bbd71 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs @@ -160,7 +160,7 @@ public class SkeletonUtilityInspector : Editor { List attachments = new List(); skin.FindAttachmentsForSlot(i, attachments); - attachmentTable.Add(skeleton.Slots[i], attachments); + attachmentTable.Add(skeleton.Slots.Items[i], attachments); } } diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs index 519c0e313..37e84e884 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs @@ -170,9 +170,9 @@ public class SkeletonUtility : MonoBehaviour { if (boneRoot != null) { List constraintTargetNames = new List(); - foreach (IkConstraint c in skeletonRenderer.skeleton.IkConstraints) { - constraintTargetNames.Add(c.Target.Data.Name); - } + ExposedList ikConstraints = skeletonRenderer.skeleton.IkConstraints; + for (int i = 0, n = ikConstraints.Count; i < n; i++) + constraintTargetNames.Add(ikConstraints.Items[n].Target.Data.Name); foreach (var b in utilityBones) { if (b.bone == null) { @@ -289,7 +289,9 @@ public class SkeletonUtility : MonoBehaviour { public GameObject SpawnBoneRecursively (Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca) { GameObject go = SpawnBone(bone, parent, mode, pos, rot, sca); - foreach (Bone child in bone.Children) { + ExposedList childrenBones = bone.Children; + for (int i = 0, n = childrenBones.Count; i < n; i++) { + Bone child = childrenBones.Items[i]; SpawnBoneRecursively(child, go.transform, mode, pos, rot, sca); } From 0635c19fef5fa129c254562eb5a44f87d9e6e690 Mon Sep 17 00:00:00 2001 From: ZimM Date: Thu, 26 Feb 2015 05:37:28 +0200 Subject: [PATCH 02/24] replace some more List with ExposedList fix some stupidity from previous commit --- spine-csharp/src/Animation.cs | 46 +- spine-csharp/src/AnimationState.cs | 26 +- spine-csharp/src/ExposedList.cs | 1327 +++++++++-------- spine-csharp/src/ExposedList.cs.meta | 8 - spine-csharp/src/Skeleton.cs | 4 +- spine-csharp/src/SkeletonBounds.cs | 2 +- spine-csharp/src/SkeletonData.cs | 48 +- spine-csharp/src/SkeletonJson.cs | 2 +- .../Editor/BoneFollowerInspector.cs | 2 +- .../Editor/SkeletonAnimationInspector.cs | 2 +- .../spine-unity/Editor/SkeletonBaker.cs | 52 +- .../Editor/SkeletonDataAssetInspector.cs | 8 +- .../Editor/SkeletonRendererInspector.cs | 2 +- .../Editor/SpineAttributeDrawers.cs | 18 +- .../Editor/SpineEditorUtilities.cs | 4 +- .../Assets/spine-unity/SkeletonRenderer.cs | 20 +- .../SkeletonUtility/SkeletonUtility.cs | 8 +- 17 files changed, 804 insertions(+), 775 deletions(-) delete mode 100644 spine-csharp/src/ExposedList.cs.meta diff --git a/spine-csharp/src/Animation.cs b/spine-csharp/src/Animation.cs index a31b12c10..65374fccf 100644 --- a/spine-csharp/src/Animation.cs +++ b/spine-csharp/src/Animation.cs @@ -33,15 +33,15 @@ using System.Collections.Generic; namespace Spine { public class Animation { - internal List timelines; + internal ExposedList timelines; internal float duration; internal String name; public String Name { get { return name; } } - public List Timelines { get { return timelines; } set { timelines = value; } } + public ExposedList Timelines { get { return timelines; } set { timelines = value; } } public float Duration { get { return duration; } set { duration = value; } } - public Animation (String name, List timelines, float duration) { + public Animation (String name, ExposedList timelines, float duration) { if (name == null) throw new ArgumentNullException("name cannot be null."); if (timelines == null) throw new ArgumentNullException("timelines cannot be null."); this.name = name; @@ -52,7 +52,7 @@ namespace Spine { /// Poses the skeleton at the specified time for this animation. /// The last time the animation was applied. /// Any triggered events are added. - public void Apply (Skeleton skeleton, float lastTime, float time, bool loop, List events) { + public void Apply (Skeleton skeleton, float lastTime, float time, bool loop, ExposedList events) { if (skeleton == null) throw new ArgumentNullException("skeleton cannot be null."); if (loop && duration != 0) { @@ -60,16 +60,16 @@ namespace Spine { lastTime %= duration; } - List timelines = this.timelines; + ExposedList timelines = this.timelines; for (int i = 0, n = timelines.Count; i < n; i++) - timelines[i].Apply(skeleton, lastTime, time, events, 1); + timelines.Items[i].Apply(skeleton, lastTime, time, events, 1); } /// Poses the skeleton at the specified time for this animation mixed with the current pose. /// The last time the animation was applied. /// Any triggered events are added. /// The amount of this animation that affects the current pose. - public void Mix (Skeleton skeleton, float lastTime, float time, bool loop, List events, float alpha) { + public void Mix (Skeleton skeleton, float lastTime, float time, bool loop, ExposedList events, float alpha) { if (skeleton == null) throw new ArgumentNullException("skeleton cannot be null."); if (loop && duration != 0) { @@ -77,9 +77,9 @@ namespace Spine { lastTime %= duration; } - List timelines = this.timelines; + ExposedList timelines = this.timelines; for (int i = 0, n = timelines.Count; i < n; i++) - timelines[i].Apply(skeleton, lastTime, time, events, alpha); + timelines.Items[i].Apply(skeleton, lastTime, time, events, alpha); } /// After the first and before the last entry. @@ -124,7 +124,7 @@ namespace Spine { public interface Timeline { /// Sets the value(s) for the specified time. /// May be null to not collect fired events. - void Apply (Skeleton skeleton, float lastTime, float time, List events, float alpha); + void Apply (Skeleton skeleton, float lastTime, float time, ExposedList events, float alpha); } /// Base class for frames that use an interpolation bezier curve. @@ -139,7 +139,7 @@ namespace Spine { curves = new float[(frameCount - 1) * BEZIER_SIZE]; } - abstract public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha); + abstract public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha); public void SetLinear (int frameIndex) { curves[frameIndex * BEZIER_SIZE] = LINEAR; @@ -229,7 +229,7 @@ namespace Spine { frames[frameIndex + 1] = angle; } - override public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { + override public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha) { float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. @@ -292,7 +292,7 @@ namespace Spine { frames[frameIndex + 2] = y; } - override public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { + override public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha) { float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. @@ -322,7 +322,7 @@ namespace Spine { : base(frameCount) { } - override public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { + override public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha) { float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. @@ -374,7 +374,7 @@ namespace Spine { frames[frameIndex + 4] = a; } - override public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { + override public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha) { float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. @@ -438,7 +438,7 @@ namespace Spine { attachmentNames[frameIndex] = attachmentName; } - public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { + public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha) { float[] frames = this.frames; if (time < frames[0]) { if (lastTime > time) Apply(skeleton, lastTime, int.MaxValue, null, 0); @@ -475,7 +475,7 @@ namespace Spine { } /// Fires events for frames > lastTime and <= time. - public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { + public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha) { if (firedEvents == null) return; float[] frames = this.frames; int frameCount = frames.Length; @@ -523,7 +523,7 @@ namespace Spine { drawOrders[frameIndex] = drawOrder; } - public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { + public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha) { float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. @@ -538,8 +538,8 @@ namespace Spine { int[] drawOrderToSetupIndex = drawOrders[frameIndex]; if (drawOrderToSetupIndex == null) { drawOrder.Clear(); - for (int i = 0, n = slots.Count; i < n; i++) - drawOrder.Add(slots.Items[i]); + for (int i = 0, n = slots.Count; i < n; i++) + drawOrder.Add(slots.Items[i]); } else { for (int i = 0, n = drawOrderToSetupIndex.Length; i < n; i++) drawOrder.Items[i] = slots.Items[drawOrderToSetupIndex[i]]; @@ -570,7 +570,7 @@ namespace Spine { frameVertices[frameIndex] = vertices; } - override public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { + override public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha) { Slot slot = skeleton.slots.Items[slotIndex]; if (slot.attachment != attachment) return; @@ -649,7 +649,7 @@ namespace Spine { frames[frameIndex + 2] = bendDirection; } - override public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { + override public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha) { float[] frames = this.frames; if (time < frames[0]) return; // Time is before first frame. @@ -693,7 +693,7 @@ namespace Spine { frames[frameIndex + 1] = flip ? 1 : 0; } - public void Apply (Skeleton skeleton, float lastTime, float time, List firedEvents, float alpha) { + public void Apply (Skeleton skeleton, float lastTime, float time, ExposedList firedEvents, float alpha) { float[] frames = this.frames; if (time < frames[0]) { if (lastTime > time) Apply(skeleton, lastTime, int.MaxValue, null, 0); diff --git a/spine-csharp/src/AnimationState.cs b/spine-csharp/src/AnimationState.cs index 3a774b330..6262a9375 100644 --- a/spine-csharp/src/AnimationState.cs +++ b/spine-csharp/src/AnimationState.cs @@ -35,8 +35,8 @@ using System.Text; namespace Spine { public class AnimationState { private AnimationStateData data; - private List tracks = new List(); - private List events = new List(); + private ExposedList tracks = new ExposedList(); + private ExposedList events = new ExposedList(); private float timeScale = 1; public AnimationStateData Data { get { return data; } } @@ -60,7 +60,7 @@ namespace Spine { public void Update (float delta) { delta *= timeScale; for (int i = 0; i < tracks.Count; i++) { - TrackEntry current = tracks[i]; + TrackEntry current = tracks.Items[i]; if (current == null) continue; float trackDelta = delta * current.timeScale; @@ -92,10 +92,10 @@ namespace Spine { } public void Apply (Skeleton skeleton) { - List events = this.events; + ExposedList events = this.events; for (int i = 0; i < tracks.Count; i++) { - TrackEntry current = tracks[i]; + TrackEntry current = tracks.Items[i]; if (current == null) continue; events.Clear(); @@ -124,7 +124,7 @@ namespace Spine { } for (int ii = 0, nn = events.Count; ii < nn; ii++) { - Event e = events[ii]; + Event e = events.Items[ii]; current.OnEvent(this, i, e); if (Event != null) Event(this, i, e); } @@ -141,17 +141,17 @@ namespace Spine { public void ClearTrack (int trackIndex) { if (trackIndex >= tracks.Count) return; - TrackEntry current = tracks[trackIndex]; + TrackEntry current = tracks.Items[trackIndex]; if (current == null) return; current.OnEnd(this, trackIndex); if (End != null) End(this, trackIndex); - tracks[trackIndex] = null; + tracks.Items[trackIndex] = null; } private TrackEntry ExpandToIndex (int index) { - if (index < tracks.Count) return tracks[index]; + if (index < tracks.Count) return tracks.Items[index]; while (index >= tracks.Count) tracks.Add(null); return null; @@ -177,7 +177,7 @@ namespace Spine { } } - tracks[index] = entry; + tracks.Items[index] = entry; entry.OnStart(this, index); if (Start != null) Start(this, index); @@ -223,7 +223,7 @@ namespace Spine { last = last.next; last.next = entry; } else - tracks[trackIndex] = entry; + tracks.Items[trackIndex] = entry; if (delay <= 0) { if (last != null) @@ -239,13 +239,13 @@ namespace Spine { /// May be null. public TrackEntry GetCurrent (int trackIndex) { if (trackIndex >= tracks.Count) return null; - return tracks[trackIndex]; + return tracks.Items[trackIndex]; } override public String ToString () { StringBuilder buffer = new StringBuilder(); for (int i = 0, n = tracks.Count; i < n; i++) { - TrackEntry entry = tracks[i]; + TrackEntry entry = tracks.Items[i]; if (entry == null) continue; if (buffer.Length > 0) buffer.Append(", "); buffer.Append(entry.ToString()); diff --git a/spine-csharp/src/ExposedList.cs b/spine-csharp/src/ExposedList.cs index 7d4469bf6..03eaa6c23 100644 --- a/spine-csharp/src/ExposedList.cs +++ b/spine-csharp/src/ExposedList.cs @@ -2,666 +2,701 @@ using System.Collections.Generic; namespace Spine { - /// - /// Represents a strongly typed list of objects that can be accessed by index. Provides methods to search and manipulate lists. - /// - /// The type of elements in the list. - public class ExposedList : IEnumerable { - private const int _defaultCapacity = 4; - private static readonly T[] _emptyArray = new T[0]; - public T[] Items; + /// + /// Represents a strongly typed list of objects that can be accessed by index. Provides methods to search and manipulate lists. + /// + /// The type of elements in the list. + public class ExposedList : IEnumerable { + private const int defaultCapacity = 4; + private static readonly T[] emptyArray = new T[0]; + public T[] Items; - private int _size; + private int size; - /// - /// Initializes a new instance of the class that is empty and has the default initial capacity. - /// - public ExposedList() { - Items = _emptyArray; - } + /// + /// Initializes a new instance of the class that is empty and has the default initial capacity. + /// + public ExposedList() { + Items = emptyArray; + } - /// - /// Initializes a new instance of the class that is empty and has the specified initial capacity. - /// - /// The number of elements that the new list can initially store. - /// - /// is less than 0. - /// - public ExposedList(int capacity) { - if (capacity < 0) { - throw new ArgumentOutOfRangeException("capacity"); - } - Items = new T[capacity]; - } + /// + /// Initializes a new instance of the class that is empty and has the specified initial capacity. + /// + /// The number of elements that the new list can initially store. + /// + /// is less than 0. + /// + public ExposedList(int capacity) { + if (capacity < 0) { + throw new ArgumentOutOfRangeException("capacity"); + } + Items = new T[capacity]; + } - /// - /// Gets or sets the total number of elements the internal data structure can hold without resizing. - /// - /// - /// The number of elements that the can contain before resizing is required. - /// - /// - /// is set to a value that is less than - /// - /// . - /// - /// There is not enough memory available on the system. - public int Capacity { - get { - return Items.Length; - } - set { - if (value == Items.Length) { - return; - } - if (value < _size) { - throw new ArgumentOutOfRangeException("value"); - } - if (value > 0) { - var objArray = new T[value]; - if (_size > 0) { - Array.Copy(Items, 0, objArray, 0, _size); - } - Items = objArray; - } else { - Items = _emptyArray; - } - } - } - - /// - /// Gets the number of elements actually contained in the . - /// - /// - /// The number of elements actually contained in the . - /// - public int Count { - get { - return _size; - } - } - - /// - /// Adds an object to the end of the . - /// - /// - /// The object to be added to the end of the . The value can be null for reference types. - /// - public void Add(T item) { - if (_size == Items.Length) { - EnsureCapacity(_size + 1); - } - Items[_size++] = item; - } - - /// - /// Removes all elements from the . - /// - public void Clear() { - if (_size > 0) { - Array.Clear(Items, 0, _size); - _size = 0; - } - } - - /// - /// Determines whether an element is in the . - /// - /// - /// true if is found in the ; otherwise, false. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - public bool Contains(T item) { - if (item == null) { - for (int index = 0; index < _size; ++index) { - if (Items[index] == null) { - return true; - } - } - return false; - } else { - EqualityComparer @default = EqualityComparer.Default; - for (int index = 0; index < _size; ++index) { - if (@default.Equals(Items[index], item)) { - return true; - } - } - return false; - } - } - - /// - /// Copies the entire to a compatible one-dimensional array, starting at the specified index of the target array. - /// - /// - /// The one-dimensional that is the destination of the elements copied from - /// - /// . The must have zero-based indexing. - /// - /// - /// The zero-based index in at which copying begins. - /// - /// - /// is null. - /// - /// - /// is less than 0. - /// - /// - /// The number of elements in the source is greater than the available space from - /// - /// to the end of the destination . - /// - public void CopyTo(T[] array, int arrayIndex) { - Array.Copy(Items, 0, array, arrayIndex, _size); - } - - /// - /// Searches for the specified object and returns the zero-based index of the first occurrence within the entire - /// - /// . - /// - /// - /// The zero-based index of the first occurrence of within the entire - /// - /// , if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - public int IndexOf(T item) { - return Array.IndexOf(Items, item, 0, _size); - } - - /// - /// Inserts an element into the at the specified index. - /// - /// - /// The zero-based index at which should be inserted. - /// - /// The object to insert. The value can be null for reference types. - /// - /// is less than 0.-or- is greater than - /// - /// . - /// - public void Insert(int index, T item) { - if ((uint) index > (uint) _size) { - throw new ArgumentOutOfRangeException("index"); - } - if (_size == Items.Length) { - EnsureCapacity(_size + 1); - } - if (index < _size) { - Array.Copy(Items, index, Items, index + 1, _size - index); - } - Items[index] = item; - ++_size; - } - - /// - /// Removes the first occurrence of a specific object from the . - /// - /// - /// true if is successfully removed; otherwise, false. This method also returns false if - /// - /// was not found in the . - /// - /// - /// The object to remove from the . The value can be null for reference types. - /// - public bool Remove(T item) { - int index = IndexOf(item); - if (index < 0) { - return false; - } - RemoveAt(index); - return true; - } - - /// - /// Removes the element at the specified index of the . - /// - /// The zero-based index of the element to remove. - /// - /// is less than 0.-or- is equal to or greater than - /// - /// . - /// - public void RemoveAt(int index) { - if ((uint) index >= (uint) _size) { - throw new ArgumentOutOfRangeException(); - } - --_size; - if (index < _size) { - Array.Copy(Items, index + 1, Items, index, _size - index); - } - Items[_size] = default (T); - } - - /// - /// Copies the entire to a compatible one-dimensional array, starting at the beginning of the target array. - /// - /// - /// The one-dimensional that is the destination of the elements copied from - /// - /// . The must have zero-based indexing. - /// - /// - /// is null. - /// - /// - /// The number of elements in the source is greater than the number of elements that the destination - /// - /// can contain. - /// - public void CopyTo(T[] array) { - CopyTo(array, 0); - } - - /// - /// Copies a range of elements from the to a compatible one-dimensional array, starting at the specified index of the target array. - /// - /// - /// The zero-based index in the source at which copying begins. - /// - /// - /// The one-dimensional that is the destination of the elements copied from - /// - /// . The must have zero-based indexing. - /// - /// - /// The zero-based index in at which copying begins. - /// - /// The number of elements to copy. - /// - /// is null. - /// - /// - /// is less than 0.-or- is less than 0.-or- - /// - /// is less than 0. - /// - /// - /// is equal to or greater than the of the source - /// - /// .-or-The number of elements from to the end of the source - /// - /// is greater than the available space from - /// - /// to the end of the destination . - /// - public void CopyTo(int index, T[] array, int arrayIndex, int count) { - if (_size - index < count) { - throw new ArgumentException("Invalid length"); - } - Array.Copy(Items, index, array, arrayIndex, count); - } - - private void EnsureCapacity(int min) { - if (Items.Length >= min) { - return; - } - int num = Items.Length == 0 ? 4 : Items.Length * 2; - if (num < min) { - num = min; - } - Capacity = num; - } - - /// - /// Creates a shallow copy of a range of elements in the source . - /// - /// - /// A shallow copy of a range of elements in the source . - /// - /// - /// The zero-based index at which the range starts. - /// - /// The number of elements in the range. - /// - /// is less than 0.-or- is less than 0. - /// - /// - /// and do not denote a valid range of elements in the - /// - /// . - /// - public ExposedList GetRange(int index, int count) { - if (index < 0 || count < 0) { - throw new ArgumentOutOfRangeException("index || count"); - } - if (_size - index < count) { - throw new ArgumentException("Invalid length"); - } - var list = new ExposedList(count); - Array.Copy(Items, index, list.Items, 0, count); - list._size = count; - return list; - } - - /// - /// Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the - /// - /// that extends from the specified index to the last element. - /// - /// - /// The zero-based index of the first occurrence of within the range of elements in the - /// - /// that extends from to the last element, if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - /// The zero-based starting index of the search. 0 (zero) is valid in an empty list. - /// - /// is outside the range of valid indexes for the - /// - /// . - /// - public int IndexOf(T item, int index) { - if (index > _size) { - throw new ArgumentOutOfRangeException("index"); - } - return Array.IndexOf(Items, item, index, _size - index); - } - - /// - /// Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the - /// - /// that starts at the specified index and contains the specified number of elements. - /// - /// - /// The zero-based index of the first occurrence of within the range of elements in the - /// - /// that starts at and contains - /// - /// number of elements, if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - /// The zero-based starting index of the search. 0 (zero) is valid in an empty list. - /// The number of elements in the section to search. - /// - /// is outside the range of valid indexes for the - /// - /// .-or- is less than 0.-or- - /// - /// and do not specify a valid section in the - /// - /// . - /// - public int IndexOf(T item, int index, int count) { - if (index > _size) { - throw new ArgumentOutOfRangeException("index"); - } - if (count < 0 || index > _size - count) { - throw new ArgumentOutOfRangeException("count"); - } - return Array.IndexOf(Items, item, index, count); - } - - /// - /// Searches for the specified object and returns the zero-based index of the last occurrence within the entire - /// - /// . - /// - /// - /// The zero-based index of the last occurrence of within the entire the - /// - /// , if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - public int LastIndexOf(T item) { - return LastIndexOf(item, _size - 1, _size); - } - - /// - /// Searches for the specified object and returns the zero-based index of the last occurrence within the range of elements in the - /// - /// that extends from the first element to the specified index. - /// - /// - /// The zero-based index of the last occurrence of within the range of elements in the - /// - /// that extends from the first element to , if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - /// The zero-based starting index of the backward search. - /// - /// is outside the range of valid indexes for the - /// - /// . - /// - public int LastIndexOf(T item, int index) { - if (index >= _size) { - throw new ArgumentOutOfRangeException("index"); - } - return LastIndexOf(item, index, index + 1); - } - - /// - /// Searches for the specified object and returns the zero-based index of the last occurrence within the range of elements in the - /// - /// that contains the specified number of elements and ends at the specified index. - /// - /// - /// The zero-based index of the last occurrence of within the range of elements in the - /// - /// that contains number of elements and ends at - /// - /// , if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - /// The zero-based starting index of the backward search. - /// The number of elements in the section to search. - /// - /// is outside the range of valid indexes for the - /// - /// .-or- is less than 0.-or- - /// - /// and do not specify a valid section in the - /// - /// . - /// - public int LastIndexOf(T item, int index, int count) { - if (_size == 0) { - return -1; - } - if (index < 0 || count < 0) { - throw new ArgumentOutOfRangeException("index || count"); - } - if (index >= _size || count > index + 1) { - throw new ArgumentOutOfRangeException("size || count"); - } - return Array.LastIndexOf(Items, item, index, count); - } - - /// - /// Removes a range of elements from the . - /// - /// The zero-based starting index of the range of elements to remove. - /// The number of elements to remove. - /// - /// is less than 0.-or- is less than 0. - /// - /// - /// and do not denote a valid range of elements in the - /// - /// . - /// - public void RemoveRange(int index, int count) { - if (index < 0 || count < 0) { - throw new ArgumentOutOfRangeException("index || count"); - } - if (_size - index < count) { - throw new ArgumentException("Invalid length"); - } - if (count <= 0) { - return; - } - _size -= count; - if (index < _size) { - Array.Copy(Items, index + count, Items, index, _size - index); - } - Array.Clear(Items, _size, count); - } - - //public void Sort(Comparison comparison) - //{ - // if (comparison == null) - // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); - // if (this._size <= 0) - // return; - // Array.Sort(this._items, 0, this._size, (IComparer) new Array.FunctorComparer(comparison)); - //} - /// - /// Sorts the elements in the entire using the specified - /// - /// . - /// - /// - /// The to use when comparing elements. - /// - /// - /// is null. - /// - /// - /// The implementation of caused an error during the sort. For example, - /// - /// might not return 0 when comparing an item with itself. - /// - /// - /// Copies the elements of the to a new array. - /// - /// - /// An array containing copies of the elements of the . - /// - public T[] ToArray() { - var objArray = new T[_size]; - Array.Copy(Items, 0, objArray, 0, _size); - return objArray; - } - - // Returns an enumerator for this list with the given - // permission for removal of elements. If modifications made to the list - // while an enumeration is in progress, the MoveNext and - // GetObject methods of the enumerator will throw an exception. - // - public Enumerator GetEnumerator() { - return new Enumerator(this); - } - /// - IEnumerator IEnumerable.GetEnumerator() { - return new Enumerator(this); - } + // Constructs a List, copying the contents of the given collection. The + // size and capacity of the new list will both be equal to the size of the + // given collection. + // + public ExposedList(IEnumerable collection) { + if (collection==null) + throw new ArgumentNullException("collection"); - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { - return new Enumerator(this); - } + ICollection c = collection as ICollection; + if( c != null) { + int count = c.Count; + Items = new T[count]; + c.CopyTo(Items, 0); + size = count; + } + else { + size = 0; + Items = new T[defaultCapacity]; - [Serializable()] - public struct Enumerator : IEnumerator, System.Collections.IEnumerator - { - private readonly ExposedList _list; - private int _index; - private T _current; + using(IEnumerator en = collection.GetEnumerator()) { + while(en.MoveNext()) { + Add(en.Current); + } + } + } + } + + /// + /// Gets or sets the total number of elements the internal data structure can hold without resizing. + /// + /// + /// The number of elements that the can contain before resizing is required. + /// + /// + /// is set to a value that is less than + /// + /// . + /// + /// There is not enough memory available on the system. + public int Capacity { + get { + return Items.Length; + } + set { + if (value == Items.Length) { + return; + } + if (value < size) { + throw new ArgumentOutOfRangeException("value"); + } + if (value > 0) { + var objArray = new T[value]; + if (size > 0) { + Array.Copy(Items, 0, objArray, 0, size); + } + Items = objArray; + } else { + Items = emptyArray; + } + } + } + + /// + /// Gets the number of elements actually contained in the . + /// + /// + /// The number of elements actually contained in the . + /// + public int Count { + get { + return size; + } + } + + /// + /// Adds an object to the end of the . + /// + /// + /// The object to be added to the end of the . The value can be null for reference types. + /// + public void Add(T item) { + if (size == Items.Length) { + EnsureCapacity(size + 1); + } + Items[size++] = item; + } + + /// + /// Removes all elements from the . + /// + public void Clear() { + if (size > 0) { + Array.Clear(Items, 0, size); + size = 0; + } + } + + /// + /// Determines whether an element is in the . + /// + /// + /// true if is found in the ; otherwise, false. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + public bool Contains(T item) { + if (item == null) { + for (int index = 0; index < size; ++index) { + if (Items[index] == null) { + return true; + } + } + return false; + } else { + EqualityComparer @default = EqualityComparer.Default; + for (int index = 0; index < size; ++index) { + if (@default.Equals(Items[index], item)) { + return true; + } + } + return false; + } + } + + /// + /// Copies the entire to a compatible one-dimensional array, starting at the specified index of the target array. + /// + /// + /// The one-dimensional that is the destination of the elements copied from + /// + /// . The must have zero-based indexing. + /// + /// + /// The zero-based index in at which copying begins. + /// + /// + /// is null. + /// + /// + /// is less than 0. + /// + /// + /// The number of elements in the source is greater than the available space from + /// + /// to the end of the destination . + /// + public void CopyTo(T[] array, int arrayIndex) { + Array.Copy(Items, 0, array, arrayIndex, size); + } + + /// + /// Searches for the specified object and returns the zero-based index of the first occurrence within the entire + /// + /// . + /// + /// + /// The zero-based index of the first occurrence of within the entire + /// + /// , if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + public int IndexOf(T item) { + return Array.IndexOf(Items, item, 0, size); + } + + /// + /// Inserts an element into the at the specified index. + /// + /// + /// The zero-based index at which should be inserted. + /// + /// The object to insert. The value can be null for reference types. + /// + /// is less than 0.-or- is greater than + /// + /// . + /// + public void Insert(int index, T item) { + if ((uint) index > (uint) size) { + throw new ArgumentOutOfRangeException("index"); + } + if (size == Items.Length) { + EnsureCapacity(size + 1); + } + if (index < size) { + Array.Copy(Items, index, Items, index + 1, size - index); + } + Items[index] = item; + ++size; + } + + /// + /// Removes the first occurrence of a specific object from the . + /// + /// + /// true if is successfully removed; otherwise, false. This method also returns false if + /// + /// was not found in the . + /// + /// + /// The object to remove from the . The value can be null for reference types. + /// + public bool Remove(T item) { + int index = IndexOf(item); + if (index < 0) { + return false; + } + RemoveAt(index); + return true; + } + + /// + /// Removes the element at the specified index of the . + /// + /// The zero-based index of the element to remove. + /// + /// is less than 0.-or- is equal to or greater than + /// + /// . + /// + public void RemoveAt(int index) { + if ((uint) index >= (uint) size) { + throw new ArgumentOutOfRangeException(); + } + --size; + if (index < size) { + Array.Copy(Items, index + 1, Items, index, size - index); + } + Items[size] = default (T); + } + + /// + /// Copies the entire to a compatible one-dimensional array, starting at the beginning of the target array. + /// + /// + /// The one-dimensional that is the destination of the elements copied from + /// + /// . The must have zero-based indexing. + /// + /// + /// is null. + /// + /// + /// The number of elements in the source is greater than the number of elements that the destination + /// + /// can contain. + /// + public void CopyTo(T[] array) { + CopyTo(array, 0); + } + + /// + /// Copies a range of elements from the to a compatible one-dimensional array, starting at the specified index of the target array. + /// + /// + /// The zero-based index in the source at which copying begins. + /// + /// + /// The one-dimensional that is the destination of the elements copied from + /// + /// . The must have zero-based indexing. + /// + /// + /// The zero-based index in at which copying begins. + /// + /// The number of elements to copy. + /// + /// is null. + /// + /// + /// is less than 0.-or- is less than 0.-or- + /// + /// is less than 0. + /// + /// + /// is equal to or greater than the of the source + /// + /// .-or-The number of elements from to the end of the source + /// + /// is greater than the available space from + /// + /// to the end of the destination . + /// + public void CopyTo(int index, T[] array, int arrayIndex, int count) { + if (size - index < count) { + throw new ArgumentException("Invalid length"); + } + Array.Copy(Items, index, array, arrayIndex, count); + } + + private void EnsureCapacity(int min) { + if (Items.Length >= min) { + return; + } + int num = Items.Length == 0 ? 4 : Items.Length * 2; + if (num < min) { + num = min; + } + Capacity = num; + } + + /// + /// Creates a shallow copy of a range of elements in the source . + /// + /// + /// A shallow copy of a range of elements in the source . + /// + /// + /// The zero-based index at which the range starts. + /// + /// The number of elements in the range. + /// + /// is less than 0.-or- is less than 0. + /// + /// + /// and do not denote a valid range of elements in the + /// + /// . + /// + public ExposedList GetRange(int index, int count) { + if (index < 0 || count < 0) { + throw new ArgumentOutOfRangeException("index || count"); + } + if (size - index < count) { + throw new ArgumentException("Invalid length"); + } + var list = new ExposedList(count); + Array.Copy(Items, index, list.Items, 0, count); + list.size = count; + return list; + } + + /// + /// Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the + /// + /// that extends from the specified index to the last element. + /// + /// + /// The zero-based index of the first occurrence of within the range of elements in the + /// + /// that extends from to the last element, if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + /// The zero-based starting index of the search. 0 (zero) is valid in an empty list. + /// + /// is outside the range of valid indexes for the + /// + /// . + /// + public int IndexOf(T item, int index) { + if (index > size) { + throw new ArgumentOutOfRangeException("index"); + } + return Array.IndexOf(Items, item, index, size - index); + } + + /// + /// Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the + /// + /// that starts at the specified index and contains the specified number of elements. + /// + /// + /// The zero-based index of the first occurrence of within the range of elements in the + /// + /// that starts at and contains + /// + /// number of elements, if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + /// The zero-based starting index of the search. 0 (zero) is valid in an empty list. + /// The number of elements in the section to search. + /// + /// is outside the range of valid indexes for the + /// + /// .-or- is less than 0.-or- + /// + /// and do not specify a valid section in the + /// + /// . + /// + public int IndexOf(T item, int index, int count) { + if (index > size) { + throw new ArgumentOutOfRangeException("index"); + } + if (count < 0 || index > size - count) { + throw new ArgumentOutOfRangeException("count"); + } + return Array.IndexOf(Items, item, index, count); + } + + /// + /// Searches for the specified object and returns the zero-based index of the last occurrence within the entire + /// + /// . + /// + /// + /// The zero-based index of the last occurrence of within the entire the + /// + /// , if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + public int LastIndexOf(T item) { + return LastIndexOf(item, size - 1, size); + } + + /// + /// Searches for the specified object and returns the zero-based index of the last occurrence within the range of elements in the + /// + /// that extends from the first element to the specified index. + /// + /// + /// The zero-based index of the last occurrence of within the range of elements in the + /// + /// that extends from the first element to , if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + /// The zero-based starting index of the backward search. + /// + /// is outside the range of valid indexes for the + /// + /// . + /// + public int LastIndexOf(T item, int index) { + if (index >= size) { + throw new ArgumentOutOfRangeException("index"); + } + return LastIndexOf(item, index, index + 1); + } + + /// + /// Searches for the specified object and returns the zero-based index of the last occurrence within the range of elements in the + /// + /// that contains the specified number of elements and ends at the specified index. + /// + /// + /// The zero-based index of the last occurrence of within the range of elements in the + /// + /// that contains number of elements and ends at + /// + /// , if found; otherwise, –1. + /// + /// + /// The object to locate in the . The value can be null for reference types. + /// + /// The zero-based starting index of the backward search. + /// The number of elements in the section to search. + /// + /// is outside the range of valid indexes for the + /// + /// .-or- is less than 0.-or- + /// + /// and do not specify a valid section in the + /// + /// . + /// + public int LastIndexOf(T item, int index, int count) { + if (size == 0) { + return -1; + } + if (index < 0 || count < 0) { + throw new ArgumentOutOfRangeException("index || count"); + } + if (index >= size || count > index + 1) { + throw new ArgumentOutOfRangeException("size || count"); + } + return Array.LastIndexOf(Items, item, index, count); + } + + /// + /// Removes a range of elements from the . + /// + /// The zero-based starting index of the range of elements to remove. + /// The number of elements to remove. + /// + /// is less than 0.-or- is less than 0. + /// + /// + /// and do not denote a valid range of elements in the + /// + /// . + /// + public void RemoveRange(int index, int count) { + if (index < 0 || count < 0) { + throw new ArgumentOutOfRangeException("index || count"); + } + if (size - index < count) { + throw new ArgumentException("Invalid length"); + } + if (count <= 0) { + return; + } + size -= count; + if (index < size) { + Array.Copy(Items, index + count, Items, index, size - index); + } + Array.Clear(Items, size, count); + } + + public void TrimExcess() { + int threshold = (int)(((double) Items.Length) * 0.9); + if( size < threshold ) { + Capacity = size; + } + } + + //public void Sort(Comparison comparison) + //{ + // if (comparison == null) + // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); + // if (this.size <= 0) + // return; + // Array.Sort(this._items, 0, this.size, (IComparer) new Array.FunctorComparer(comparison)); + //} + + /// + /// Sorts the elements in the entire using the specified + /// + /// . + /// + /// + /// The to use when comparing elements. + /// + /// + /// is null. + /// + /// + /// The implementation of caused an error during the sort. For example, + /// + /// might not return 0 when comparing an item with itself. + /// + /// + /// Copies the elements of the to a new array. + /// + /// + /// An array containing copies of the elements of the . + /// + public T[] ToArray() { + var objArray = new T[size]; + Array.Copy(Items, 0, objArray, 0, size); + return objArray; + } + + // Returns an enumerator for this list with the given + // permission for removal of elements. If modifications made to the list + // while an enumeration is in progress, the MoveNext and + // GetObject methods of the enumerator will throw an exception. + // + public Enumerator GetEnumerator() { + return new Enumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() { + return new Enumerator(this); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { + return new Enumerator(this); + } + + [Serializable()] + public struct Enumerator : IEnumerator, System.Collections.IEnumerator + { + private readonly ExposedList list; + private int index; + private T current; - internal Enumerator(ExposedList list) { - _list = list; - _index = 0; - _current = default(T); - } + internal Enumerator(ExposedList list) { + this.list = list; + index = 0; + current = default(T); + } - public void Dispose() { - } + public void Dispose() { + } - public bool MoveNext() { - ExposedList localList = _list; + public bool MoveNext() { + ExposedList localList = list; - if (((uint)_index < (uint)localList._size)) { - _current = localList.Items[_index]; - _index++; - return true; - } - return MoveNextRare(); - } + if (((uint)index < (uint)localList.size)) { + current = localList.Items[index]; + index++; + return true; + } + return MoveNextRare(); + } - private bool MoveNextRare() - { - _index = _list._size + 1; - _current = default(T); - return false; - } + private bool MoveNextRare() + { + index = list.size + 1; + current = default(T); + return false; + } - public T Current { - get { - return _current; - } - } + public T Current { + get { + return current; + } + } - Object System.Collections.IEnumerator.Current { - get { - if( _index == 0 || _index == _list._size + 1) - throw new InvalidOperationException(); - return Current; - } - } + Object System.Collections.IEnumerator.Current { + get { + if( index == 0 || index == list.size + 1) + throw new InvalidOperationException(); + return Current; + } + } - void System.Collections.IEnumerator.Reset() { - _index = 0; - _current = default(T); - } + void System.Collections.IEnumerator.Reset() { + index = 0; + current = default(T); + } - } - } + } + } } \ No newline at end of file diff --git a/spine-csharp/src/ExposedList.cs.meta b/spine-csharp/src/ExposedList.cs.meta deleted file mode 100644 index e12f21463..000000000 --- a/spine-csharp/src/ExposedList.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 540cf6a03c85e284e83831880e3f25a8 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/spine-csharp/src/Skeleton.cs b/spine-csharp/src/Skeleton.cs index 56f1c421b..c8c26df69 100644 --- a/spine-csharp/src/Skeleton.cs +++ b/spine-csharp/src/Skeleton.cs @@ -178,8 +178,8 @@ namespace Spine { public void SetSlotsToSetupPose () { ExposedList slots = this.slots; drawOrder.Clear(); - for (int i = 0, n = slots.Count; i < n; i++) - drawOrder.Add(slots.Items[i]); + for (int i = 0, n = slots.Count; i < n; i++) + drawOrder.Add(slots.Items[i]); for (int i = 0, n = slots.Count; i < n; i++) slots.Items[i].SetToSetupPose(i); diff --git a/spine-csharp/src/SkeletonBounds.cs b/spine-csharp/src/SkeletonBounds.cs index 0c1a146f2..9fe27ae9d 100644 --- a/spine-csharp/src/SkeletonBounds.cs +++ b/spine-csharp/src/SkeletonBounds.cs @@ -57,7 +57,7 @@ namespace Spine { int slotCount = slots.Count; boundingBoxes.Clear(); - for (int i = 0, n = polygons.Count; i < n; i++) + for (int i = 0, n = polygons.Count; i < n; i++) polygonPool.Add(polygons.Items[n]); polygons.Clear(); diff --git a/spine-csharp/src/SkeletonData.cs b/spine-csharp/src/SkeletonData.cs index 48b500363..4e62dfed4 100644 --- a/spine-csharp/src/SkeletonData.cs +++ b/spine-csharp/src/SkeletonData.cs @@ -34,25 +34,25 @@ using System.Collections.Generic; namespace Spine { public class SkeletonData { internal String name; - internal List bones = new List(); - internal List slots = new List(); - internal List skins = new List(); + internal ExposedList bones = new ExposedList(); + internal ExposedList slots = new ExposedList(); + internal ExposedList skins = new ExposedList(); internal Skin defaultSkin; - internal List events = new List(); - internal List animations = new List(); - internal List ikConstraints = new List(); + internal ExposedList events = new ExposedList(); + internal ExposedList animations = new ExposedList(); + internal ExposedList ikConstraints = new ExposedList(); internal float width, height; internal String version, hash; public String Name { get { return name; } set { name = value; } } - public List Bones { get { return bones; } } // Ordered parents first. - public List Slots { get { return slots; } } // Setup pose draw order. - public List Skins { get { return skins; } set { skins = value; } } + public ExposedList Bones { get { return bones; } } // Ordered parents first. + public ExposedList Slots { get { return slots; } } // Setup pose draw order. + public ExposedList Skins { get { return skins; } set { skins = value; } } /// May be null. public Skin DefaultSkin { get { return defaultSkin; } set { defaultSkin = value; } } - public List Events { get { return events; } set { events = value; } } - public List Animations { get { return animations; } set { animations = value; } } - public List IkConstraints { get { return ikConstraints; } set { ikConstraints = value; } } + public ExposedList Events { get { return events; } set { events = value; } } + public ExposedList Animations { get { return animations; } set { animations = value; } } + public ExposedList IkConstraints { get { return ikConstraints; } set { ikConstraints = value; } } public float Width { get { return width; } set { width = value; } } public float Height { get { return height; } set { height = value; } } /// The Spine version used to export this data. @@ -64,9 +64,9 @@ namespace Spine { /// May be null. public BoneData FindBone (String boneName) { if (boneName == null) throw new ArgumentNullException("boneName cannot be null."); - List bones = this.bones; + ExposedList bones = this.bones; for (int i = 0, n = bones.Count; i < n; i++) { - BoneData bone = bones[i]; + BoneData bone = bones.Items[i]; if (bone.name == boneName) return bone; } return null; @@ -75,9 +75,9 @@ namespace Spine { /// -1 if the bone was not found. public int FindBoneIndex (String boneName) { if (boneName == null) throw new ArgumentNullException("boneName cannot be null."); - List bones = this.bones; + ExposedList bones = this.bones; for (int i = 0, n = bones.Count; i < n; i++) - if (bones[i].name == boneName) return i; + if (bones.Items[i].name == boneName) return i; return -1; } @@ -86,9 +86,9 @@ namespace Spine { /// May be null. public SlotData FindSlot (String slotName) { if (slotName == null) throw new ArgumentNullException("slotName cannot be null."); - List slots = this.slots; + ExposedList slots = this.slots; for (int i = 0, n = slots.Count; i < n; i++) { - SlotData slot = slots[i]; + SlotData slot = slots.Items[i]; if (slot.name == slotName) return slot; } return null; @@ -97,9 +97,9 @@ namespace Spine { /// -1 if the bone was not found. public int FindSlotIndex (String slotName) { if (slotName == null) throw new ArgumentNullException("slotName cannot be null."); - List slots = this.slots; + ExposedList slots = this.slots; for (int i = 0, n = slots.Count; i < n; i++) - if (slots[i].name == slotName) return i; + if (slots.Items[i].name == slotName) return i; return -1; } @@ -128,9 +128,9 @@ namespace Spine { /// May be null. public Animation FindAnimation (String animationName) { if (animationName == null) throw new ArgumentNullException("animationName cannot be null."); - List animations = this.animations; + ExposedList animations = this.animations; for (int i = 0, n = animations.Count; i < n; i++) { - Animation animation = animations[i]; + Animation animation = animations.Items[i]; if (animation.name == animationName) return animation; } return null; @@ -141,9 +141,9 @@ namespace Spine { /// May be null. public IkConstraintData FindIkConstraint (String ikConstraintName) { if (ikConstraintName == null) throw new ArgumentNullException("ikConstraintName cannot be null."); - List ikConstraints = this.ikConstraints; + ExposedList ikConstraints = this.ikConstraints; for (int i = 0, n = ikConstraints.Count; i < n; i++) { - IkConstraintData ikConstraint = ikConstraints[i]; + IkConstraintData ikConstraint = ikConstraints.Items[i]; if (ikConstraint.name == ikConstraintName) return ikConstraint; } return null; diff --git a/spine-csharp/src/SkeletonJson.cs b/spine-csharp/src/SkeletonJson.cs index b83f88a82..0dea14062 100644 --- a/spine-csharp/src/SkeletonJson.cs +++ b/spine-csharp/src/SkeletonJson.cs @@ -376,7 +376,7 @@ namespace Spine { } private void ReadAnimation (String name, Dictionary map, SkeletonData skeletonData) { - var timelines = new List(); + var timelines = new ExposedList(); float duration = 0; float scale = Scale; diff --git a/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs b/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs index 943a98715..e59610626 100644 --- a/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs @@ -80,7 +80,7 @@ public class BoneFollowerInspector : Editor { bones[0] = ""; for (int i = 0; i < bones.Length - 1; i++) - bones[i + 1] = component.skeletonRenderer.skeleton.Data.Bones[i].Name; + bones[i + 1] = component.skeletonRenderer.skeleton.Data.Bones.Items[i].Name; Array.Sort(bones); int boneIndex = Math.Max(0, Array.IndexOf(bones, boneName.stringValue)); diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs index f338626b2..27a590b19 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs @@ -74,7 +74,7 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector { animations[0] = ""; int animationIndex = 0; for (int i = 0; i < animations.Length - 1; i++) { - String name = component.skeleton.Data.Animations[i].Name; + String name = component.skeleton.Data.Animations.Items[i].Name; animations[i + 1] = name; if (name == animationName.stringValue) animationIndex = i + 1; diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs index 4fa1a0161..db2ba8420 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs @@ -76,7 +76,7 @@ public static class SkeletonBaker { /// const float bakeIncrement = 1 / 60f; - public static void BakeToPrefab (SkeletonDataAsset skeletonDataAsset, List skins, string outputPath = "", bool bakeAnimations = true, bool bakeIK = true, SendMessageOptions eventOptions = SendMessageOptions.DontRequireReceiver) { + public static void BakeToPrefab (SkeletonDataAsset skeletonDataAsset, ExposedList skins, string outputPath = "", bool bakeAnimations = true, bool bakeIK = true, SendMessageOptions eventOptions = SendMessageOptions.DontRequireReceiver) { if (skeletonDataAsset == null || skeletonDataAsset.GetSkeletonData(true) == null) { Debug.LogError("Could not export Spine Skeleton because SkeletonDataAsset is null or invalid!"); return; @@ -135,7 +135,7 @@ public static class SkeletonBaker { for (int s = 0; s < skeletonData.Slots.Count; s++) { List attachmentNames = new List(); for (int i = 0; i < skinCount; i++) { - var skin = skins[i]; + var skin = skins.Items[i]; List temp = new List(); skin.FindNamesForSlot(s, temp); foreach (string str in temp) { @@ -216,7 +216,7 @@ public static class SkeletonBaker { //create bones for (int i = 0; i < skeletonData.Bones.Count; i++) { - var boneData = skeletonData.Bones[i]; + var boneData = skeletonData.Bones.Items[i]; Transform boneTransform = new GameObject(boneData.Name).transform; boneTransform.parent = prefabRoot.transform; boneTable.Add(boneTransform.name, boneTransform); @@ -225,7 +225,7 @@ public static class SkeletonBaker { for (int i = 0; i < skeletonData.Bones.Count; i++) { - var boneData = skeletonData.Bones[i]; + var boneData = skeletonData.Bones.Items[i]; Transform boneTransform = boneTable[boneData.Name]; Transform parentTransform = null; if (i > 0) @@ -246,7 +246,7 @@ public static class SkeletonBaker { //create slots and attachments for (int i = 0; i < skeletonData.Slots.Count; i++) { - var slotData = skeletonData.Slots[i]; + var slotData = skeletonData.Slots.Items[i]; Transform slotTransform = new GameObject(slotData.Name).transform; slotTransform.parent = prefabRoot.transform; slotTable.Add(slotData.Name, slotTransform); @@ -807,26 +807,26 @@ public static class SkeletonBaker { List ignoreRotateTimelineIndexes = new List(); - //if (bakeIK) { - // foreach (IkConstraint i in skeleton.IkConstraints) { - // foreach (Bone b in i.Bones) { - // int index = skeleton.FindBoneIndex(b.Data.Name); - // ignoreRotateTimelineIndexes.Add(index); - // BakeBone(b, animation, clip); - // } - // } - //} + if (bakeIK) { + foreach (IkConstraint i in skeleton.IkConstraints) { + foreach (Bone b in i.Bones) { + int index = skeleton.FindBoneIndex(b.Data.Name); + ignoreRotateTimelineIndexes.Add(index); + BakeBone(b, animation, clip); + } + } + } - //foreach (Bone b in skeleton.Bones) { - // if (b.Data.InheritRotation == false) { - // int index = skeleton.FindBoneIndex(b.Data.Name); + foreach (Bone b in skeleton.Bones) { + if (b.Data.InheritRotation == false) { + int index = skeleton.FindBoneIndex(b.Data.Name); - // if (ignoreRotateTimelineIndexes.Contains(index) == false) { - // ignoreRotateTimelineIndexes.Add(index); - // BakeBone(b, animation, clip); - // } - // } - //} + if (ignoreRotateTimelineIndexes.Contains(index) == false) { + ignoreRotateTimelineIndexes.Add(index); + BakeBone(b, animation, clip); + } + } + } foreach (Timeline t in timelines) { skeleton.SetToSetupPose(); @@ -1061,7 +1061,7 @@ public static class SkeletonBaker { } static void ParseTranslateTimeline (Skeleton skeleton, TranslateTimeline timeline, AnimationClip clip) { - var boneData = skeleton.Data.Bones[timeline.BoneIndex]; + var boneData = skeleton.Data.Bones.Items[timeline.BoneIndex]; var bone = skeleton.Bones.Items[timeline.BoneIndex]; AnimationCurve xCurve = new AnimationCurve(); @@ -1207,7 +1207,7 @@ public static class SkeletonBaker { } static void ParseScaleTimeline (Skeleton skeleton, ScaleTimeline timeline, AnimationClip clip) { - var boneData = skeleton.Data.Bones[timeline.BoneIndex]; + var boneData = skeleton.Data.Bones.Items[timeline.BoneIndex]; var bone = skeleton.Bones.Items[timeline.BoneIndex]; AnimationCurve xCurve = new AnimationCurve(); @@ -1340,7 +1340,7 @@ public static class SkeletonBaker { } static void ParseRotateTimeline (Skeleton skeleton, RotateTimeline timeline, AnimationClip clip) { - var boneData = skeleton.Data.Bones[timeline.BoneIndex]; + var boneData = skeleton.Data.Bones.Items[timeline.BoneIndex]; var bone = skeleton.Bones.Items[timeline.BoneIndex]; AnimationCurve curve = new AnimationCurve(); diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs index 81d2c37a0..ed7c90e05 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs @@ -186,7 +186,7 @@ public class SkeletonDataAssetInspector : Editor { Skin bakeSkin = m_skeletonAnimation.skeleton.Skin; if (bakeSkin == null) { skinName = "Default"; - bakeSkin = m_skeletonData.Skins[0]; + bakeSkin = m_skeletonData.Skins.Items[0]; } else skinName = m_skeletonAnimation.skeleton.Skin.Name; @@ -195,7 +195,7 @@ public class SkeletonDataAssetInspector : Editor { try { GUILayout.BeginVertical(); if (GUILayout.Button(new GUIContent("Bake " + skinName, SpineEditorUtilities.Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(250))) - SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, new List(new Skin[] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions); + SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, new ExposedList(new Skin[] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions); GUILayout.BeginHorizontal(); GUILayout.Label(new GUIContent("Skins", SpineEditorUtilities.Icons.skinsRoot), GUILayout.Width(50)); @@ -259,7 +259,7 @@ public class SkeletonDataAssetInspector : Editor { // Animation names String[] animations = new String[m_skeletonData.Animations.Count]; for (int i = 0; i < animations.Length; i++) - animations[i] = m_skeletonData.Animations[i].Name; + animations[i] = m_skeletonData.Animations.Items[i].Name; for (int i = 0; i < fromAnimation.arraySize; i++) { SerializedProperty from = fromAnimation.GetArrayElementAtIndex(i); @@ -350,7 +350,7 @@ public class SkeletonDataAssetInspector : Editor { List slotAttachments = new List(); List slotAttachmentNames = new List(); List defaultSkinAttachmentNames = new List(); - var defaultSkin = m_skeletonData.Skins[0]; + var defaultSkin = m_skeletonData.Skins.Items[0]; Skin skin = m_skeletonAnimation.skeleton.Skin; if (skin == null) { skin = defaultSkin; diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs index e2f8ff52f..bb8961aac 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs @@ -78,7 +78,7 @@ public class SkeletonRendererInspector : Editor { String[] skins = new String[component.skeleton.Data.Skins.Count]; int skinIndex = 0; for (int i = 0; i < skins.Length; i++) { - String name = component.skeleton.Data.Skins[i].Name; + String name = component.skeleton.Data.Skins.Items[i].Name; skins[i] = name; if (name == initialSkinName.stringValue) skinIndex = i; diff --git a/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs b/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs index 9d9e3b3d2..703b54bad 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs @@ -113,7 +113,7 @@ public class SpineSlotDrawer : PropertyDrawer { menu.AddSeparator(""); for (int i = 0; i < data.Slots.Count; i++) { - string name = data.Slots[i].Name; + string name = data.Slots.Items[i].Name; if (name.StartsWith(attrib.startsWith)) menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property)); } @@ -191,7 +191,7 @@ public class SpineSkinDrawer : PropertyDrawer { menu.AddSeparator(""); for (int i = 0; i < data.Skins.Count; i++) { - string name = data.Skins[i].Name; + string name = data.Skins.Items[i].Name; if (name.StartsWith(attrib.startsWith)) menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property)); } @@ -331,7 +331,7 @@ public class SpineAnimationDrawer : PropertyDrawer { var animations = skeletonDataAsset.GetAnimationStateData().SkeletonData.Animations; for (int i = 0; i < animations.Count; i++) { - string name = animations[i].Name; + string name = animations.Items[i].Name; if (name.StartsWith(attrib.startsWith)) menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property)); } @@ -417,7 +417,7 @@ public class SpineAttachmentDrawer : PropertyDrawer { if (skeletonRenderer.skeleton.Skin != null) { validSkins.Add(skeletonRenderer.skeleton.Skin); } else { - validSkins.Add(data.Skins[0]); + validSkins.Add(data.Skins.Items[0]); } } else { foreach (Skin skin in data.Skins) { @@ -441,7 +441,7 @@ public class SpineAttachmentDrawer : PropertyDrawer { menu.AddItem(new GUIContent("Null"), property.stringValue == "", HandleSelect, new SpineDrawerValuePair("", property)); menu.AddSeparator(""); - Skin defaultSkin = data.Skins[0]; + Skin defaultSkin = data.Skins.Items[0]; SerializedProperty slotProperty = property.serializedObject.FindProperty(attrib.slotField); string slotMatch = ""; @@ -458,7 +458,7 @@ public class SpineAttachmentDrawer : PropertyDrawer { prefix = skinPrefix; for (int i = 0; i < data.Slots.Count; i++) { - if (slotMatch.Length > 0 && data.Slots[i].Name.ToLower().Contains(slotMatch) == false) + if (slotMatch.Length > 0 && data.Slots.Items[i].Name.ToLower().Contains(slotMatch) == false) continue; attachmentNames.Clear(); @@ -474,11 +474,11 @@ public class SpineAttachmentDrawer : PropertyDrawer { for (int a = 0; a < attachmentNames.Count; a++) { string attachmentPath = attachmentNames[a]; - string menuPath = prefix + data.Slots[i].Name + "/" + attachmentPath; + string menuPath = prefix + data.Slots.Items[i].Name + "/" + attachmentPath; string name = attachmentNames[a]; if (attrib.returnAttachmentPath) - name = skin.Name + "/" + data.Slots[i].Name + "/" + attachmentPath; + name = skin.Name + "/" + data.Slots.Items[i].Name + "/" + attachmentPath; if (attrib.placeholdersOnly && placeholderNames.Contains(attachmentPath) == false) { menu.AddDisabledItem(new GUIContent(menuPath)); @@ -565,7 +565,7 @@ public class SpineBoneDrawer : PropertyDrawer { menu.AddSeparator(""); for (int i = 0; i < data.Bones.Count; i++) { - string name = data.Bones[i].Name; + string name = data.Bones.Items[i].Name; if (name.StartsWith(attrib.startsWith)) menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property)); } diff --git a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs index c1ebb804f..93936e985 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs @@ -779,7 +779,7 @@ public class SpineEditorUtilities : AssetPostprocessor { skin = data.DefaultSkin; if (skin == null) - skin = data.Skins[0]; + skin = data.Skins.Items[0]; anim.Reset(); @@ -865,7 +865,7 @@ public class SpineEditorUtilities : AssetPostprocessor { skin = data.DefaultSkin; if (skin == null) - skin = data.Skins[0]; + skin = data.Skins.Items[0]; anim.Reset(); diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index 450e7b50b..524e9ef12 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -190,18 +190,20 @@ public class SkeletonRenderer : MonoBehaviour { } else { if (!renderMeshes) continue; - if (attachment is MeshAttachment) { - MeshAttachment meshAttachment = (MeshAttachment)attachment; + MeshAttachment meshAttachment = attachment as MeshAttachment; + if (meshAttachment != null) { rendererObject = meshAttachment.RendererObject; attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentTriangleCount = meshAttachment.triangles.Length; - } else if (attachment is SkinnedMeshAttachment) { - SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; - rendererObject = meshAttachment.RendererObject; - attachmentVertexCount = meshAttachment.uvs.Length >> 1; - attachmentTriangleCount = meshAttachment.triangles.Length; - } else - continue; + } else { + SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; + if (skinnedMeshAttachment != null) { + rendererObject = skinnedMeshAttachment.RendererObject; + attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1; + attachmentTriangleCount = skinnedMeshAttachment.triangles.Length; + } else + continue; + } } // Populate submesh when material changes. diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs index 37e84e884..5183f42f0 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs @@ -170,8 +170,8 @@ public class SkeletonUtility : MonoBehaviour { if (boneRoot != null) { List constraintTargetNames = new List(); - ExposedList ikConstraints = skeletonRenderer.skeleton.IkConstraints; - for (int i = 0, n = ikConstraints.Count; i < n; i++) + ExposedList ikConstraints = skeletonRenderer.skeleton.IkConstraints; + for (int i = 0, n = ikConstraints.Count; i < n; i++) constraintTargetNames.Add(ikConstraints.Items[n].Target.Data.Name); foreach (var b in utilityBones) { @@ -290,8 +290,8 @@ public class SkeletonUtility : MonoBehaviour { GameObject go = SpawnBone(bone, parent, mode, pos, rot, sca); ExposedList childrenBones = bone.Children; - for (int i = 0, n = childrenBones.Count; i < n; i++) { - Bone child = childrenBones.Items[i]; + for (int i = 0, n = childrenBones.Count; i < n; i++) { + Bone child = childrenBones.Items[i]; SpawnBoneRecursively(child, go.transform, mode, pos, rot, sca); } From 169ec1528599bcb3a29bae0cbc82940261e1cffe Mon Sep 17 00:00:00 2001 From: ZimM Date: Thu, 26 Feb 2015 06:34:31 +0200 Subject: [PATCH 03/24] reduce method calls overhead in SkeletonRenderer reduce GC pressure in SkeletonAnimator --- spine-csharp/src/Skeleton.cs | 14 ++- .../Assets/spine-unity/SkeletonAnimator.cs | 24 +++- .../Assets/spine-unity/SkeletonRenderer.cs | 103 +++++++++++------- 3 files changed, 91 insertions(+), 50 deletions(-) diff --git a/spine-csharp/src/Skeleton.cs b/spine-csharp/src/Skeleton.cs index c8c26df69..e92c4a7e6 100644 --- a/spine-csharp/src/Skeleton.cs +++ b/spine-csharp/src/Skeleton.cs @@ -139,12 +139,14 @@ namespace Spine { /// Updates the world transform for each bone and applies IK constraints. public void UpdateWorldTransform () { ExposedList bones = this.bones; - for (int ii = 0, nn = bones.Count; ii < nn; ii++) { - Bone bone = bones.Items[ii]; - bone.rotationIK = bone.rotation; - } - ExposedList> boneCache = this.boneCache; - ExposedList ikConstraints = this.ikConstraints; + ExposedList ikConstraints = this.ikConstraints; + if (ikConstraints.Count > 0) { + for (int ii = 0, nn = bones.Count; ii < nn; ii++) { + Bone bone = bones.Items[ii]; + bone.rotationIK = bone.rotation; + } + } + ExposedList> boneCache = this.boneCache; int i = 0, last = boneCache.Count - 1; while (true) { ExposedList updateBones = boneCache.Items[i]; diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs index 4adba2684..1017de4aa 100644 --- a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs +++ b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs @@ -63,6 +63,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { protected event UpdateBonesDelegate _UpdateComplete; Dictionary animationTable = new Dictionary(); + Dictionary clipNameTable = new Dictionary(); Animator animator; public override void Reset () { @@ -71,6 +72,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { return; animationTable.Clear(); + clipNameTable.Clear(); var data = skeletonDataAsset.GetSkeletonData(true); @@ -122,7 +124,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = stateInfo.normalizedTime * info.clip.length; - animationTable[info.clip.name].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight); + animationTable[GetAnimationClipName(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight); } foreach (var info in nextClipInfo) { @@ -131,7 +133,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = nextStateInfo.normalizedTime * info.clip.length; - animationTable[info.clip.name].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); + animationTable[GetAnimationClipName(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); } } else if (mode >= MixMode.MixNext) { //apply first non-zero weighted clip @@ -144,7 +146,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = stateInfo.normalizedTime * info.clip.length; - animationTable[info.clip.name].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null); + animationTable[GetAnimationClipName(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null); break; } @@ -156,7 +158,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = stateInfo.normalizedTime * info.clip.length; - animationTable[info.clip.name].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight); + animationTable[GetAnimationClipName(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight); } c = 0; @@ -170,7 +172,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = nextStateInfo.normalizedTime * info.clip.length; - animationTable[info.clip.name].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null); + animationTable[GetAnimationClipName(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null); break; } } @@ -183,7 +185,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = nextStateInfo.normalizedTime * info.clip.length; - animationTable[info.clip.name].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); + animationTable[GetAnimationClipName(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); } } } @@ -202,4 +204,14 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { _UpdateComplete(this); } } + + private string GetAnimationClipName(AnimationClip clip) { + string clipName; + if (!clipNameTable.TryGetValue(clip, out clipName)) { + clipName = clip.name; + clipNameTable.Add(clip, clipName); + } + + return clipName; + } } diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index 524e9ef12..900918be0 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -173,8 +173,9 @@ public class SkeletonRenderer : MonoBehaviour { int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; Material lastMaterial = null; submeshMaterials.Clear(); - ExposedList drawOrder = skeleton.DrawOrder; + ExposedList drawOrder = skeleton.drawOrder; int drawOrderCount = drawOrder.Count; + int submeshSeparatorSlotsCount = submeshSeparatorSlots.Count; bool renderMeshes = this.renderMeshes; for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder.Items[i]; @@ -183,33 +184,34 @@ public class SkeletonRenderer : MonoBehaviour { object rendererObject; int attachmentVertexCount, attachmentTriangleCount; - if (attachment is RegionAttachment) { - rendererObject = ((RegionAttachment)attachment).RendererObject; + RegionAttachment regionAttachment = attachment as RegionAttachment; + if (regionAttachment != null) { + rendererObject = regionAttachment.RendererObject; attachmentVertexCount = 4; attachmentTriangleCount = 6; } else { if (!renderMeshes) continue; - MeshAttachment meshAttachment = attachment as MeshAttachment; - if (meshAttachment != null) { + MeshAttachment meshAttachment = attachment as MeshAttachment; + if (meshAttachment != null) { rendererObject = meshAttachment.RendererObject; attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentTriangleCount = meshAttachment.triangles.Length; } else { - SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; - if (skinnedMeshAttachment != null) { - rendererObject = skinnedMeshAttachment.RendererObject; - attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1; - attachmentTriangleCount = skinnedMeshAttachment.triangles.Length; - } else - continue; - } + SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; + if (skinnedMeshAttachment != null) { + rendererObject = skinnedMeshAttachment.RendererObject; + attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1; + attachmentTriangleCount = skinnedMeshAttachment.triangles.Length; + } else + continue; + } } // Populate submesh when material changes. Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject; - - if ((lastMaterial != material && lastMaterial != null) || submeshSeparatorSlots.Contains(slot)) { + if ((lastMaterial != null && lastMaterial.GetInstanceID() != material.GetInstanceID()) || + (submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot))) { AddSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false); submeshTriangleCount = 0; submeshFirstVertex = vertexCount; @@ -258,15 +260,23 @@ public class SkeletonRenderer : MonoBehaviour { for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder.Items[i]; Attachment attachment = slot.attachment; - if (attachment is RegionAttachment) { - RegionAttachment regionAttachment = (RegionAttachment)attachment; + RegionAttachment regionAttachment = attachment as RegionAttachment; + if (regionAttachment != null) { regionAttachment.ComputeWorldVertices(slot.bone, tempVertices); float z = i * zSpacing; - vertices[vertexIndex] = new Vector3(tempVertices[RegionAttachment.X1], tempVertices[RegionAttachment.Y1], z); - vertices[vertexIndex + 1] = new Vector3(tempVertices[RegionAttachment.X4], tempVertices[RegionAttachment.Y4], z); - vertices[vertexIndex + 2] = new Vector3(tempVertices[RegionAttachment.X2], tempVertices[RegionAttachment.Y2], z); - vertices[vertexIndex + 3] = new Vector3(tempVertices[RegionAttachment.X3], tempVertices[RegionAttachment.Y3], z); + vertices[vertexIndex].x = tempVertices[RegionAttachment.X1]; + vertices[vertexIndex].y = tempVertices[RegionAttachment.Y1]; + vertices[vertexIndex].z = z; + vertices[vertexIndex + 1].x = tempVertices[RegionAttachment.X4]; + vertices[vertexIndex + 1].y = tempVertices[RegionAttachment.Y4]; + vertices[vertexIndex + 1].z = z; + vertices[vertexIndex + 2].x = tempVertices[RegionAttachment.X2]; + vertices[vertexIndex + 2].y = tempVertices[RegionAttachment.Y2]; + vertices[vertexIndex + 2].z = z; + vertices[vertexIndex + 3].x = tempVertices[RegionAttachment.X3]; + vertices[vertexIndex + 3].y = tempVertices[RegionAttachment.Y3]; + vertices[vertexIndex + 3].z = z; color.a = (byte)(a * slot.a * regionAttachment.a); color.r = (byte)(r * slot.r * regionAttachment.r * color.a); @@ -280,10 +290,14 @@ public class SkeletonRenderer : MonoBehaviour { colors[vertexIndex + 3] = color; float[] regionUVs = regionAttachment.uvs; - uvs[vertexIndex] = new Vector2(regionUVs[RegionAttachment.X1], regionUVs[RegionAttachment.Y1]); - uvs[vertexIndex + 1] = new Vector2(regionUVs[RegionAttachment.X4], regionUVs[RegionAttachment.Y4]); - uvs[vertexIndex + 2] = new Vector2(regionUVs[RegionAttachment.X2], regionUVs[RegionAttachment.Y2]); - uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]); + uvs[vertexIndex].x = regionUVs[RegionAttachment.X1]; + uvs[vertexIndex].y = regionUVs[RegionAttachment.Y1]; + uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4]; + uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4]; + uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2]; + uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2]; + uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3]; + uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3]; vertexIndex += 4; } else { @@ -306,9 +320,12 @@ public class SkeletonRenderer : MonoBehaviour { float[] meshUVs = meshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { - vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z); + vertices[vertexIndex].x = tempVertices[ii]; + vertices[vertexIndex].y = tempVertices[ii + 1]; + vertices[vertexIndex].z = z; colors[vertexIndex] = color; - uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]); + uvs[vertexIndex].x = meshUVs[ii]; + uvs[vertexIndex].y = meshUVs[ii + 1]; } } else if (attachment is SkinnedMeshAttachment) { SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; @@ -327,9 +344,12 @@ public class SkeletonRenderer : MonoBehaviour { float[] meshUVs = meshAttachment.uvs; float z = i * zSpacing; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { - vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z); + vertices[vertexIndex].x = tempVertices[ii]; + vertices[vertexIndex].y = tempVertices[ii + 1]; + vertices[vertexIndex].z = z; colors[vertexIndex] = color; - uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]); + uvs[vertexIndex].x = meshUVs[ii]; + uvs[vertexIndex].y = meshUVs[ii + 1]; } } } @@ -420,7 +440,12 @@ public class SkeletonRenderer : MonoBehaviour { Slot slot = drawOrder.Items[i]; Attachment attachment = slot.attachment; Bone bone = slot.bone; - bool flip = frontFacing && ((bone.WorldFlipX != bone.WorldFlipY) != (Mathf.Sign(bone.WorldScaleX) != Mathf.Sign(bone.WorldScaleY))); + + bool worldScaleXIsPositive = bone.worldScaleX >= 0f; + bool worldScaleYIsPositive = bone.worldScaleY >= 0f; + bool worldScaleIsSameSigns = (worldScaleXIsPositive && worldScaleYIsPositive) || + (!worldScaleXIsPositive && !worldScaleYIsPositive); + bool flip = frontFacing && ((bone.worldFlipX != bone.worldFlipY) != worldScaleIsSameSigns); if (attachment is RegionAttachment) { if (!flip) { @@ -445,16 +470,18 @@ public class SkeletonRenderer : MonoBehaviour { } int[] attachmentTriangles; int attachmentVertexCount; - if (attachment is MeshAttachment) { - MeshAttachment meshAttachment = (MeshAttachment)attachment; + MeshAttachment meshAttachment = attachment as MeshAttachment; + if (meshAttachment != null) { attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentTriangles = meshAttachment.triangles; - } else if (attachment is SkinnedMeshAttachment) { - SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; - attachmentVertexCount = meshAttachment.uvs.Length >> 1; - attachmentTriangles = meshAttachment.triangles; - } else - continue; + } else { + SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; + if (skinnedMeshAttachment != null) { + attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1; + attachmentTriangles = skinnedMeshAttachment.triangles; + } else + continue; + } if (flip) { for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii += 3, triangleIndex += 3) { From 0b86e3330a4a86bd1f4f0d258e488d1527a74699 Mon Sep 17 00:00:00 2001 From: ZimM Date: Thu, 26 Feb 2015 06:56:05 +0200 Subject: [PATCH 04/24] oops. spaces to tabs --- spine-csharp/src/Skeleton.cs | 16 ++++++++-------- .../Assets/spine-unity/SkeletonAnimator.cs | 18 +++++++++--------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/spine-csharp/src/Skeleton.cs b/spine-csharp/src/Skeleton.cs index e92c4a7e6..fbaeafe36 100644 --- a/spine-csharp/src/Skeleton.cs +++ b/spine-csharp/src/Skeleton.cs @@ -139,14 +139,14 @@ namespace Spine { /// Updates the world transform for each bone and applies IK constraints. public void UpdateWorldTransform () { ExposedList bones = this.bones; - ExposedList ikConstraints = this.ikConstraints; - if (ikConstraints.Count > 0) { - for (int ii = 0, nn = bones.Count; ii < nn; ii++) { - Bone bone = bones.Items[ii]; - bone.rotationIK = bone.rotation; - } - } - ExposedList> boneCache = this.boneCache; + ExposedList ikConstraints = this.ikConstraints; + if (ikConstraints.Count > 0) { + for (int ii = 0, nn = bones.Count; ii < nn; ii++) { + Bone bone = bones.Items[ii]; + bone.rotationIK = bone.rotation; + } + } + ExposedList> boneCache = this.boneCache; int i = 0, last = boneCache.Count - 1; while (true) { ExposedList updateBones = boneCache.Items[i]; diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs index 1017de4aa..cf147ee7c 100644 --- a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs +++ b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs @@ -72,7 +72,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { return; animationTable.Clear(); - clipNameTable.Clear(); + clipNameTable.Clear(); var data = skeletonDataAsset.GetSkeletonData(true); @@ -205,13 +205,13 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { } } - private string GetAnimationClipName(AnimationClip clip) { - string clipName; - if (!clipNameTable.TryGetValue(clip, out clipName)) { - clipName = clip.name; - clipNameTable.Add(clip, clipName); - } + private string GetAnimationClipName(AnimationClip clip) { + string clipName; + if (!clipNameTable.TryGetValue(clip, out clipName)) { + clipName = clip.name; + clipNameTable.Add(clip, clipName); + } - return clipName; - } + return clipName; + } } From 905890f7cafdb6db18a6e445eae3891b716e2761 Mon Sep 17 00:00:00 2001 From: ZimM Date: Thu, 26 Feb 2015 14:40:59 +0200 Subject: [PATCH 05/24] one more is + as -> as + null check --- .../Assets/spine-unity/SkeletonRenderer.cs | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index 900918be0..da10d6e9f 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -303,8 +303,8 @@ public class SkeletonRenderer : MonoBehaviour { } else { if (!renderMeshes) continue; - if (attachment is MeshAttachment) { - MeshAttachment meshAttachment = (MeshAttachment)attachment; + MeshAttachment meshAttachment = attachment as MeshAttachment; + if (meshAttachment != null) { int meshVertexCount = meshAttachment.vertices.Length; if (tempVertices.Length < meshVertexCount) this.tempVertices = tempVertices = new float[meshVertexCount]; @@ -327,29 +327,31 @@ public class SkeletonRenderer : MonoBehaviour { uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; } - } else if (attachment is SkinnedMeshAttachment) { - SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; - int meshVertexCount = meshAttachment.uvs.Length; - if (tempVertices.Length < meshVertexCount) - this.tempVertices = tempVertices = new float[meshVertexCount]; - meshAttachment.ComputeWorldVertices(slot, tempVertices); + } else { + SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; + if (skinnedMeshAttachment != null) { + int meshVertexCount = skinnedMeshAttachment.uvs.Length; + if (tempVertices.Length < meshVertexCount) + this.tempVertices = tempVertices = new float[meshVertexCount]; + skinnedMeshAttachment.ComputeWorldVertices(slot, tempVertices); - color.a = (byte)(a * slot.a * meshAttachment.a); - color.r = (byte)(r * slot.r * meshAttachment.r * color.a); - color.g = (byte)(g * slot.g * meshAttachment.g * color.a); - color.b = (byte)(b * slot.b * meshAttachment.b * color.a); - if (slot.data.additiveBlending) - color.a = 0; + color.a = (byte)(a * slot.a * skinnedMeshAttachment.a); + color.r = (byte)(r * slot.r * skinnedMeshAttachment.r * color.a); + color.g = (byte)(g * slot.g * skinnedMeshAttachment.g * color.a); + color.b = (byte)(b * slot.b * skinnedMeshAttachment.b * color.a); + if (slot.data.additiveBlending) + color.a = 0; - float[] meshUVs = meshAttachment.uvs; - float z = i * zSpacing; - for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { - vertices[vertexIndex].x = tempVertices[ii]; - vertices[vertexIndex].y = tempVertices[ii + 1]; - vertices[vertexIndex].z = z; - colors[vertexIndex] = color; - uvs[vertexIndex].x = meshUVs[ii]; - uvs[vertexIndex].y = meshUVs[ii + 1]; + float[] meshUVs = skinnedMeshAttachment.uvs; + float z = i * zSpacing; + for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { + vertices[vertexIndex].x = tempVertices[ii]; + vertices[vertexIndex].y = tempVertices[ii + 1]; + vertices[vertexIndex].z = z; + colors[vertexIndex] = color; + uvs[vertexIndex].x = meshUVs[ii]; + uvs[vertexIndex].y = meshUVs[ii + 1]; + } } } } From 9b6553fdb5fbbc0482244b7cae8c20a57b38a267 Mon Sep 17 00:00:00 2001 From: ZimM Date: Thu, 26 Feb 2015 17:36:29 +0200 Subject: [PATCH 06/24] replaced ExposedList by MIT licensed version from Mono project --- spine-csharp/src/ExposedList.cs | 1195 ++++++++++++++----------------- 1 file changed, 538 insertions(+), 657 deletions(-) diff --git a/spine-csharp/src/ExposedList.cs b/spine-csharp/src/ExposedList.cs index 03eaa6c23..62b1ed1f4 100644 --- a/spine-csharp/src/ExposedList.cs +++ b/spine-csharp/src/ExposedList.cs @@ -1,702 +1,583 @@ -using System; +// +// System.Collections.Generic.List +// +// Authors: +// Ben Maurer (bmaurer@ximian.com) +// Martin Baulig (martin@ximian.com) +// Carlos Alberto Cortez (calberto.cortez@gmail.com) +// David Waite (mass@akuma.org) +// +// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com) +// Copyright (C) 2005 David Waite +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections; using System.Collections.Generic; +using System.Diagnostics; namespace Spine { - /// - /// Represents a strongly typed list of objects that can be accessed by index. Provides methods to search and manipulate lists. - /// - /// The type of elements in the list. - public class ExposedList : IEnumerable { - private const int defaultCapacity = 4; - private static readonly T[] emptyArray = new T[0]; - public T[] Items; + [Serializable] + [DebuggerDisplay("Count={Count}")] + public class ExposedList : IEnumerable { + public T[] Items; + public int Count; - private int size; + private const int DefaultCapacity = 4; + private static readonly T[] EmptyArray = new T[0]; + private int _version; - /// - /// Initializes a new instance of the class that is empty and has the default initial capacity. - /// - public ExposedList() { - Items = emptyArray; - } + public ExposedList() { + Items = EmptyArray; + } - /// - /// Initializes a new instance of the class that is empty and has the specified initial capacity. - /// - /// The number of elements that the new list can initially store. - /// - /// is less than 0. - /// - public ExposedList(int capacity) { - if (capacity < 0) { - throw new ArgumentOutOfRangeException("capacity"); - } - Items = new T[capacity]; - } + public ExposedList(IEnumerable collection) { + CheckCollection(collection); - - // Constructs a List, copying the contents of the given collection. The - // size and capacity of the new list will both be equal to the size of the - // given collection. - // - public ExposedList(IEnumerable collection) { - if (collection==null) - throw new ArgumentNullException("collection"); + // initialize to needed size (if determinable) + ICollection c = collection as ICollection; + if (c == null) { + Items = EmptyArray; + AddEnumerable(collection); + } else { + Items = new T[c.Count]; + AddCollection(c); + } + } - ICollection c = collection as ICollection; - if( c != null) { - int count = c.Count; - Items = new T[count]; - c.CopyTo(Items, 0); - size = count; - } - else { - size = 0; - Items = new T[defaultCapacity]; + public ExposedList(int capacity) { + if (capacity < 0) + throw new ArgumentOutOfRangeException("capacity"); + Items = new T[capacity]; + } - using(IEnumerator en = collection.GetEnumerator()) { - while(en.MoveNext()) { - Add(en.Current); - } - } - } - } + internal ExposedList(T[] data, int size) { + Items = data; + Count = size; + } - /// - /// Gets or sets the total number of elements the internal data structure can hold without resizing. - /// - /// - /// The number of elements that the can contain before resizing is required. - /// - /// - /// is set to a value that is less than - /// - /// . - /// - /// There is not enough memory available on the system. - public int Capacity { - get { - return Items.Length; - } - set { - if (value == Items.Length) { - return; - } - if (value < size) { - throw new ArgumentOutOfRangeException("value"); - } - if (value > 0) { - var objArray = new T[value]; - if (size > 0) { - Array.Copy(Items, 0, objArray, 0, size); - } - Items = objArray; - } else { - Items = emptyArray; - } - } - } + public void Add(T item) { + // If we check to see if we need to grow before trying to grow + // we can speed things up by 25% + if (Count == Items.Length) + GrowIfNeeded(1); + Items[Count ++] = item; + _version++; + } - /// - /// Gets the number of elements actually contained in the . - /// - /// - /// The number of elements actually contained in the . - /// - public int Count { - get { - return size; - } - } + private void GrowIfNeeded(int newCount) { + int minimumSize = Count + newCount; + if (minimumSize > Items.Length) + Capacity = Math.Max(Math.Max(Capacity * 2, DefaultCapacity), minimumSize); + } - /// - /// Adds an object to the end of the . - /// - /// - /// The object to be added to the end of the . The value can be null for reference types. - /// - public void Add(T item) { - if (size == Items.Length) { - EnsureCapacity(size + 1); - } - Items[size++] = item; - } + private void CheckRange(int idx, int count) { + if (idx < 0) + throw new ArgumentOutOfRangeException("index"); - /// - /// Removes all elements from the . - /// - public void Clear() { - if (size > 0) { - Array.Clear(Items, 0, size); - size = 0; - } - } + if (count < 0) + throw new ArgumentOutOfRangeException("count"); - /// - /// Determines whether an element is in the . - /// - /// - /// true if is found in the ; otherwise, false. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - public bool Contains(T item) { - if (item == null) { - for (int index = 0; index < size; ++index) { - if (Items[index] == null) { - return true; - } - } - return false; - } else { - EqualityComparer @default = EqualityComparer.Default; - for (int index = 0; index < size; ++index) { - if (@default.Equals(Items[index], item)) { - return true; - } - } - return false; - } - } + if ((uint) idx + (uint) count > (uint) Count) + throw new ArgumentException("index and count exceed length of list"); + } - /// - /// Copies the entire to a compatible one-dimensional array, starting at the specified index of the target array. - /// - /// - /// The one-dimensional that is the destination of the elements copied from - /// - /// . The must have zero-based indexing. - /// - /// - /// The zero-based index in at which copying begins. - /// - /// - /// is null. - /// - /// - /// is less than 0. - /// - /// - /// The number of elements in the source is greater than the available space from - /// - /// to the end of the destination . - /// - public void CopyTo(T[] array, int arrayIndex) { - Array.Copy(Items, 0, array, arrayIndex, size); - } + private void AddCollection(ICollection collection) { + int collectionCount = collection.Count; + if (collectionCount == 0) + return; - /// - /// Searches for the specified object and returns the zero-based index of the first occurrence within the entire - /// - /// . - /// - /// - /// The zero-based index of the first occurrence of within the entire - /// - /// , if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - public int IndexOf(T item) { - return Array.IndexOf(Items, item, 0, size); - } + GrowIfNeeded(collectionCount); + collection.CopyTo(Items, Count); + Count += collectionCount; + } - /// - /// Inserts an element into the at the specified index. - /// - /// - /// The zero-based index at which should be inserted. - /// - /// The object to insert. The value can be null for reference types. - /// - /// is less than 0.-or- is greater than - /// - /// . - /// - public void Insert(int index, T item) { - if ((uint) index > (uint) size) { - throw new ArgumentOutOfRangeException("index"); - } - if (size == Items.Length) { - EnsureCapacity(size + 1); - } - if (index < size) { - Array.Copy(Items, index, Items, index + 1, size - index); - } - Items[index] = item; - ++size; - } + private void AddEnumerable(IEnumerable enumerable) { + foreach (T t in enumerable) { + Add(t); + } + } - /// - /// Removes the first occurrence of a specific object from the . - /// - /// - /// true if is successfully removed; otherwise, false. This method also returns false if - /// - /// was not found in the . - /// - /// - /// The object to remove from the . The value can be null for reference types. - /// - public bool Remove(T item) { - int index = IndexOf(item); - if (index < 0) { - return false; - } - RemoveAt(index); - return true; - } + public void AddRange(IEnumerable collection) { + CheckCollection(collection); - /// - /// Removes the element at the specified index of the . - /// - /// The zero-based index of the element to remove. - /// - /// is less than 0.-or- is equal to or greater than - /// - /// . - /// - public void RemoveAt(int index) { - if ((uint) index >= (uint) size) { - throw new ArgumentOutOfRangeException(); - } - --size; - if (index < size) { - Array.Copy(Items, index + 1, Items, index, size - index); - } - Items[size] = default (T); - } + ICollection c = collection as ICollection; + if (c != null) + AddCollection(c); + else + AddEnumerable(collection); + _version++; + } - /// - /// Copies the entire to a compatible one-dimensional array, starting at the beginning of the target array. - /// - /// - /// The one-dimensional that is the destination of the elements copied from - /// - /// . The must have zero-based indexing. - /// - /// - /// is null. - /// - /// - /// The number of elements in the source is greater than the number of elements that the destination - /// - /// can contain. - /// - public void CopyTo(T[] array) { - CopyTo(array, 0); - } + public int BinarySearch(T item) { + return Array.BinarySearch(Items, 0, Count, item); + } - /// - /// Copies a range of elements from the to a compatible one-dimensional array, starting at the specified index of the target array. - /// - /// - /// The zero-based index in the source at which copying begins. - /// - /// - /// The one-dimensional that is the destination of the elements copied from - /// - /// . The must have zero-based indexing. - /// - /// - /// The zero-based index in at which copying begins. - /// - /// The number of elements to copy. - /// - /// is null. - /// - /// - /// is less than 0.-or- is less than 0.-or- - /// - /// is less than 0. - /// - /// - /// is equal to or greater than the of the source - /// - /// .-or-The number of elements from to the end of the source - /// - /// is greater than the available space from - /// - /// to the end of the destination . - /// - public void CopyTo(int index, T[] array, int arrayIndex, int count) { - if (size - index < count) { - throw new ArgumentException("Invalid length"); - } - Array.Copy(Items, index, array, arrayIndex, count); - } + public int BinarySearch(T item, IComparer comparer) { + return Array.BinarySearch(Items, 0, Count, item, comparer); + } - private void EnsureCapacity(int min) { - if (Items.Length >= min) { - return; - } - int num = Items.Length == 0 ? 4 : Items.Length * 2; - if (num < min) { - num = min; - } - Capacity = num; - } + public int BinarySearch(int index, int count, T item, IComparer comparer) { + CheckRange(index, count); + return Array.BinarySearch(Items, index, count, item, comparer); + } - /// - /// Creates a shallow copy of a range of elements in the source . - /// - /// - /// A shallow copy of a range of elements in the source . - /// - /// - /// The zero-based index at which the range starts. - /// - /// The number of elements in the range. - /// - /// is less than 0.-or- is less than 0. - /// - /// - /// and do not denote a valid range of elements in the - /// - /// . - /// - public ExposedList GetRange(int index, int count) { - if (index < 0 || count < 0) { - throw new ArgumentOutOfRangeException("index || count"); - } - if (size - index < count) { - throw new ArgumentException("Invalid length"); - } - var list = new ExposedList(count); - Array.Copy(Items, index, list.Items, 0, count); - list.size = count; - return list; - } + public void Clear() { + Array.Clear(Items, 0, Items.Length); + Count = 0; + _version++; + } - /// - /// Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the - /// - /// that extends from the specified index to the last element. - /// - /// - /// The zero-based index of the first occurrence of within the range of elements in the - /// - /// that extends from to the last element, if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - /// The zero-based starting index of the search. 0 (zero) is valid in an empty list. - /// - /// is outside the range of valid indexes for the - /// - /// . - /// - public int IndexOf(T item, int index) { - if (index > size) { - throw new ArgumentOutOfRangeException("index"); - } - return Array.IndexOf(Items, item, index, size - index); - } + public bool Contains(T item) { + return Array.IndexOf(Items, item, 0, Count) != -1; + } - /// - /// Searches for the specified object and returns the zero-based index of the first occurrence within the range of elements in the - /// - /// that starts at the specified index and contains the specified number of elements. - /// - /// - /// The zero-based index of the first occurrence of within the range of elements in the - /// - /// that starts at and contains - /// - /// number of elements, if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - /// The zero-based starting index of the search. 0 (zero) is valid in an empty list. - /// The number of elements in the section to search. - /// - /// is outside the range of valid indexes for the - /// - /// .-or- is less than 0.-or- - /// - /// and do not specify a valid section in the - /// - /// . - /// - public int IndexOf(T item, int index, int count) { - if (index > size) { - throw new ArgumentOutOfRangeException("index"); - } - if (count < 0 || index > size - count) { - throw new ArgumentOutOfRangeException("count"); - } - return Array.IndexOf(Items, item, index, count); - } + public ExposedList ConvertAll(Converter converter) { + if (converter == null) + throw new ArgumentNullException("converter"); + ExposedList u = new ExposedList(Count); + for (int i = 0; i < Count; i++) + u.Items[i] = converter(Items[i]); - /// - /// Searches for the specified object and returns the zero-based index of the last occurrence within the entire - /// - /// . - /// - /// - /// The zero-based index of the last occurrence of within the entire the - /// - /// , if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - public int LastIndexOf(T item) { - return LastIndexOf(item, size - 1, size); - } + u.Count = Count; + return u; + } - /// - /// Searches for the specified object and returns the zero-based index of the last occurrence within the range of elements in the - /// - /// that extends from the first element to the specified index. - /// - /// - /// The zero-based index of the last occurrence of within the range of elements in the - /// - /// that extends from the first element to , if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - /// The zero-based starting index of the backward search. - /// - /// is outside the range of valid indexes for the - /// - /// . - /// - public int LastIndexOf(T item, int index) { - if (index >= size) { - throw new ArgumentOutOfRangeException("index"); - } - return LastIndexOf(item, index, index + 1); - } + public void CopyTo(T[] array) { + Array.Copy(Items, 0, array, 0, Count); + } - /// - /// Searches for the specified object and returns the zero-based index of the last occurrence within the range of elements in the - /// - /// that contains the specified number of elements and ends at the specified index. - /// - /// - /// The zero-based index of the last occurrence of within the range of elements in the - /// - /// that contains number of elements and ends at - /// - /// , if found; otherwise, –1. - /// - /// - /// The object to locate in the . The value can be null for reference types. - /// - /// The zero-based starting index of the backward search. - /// The number of elements in the section to search. - /// - /// is outside the range of valid indexes for the - /// - /// .-or- is less than 0.-or- - /// - /// and do not specify a valid section in the - /// - /// . - /// - public int LastIndexOf(T item, int index, int count) { - if (size == 0) { - return -1; - } - if (index < 0 || count < 0) { - throw new ArgumentOutOfRangeException("index || count"); - } - if (index >= size || count > index + 1) { - throw new ArgumentOutOfRangeException("size || count"); - } - return Array.LastIndexOf(Items, item, index, count); - } + public void CopyTo(T[] array, int arrayIndex) { + Array.Copy(Items, 0, array, arrayIndex, Count); + } - /// - /// Removes a range of elements from the . - /// - /// The zero-based starting index of the range of elements to remove. - /// The number of elements to remove. - /// - /// is less than 0.-or- is less than 0. - /// - /// - /// and do not denote a valid range of elements in the - /// - /// . - /// - public void RemoveRange(int index, int count) { - if (index < 0 || count < 0) { - throw new ArgumentOutOfRangeException("index || count"); - } - if (size - index < count) { - throw new ArgumentException("Invalid length"); - } - if (count <= 0) { - return; - } - size -= count; - if (index < size) { - Array.Copy(Items, index + count, Items, index, size - index); - } - Array.Clear(Items, size, count); - } + public void CopyTo(int index, T[] array, int arrayIndex, int count) { + CheckRange(index, count); + Array.Copy(Items, index, array, arrayIndex, count); + } - public void TrimExcess() { - int threshold = (int)(((double) Items.Length) * 0.9); - if( size < threshold ) { - Capacity = size; - } - } + public bool Exists(Predicate match) { + CheckMatch(match); + return GetIndex(0, Count, match) != -1; + } - //public void Sort(Comparison comparison) - //{ - // if (comparison == null) - // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); - // if (this.size <= 0) - // return; - // Array.Sort(this._items, 0, this.size, (IComparer) new Array.FunctorComparer(comparison)); - //} + public T Find(Predicate match) { + CheckMatch(match); + int i = GetIndex(0, Count, match); + return (i != -1) ? Items[i] : default (T); + } - /// - /// Sorts the elements in the entire using the specified - /// - /// . - /// - /// - /// The to use when comparing elements. - /// - /// - /// is null. - /// - /// - /// The implementation of caused an error during the sort. For example, - /// - /// might not return 0 when comparing an item with itself. - /// - /// - /// Copies the elements of the to a new array. - /// - /// - /// An array containing copies of the elements of the . - /// - public T[] ToArray() { - var objArray = new T[size]; - Array.Copy(Items, 0, objArray, 0, size); - return objArray; - } + private static void CheckMatch(Predicate match) { + if (match == null) + throw new ArgumentNullException("match"); + } - // Returns an enumerator for this list with the given - // permission for removal of elements. If modifications made to the list - // while an enumeration is in progress, the MoveNext and - // GetObject methods of the enumerator will throw an exception. - // - public Enumerator GetEnumerator() { - return new Enumerator(this); - } + public ExposedList FindAll(Predicate match) { + CheckMatch(match); + return FindAllList(match); + } - IEnumerator IEnumerable.GetEnumerator() { - return new Enumerator(this); - } + private ExposedList FindAllList(Predicate match) { + ExposedList results = new ExposedList(); + for (int i = 0; i < Count; i++) + if (match(Items[i])) + results.Add(Items[i]); - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { - return new Enumerator(this); - } + return results; + } - [Serializable()] - public struct Enumerator : IEnumerator, System.Collections.IEnumerator - { - private readonly ExposedList list; - private int index; - private T current; - - internal Enumerator(ExposedList list) { - this.list = list; - index = 0; - current = default(T); - } + public int FindIndex(Predicate match) { + CheckMatch(match); + return GetIndex(0, Count, match); + } - public void Dispose() { - } + public int FindIndex(int startIndex, Predicate match) { + CheckMatch(match); + CheckIndex(startIndex); + return GetIndex(startIndex, Count - startIndex, match); + } - public bool MoveNext() { - ExposedList localList = list; + public int FindIndex(int startIndex, int count, Predicate match) { + CheckMatch(match); + CheckRange(startIndex, count); + return GetIndex(startIndex, count, match); + } - if (((uint)index < (uint)localList.size)) { - current = localList.Items[index]; - index++; - return true; - } - return MoveNextRare(); - } + private int GetIndex(int startIndex, int count, Predicate match) { + int end = startIndex + count; + for (int i = startIndex; i < end; i ++) + if (match(Items[i])) + return i; - private bool MoveNextRare() - { - index = list.size + 1; - current = default(T); - return false; - } + return -1; + } - public T Current { - get { - return current; - } - } + public T FindLast(Predicate match) { + CheckMatch(match); + int i = GetLastIndex(0, Count, match); + return i == -1 ? default (T) : Items[i]; + } - Object System.Collections.IEnumerator.Current { - get { - if( index == 0 || index == list.size + 1) - throw new InvalidOperationException(); - return Current; - } - } + public int FindLastIndex(Predicate match) { + CheckMatch(match); + return GetLastIndex(0, Count, match); + } - void System.Collections.IEnumerator.Reset() { - index = 0; - current = default(T); - } + public int FindLastIndex(int startIndex, Predicate match) { + CheckMatch(match); + CheckIndex(startIndex); + return GetLastIndex(0, startIndex + 1, match); + } - } - } + public int FindLastIndex(int startIndex, int count, Predicate match) { + CheckMatch(match); + int start = startIndex - count + 1; + CheckRange(start, count); + return GetLastIndex(start, count, match); + } + + private int GetLastIndex(int startIndex, int count, Predicate match) { + // unlike FindLastIndex, takes regular params for search range + for (int i = startIndex + count; i != startIndex;) + if (match(Items[--i])) + return i; + return -1; + } + + public void ForEach(Action action) { + if (action == null) + throw new ArgumentNullException("action"); + for (int i = 0; i < Count; i++) + action(Items[i]); + } + + public Enumerator GetEnumerator() { + return new Enumerator(this); + } + + public ExposedList GetRange(int index, int count) { + CheckRange(index, count); + T[] tmpArray = new T[count]; + Array.Copy(Items, index, tmpArray, 0, count); + return new ExposedList(tmpArray, count); + } + + public int IndexOf(T item) { + return Array.IndexOf(Items, item, 0, Count); + } + + public int IndexOf(T item, int index) { + CheckIndex(index); + return Array.IndexOf(Items, item, index, Count - index); + } + + public int IndexOf(T item, int index, int count) { + if (index < 0) + throw new ArgumentOutOfRangeException("index"); + + if (count < 0) + throw new ArgumentOutOfRangeException("count"); + + if ((uint) index + (uint) count > (uint) Count) + throw new ArgumentOutOfRangeException("index and count exceed length of list"); + + return Array.IndexOf(Items, item, index, count); + } + + private void Shift(int start, int delta) { + if (delta < 0) + start -= delta; + + if (start < Count) + Array.Copy(Items, start, Items, start + delta, Count - start); + + Count += delta; + + if (delta < 0) + Array.Clear(Items, Count, -delta); + } + + private void CheckIndex(int index) { + if (index < 0 || (uint) index > (uint) Count) + throw new ArgumentOutOfRangeException("index"); + } + + public void Insert(int index, T item) { + CheckIndex(index); + if (Count == Items.Length) + GrowIfNeeded(1); + Shift(index, 1); + Items[index] = item; + _version++; + } + + private void CheckCollection(IEnumerable collection) { + if (collection == null) + throw new ArgumentNullException("collection"); + } + + public void InsertRange(int index, IEnumerable collection) { + CheckCollection(collection); + CheckIndex(index); + if (collection == this) { + T[] buffer = new T[Count]; + CopyTo(buffer, 0); + GrowIfNeeded(Count); + Shift(index, buffer.Length); + Array.Copy(buffer, 0, Items, index, buffer.Length); + } else { + ICollection c = collection as ICollection; + if (c != null) + InsertCollection(index, c); + else + InsertEnumeration(index, collection); + } + _version++; + } + + private void InsertCollection(int index, ICollection collection) { + int collectionCount = collection.Count; + GrowIfNeeded(collectionCount); + + Shift(index, collectionCount); + collection.CopyTo(Items, index); + } + + private void InsertEnumeration(int index, IEnumerable enumerable) { + foreach (T t in enumerable) + Insert(index++, t); + } + + public int LastIndexOf(T item) { + return Array.LastIndexOf(Items, item, Count - 1, Count); + } + + public int LastIndexOf(T item, int index) { + CheckIndex(index); + return Array.LastIndexOf(Items, item, index, index + 1); + } + + public int LastIndexOf(T item, int index, int count) { + if (index < 0) + throw new ArgumentOutOfRangeException("index", index, "index is negative"); + + if (count < 0) + throw new ArgumentOutOfRangeException("count", count, "count is negative"); + + if (index - count + 1 < 0) + throw new ArgumentOutOfRangeException("count", count, "count is too large"); + + return Array.LastIndexOf(Items, item, index, count); + } + + public bool Remove(T item) { + int loc = IndexOf(item); + if (loc != -1) + RemoveAt(loc); + + return loc != -1; + } + + public int RemoveAll(Predicate match) { + CheckMatch(match); + int i = 0; + int j = 0; + + // Find the first item to remove + for (i = 0; i < Count; i++) + if (match(Items[i])) + break; + + if (i == Count) + return 0; + + _version++; + + // Remove any additional items + for (j = i + 1; j < Count; j++) { + if (!match(Items[j])) + Items[i++] = Items[j]; + } + if (j - i > 0) + Array.Clear(Items, i, j - i); + + Count = i; + return (j - i); + } + + public void RemoveAt(int index) { + if (index < 0 || (uint) index >= (uint) Count) + throw new ArgumentOutOfRangeException("index"); + Shift(index, -1); + Array.Clear(Items, Count, 1); + _version++; + } + + public void RemoveRange(int index, int count) { + CheckRange(index, count); + if (count > 0) { + Shift(index, -count); + Array.Clear(Items, Count, count); + _version++; + } + } + + public void Reverse() { + Array.Reverse(Items, 0, Count); + _version++; + } + + public void Reverse(int index, int count) { + CheckRange(index, count); + Array.Reverse(Items, index, count); + _version++; + } + + public void Sort() { + Array.Sort(Items, 0, Count, Comparer.Default); + _version++; + } + + public void Sort(IComparer comparer) { + Array.Sort(Items, 0, Count, comparer); + _version++; + } + + public void Sort(Comparison comparison) { + Array.Sort(Items, comparison); + _version++; + } + + public void Sort(int index, int count, IComparer comparer) { + CheckRange(index, count); + Array.Sort(Items, index, count, comparer); + _version++; + } + + public T[] ToArray() { + T[] t = new T[Count]; + Array.Copy(Items, t, Count); + + return t; + } + + public void TrimExcess() { + Capacity = Count; + } + + public bool TrueForAll(Predicate match) { + CheckMatch(match); + + for (int i = 0; i < Count; i++) + if (!match(Items[i])) + return false; + + return true; + } + + public int Capacity { + get { + return Items.Length; + } + set { + if ((uint) value < (uint) Count) + throw new ArgumentOutOfRangeException(); + + Array.Resize(ref Items, value); + } + } + + #region Interface implementations. + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + #endregion + + [Serializable] + public struct Enumerator : IEnumerator, IDisposable { + private ExposedList l; + private int next; + private int ver; + + private T current; + + internal Enumerator(ExposedList l) + : this() { + this.l = l; + ver = l._version; + } + + public void Dispose() { + l = null; + } + + private void VerifyState() { + if (l == null) + throw new ObjectDisposedException(GetType().FullName); + if (ver != l._version) + throw new InvalidOperationException( + "Collection was modified; enumeration operation may not execute."); + } + + public bool MoveNext() { + VerifyState(); + + if (next < 0) + return false; + + if (next < l.Count) { + current = l.Items[next++]; + return true; + } + + next = -1; + return false; + } + + public T Current { + get { + return current; + } + } + + void IEnumerator.Reset() { + VerifyState(); + next = 0; + } + + object IEnumerator.Current { + get { + VerifyState(); + if (next <= 0) + throw new InvalidOperationException(); + return current; + } + } + } + } } \ No newline at end of file From 990d8d3016298cd10ea2caf536a57ef2947d63d4 Mon Sep 17 00:00:00 2001 From: ZimM Date: Thu, 26 Feb 2015 17:36:52 +0200 Subject: [PATCH 07/24] fix regression --- spine-csharp/src/Skeleton.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/spine-csharp/src/Skeleton.cs b/spine-csharp/src/Skeleton.cs index fbaeafe36..c8c26df69 100644 --- a/spine-csharp/src/Skeleton.cs +++ b/spine-csharp/src/Skeleton.cs @@ -139,14 +139,12 @@ namespace Spine { /// Updates the world transform for each bone and applies IK constraints. public void UpdateWorldTransform () { ExposedList bones = this.bones; - ExposedList ikConstraints = this.ikConstraints; - if (ikConstraints.Count > 0) { - for (int ii = 0, nn = bones.Count; ii < nn; ii++) { - Bone bone = bones.Items[ii]; - bone.rotationIK = bone.rotation; - } + for (int ii = 0, nn = bones.Count; ii < nn; ii++) { + Bone bone = bones.Items[ii]; + bone.rotationIK = bone.rotation; } ExposedList> boneCache = this.boneCache; + ExposedList ikConstraints = this.ikConstraints; int i = 0, last = boneCache.Count - 1; while (true) { ExposedList updateBones = boneCache.Items[i]; From b07e24f910b7520b413fb701be9988d5820363db Mon Sep 17 00:00:00 2001 From: ZimM Date: Thu, 26 Feb 2015 18:07:36 +0200 Subject: [PATCH 08/24] replaced Mesh.RecalculateBounds() in SkeletonRenderer with manual calculation, since we're going through all the vertices anyway optimized SkeletonRenderer.OnDrawGizmos --- .../Assets/spine-unity/SkeletonRenderer.cs | 112 ++++++++++++++---- 1 file changed, 92 insertions(+), 20 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index da10d6e9f..e24414531 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -69,8 +69,8 @@ public class SkeletonRenderer : MonoBehaviour { private Color32[] colors; private Vector2[] uvs; private Material[] sharedMaterials = new Material[0]; - private readonly List submeshMaterials = new List(); - private readonly List submeshes = new List(); + private readonly ExposedList submeshMaterials = new ExposedList(); + private readonly ExposedList submeshes = new ExposedList(); public virtual void Reset () { @@ -250,6 +250,14 @@ public class SkeletonRenderer : MonoBehaviour { lastVertexCount = vertexCount; // Setup mesh. + Vector3 meshBoundsMin; + meshBoundsMin.x = float.MaxValue; + meshBoundsMin.y = float.MaxValue; + meshBoundsMin.z = float.MaxValue; + Vector3 meshBoundsMax; + meshBoundsMax.x = float.MinValue; + meshBoundsMax.y = float.MinValue; + meshBoundsMax.z = float.MinValue; float[] tempVertices = this.tempVertices; Vector2[] uvs = this.uvs; Color32[] colors = this.colors; @@ -299,6 +307,48 @@ public class SkeletonRenderer : MonoBehaviour { uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3]; uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3]; + // Calculate min/max X + if (tempVertices[RegionAttachment.X1] < meshBoundsMin.x) + meshBoundsMin.x = tempVertices[RegionAttachment.X1]; + else if (tempVertices[RegionAttachment.X1] > meshBoundsMax.x) + meshBoundsMax.x = tempVertices[RegionAttachment.X1]; + if (tempVertices[RegionAttachment.X2] < meshBoundsMin.x) + meshBoundsMin.x = tempVertices[RegionAttachment.X2]; + else if (tempVertices[RegionAttachment.X2] > meshBoundsMax.x) + meshBoundsMax.x = tempVertices[RegionAttachment.X2]; + if (tempVertices[RegionAttachment.X3] < meshBoundsMin.x) + meshBoundsMin.x = tempVertices[RegionAttachment.X3]; + else if (tempVertices[RegionAttachment.X3] > meshBoundsMax.x) + meshBoundsMax.x = tempVertices[RegionAttachment.X3]; + if (tempVertices[RegionAttachment.X4] < meshBoundsMin.x) + meshBoundsMin.x = tempVertices[RegionAttachment.X4]; + else if (tempVertices[RegionAttachment.X4] > meshBoundsMax.x) + meshBoundsMax.x = tempVertices[RegionAttachment.X4]; + + // Calculate min/max Y + if (tempVertices[RegionAttachment.Y1] < meshBoundsMin.y) + meshBoundsMin.y = tempVertices[RegionAttachment.Y1]; + else if (tempVertices[RegionAttachment.Y1] > meshBoundsMax.y) + meshBoundsMax.y = tempVertices[RegionAttachment.Y1]; + if (tempVertices[RegionAttachment.Y2] < meshBoundsMin.y) + meshBoundsMin.y = tempVertices[RegionAttachment.Y2]; + else if (tempVertices[RegionAttachment.Y2] > meshBoundsMax.y) + meshBoundsMax.y = tempVertices[RegionAttachment.Y2]; + if (tempVertices[RegionAttachment.Y3] < meshBoundsMin.y) + meshBoundsMin.y = tempVertices[RegionAttachment.Y3]; + else if (tempVertices[RegionAttachment.Y3] > meshBoundsMax.y) + meshBoundsMax.y = tempVertices[RegionAttachment.Y3]; + if (tempVertices[RegionAttachment.Y4] < meshBoundsMin.y) + meshBoundsMin.y = tempVertices[RegionAttachment.Y4]; + else if (tempVertices[RegionAttachment.Y4] > meshBoundsMax.y) + meshBoundsMax.y = tempVertices[RegionAttachment.Y4]; + + // Calculate min/max Z + if (z < meshBoundsMin.z) + meshBoundsMin.z = z; + else if (z > meshBoundsMax.z) + meshBoundsMax.z = z; + vertexIndex += 4; } else { if (!renderMeshes) @@ -326,6 +376,19 @@ public class SkeletonRenderer : MonoBehaviour { colors[vertexIndex] = color; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; + + if (tempVertices[ii] < meshBoundsMin.x) + meshBoundsMin.x = tempVertices[ii]; + else if (tempVertices[ii] > meshBoundsMax.x) + meshBoundsMax.x = tempVertices[ii]; + if (tempVertices[ii + 1]< meshBoundsMin.y) + meshBoundsMin.y = tempVertices[ii + 1]; + else if (tempVertices[ii + 1] > meshBoundsMax.y) + meshBoundsMax.y = tempVertices[ii + 1]; + if (z < meshBoundsMin.z) + meshBoundsMin.z = z; + else if (z > meshBoundsMax.z) + meshBoundsMax.z = z; } } else { SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; @@ -351,6 +414,19 @@ public class SkeletonRenderer : MonoBehaviour { colors[vertexIndex] = color; uvs[vertexIndex].x = meshUVs[ii]; uvs[vertexIndex].y = meshUVs[ii + 1]; + + if (tempVertices[ii] < meshBoundsMin.x) + meshBoundsMin.x = tempVertices[ii]; + else if (tempVertices[ii] > meshBoundsMax.x) + meshBoundsMax.x = tempVertices[ii]; + if (tempVertices[ii + 1]< meshBoundsMin.y) + meshBoundsMin.y = tempVertices[ii + 1]; + else if (tempVertices[ii + 1] > meshBoundsMax.y) + meshBoundsMax.y = tempVertices[ii + 1]; + if (z < meshBoundsMin.z) + meshBoundsMin.z = z; + else if (z > meshBoundsMax.z) + meshBoundsMax.z = z; } } } @@ -368,8 +444,10 @@ public class SkeletonRenderer : MonoBehaviour { int submeshCount = submeshMaterials.Count; mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; ++i) - mesh.SetTriangles(submeshes[i].triangles, i); - mesh.RecalculateBounds(); + mesh.SetTriangles(submeshes.Items[i].triangles, i); + + Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin; + mesh.bounds = new Bounds(meshBoundsMin + meshBoundsExtents * 0.5f, meshBoundsExtents); if (newTriangles && calculateNormals) { Vector3[] normals = new Vector3[vertexCount]; @@ -403,7 +481,7 @@ public class SkeletonRenderer : MonoBehaviour { else if (immutableTriangles) return; - Submesh submesh = submeshes[submeshIndex]; + Submesh submesh = submeshes.Items[submeshIndex]; int[] triangles = submesh.triangles; int trianglesCapacity = triangles.Length; @@ -504,22 +582,16 @@ public class SkeletonRenderer : MonoBehaviour { #if UNITY_EDITOR void OnDrawGizmos () { // Make selection easier by drawing a clear gizmo over the skeleton. - if (vertices == null) return; - Vector3 gizmosCenter = new Vector3(); - Vector3 gizmosSize = new Vector3(); - Vector3 min = new Vector3(float.MaxValue, float.MaxValue, 0f); - Vector3 max = new Vector3(float.MinValue, float.MinValue, 0f); - foreach (Vector3 vert in vertices) { - min = Vector3.Min(min, vert); - max = Vector3.Max(max, vert); - } - float width = max.x - min.x; - float height = max.y - min.y; - gizmosCenter = new Vector3(min.x + (width / 2f), min.y + (height / 2f), 0f); - gizmosSize = new Vector3(width, height, 1f); - Gizmos.color = Color.clear; + meshFilter = GetComponent(); + if (meshFilter == null) return; + + Mesh mesh = meshFilter.sharedMesh; + if (mesh == null) return; + + Bounds meshBounds = mesh.bounds; + Gizmos.color = Color.red; Gizmos.matrix = transform.localToWorldMatrix; - Gizmos.DrawCube(gizmosCenter, gizmosSize); + Gizmos.DrawCube(meshBounds.center, meshBounds.size); } #endif } From 77b5f36336084fb8a48035c87d463831d924311d Mon Sep 17 00:00:00 2001 From: ZimM Date: Thu, 26 Feb 2015 23:29:53 +0200 Subject: [PATCH 09/24] derp. forgot to revert Gizmo color. do not calculate alpha when using additive blending --- spine-unity/Assets/spine-unity/SkeletonRenderer.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index e24414531..883021ef9 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -286,12 +286,11 @@ public class SkeletonRenderer : MonoBehaviour { vertices[vertexIndex + 3].y = tempVertices[RegionAttachment.Y3]; vertices[vertexIndex + 3].z = z; - color.a = (byte)(a * slot.a * regionAttachment.a); + color.a = slot.data.additiveBlending ? (byte) 0 : (byte)(a * slot.a * regionAttachment.a); color.r = (byte)(r * slot.r * regionAttachment.r * color.a); color.g = (byte)(g * slot.g * regionAttachment.g * color.a); color.b = (byte)(b * slot.b * regionAttachment.b * color.a); - if (slot.data.additiveBlending) - color.a = 0; + colors[vertexIndex] = color; colors[vertexIndex + 1] = color; colors[vertexIndex + 2] = color; @@ -589,7 +588,7 @@ public class SkeletonRenderer : MonoBehaviour { if (mesh == null) return; Bounds meshBounds = mesh.bounds; - Gizmos.color = Color.red; + Gizmos.color = Color.clear; Gizmos.matrix = transform.localToWorldMatrix; Gizmos.DrawCube(meshBounds.center, meshBounds.size); } From cdaa7c7460a0c0a38d4cb4e467020faf41fd2e07 Mon Sep 17 00:00:00 2001 From: ZimM Date: Fri, 27 Feb 2015 05:14:36 +0200 Subject: [PATCH 10/24] don't update the mesh if Renderer is disabled --- .../Assets/spine-unity/SkeletonRenderer.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index 883021ef9..4884cb969 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -60,6 +60,7 @@ public class SkeletonRenderer : MonoBehaviour { public List submeshSeparatorSlots = new List(); + private Renderer meshRenderer; private MeshFilter meshFilter; private Mesh mesh1, mesh2; private bool useMesh1; @@ -76,8 +77,9 @@ public class SkeletonRenderer : MonoBehaviour { public virtual void Reset () { if (meshFilter != null) meshFilter.sharedMesh = null; - if (GetComponent() != null) - GetComponent().sharedMaterial = null; + + if (meshRenderer != null) + meshRenderer.sharedMaterial = null; if (mesh1 != null) { if (Application.isPlaying) @@ -117,6 +119,7 @@ public class SkeletonRenderer : MonoBehaviour { valid = true; meshFilter = GetComponent(); + meshRenderer = GetComponent(); mesh1 = newMesh(); mesh2 = newMesh(); vertices = new Vector3[0]; @@ -166,8 +169,9 @@ public class SkeletonRenderer : MonoBehaviour { } public virtual void LateUpdate () { - if (!valid) + if (!valid || !meshRenderer.enabled) return; + // Count vertices and submesh triangles. int vertexCount = 0; int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; @@ -229,7 +233,7 @@ public class SkeletonRenderer : MonoBehaviour { submeshMaterials.CopyTo(sharedMaterials); else sharedMaterials = submeshMaterials.ToArray(); - GetComponent().sharedMaterials = sharedMaterials; + meshRenderer.sharedMaterials = sharedMaterials; // Ensure mesh data is the right size. Vector3[] vertices = this.vertices; @@ -359,12 +363,10 @@ public class SkeletonRenderer : MonoBehaviour { this.tempVertices = tempVertices = new float[meshVertexCount]; meshAttachment.ComputeWorldVertices(slot, tempVertices); - color.a = (byte)(a * slot.a * meshAttachment.a); + color.a = slot.data.additiveBlending ? (byte) 0 : (byte)(a * slot.a * meshAttachment.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.b = (byte)(b * slot.b * meshAttachment.b * color.a); - if (slot.data.additiveBlending) - color.a = 0; float[] meshUVs = meshAttachment.uvs; float z = i * zSpacing; @@ -397,12 +399,10 @@ public class SkeletonRenderer : MonoBehaviour { this.tempVertices = tempVertices = new float[meshVertexCount]; skinnedMeshAttachment.ComputeWorldVertices(slot, tempVertices); - color.a = (byte)(a * slot.a * skinnedMeshAttachment.a); + color.a = slot.data.additiveBlending ? (byte) 0 : (byte)(a * slot.a * skinnedMeshAttachment.a); color.r = (byte)(r * slot.r * skinnedMeshAttachment.r * color.a); color.g = (byte)(g * slot.g * skinnedMeshAttachment.g * color.a); color.b = (byte)(b * slot.b * skinnedMeshAttachment.b * color.a); - if (slot.data.additiveBlending) - color.a = 0; float[] meshUVs = skinnedMeshAttachment.uvs; float z = i * zSpacing; From ab396af5f323330b9cefb94deadb677fc9d49904 Mon Sep 17 00:00:00 2001 From: ZimM Date: Sat, 28 Feb 2015 03:09:09 +0200 Subject: [PATCH 11/24] fixed type in SkeletonUtility --- .../Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs index 5183f42f0..3ae9873bc 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs @@ -172,7 +172,7 @@ public class SkeletonUtility : MonoBehaviour { ExposedList ikConstraints = skeletonRenderer.skeleton.IkConstraints; for (int i = 0, n = ikConstraints.Count; i < n; i++) - constraintTargetNames.Add(ikConstraints.Items[n].Target.Data.Name); + constraintTargetNames.Add(ikConstraints.Items[i].Target.Data.Name); foreach (var b in utilityBones) { if (b.bone == null) { From de4fc8b483a5fcc149f4659f87cdb11d6f8e3726 Mon Sep 17 00:00:00 2001 From: ZimM Date: Sat, 28 Feb 2015 03:10:07 +0200 Subject: [PATCH 12/24] remove string comparisons in SkeletonAnimator --- .../Assets/spine-unity/SkeletonAnimator.cs | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs index cf147ee7c..3eac9332d 100644 --- a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs +++ b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs @@ -62,8 +62,8 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { protected event UpdateBonesDelegate _UpdateWorld; protected event UpdateBonesDelegate _UpdateComplete; - Dictionary animationTable = new Dictionary(); - Dictionary clipNameTable = new Dictionary(); + Dictionary animationTable = new Dictionary(); + Dictionary clipNameHashCodeTable = new Dictionary(); Animator animator; public override void Reset () { @@ -72,12 +72,12 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { return; animationTable.Clear(); - clipNameTable.Clear(); + clipNameHashCodeTable.Clear(); var data = skeletonDataAsset.GetSkeletonData(true); foreach (var a in data.Animations) { - animationTable.Add(a.Name, a); + animationTable.Add(a.Name.GetHashCode(), a); } animator = GetComponent(); @@ -124,7 +124,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = stateInfo.normalizedTime * info.clip.length; - animationTable[GetAnimationClipName(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight); + animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight); } foreach (var info in nextClipInfo) { @@ -133,7 +133,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = nextStateInfo.normalizedTime * info.clip.length; - animationTable[GetAnimationClipName(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); + animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); } } else if (mode >= MixMode.MixNext) { //apply first non-zero weighted clip @@ -146,7 +146,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = stateInfo.normalizedTime * info.clip.length; - animationTable[GetAnimationClipName(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null); + animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null); break; } @@ -158,7 +158,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = stateInfo.normalizedTime * info.clip.length; - animationTable[GetAnimationClipName(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight); + animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight); } c = 0; @@ -172,7 +172,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = nextStateInfo.normalizedTime * info.clip.length; - animationTable[GetAnimationClipName(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null); + animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null); break; } } @@ -185,7 +185,7 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { continue; float time = nextStateInfo.normalizedTime * info.clip.length; - animationTable[GetAnimationClipName(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); + animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight); } } } @@ -205,13 +205,13 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { } } - private string GetAnimationClipName(AnimationClip clip) { - string clipName; - if (!clipNameTable.TryGetValue(clip, out clipName)) { - clipName = clip.name; - clipNameTable.Add(clip, clipName); + private int GetAnimationClipNameHashCode(AnimationClip clip) { + int clipNameHashCode; + if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) { + clipNameHashCode = clip.name.GetHashCode(); + clipNameHashCodeTable.Add(clip, clipNameHashCode); } - return clipName; + return clipNameHashCode; } } From 08695c07a3f504872138d0665340fa2fb0251c79 Mon Sep 17 00:00:00 2001 From: ZimM Date: Sat, 28 Feb 2015 03:10:50 +0200 Subject: [PATCH 13/24] fixed typo in SkeletonBounds --- spine-csharp/src/SkeletonBounds.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-csharp/src/SkeletonBounds.cs b/spine-csharp/src/SkeletonBounds.cs index 9fe27ae9d..48caf8d5d 100644 --- a/spine-csharp/src/SkeletonBounds.cs +++ b/spine-csharp/src/SkeletonBounds.cs @@ -58,7 +58,7 @@ namespace Spine { boundingBoxes.Clear(); for (int i = 0, n = polygons.Count; i < n; i++) - polygonPool.Add(polygons.Items[n]); + polygonPool.Add(polygons.Items[i]); polygons.Clear(); for (int i = 0; i < slotCount; i++) { From 0df69e04fdb6674fcc7b4c1c9434021d241799d9 Mon Sep 17 00:00:00 2001 From: ZimM Date: Sat, 28 Feb 2015 03:12:27 +0200 Subject: [PATCH 14/24] removed string comparisons and reduced noticeable method call overhead in Skin --- spine-csharp/src/Skin.cs | 46 +++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/spine-csharp/src/Skin.cs b/spine-csharp/src/Skin.cs index 7b4c57b15..e7f8d8c06 100644 --- a/spine-csharp/src/Skin.cs +++ b/spine-csharp/src/Skin.cs @@ -35,8 +35,8 @@ namespace Spine { /// Stores attachments by slot index and attachment name. public class Skin { internal String name; - private Dictionary, Attachment> attachments = - new Dictionary, Attachment>(AttachmentComparer.Instance); + private Dictionary attachments = + new Dictionary(AttachmentKeyTupleComparer.Instance); public String Name { get { return name; } } @@ -47,26 +47,26 @@ namespace Spine { public void AddAttachment (int slotIndex, String name, Attachment attachment) { if (attachment == null) throw new ArgumentNullException("attachment cannot be null."); - attachments[new KeyValuePair(slotIndex, name)] = attachment; + attachments[new AttachmentKeyTuple(slotIndex, name)] = attachment; } /// May be null. public Attachment GetAttachment (int slotIndex, String name) { Attachment attachment; - attachments.TryGetValue(new KeyValuePair(slotIndex, name), out attachment); + attachments.TryGetValue(new AttachmentKeyTuple(slotIndex, name), out attachment); return attachment; } public void FindNamesForSlot (int slotIndex, List names) { if (names == null) throw new ArgumentNullException("names cannot be null."); - foreach (KeyValuePair key in attachments.Keys) - if (key.Key == slotIndex) names.Add(key.Value); + foreach (AttachmentKeyTuple key in attachments.Keys) + if (key.SlotIndex == slotIndex) names.Add(key.Name); } public void FindAttachmentsForSlot (int slotIndex, List attachments) { if (attachments == null) throw new ArgumentNullException("attachments cannot be null."); - foreach (KeyValuePair, Attachment> entry in this.attachments) - if (entry.Key.Key == slotIndex) attachments.Add(entry.Value); + foreach (KeyValuePair entry in this.attachments) + if (entry.Key.SlotIndex == slotIndex) attachments.Add(entry.Value); } override public String ToString () { @@ -75,27 +75,39 @@ namespace Spine { /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. internal void AttachAll (Skeleton skeleton, Skin oldSkin) { - foreach (KeyValuePair, Attachment> entry in oldSkin.attachments) { - int slotIndex = entry.Key.Key; + foreach (KeyValuePair entry in oldSkin.attachments) { + int slotIndex = entry.Key.SlotIndex; Slot slot = skeleton.slots.Items[slotIndex]; if (slot.attachment == entry.Value) { - Attachment attachment = GetAttachment(slotIndex, entry.Key.Value); + Attachment attachment = GetAttachment(slotIndex, entry.Key.Name); if (attachment != null) slot.Attachment = attachment; } } } // Avoids boxing in the dictionary. - private class AttachmentComparer : IEqualityComparer> { - internal static readonly AttachmentComparer Instance = new AttachmentComparer(); + private class AttachmentKeyTupleComparer : IEqualityComparer { + internal static readonly AttachmentKeyTupleComparer Instance = new AttachmentKeyTupleComparer(); - bool IEqualityComparer>.Equals (KeyValuePair o1, KeyValuePair o2) { - return o1.Key == o2.Key && o1.Value == o2.Value; + bool IEqualityComparer.Equals (AttachmentKeyTuple o1, AttachmentKeyTuple o2) { + return o1.SlotIndex == o2.SlotIndex && o1.NameHashCode == o2.NameHashCode; } - int IEqualityComparer>.GetHashCode (KeyValuePair o) { - return o.Key; + int IEqualityComparer.GetHashCode (AttachmentKeyTuple o) { + return o.SlotIndex; } } + + private class AttachmentKeyTuple { + public readonly int SlotIndex; + public readonly string Name; + public readonly int NameHashCode; + + public AttachmentKeyTuple(int slotIndex, string name) { + SlotIndex = slotIndex; + Name = name; + NameHashCode = Name.GetHashCode(); + } + } } } From c7644ec0ad01066e7a17f0c89858b3a927c8fd1d Mon Sep 17 00:00:00 2001 From: ZimM Date: Sat, 28 Feb 2015 03:13:12 +0200 Subject: [PATCH 15/24] ExposedList: spaces to tabs --- spine-csharp/src/ExposedList.cs | 1088 +++++++++++++++---------------- 1 file changed, 544 insertions(+), 544 deletions(-) diff --git a/spine-csharp/src/ExposedList.cs b/spine-csharp/src/ExposedList.cs index 62b1ed1f4..0f17a6e2b 100644 --- a/spine-csharp/src/ExposedList.cs +++ b/spine-csharp/src/ExposedList.cs @@ -36,548 +36,548 @@ using System.Collections.Generic; using System.Diagnostics; namespace Spine { - [Serializable] - [DebuggerDisplay("Count={Count}")] - public class ExposedList : IEnumerable { - public T[] Items; - public int Count; - - private const int DefaultCapacity = 4; - private static readonly T[] EmptyArray = new T[0]; - private int _version; - - public ExposedList() { - Items = EmptyArray; - } - - public ExposedList(IEnumerable collection) { - CheckCollection(collection); - - // initialize to needed size (if determinable) - ICollection c = collection as ICollection; - if (c == null) { - Items = EmptyArray; - AddEnumerable(collection); - } else { - Items = new T[c.Count]; - AddCollection(c); - } - } - - public ExposedList(int capacity) { - if (capacity < 0) - throw new ArgumentOutOfRangeException("capacity"); - Items = new T[capacity]; - } - - internal ExposedList(T[] data, int size) { - Items = data; - Count = size; - } - - public void Add(T item) { - // If we check to see if we need to grow before trying to grow - // we can speed things up by 25% - if (Count == Items.Length) - GrowIfNeeded(1); - Items[Count ++] = item; - _version++; - } - - private void GrowIfNeeded(int newCount) { - int minimumSize = Count + newCount; - if (minimumSize > Items.Length) - Capacity = Math.Max(Math.Max(Capacity * 2, DefaultCapacity), minimumSize); - } - - private void CheckRange(int idx, int count) { - if (idx < 0) - throw new ArgumentOutOfRangeException("index"); - - if (count < 0) - throw new ArgumentOutOfRangeException("count"); - - if ((uint) idx + (uint) count > (uint) Count) - throw new ArgumentException("index and count exceed length of list"); - } - - private void AddCollection(ICollection collection) { - int collectionCount = collection.Count; - if (collectionCount == 0) - return; - - GrowIfNeeded(collectionCount); - collection.CopyTo(Items, Count); - Count += collectionCount; - } - - private void AddEnumerable(IEnumerable enumerable) { - foreach (T t in enumerable) { - Add(t); - } - } - - public void AddRange(IEnumerable collection) { - CheckCollection(collection); - - ICollection c = collection as ICollection; - if (c != null) - AddCollection(c); - else - AddEnumerable(collection); - _version++; - } - - public int BinarySearch(T item) { - return Array.BinarySearch(Items, 0, Count, item); - } - - public int BinarySearch(T item, IComparer comparer) { - return Array.BinarySearch(Items, 0, Count, item, comparer); - } - - public int BinarySearch(int index, int count, T item, IComparer comparer) { - CheckRange(index, count); - return Array.BinarySearch(Items, index, count, item, comparer); - } - - public void Clear() { - Array.Clear(Items, 0, Items.Length); - Count = 0; - _version++; - } - - public bool Contains(T item) { - return Array.IndexOf(Items, item, 0, Count) != -1; - } - - public ExposedList ConvertAll(Converter converter) { - if (converter == null) - throw new ArgumentNullException("converter"); - ExposedList u = new ExposedList(Count); - for (int i = 0; i < Count; i++) - u.Items[i] = converter(Items[i]); - - u.Count = Count; - return u; - } - - public void CopyTo(T[] array) { - Array.Copy(Items, 0, array, 0, Count); - } - - public void CopyTo(T[] array, int arrayIndex) { - Array.Copy(Items, 0, array, arrayIndex, Count); - } - - public void CopyTo(int index, T[] array, int arrayIndex, int count) { - CheckRange(index, count); - Array.Copy(Items, index, array, arrayIndex, count); - } - - public bool Exists(Predicate match) { - CheckMatch(match); - return GetIndex(0, Count, match) != -1; - } - - public T Find(Predicate match) { - CheckMatch(match); - int i = GetIndex(0, Count, match); - return (i != -1) ? Items[i] : default (T); - } - - private static void CheckMatch(Predicate match) { - if (match == null) - throw new ArgumentNullException("match"); - } - - public ExposedList FindAll(Predicate match) { - CheckMatch(match); - return FindAllList(match); - } - - private ExposedList FindAllList(Predicate match) { - ExposedList results = new ExposedList(); - for (int i = 0; i < Count; i++) - if (match(Items[i])) - results.Add(Items[i]); - - return results; - } - - public int FindIndex(Predicate match) { - CheckMatch(match); - return GetIndex(0, Count, match); - } - - public int FindIndex(int startIndex, Predicate match) { - CheckMatch(match); - CheckIndex(startIndex); - return GetIndex(startIndex, Count - startIndex, match); - } - - public int FindIndex(int startIndex, int count, Predicate match) { - CheckMatch(match); - CheckRange(startIndex, count); - return GetIndex(startIndex, count, match); - } - - private int GetIndex(int startIndex, int count, Predicate match) { - int end = startIndex + count; - for (int i = startIndex; i < end; i ++) - if (match(Items[i])) - return i; - - return -1; - } - - public T FindLast(Predicate match) { - CheckMatch(match); - int i = GetLastIndex(0, Count, match); - return i == -1 ? default (T) : Items[i]; - } - - public int FindLastIndex(Predicate match) { - CheckMatch(match); - return GetLastIndex(0, Count, match); - } - - public int FindLastIndex(int startIndex, Predicate match) { - CheckMatch(match); - CheckIndex(startIndex); - return GetLastIndex(0, startIndex + 1, match); - } - - public int FindLastIndex(int startIndex, int count, Predicate match) { - CheckMatch(match); - int start = startIndex - count + 1; - CheckRange(start, count); - return GetLastIndex(start, count, match); - } - - private int GetLastIndex(int startIndex, int count, Predicate match) { - // unlike FindLastIndex, takes regular params for search range - for (int i = startIndex + count; i != startIndex;) - if (match(Items[--i])) - return i; - return -1; - } - - public void ForEach(Action action) { - if (action == null) - throw new ArgumentNullException("action"); - for (int i = 0; i < Count; i++) - action(Items[i]); - } - - public Enumerator GetEnumerator() { - return new Enumerator(this); - } - - public ExposedList GetRange(int index, int count) { - CheckRange(index, count); - T[] tmpArray = new T[count]; - Array.Copy(Items, index, tmpArray, 0, count); - return new ExposedList(tmpArray, count); - } - - public int IndexOf(T item) { - return Array.IndexOf(Items, item, 0, Count); - } - - public int IndexOf(T item, int index) { - CheckIndex(index); - return Array.IndexOf(Items, item, index, Count - index); - } - - public int IndexOf(T item, int index, int count) { - if (index < 0) - throw new ArgumentOutOfRangeException("index"); - - if (count < 0) - throw new ArgumentOutOfRangeException("count"); - - if ((uint) index + (uint) count > (uint) Count) - throw new ArgumentOutOfRangeException("index and count exceed length of list"); - - return Array.IndexOf(Items, item, index, count); - } - - private void Shift(int start, int delta) { - if (delta < 0) - start -= delta; - - if (start < Count) - Array.Copy(Items, start, Items, start + delta, Count - start); - - Count += delta; - - if (delta < 0) - Array.Clear(Items, Count, -delta); - } - - private void CheckIndex(int index) { - if (index < 0 || (uint) index > (uint) Count) - throw new ArgumentOutOfRangeException("index"); - } - - public void Insert(int index, T item) { - CheckIndex(index); - if (Count == Items.Length) - GrowIfNeeded(1); - Shift(index, 1); - Items[index] = item; - _version++; - } - - private void CheckCollection(IEnumerable collection) { - if (collection == null) - throw new ArgumentNullException("collection"); - } - - public void InsertRange(int index, IEnumerable collection) { - CheckCollection(collection); - CheckIndex(index); - if (collection == this) { - T[] buffer = new T[Count]; - CopyTo(buffer, 0); - GrowIfNeeded(Count); - Shift(index, buffer.Length); - Array.Copy(buffer, 0, Items, index, buffer.Length); - } else { - ICollection c = collection as ICollection; - if (c != null) - InsertCollection(index, c); - else - InsertEnumeration(index, collection); - } - _version++; - } - - private void InsertCollection(int index, ICollection collection) { - int collectionCount = collection.Count; - GrowIfNeeded(collectionCount); - - Shift(index, collectionCount); - collection.CopyTo(Items, index); - } - - private void InsertEnumeration(int index, IEnumerable enumerable) { - foreach (T t in enumerable) - Insert(index++, t); - } - - public int LastIndexOf(T item) { - return Array.LastIndexOf(Items, item, Count - 1, Count); - } - - public int LastIndexOf(T item, int index) { - CheckIndex(index); - return Array.LastIndexOf(Items, item, index, index + 1); - } - - public int LastIndexOf(T item, int index, int count) { - if (index < 0) - throw new ArgumentOutOfRangeException("index", index, "index is negative"); - - if (count < 0) - throw new ArgumentOutOfRangeException("count", count, "count is negative"); - - if (index - count + 1 < 0) - throw new ArgumentOutOfRangeException("count", count, "count is too large"); - - return Array.LastIndexOf(Items, item, index, count); - } - - public bool Remove(T item) { - int loc = IndexOf(item); - if (loc != -1) - RemoveAt(loc); - - return loc != -1; - } - - public int RemoveAll(Predicate match) { - CheckMatch(match); - int i = 0; - int j = 0; - - // Find the first item to remove - for (i = 0; i < Count; i++) - if (match(Items[i])) - break; - - if (i == Count) - return 0; - - _version++; - - // Remove any additional items - for (j = i + 1; j < Count; j++) { - if (!match(Items[j])) - Items[i++] = Items[j]; - } - if (j - i > 0) - Array.Clear(Items, i, j - i); - - Count = i; - return (j - i); - } - - public void RemoveAt(int index) { - if (index < 0 || (uint) index >= (uint) Count) - throw new ArgumentOutOfRangeException("index"); - Shift(index, -1); - Array.Clear(Items, Count, 1); - _version++; - } - - public void RemoveRange(int index, int count) { - CheckRange(index, count); - if (count > 0) { - Shift(index, -count); - Array.Clear(Items, Count, count); - _version++; - } - } - - public void Reverse() { - Array.Reverse(Items, 0, Count); - _version++; - } - - public void Reverse(int index, int count) { - CheckRange(index, count); - Array.Reverse(Items, index, count); - _version++; - } - - public void Sort() { - Array.Sort(Items, 0, Count, Comparer.Default); - _version++; - } - - public void Sort(IComparer comparer) { - Array.Sort(Items, 0, Count, comparer); - _version++; - } - - public void Sort(Comparison comparison) { - Array.Sort(Items, comparison); - _version++; - } - - public void Sort(int index, int count, IComparer comparer) { - CheckRange(index, count); - Array.Sort(Items, index, count, comparer); - _version++; - } - - public T[] ToArray() { - T[] t = new T[Count]; - Array.Copy(Items, t, Count); - - return t; - } - - public void TrimExcess() { - Capacity = Count; - } - - public bool TrueForAll(Predicate match) { - CheckMatch(match); - - for (int i = 0; i < Count; i++) - if (!match(Items[i])) - return false; - - return true; - } - - public int Capacity { - get { - return Items.Length; - } - set { - if ((uint) value < (uint) Count) - throw new ArgumentOutOfRangeException(); - - Array.Resize(ref Items, value); - } - } - - #region Interface implementations. - - IEnumerator IEnumerable.GetEnumerator() { - return GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() { - return GetEnumerator(); - } - - #endregion - - [Serializable] - public struct Enumerator : IEnumerator, IDisposable { - private ExposedList l; - private int next; - private int ver; - - private T current; - - internal Enumerator(ExposedList l) - : this() { - this.l = l; - ver = l._version; - } - - public void Dispose() { - l = null; - } - - private void VerifyState() { - if (l == null) - throw new ObjectDisposedException(GetType().FullName); - if (ver != l._version) - throw new InvalidOperationException( - "Collection was modified; enumeration operation may not execute."); - } - - public bool MoveNext() { - VerifyState(); - - if (next < 0) - return false; - - if (next < l.Count) { - current = l.Items[next++]; - return true; - } - - next = -1; - return false; - } - - public T Current { - get { - return current; - } - } - - void IEnumerator.Reset() { - VerifyState(); - next = 0; - } - - object IEnumerator.Current { - get { - VerifyState(); - if (next <= 0) - throw new InvalidOperationException(); - return current; - } - } - } - } + [Serializable] + [DebuggerDisplay("Count={Count}")] + public class ExposedList : IEnumerable { + public T[] Items; + public int Count; + + private const int DefaultCapacity = 4; + private static readonly T[] EmptyArray = new T[0]; + private int version; + + public ExposedList() { + Items = EmptyArray; + } + + public ExposedList(IEnumerable collection) { + CheckCollection(collection); + + // initialize to needed size (if determinable) + ICollection c = collection as ICollection; + if (c == null) { + Items = EmptyArray; + AddEnumerable(collection); + } else { + Items = new T[c.Count]; + AddCollection(c); + } + } + + public ExposedList(int capacity) { + if (capacity < 0) + throw new ArgumentOutOfRangeException("capacity"); + Items = new T[capacity]; + } + + internal ExposedList(T[] data, int size) { + Items = data; + Count = size; + } + + public void Add(T item) { + // If we check to see if we need to grow before trying to grow + // we can speed things up by 25% + if (Count == Items.Length) + GrowIfNeeded(1); + Items[Count ++] = item; + version++; + } + + public void GrowIfNeeded(int newCount) { + int minimumSize = Count + newCount; + if (minimumSize > Items.Length) + Capacity = Math.Max(Math.Max(Capacity * 2, DefaultCapacity), minimumSize); + } + + private void CheckRange(int idx, int count) { + if (idx < 0) + throw new ArgumentOutOfRangeException("index"); + + if (count < 0) + throw new ArgumentOutOfRangeException("count"); + + if ((uint) idx + (uint) count > (uint) Count) + throw new ArgumentException("index and count exceed length of list"); + } + + private void AddCollection(ICollection collection) { + int collectionCount = collection.Count; + if (collectionCount == 0) + return; + + GrowIfNeeded(collectionCount); + collection.CopyTo(Items, Count); + Count += collectionCount; + } + + private void AddEnumerable(IEnumerable enumerable) { + foreach (T t in enumerable) { + Add(t); + } + } + + public void AddRange(IEnumerable collection) { + CheckCollection(collection); + + ICollection c = collection as ICollection; + if (c != null) + AddCollection(c); + else + AddEnumerable(collection); + version++; + } + + public int BinarySearch(T item) { + return Array.BinarySearch(Items, 0, Count, item); + } + + public int BinarySearch(T item, IComparer comparer) { + return Array.BinarySearch(Items, 0, Count, item, comparer); + } + + public int BinarySearch(int index, int count, T item, IComparer comparer) { + CheckRange(index, count); + return Array.BinarySearch(Items, index, count, item, comparer); + } + + public void Clear(bool clearArray = true) { + Array.Clear(Items, 0, Items.Length); + Count = 0; + version++; + } + + public bool Contains(T item) { + return Array.IndexOf(Items, item, 0, Count) != -1; + } + + public ExposedList ConvertAll(Converter converter) { + if (converter == null) + throw new ArgumentNullException("converter"); + ExposedList u = new ExposedList(Count); + for (int i = 0; i < Count; i++) + u.Items[i] = converter(Items[i]); + + u.Count = Count; + return u; + } + + public void CopyTo(T[] array) { + Array.Copy(Items, 0, array, 0, Count); + } + + public void CopyTo(T[] array, int arrayIndex) { + Array.Copy(Items, 0, array, arrayIndex, Count); + } + + public void CopyTo(int index, T[] array, int arrayIndex, int count) { + CheckRange(index, count); + Array.Copy(Items, index, array, arrayIndex, count); + } + + public bool Exists(Predicate match) { + CheckMatch(match); + return GetIndex(0, Count, match) != -1; + } + + public T Find(Predicate match) { + CheckMatch(match); + int i = GetIndex(0, Count, match); + return (i != -1) ? Items[i] : default (T); + } + + private static void CheckMatch(Predicate match) { + if (match == null) + throw new ArgumentNullException("match"); + } + + public ExposedList FindAll(Predicate match) { + CheckMatch(match); + return FindAllList(match); + } + + private ExposedList FindAllList(Predicate match) { + ExposedList results = new ExposedList(); + for (int i = 0; i < Count; i++) + if (match(Items[i])) + results.Add(Items[i]); + + return results; + } + + public int FindIndex(Predicate match) { + CheckMatch(match); + return GetIndex(0, Count, match); + } + + public int FindIndex(int startIndex, Predicate match) { + CheckMatch(match); + CheckIndex(startIndex); + return GetIndex(startIndex, Count - startIndex, match); + } + + public int FindIndex(int startIndex, int count, Predicate match) { + CheckMatch(match); + CheckRange(startIndex, count); + return GetIndex(startIndex, count, match); + } + + private int GetIndex(int startIndex, int count, Predicate match) { + int end = startIndex + count; + for (int i = startIndex; i < end; i ++) + if (match(Items[i])) + return i; + + return -1; + } + + public T FindLast(Predicate match) { + CheckMatch(match); + int i = GetLastIndex(0, Count, match); + return i == -1 ? default (T) : Items[i]; + } + + public int FindLastIndex(Predicate match) { + CheckMatch(match); + return GetLastIndex(0, Count, match); + } + + public int FindLastIndex(int startIndex, Predicate match) { + CheckMatch(match); + CheckIndex(startIndex); + return GetLastIndex(0, startIndex + 1, match); + } + + public int FindLastIndex(int startIndex, int count, Predicate match) { + CheckMatch(match); + int start = startIndex - count + 1; + CheckRange(start, count); + return GetLastIndex(start, count, match); + } + + private int GetLastIndex(int startIndex, int count, Predicate match) { + // unlike FindLastIndex, takes regular params for search range + for (int i = startIndex + count; i != startIndex;) + if (match(Items[--i])) + return i; + return -1; + } + + public void ForEach(Action action) { + if (action == null) + throw new ArgumentNullException("action"); + for (int i = 0; i < Count; i++) + action(Items[i]); + } + + public Enumerator GetEnumerator() { + return new Enumerator(this); + } + + public ExposedList GetRange(int index, int count) { + CheckRange(index, count); + T[] tmpArray = new T[count]; + Array.Copy(Items, index, tmpArray, 0, count); + return new ExposedList(tmpArray, count); + } + + public int IndexOf(T item) { + return Array.IndexOf(Items, item, 0, Count); + } + + public int IndexOf(T item, int index) { + CheckIndex(index); + return Array.IndexOf(Items, item, index, Count - index); + } + + public int IndexOf(T item, int index, int count) { + if (index < 0) + throw new ArgumentOutOfRangeException("index"); + + if (count < 0) + throw new ArgumentOutOfRangeException("count"); + + if ((uint) index + (uint) count > (uint) Count) + throw new ArgumentOutOfRangeException("index and count exceed length of list"); + + return Array.IndexOf(Items, item, index, count); + } + + private void Shift(int start, int delta) { + if (delta < 0) + start -= delta; + + if (start < Count) + Array.Copy(Items, start, Items, start + delta, Count - start); + + Count += delta; + + if (delta < 0) + Array.Clear(Items, Count, -delta); + } + + private void CheckIndex(int index) { + if (index < 0 || (uint) index > (uint) Count) + throw new ArgumentOutOfRangeException("index"); + } + + public void Insert(int index, T item) { + CheckIndex(index); + if (Count == Items.Length) + GrowIfNeeded(1); + Shift(index, 1); + Items[index] = item; + version++; + } + + private void CheckCollection(IEnumerable collection) { + if (collection == null) + throw new ArgumentNullException("collection"); + } + + public void InsertRange(int index, IEnumerable collection) { + CheckCollection(collection); + CheckIndex(index); + if (collection == this) { + T[] buffer = new T[Count]; + CopyTo(buffer, 0); + GrowIfNeeded(Count); + Shift(index, buffer.Length); + Array.Copy(buffer, 0, Items, index, buffer.Length); + } else { + ICollection c = collection as ICollection; + if (c != null) + InsertCollection(index, c); + else + InsertEnumeration(index, collection); + } + version++; + } + + private void InsertCollection(int index, ICollection collection) { + int collectionCount = collection.Count; + GrowIfNeeded(collectionCount); + + Shift(index, collectionCount); + collection.CopyTo(Items, index); + } + + private void InsertEnumeration(int index, IEnumerable enumerable) { + foreach (T t in enumerable) + Insert(index++, t); + } + + public int LastIndexOf(T item) { + return Array.LastIndexOf(Items, item, Count - 1, Count); + } + + public int LastIndexOf(T item, int index) { + CheckIndex(index); + return Array.LastIndexOf(Items, item, index, index + 1); + } + + public int LastIndexOf(T item, int index, int count) { + if (index < 0) + throw new ArgumentOutOfRangeException("index", index, "index is negative"); + + if (count < 0) + throw new ArgumentOutOfRangeException("count", count, "count is negative"); + + if (index - count + 1 < 0) + throw new ArgumentOutOfRangeException("count", count, "count is too large"); + + return Array.LastIndexOf(Items, item, index, count); + } + + public bool Remove(T item) { + int loc = IndexOf(item); + if (loc != -1) + RemoveAt(loc); + + return loc != -1; + } + + public int RemoveAll(Predicate match) { + CheckMatch(match); + int i = 0; + int j = 0; + + // Find the first item to remove + for (i = 0; i < Count; i++) + if (match(Items[i])) + break; + + if (i == Count) + return 0; + + version++; + + // Remove any additional items + for (j = i + 1; j < Count; j++) { + if (!match(Items[j])) + Items[i++] = Items[j]; + } + if (j - i > 0) + Array.Clear(Items, i, j - i); + + Count = i; + return (j - i); + } + + public void RemoveAt(int index) { + if (index < 0 || (uint) index >= (uint) Count) + throw new ArgumentOutOfRangeException("index"); + Shift(index, -1); + Array.Clear(Items, Count, 1); + version++; + } + + public void RemoveRange(int index, int count) { + CheckRange(index, count); + if (count > 0) { + Shift(index, -count); + Array.Clear(Items, Count, count); + version++; + } + } + + public void Reverse() { + Array.Reverse(Items, 0, Count); + version++; + } + + public void Reverse(int index, int count) { + CheckRange(index, count); + Array.Reverse(Items, index, count); + version++; + } + + public void Sort() { + Array.Sort(Items, 0, Count, Comparer.Default); + version++; + } + + public void Sort(IComparer comparer) { + Array.Sort(Items, 0, Count, comparer); + version++; + } + + public void Sort(Comparison comparison) { + Array.Sort(Items, comparison); + version++; + } + + public void Sort(int index, int count, IComparer comparer) { + CheckRange(index, count); + Array.Sort(Items, index, count, comparer); + version++; + } + + public T[] ToArray() { + T[] t = new T[Count]; + Array.Copy(Items, t, Count); + + return t; + } + + public void TrimExcess() { + Capacity = Count; + } + + public bool TrueForAll(Predicate match) { + CheckMatch(match); + + for (int i = 0; i < Count; i++) + if (!match(Items[i])) + return false; + + return true; + } + + public int Capacity { + get { + return Items.Length; + } + set { + if ((uint) value < (uint) Count) + throw new ArgumentOutOfRangeException(); + + Array.Resize(ref Items, value); + } + } + + #region Interface implementations. + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + #endregion + + [Serializable] + public struct Enumerator : IEnumerator, IDisposable { + private ExposedList l; + private int next; + private int ver; + + private T current; + + internal Enumerator(ExposedList l) + : this() { + this.l = l; + ver = l.version; + } + + public void Dispose() { + l = null; + } + + private void VerifyState() { + if (l == null) + throw new ObjectDisposedException(GetType().FullName); + if (ver != l.version) + throw new InvalidOperationException( + "Collection was modified; enumeration operation may not execute."); + } + + public bool MoveNext() { + VerifyState(); + + if (next < 0) + return false; + + if (next < l.Count) { + current = l.Items[next++]; + return true; + } + + next = -1; + return false; + } + + public T Current { + get { + return current; + } + } + + void IEnumerator.Reset() { + VerifyState(); + next = 0; + } + + object IEnumerator.Current { + get { + VerifyState(); + if (next <= 0) + throw new InvalidOperationException(); + return current; + } + } + } + } } \ No newline at end of file From be7480bca4369ca67101305097204557e5076ac0 Mon Sep 17 00:00:00 2001 From: ZimM Date: Sat, 28 Feb 2015 03:43:30 +0200 Subject: [PATCH 16/24] update and set mesh triangles only when it's required --- .../Assets/spine-unity/SkeletonRenderer.cs | 191 ++++++++++++++++-- 1 file changed, 170 insertions(+), 21 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index 4884cb969..a9497e791 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -29,7 +29,6 @@ *****************************************************************************/ using System; -using System.IO; using System.Collections.Generic; using UnityEngine; using Spine; @@ -65,15 +64,14 @@ public class SkeletonRenderer : MonoBehaviour { private Mesh mesh1, mesh2; private bool useMesh1; private float[] tempVertices = new float[8]; - private int lastVertexCount; private Vector3[] vertices; private Color32[] colors; private Vector2[] uvs; private Material[] sharedMaterials = new Material[0]; + private LastState lastState = new LastState(); private readonly ExposedList submeshMaterials = new ExposedList(); private readonly ExposedList submeshes = new ExposedList(); - public virtual void Reset () { if (meshFilter != null) meshFilter.sharedMesh = null; @@ -95,9 +93,9 @@ public class SkeletonRenderer : MonoBehaviour { DestroyImmediate(mesh2); } + lastState = new LastState(); mesh1 = null; mesh2 = null; - lastVertexCount = 0; vertices = null; colors = null; uvs = null; @@ -176,11 +174,18 @@ public class SkeletonRenderer : MonoBehaviour { int vertexCount = 0; int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; Material lastMaterial = null; - submeshMaterials.Clear(); ExposedList drawOrder = skeleton.drawOrder; int drawOrderCount = drawOrder.Count; int submeshSeparatorSlotsCount = submeshSeparatorSlots.Count; bool renderMeshes = this.renderMeshes; + + // Clear last state of attachments and submeshes + ExposedList attachmentsTriangleCountTemp = lastState.attachmentsTriangleCountTemp; + attachmentsTriangleCountTemp.GrowIfNeeded(drawOrderCount); + attachmentsTriangleCountTemp.Count = drawOrderCount; + + ExposedList addSubmeshArgumentsTemp = lastState.addSubmeshArgumentsTemp; + addSubmeshArgumentsTemp.Clear(false); for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder.Items[i]; Attachment attachment = slot.attachment; @@ -188,6 +193,7 @@ public class SkeletonRenderer : MonoBehaviour { object rendererObject; int attachmentVertexCount, attachmentTriangleCount; + attachmentsTriangleCountTemp.Items[i] = -1; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { rendererObject = regionAttachment.RendererObject; @@ -216,7 +222,9 @@ public class SkeletonRenderer : MonoBehaviour { Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject; if ((lastMaterial != null && lastMaterial.GetInstanceID() != material.GetInstanceID()) || (submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot))) { - AddSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false); + addSubmeshArgumentsTemp.Add( + new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false) + ); submeshTriangleCount = 0; submeshFirstVertex = vertexCount; submeshStartSlotIndex = i; @@ -225,15 +233,36 @@ public class SkeletonRenderer : MonoBehaviour { submeshTriangleCount += attachmentTriangleCount; vertexCount += attachmentVertexCount; - } - AddSubmesh(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true); - // Set materials. - if (submeshMaterials.Count == sharedMaterials.Length) - submeshMaterials.CopyTo(sharedMaterials); - else - sharedMaterials = submeshMaterials.ToArray(); - meshRenderer.sharedMaterials = sharedMaterials; + attachmentsTriangleCountTemp.Items[i] = attachmentTriangleCount; + } + addSubmeshArgumentsTemp.Add( + new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true) + ); + + bool mustUpdateMeshStructure = MustUpdateMeshStructure(attachmentsTriangleCountTemp, addSubmeshArgumentsTemp); + if (mustUpdateMeshStructure) { + submeshMaterials.Clear(); + for (int i = 0, n = addSubmeshArgumentsTemp.Count; i < n; i++) { + LastState.AddSubmeshArguments arguments = addSubmeshArgumentsTemp.Items[i]; + AddSubmesh( + arguments.material, + arguments.startSlot, + arguments.endSlot, + arguments.triangleCount, + arguments.firstVertex, + arguments.lastSubmesh + ); + } + + // Set materials. + if (submeshMaterials.Count == sharedMaterials.Length) + submeshMaterials.CopyTo(sharedMaterials); + else + sharedMaterials = submeshMaterials.ToArray(); + + meshRenderer.sharedMaterials = sharedMaterials; + } // Ensure mesh data is the right size. Vector3[] vertices = this.vertices; @@ -248,10 +277,10 @@ public class SkeletonRenderer : MonoBehaviour { } else { // Too many vertices, zero the extra. Vector3 zero = Vector3.zero; - for (int i = vertexCount, n = lastVertexCount; i < n; i++) + for (int i = vertexCount, n = lastState.vertexCount ; i < n; i++) vertices[i] = zero; } - lastVertexCount = vertexCount; + lastState.vertexCount = vertexCount; // Setup mesh. Vector3 meshBoundsMin; @@ -440,13 +469,16 @@ public class SkeletonRenderer : MonoBehaviour { mesh.colors32 = colors; mesh.uv = uvs; - int submeshCount = submeshMaterials.Count; - mesh.subMeshCount = submeshCount; - for (int i = 0; i < submeshCount; ++i) - mesh.SetTriangles(submeshes.Items[i].triangles, i); + if (mustUpdateMeshStructure) { + int submeshCount = submeshMaterials.Count; + mesh.subMeshCount = submeshCount; + for (int i = 0; i < submeshCount; ++i) + mesh.SetTriangles(submeshes.Items[i].triangles, i); + } Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin; - mesh.bounds = new Bounds(meshBoundsMin + meshBoundsExtents * 0.5f, meshBoundsExtents); + Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f; + mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents); if (newTriangles && calculateNormals) { Vector3[] normals = new Vector3[vertexCount]; @@ -467,9 +499,85 @@ public class SkeletonRenderer : MonoBehaviour { } } + // Update previous state + ExposedList attachmentsTriangleCountCurrentMesh = + useMesh1 ? + lastState.attachmentsTriangleCountMesh1 : + lastState.attachmentsTriangleCountMesh2; + ExposedList addSubmeshArgumentsCurrentMesh = + useMesh1 ? + lastState.addSubmeshArgumentsMesh1 : + lastState.addSubmeshArgumentsMesh2; + + attachmentsTriangleCountCurrentMesh.GrowIfNeeded(attachmentsTriangleCountTemp.Capacity); + attachmentsTriangleCountCurrentMesh.Count = attachmentsTriangleCountTemp.Count; + attachmentsTriangleCountTemp.CopyTo(attachmentsTriangleCountCurrentMesh.Items, 0); + + addSubmeshArgumentsCurrentMesh.GrowIfNeeded(addSubmeshArgumentsTemp.Count); + addSubmeshArgumentsCurrentMesh.Count = addSubmeshArgumentsTemp.Count; + addSubmeshArgumentsTemp.CopyTo(addSubmeshArgumentsCurrentMesh.Items); + + lastState.frontFacing = frontFacing; + lastState.immutableTriangles = immutableTriangles; + useMesh1 = !useMesh1; } + private bool MustUpdateMeshStructure(ExposedList attachmentsTriangleCountTemp, ExposedList addSubmeshArgumentsTemp) { + // Check if any mesh settings were changed + bool mustUpdateMeshStructure = + frontFacing != lastState.frontFacing || + immutableTriangles != lastState.immutableTriangles; +#if UNITY_EDITOR + mustUpdateMeshStructure |= !Application.isPlaying; +#endif + + if (mustUpdateMeshStructure) + return true; + + // Check if any attachments were enabled/disabled + // or submesh structures has changed + ExposedList attachmentsTriangleCountCurrentMesh = + useMesh1 ? + lastState.attachmentsTriangleCountMesh1 : + lastState.attachmentsTriangleCountMesh2; + ExposedList addSubmeshArgumentsCurrentMesh = + useMesh1 ? + lastState.addSubmeshArgumentsMesh1 : + lastState.addSubmeshArgumentsMesh2; + + // Check attachments + int attachmentCount = attachmentsTriangleCountTemp.Count; + if (attachmentsTriangleCountCurrentMesh.Count != attachmentCount) { + mustUpdateMeshStructure = true; + } else { + for (int i = 0; i < attachmentCount; i++) { + if (attachmentsTriangleCountCurrentMesh.Items[i] != attachmentsTriangleCountTemp.Items[i]) { + mustUpdateMeshStructure = true; + break; + } + } + } + + if (mustUpdateMeshStructure) + return true; + + // Check submeshes + int submeshCount = addSubmeshArgumentsTemp.Count; + if (addSubmeshArgumentsCurrentMesh.Count != submeshCount) { + mustUpdateMeshStructure = true; + } else { + for (int i = 0; i < submeshCount; i++) { + if (!addSubmeshArgumentsCurrentMesh.Items[i].Equals(addSubmeshArgumentsTemp.Items[i])) { + mustUpdateMeshStructure = true; + break; + } + } + } + + return mustUpdateMeshStructure; + } + /** Stores vertices and triangles for a single material. */ private void AddSubmesh (Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) { int submeshIndex = submeshMaterials.Count; @@ -593,6 +701,47 @@ public class SkeletonRenderer : MonoBehaviour { Gizmos.DrawCube(meshBounds.center, meshBounds.size); } #endif + + private class LastState { + public bool frontFacing; + public bool immutableTriangles; + public int vertexCount; + public readonly ExposedList attachmentsTriangleCountTemp = new ExposedList(); + public readonly ExposedList attachmentsTriangleCountMesh1 = new ExposedList(); + public readonly ExposedList attachmentsTriangleCountMesh2 = new ExposedList(); + public readonly ExposedList addSubmeshArgumentsTemp = new ExposedList(); + public readonly ExposedList addSubmeshArgumentsMesh1 = new ExposedList(); + public readonly ExposedList addSubmeshArgumentsMesh2 = new ExposedList(); + + public struct AddSubmeshArguments { + public Material material; + public int startSlot; + public int endSlot; + public int triangleCount; + public int firstVertex; + public bool lastSubmesh; + + public AddSubmeshArguments(Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) { + this.material = material; + this.startSlot = startSlot; + this.endSlot = endSlot; + this.triangleCount = triangleCount; + this.firstVertex = firstVertex; + this.lastSubmesh = lastSubmesh; + } + + public bool Equals(AddSubmeshArguments other) { + return + !ReferenceEquals(material, null) && + !ReferenceEquals(other.material, null) && + material.GetInstanceID() == other.material.GetInstanceID() && + startSlot == other.startSlot && + endSlot == other.endSlot && + triangleCount == other.triangleCount && + firstVertex == other.firstVertex; + } + } + } } class Submesh { From f42d76a59b22d52d1cb89702160b7ef6505fbf31 Mon Sep 17 00:00:00 2001 From: ZimM Date: Sat, 28 Feb 2015 05:31:44 +0200 Subject: [PATCH 17/24] fixed a regression when using Front Facing or Immutable Triangles --- .../Assets/spine-unity/SkeletonRenderer.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index a9497e791..c5c185871 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -517,8 +517,13 @@ public class SkeletonRenderer : MonoBehaviour { addSubmeshArgumentsCurrentMesh.Count = addSubmeshArgumentsTemp.Count; addSubmeshArgumentsTemp.CopyTo(addSubmeshArgumentsCurrentMesh.Items); - lastState.frontFacing = frontFacing; - lastState.immutableTriangles = immutableTriangles; + if (useMesh1) { + lastState.frontFacingMesh1 = frontFacing; + lastState.immutableTrianglesMesh1 = immutableTriangles; + } else { + lastState.frontFacingMesh2 = frontFacing; + lastState.immutableTrianglesMesh2 = immutableTriangles; + } useMesh1 = !useMesh1; } @@ -526,8 +531,8 @@ public class SkeletonRenderer : MonoBehaviour { private bool MustUpdateMeshStructure(ExposedList attachmentsTriangleCountTemp, ExposedList addSubmeshArgumentsTemp) { // Check if any mesh settings were changed bool mustUpdateMeshStructure = - frontFacing != lastState.frontFacing || - immutableTriangles != lastState.immutableTriangles; + frontFacing != (useMesh1 ? lastState.frontFacingMesh1 : lastState.frontFacingMesh2) || + immutableTriangles != (useMesh1 ? lastState.immutableTrianglesMesh1 : lastState.immutableTrianglesMesh2); #if UNITY_EDITOR mustUpdateMeshStructure |= !Application.isPlaying; #endif @@ -703,8 +708,10 @@ public class SkeletonRenderer : MonoBehaviour { #endif private class LastState { - public bool frontFacing; - public bool immutableTriangles; + public bool frontFacingMesh1; + public bool frontFacingMesh2; + public bool immutableTrianglesMesh1; + public bool immutableTrianglesMesh2; public int vertexCount; public readonly ExposedList attachmentsTriangleCountTemp = new ExposedList(); public readonly ExposedList attachmentsTriangleCountMesh1 = new ExposedList(); From f738ec77b9a1c4d89ffb7bc707285fbed1e75404 Mon Sep 17 00:00:00 2001 From: ZimM Date: Sat, 28 Feb 2015 05:44:46 +0200 Subject: [PATCH 18/24] brought back string equality comparison in Skin.AttachmentKeyTupleComparer --- spine-csharp/src/Skin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-csharp/src/Skin.cs b/spine-csharp/src/Skin.cs index e7f8d8c06..2c69f0f78 100644 --- a/spine-csharp/src/Skin.cs +++ b/spine-csharp/src/Skin.cs @@ -90,7 +90,7 @@ namespace Spine { internal static readonly AttachmentKeyTupleComparer Instance = new AttachmentKeyTupleComparer(); bool IEqualityComparer.Equals (AttachmentKeyTuple o1, AttachmentKeyTuple o2) { - return o1.SlotIndex == o2.SlotIndex && o1.NameHashCode == o2.NameHashCode; + return o1.SlotIndex == o2.SlotIndex && o1.NameHashCode == o2.NameHashCode && o1.Name == o2.Name; } int IEqualityComparer.GetHashCode (AttachmentKeyTuple o) { From 3347ffcf86a5b4bb3a37b5713654e6ad547d73ee Mon Sep 17 00:00:00 2001 From: ZimM Date: Sat, 28 Feb 2015 05:53:47 +0200 Subject: [PATCH 19/24] moved meshBoundsMin/Max.z calculation outside the loop pass by ref in LastState.Equals return true right away in SkeletonRenderer.MustUpdateMeshStructure --- .../Assets/spine-unity/SkeletonRenderer.cs | 72 +++++++------------ 1 file changed, 25 insertions(+), 47 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index c5c185871..cac9778c2 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -283,21 +283,22 @@ public class SkeletonRenderer : MonoBehaviour { lastState.vertexCount = vertexCount; // Setup mesh. - Vector3 meshBoundsMin; - meshBoundsMin.x = float.MaxValue; - meshBoundsMin.y = float.MaxValue; - meshBoundsMin.z = float.MaxValue; - Vector3 meshBoundsMax; - meshBoundsMax.x = float.MinValue; - meshBoundsMax.y = float.MinValue; - meshBoundsMax.z = float.MinValue; + float zSpacing = this.zSpacing; float[] tempVertices = this.tempVertices; Vector2[] uvs = this.uvs; Color32[] colors = this.colors; int vertexIndex = 0; - Color32 color = new Color32(); - float zSpacing = this.zSpacing; + Color32 color; float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b; + + Vector3 meshBoundsMin; + meshBoundsMin.x = float.MaxValue; + meshBoundsMin.y = float.MaxValue; + meshBoundsMin.z = zSpacing > 0f ? 0f : zSpacing * (drawOrderCount - 1); + Vector3 meshBoundsMax; + meshBoundsMax.x = float.MinValue; + meshBoundsMax.y = float.MinValue; + meshBoundsMax.z = zSpacing < 0f ? 0f : zSpacing * (drawOrderCount - 1); for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder.Items[i]; Attachment attachment = slot.attachment; @@ -375,12 +376,6 @@ public class SkeletonRenderer : MonoBehaviour { else if (tempVertices[RegionAttachment.Y4] > meshBoundsMax.y) meshBoundsMax.y = tempVertices[RegionAttachment.Y4]; - // Calculate min/max Z - if (z < meshBoundsMin.z) - meshBoundsMin.z = z; - else if (z > meshBoundsMax.z) - meshBoundsMax.z = z; - vertexIndex += 4; } else { if (!renderMeshes) @@ -415,10 +410,6 @@ public class SkeletonRenderer : MonoBehaviour { meshBoundsMin.y = tempVertices[ii + 1]; else if (tempVertices[ii + 1] > meshBoundsMax.y) meshBoundsMax.y = tempVertices[ii + 1]; - if (z < meshBoundsMin.z) - meshBoundsMin.z = z; - else if (z > meshBoundsMax.z) - meshBoundsMax.z = z; } } else { SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment; @@ -451,10 +442,6 @@ public class SkeletonRenderer : MonoBehaviour { meshBoundsMin.y = tempVertices[ii + 1]; else if (tempVertices[ii + 1] > meshBoundsMax.y) meshBoundsMax.y = tempVertices[ii + 1]; - if (z < meshBoundsMin.z) - meshBoundsMin.z = z; - else if (z > meshBoundsMax.z) - meshBoundsMax.z = z; } } } @@ -553,34 +540,25 @@ public class SkeletonRenderer : MonoBehaviour { // Check attachments int attachmentCount = attachmentsTriangleCountTemp.Count; - if (attachmentsTriangleCountCurrentMesh.Count != attachmentCount) { - mustUpdateMeshStructure = true; - } else { - for (int i = 0; i < attachmentCount; i++) { - if (attachmentsTriangleCountCurrentMesh.Items[i] != attachmentsTriangleCountTemp.Items[i]) { - mustUpdateMeshStructure = true; - break; - } - } - } - - if (mustUpdateMeshStructure) + if (attachmentsTriangleCountCurrentMesh.Count != attachmentCount) return true; + for (int i = 0; i < attachmentCount; i++) { + if (attachmentsTriangleCountCurrentMesh.Items[i] != attachmentsTriangleCountTemp.Items[i]) + return true; + } + // Check submeshes int submeshCount = addSubmeshArgumentsTemp.Count; - if (addSubmeshArgumentsCurrentMesh.Count != submeshCount) { - mustUpdateMeshStructure = true; - } else { - for (int i = 0; i < submeshCount; i++) { - if (!addSubmeshArgumentsCurrentMesh.Items[i].Equals(addSubmeshArgumentsTemp.Items[i])) { - mustUpdateMeshStructure = true; - break; - } - } + if (addSubmeshArgumentsCurrentMesh.Count != submeshCount) + return true; + + for (int i = 0; i < submeshCount; i++) { + if (!addSubmeshArgumentsCurrentMesh.Items[i].Equals(ref addSubmeshArgumentsTemp.Items[i])) + return true; } - return mustUpdateMeshStructure; + return false; } /** Stores vertices and triangles for a single material. */ @@ -737,7 +715,7 @@ public class SkeletonRenderer : MonoBehaviour { this.lastSubmesh = lastSubmesh; } - public bool Equals(AddSubmeshArguments other) { + public bool Equals(ref AddSubmeshArguments other) { return !ReferenceEquals(material, null) && !ReferenceEquals(other.material, null) && From dcab4d975b52e70c31a455b383b203a52c2ec903 Mon Sep 17 00:00:00 2001 From: ZimM Date: Wed, 20 May 2015 02:45:15 +0300 Subject: [PATCH 20/24] fixed frontFacing stuff --- .../Assets/spine-unity/SkeletonRenderer.cs | 91 +++++++++++-------- 1 file changed, 55 insertions(+), 36 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index cac9778c2..d53bd8efe 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -183,15 +183,25 @@ public class SkeletonRenderer : MonoBehaviour { ExposedList attachmentsTriangleCountTemp = lastState.attachmentsTriangleCountTemp; attachmentsTriangleCountTemp.GrowIfNeeded(drawOrderCount); attachmentsTriangleCountTemp.Count = drawOrderCount; + ExposedList attachmentsFlipStateTemp = lastState.attachmentsFlipStateTemp; + attachmentsFlipStateTemp.GrowIfNeeded(drawOrderCount); + attachmentsFlipStateTemp.Count = drawOrderCount; ExposedList addSubmeshArgumentsTemp = lastState.addSubmeshArgumentsTemp; addSubmeshArgumentsTemp.Clear(false); for (int i = 0; i < drawOrderCount; i++) { Slot slot = drawOrder.Items[i]; + Bone bone = slot.bone; Attachment attachment = slot.attachment; object rendererObject; int attachmentVertexCount, attachmentTriangleCount; + bool worldScaleXIsPositive = bone.worldScaleX >= 0f; + bool worldScaleYIsPositive = bone.worldScaleY >= 0f; + bool worldScaleIsSameSigns = (worldScaleXIsPositive && worldScaleYIsPositive) || + (!worldScaleXIsPositive && !worldScaleYIsPositive); + bool flip = frontFacing && ((bone.worldFlipX != bone.worldFlipY) == worldScaleIsSameSigns); + attachmentsFlipStateTemp.Items[i] = flip; attachmentsTriangleCountTemp.Items[i] = -1; RegionAttachment regionAttachment = attachment as RegionAttachment; @@ -240,7 +250,7 @@ public class SkeletonRenderer : MonoBehaviour { new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true) ); - bool mustUpdateMeshStructure = MustUpdateMeshStructure(attachmentsTriangleCountTemp, addSubmeshArgumentsTemp); + bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(attachmentsTriangleCountTemp, attachmentsFlipStateTemp, addSubmeshArgumentsTemp); if (mustUpdateMeshStructure) { submeshMaterials.Clear(); for (int i = 0, n = addSubmeshArgumentsTemp.Count; i < n; i++) { @@ -251,7 +261,8 @@ public class SkeletonRenderer : MonoBehaviour { arguments.endSlot, arguments.triangleCount, arguments.firstVertex, - arguments.lastSubmesh + arguments.lastSubmesh, + attachmentsFlipStateTemp ); } @@ -487,38 +498,39 @@ public class SkeletonRenderer : MonoBehaviour { } // Update previous state - ExposedList attachmentsTriangleCountCurrentMesh = - useMesh1 ? - lastState.attachmentsTriangleCountMesh1 : - lastState.attachmentsTriangleCountMesh2; - ExposedList addSubmeshArgumentsCurrentMesh = - useMesh1 ? - lastState.addSubmeshArgumentsMesh1 : - lastState.addSubmeshArgumentsMesh2; + ExposedList attachmentsTriangleCountCurrentMesh; + ExposedList attachmentsFlipStateCurrentMesh; + ExposedList addSubmeshArgumentsCurrentMesh; + if (useMesh1) { + attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh1; + addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh1; + attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh1; + lastState.immutableTrianglesMesh1 = immutableTriangles; + } else { + attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh2; + addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh2; + attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh2; + lastState.immutableTrianglesMesh2 = immutableTriangles; + } attachmentsTriangleCountCurrentMesh.GrowIfNeeded(attachmentsTriangleCountTemp.Capacity); attachmentsTriangleCountCurrentMesh.Count = attachmentsTriangleCountTemp.Count; attachmentsTriangleCountTemp.CopyTo(attachmentsTriangleCountCurrentMesh.Items, 0); + attachmentsFlipStateCurrentMesh.GrowIfNeeded(attachmentsFlipStateTemp.Capacity); + attachmentsFlipStateCurrentMesh.Count = attachmentsFlipStateTemp.Count; + attachmentsFlipStateTemp.CopyTo(attachmentsFlipStateCurrentMesh.Items, 0); + addSubmeshArgumentsCurrentMesh.GrowIfNeeded(addSubmeshArgumentsTemp.Count); addSubmeshArgumentsCurrentMesh.Count = addSubmeshArgumentsTemp.Count; addSubmeshArgumentsTemp.CopyTo(addSubmeshArgumentsCurrentMesh.Items); - if (useMesh1) { - lastState.frontFacingMesh1 = frontFacing; - lastState.immutableTrianglesMesh1 = immutableTriangles; - } else { - lastState.frontFacingMesh2 = frontFacing; - lastState.immutableTrianglesMesh2 = immutableTriangles; - } - useMesh1 = !useMesh1; } - private bool MustUpdateMeshStructure(ExposedList attachmentsTriangleCountTemp, ExposedList addSubmeshArgumentsTemp) { + private bool CheckIfMustUpdateMeshStructure(ExposedList attachmentsTriangleCountTemp, ExposedList attachmentsFlipStateTemp, ExposedList addSubmeshArgumentsTemp) { // Check if any mesh settings were changed bool mustUpdateMeshStructure = - frontFacing != (useMesh1 ? lastState.frontFacingMesh1 : lastState.frontFacingMesh2) || immutableTriangles != (useMesh1 ? lastState.immutableTrianglesMesh1 : lastState.immutableTrianglesMesh2); #if UNITY_EDITOR mustUpdateMeshStructure |= !Application.isPlaying; @@ -529,14 +541,18 @@ public class SkeletonRenderer : MonoBehaviour { // Check if any attachments were enabled/disabled // or submesh structures has changed - ExposedList attachmentsTriangleCountCurrentMesh = - useMesh1 ? - lastState.attachmentsTriangleCountMesh1 : - lastState.attachmentsTriangleCountMesh2; - ExposedList addSubmeshArgumentsCurrentMesh = - useMesh1 ? - lastState.addSubmeshArgumentsMesh1 : - lastState.addSubmeshArgumentsMesh2; + ExposedList attachmentsTriangleCountCurrentMesh; + ExposedList attachmentsFlipStateCurrentMesh; + ExposedList addSubmeshArgumentsCurrentMesh; + if (useMesh1) { + attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh1; + addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh1; + attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh1; + } else { + attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh2; + addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh2; + attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh2; + } // Check attachments int attachmentCount = attachmentsTriangleCountTemp.Count; @@ -548,6 +564,12 @@ public class SkeletonRenderer : MonoBehaviour { return true; } + // Check flip state + for (int i = 0; i < attachmentCount; i++) { + if (attachmentsFlipStateCurrentMesh.Items[i] != attachmentsFlipStateTemp.Items[i]) + return true; + } + // Check submeshes int submeshCount = addSubmeshArgumentsTemp.Count; if (addSubmeshArgumentsCurrentMesh.Count != submeshCount) @@ -562,7 +584,7 @@ public class SkeletonRenderer : MonoBehaviour { } /** Stores vertices and triangles for a single material. */ - private void AddSubmesh (Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) { + private void AddSubmesh (Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh, ExposedList flipStates) { int submeshIndex = submeshMaterials.Count; submeshMaterials.Add(material); @@ -611,11 +633,7 @@ public class SkeletonRenderer : MonoBehaviour { Attachment attachment = slot.attachment; Bone bone = slot.bone; - bool worldScaleXIsPositive = bone.worldScaleX >= 0f; - bool worldScaleYIsPositive = bone.worldScaleY >= 0f; - bool worldScaleIsSameSigns = (worldScaleXIsPositive && worldScaleYIsPositive) || - (!worldScaleXIsPositive && !worldScaleYIsPositive); - bool flip = frontFacing && ((bone.worldFlipX != bone.worldFlipY) != worldScaleIsSameSigns); + bool flip = flipStates.Items[i]; if (attachment is RegionAttachment) { if (!flip) { @@ -686,11 +704,12 @@ public class SkeletonRenderer : MonoBehaviour { #endif private class LastState { - public bool frontFacingMesh1; - public bool frontFacingMesh2; public bool immutableTrianglesMesh1; public bool immutableTrianglesMesh2; public int vertexCount; + public readonly ExposedList attachmentsFlipStateTemp = new ExposedList(); + public readonly ExposedList attachmentsFlipStateMesh1 = new ExposedList(); + public readonly ExposedList attachmentsFlipStateMesh2 = new ExposedList(); public readonly ExposedList attachmentsTriangleCountTemp = new ExposedList(); public readonly ExposedList attachmentsTriangleCountMesh1 = new ExposedList(); public readonly ExposedList attachmentsTriangleCountMesh2 = new ExposedList(); From 5336eedc2f9c7362e53ff03a08b6db7d18b48afd Mon Sep 17 00:00:00 2001 From: ZimM Date: Wed, 20 May 2015 02:46:11 +0300 Subject: [PATCH 21/24] actually implemented ExposedList.Clear(bool clearArray) --- spine-csharp/src/ExposedList.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spine-csharp/src/ExposedList.cs b/spine-csharp/src/ExposedList.cs index 0f17a6e2b..efac67ac2 100644 --- a/spine-csharp/src/ExposedList.cs +++ b/spine-csharp/src/ExposedList.cs @@ -142,7 +142,9 @@ namespace Spine { } public void Clear(bool clearArray = true) { - Array.Clear(Items, 0, Items.Length); + if (clearArray) + Array.Clear(Items, 0, Items.Length); + Count = 0; version++; } From 292f8a6404e3f1faf1cd217cf67115bbd4b600e2 Mon Sep 17 00:00:00 2001 From: ZimM Date: Wed, 20 May 2015 03:11:45 +0300 Subject: [PATCH 22/24] fixed SkeletonUtilitySubmeshRenderer --- .../Assets/spine-unity/SkeletonRenderer.cs | 10 +++++++++- .../SkeletonUtilitySubmeshRenderer.cs | 18 +++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index d53bd8efe..a89e18f2e 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -63,6 +63,7 @@ public class SkeletonRenderer : MonoBehaviour { private MeshFilter meshFilter; private Mesh mesh1, mesh2; private bool useMesh1; + private bool meshUpdateRequested; private float[] tempVertices = new float[8]; private Vector3[] vertices; private Color32[] colors; @@ -72,6 +73,10 @@ public class SkeletonRenderer : MonoBehaviour { private readonly ExposedList submeshMaterials = new ExposedList(); private readonly ExposedList submeshes = new ExposedList(); + public void RequestMeshUpdate() { + meshUpdateRequested = true; + } + public virtual void Reset () { if (meshFilter != null) meshFilter.sharedMesh = null; @@ -167,9 +172,12 @@ public class SkeletonRenderer : MonoBehaviour { } public virtual void LateUpdate () { - if (!valid || !meshRenderer.enabled) + if (!valid || (!meshRenderer.enabled && !meshUpdateRequested)) return; + // The force update request is only valid for one frame + meshUpdateRequested = false; + // Count vertices and submesh triangles. int vertexCount = 0; int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs index 40e3ffbc5..c20e61998 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs @@ -11,9 +11,11 @@ public class SkeletonUtilitySubmeshRenderer : MonoBehaviour { public int sortingLayerID = 0; public Material hiddenPassMaterial; Renderer cachedRenderer; + SkeletonRenderer parentSkeletonRenderer; MeshFilter filter; Material[] sharedMaterials; MeshFilter parentFilter; + bool isFirstUpdate = true; void Awake () { cachedRenderer = GetComponent(); @@ -43,23 +45,29 @@ public class SkeletonUtilitySubmeshRenderer : MonoBehaviour { parentFilter = parentRenderer.GetComponent(); mesh = parentFilter.sharedMesh; filter.sharedMesh = mesh; - Debug.Log("Mesh: " + mesh); + parentSkeletonRenderer = parentRenderer.GetComponent(); + Debug.Log("Mesh: " + (mesh == null ? "null" : mesh.name), parentFilter); } public void Update () { + if (cachedRenderer == null) + cachedRenderer = GetComponent(); + + if (isFirstUpdate || cachedRenderer.enabled) { + parentSkeletonRenderer.RequestMeshUpdate(); + isFirstUpdate = false; + } + if (mesh == null || mesh != parentFilter.sharedMesh) { mesh = parentFilter.sharedMesh; filter.sharedMesh = mesh; } - if (cachedRenderer == null) - cachedRenderer = GetComponent(); - if (mesh == null || submeshIndex > mesh.subMeshCount - 1) { cachedRenderer.enabled = false; return; } else { - GetComponent().enabled = true; + cachedRenderer.enabled = true; } bool changed = false; From 7414476841a2fe1da9c066461ab6b2473f87d652 Mon Sep 17 00:00:00 2001 From: ZimM Date: Mon, 29 Jun 2015 19:24:07 +0200 Subject: [PATCH 23/24] fix SubmeshRenderer --- .../Assets/spine-unity/SkeletonRenderer.cs | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index d5d122826..8d6a9b441 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -63,7 +63,6 @@ public class SkeletonRenderer : MonoBehaviour { private MeshFilter meshFilter; private Mesh mesh1, mesh2; private bool useMesh1; - private bool meshUpdateRequested; private float[] tempVertices = new float[8]; private Vector3[] vertices; private Color32[] colors; @@ -74,10 +73,6 @@ public class SkeletonRenderer : MonoBehaviour { private SkeletonUtilitySubmeshRenderer[] submeshRenderers; private LastState lastState = new LastState(); - public void RequestMeshUpdate() { - meshUpdateRequested = true; - } - public virtual void Reset () { if (meshFilter != null) meshFilter.sharedMesh = null; @@ -181,11 +176,12 @@ public class SkeletonRenderer : MonoBehaviour { } public virtual void LateUpdate () { - if (!valid || (!meshRenderer.enabled && !meshUpdateRequested)) + if (!valid) return; - // The force update request is only valid for one frame - meshUpdateRequested = false; + // Exit early if there is nothing to render + if (!meshRenderer.enabled && submeshRenderers.Length == 0) + return; // Count vertices and submesh triangles. int vertexCount = 0; @@ -456,7 +452,7 @@ public class SkeletonRenderer : MonoBehaviour { color.r = (byte)(r * slot.r * skinnedMeshAttachment.r * color.a); color.g = (byte)(g * slot.g * skinnedMeshAttachment.g * color.a); color.b = (byte)(b * slot.b * skinnedMeshAttachment.b * color.a); - if (slot.data.blendMode == BlendMode.additive) color.a = 0; + if (slot.data.blendMode == BlendMode.additive) color.a = 0; float[] meshUVs = skinnedMeshAttachment.uvs; float z = i * zSpacing; @@ -549,14 +545,14 @@ public class SkeletonRenderer : MonoBehaviour { addSubmeshArgumentsTemp.CopyTo(addSubmeshArgumentsCurrentMesh.Items); if (submeshRenderers.Length > 0) { - for (int i = 0; i < submeshRenderers.Length; i++) { - SkeletonUtilitySubmeshRenderer submeshRenderer = submeshRenderers[i]; - if (submeshRenderer.submeshIndex < sharedMaterials.Length) { - submeshRenderer.SetMesh(meshRenderer, useMesh1 ? mesh1 : mesh2, sharedMaterials[submeshRenderer.submeshIndex]); - } else { - submeshRenderer.GetComponent().enabled = false; - } - } + for (int i = 0; i < submeshRenderers.Length; i++) { + SkeletonUtilitySubmeshRenderer submeshRenderer = submeshRenderers[i]; + if (submeshRenderer.submeshIndex < sharedMaterials.Length) { + submeshRenderer.SetMesh(meshRenderer, useMesh1 ? mesh1 : mesh2, sharedMaterials[submeshRenderer.submeshIndex]); + } else { + submeshRenderer.GetComponent().enabled = false; + } + } } useMesh1 = !useMesh1; From 83624a2259698b39ce1feaf102e0f4c8cfe362b5 Mon Sep 17 00:00:00 2001 From: ZimM Date: Mon, 29 Jun 2015 21:02:29 +0200 Subject: [PATCH 24/24] fixed warning --- spine-unity/Assets/spine-unity/SkeletonRenderer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index 8d6a9b441..c544a9891 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -661,7 +661,6 @@ public class SkeletonRenderer : MonoBehaviour { for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) { Slot slot = drawOrder.Items[i]; Attachment attachment = slot.attachment; - Bone bone = slot.bone; bool flip = flipStates.Items[i];