From 8c4b0eccacda354796b6abd1224207ef8636f490 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 5 Feb 2016 00:55:03 +0600 Subject: [PATCH] IsoList for fast Pop --- Assembly-CSharp-Editor.csproj | 1 + Assembly-CSharp.csproj | 1 + .../Scripts/Internal/Editor/IsoListTests.cs | 157 ++++++++++++++++++ .../Internal/Editor/IsoListTests.cs.meta | 12 ++ Assets/IsoTools/Scripts/Internal/IsoList.cs | 110 ++++++++++++ .../IsoTools/Scripts/Internal/IsoList.cs.meta | 12 ++ Assets/IsoTools/Scripts/IsoObject.cs | 6 +- Assets/IsoTools/Scripts/IsoWorld.cs | 35 ++-- .../Internal/Editor/TiledMapAssetEditor.cs | 2 +- .../Tiled/Internal/Editor/TiledMapEditor.cs | 2 +- .../Internal/Editor/TiledMapLayerEditor.cs | 2 +- .../Internal/Editor/TiledMapPostprocessor.cs | 2 +- .../Editor/TiledMapPropertiesTests.cs | 2 +- .../Internal/Editor/TiledMapTileEditor.cs | 2 +- 14 files changed, 318 insertions(+), 28 deletions(-) create mode 100644 Assets/IsoTools/Scripts/Internal/Editor/IsoListTests.cs create mode 100644 Assets/IsoTools/Scripts/Internal/Editor/IsoListTests.cs.meta create mode 100644 Assets/IsoTools/Scripts/Internal/IsoList.cs create mode 100644 Assets/IsoTools/Scripts/Internal/IsoList.cs.meta diff --git a/Assembly-CSharp-Editor.csproj b/Assembly-CSharp-Editor.csproj index 6435827..59175ec 100644 --- a/Assembly-CSharp-Editor.csproj +++ b/Assembly-CSharp-Editor.csproj @@ -45,6 +45,7 @@ + diff --git a/Assembly-CSharp.csproj b/Assembly-CSharp.csproj index 7041f62..e080e67 100644 --- a/Assembly-CSharp.csproj +++ b/Assembly-CSharp.csproj @@ -54,6 +54,7 @@ + diff --git a/Assets/IsoTools/Scripts/Internal/Editor/IsoListTests.cs b/Assets/IsoTools/Scripts/Internal/Editor/IsoListTests.cs new file mode 100644 index 0000000..b3fb2de --- /dev/null +++ b/Assets/IsoTools/Scripts/Internal/Editor/IsoListTests.cs @@ -0,0 +1,157 @@ +using System; +using NUnit.Framework; + +namespace IsoTools.Internal { + class IsoListTests { + + [Test] + public void Test00() { + var list1 = new IsoList(); + Assert.AreEqual(list1.Count, 0); + Assert.AreEqual(list1.Capacity, 0); + + var list2 = new IsoList(0); + Assert.AreEqual(list2.Count, 0); + Assert.AreEqual(list2.Capacity, 0); + + var list3 = new IsoList(1); + Assert.AreEqual(list3.Count, 0); + Assert.AreEqual(list3.Capacity, 1); + + var list4 = new IsoList(); + list4.Push(1); + Assert.AreEqual(list4.Count, 1); + Assert.AreEqual(list4.Capacity, 4); + } + + [Test] + public void Test01() { + var list1 = new IsoList(1); + list1.Push(1); + Assert.AreEqual(list1.Count, 1); + Assert.AreEqual(list1.Capacity, 1); + Assert.AreEqual(list1[0], 1); + list1.Push(2); + Assert.AreEqual(list1.Count, 2); + Assert.AreEqual(list1.Capacity, 2); + Assert.AreEqual(list1[0], 1); + Assert.AreEqual(list1[1], 2); + list1.Push(3); + Assert.AreEqual(list1.Count, 3); + Assert.AreEqual(list1.Capacity, 4); + Assert.AreEqual(list1[0], 1); + Assert.AreEqual(list1[1], 2); + Assert.AreEqual(list1[2], 3); + } + + [Test] + public void Test02() { + var list1 = new IsoList(); + list1.Push(1); + list1.Push(2); + list1.Push(3); + Assert.AreEqual(list1.Peek(), 3); + Assert.AreEqual(list1.Pop(), 3); + Assert.AreEqual(list1.Count, 2); + Assert.AreEqual(list1.Capacity, 4); + Assert.AreEqual(list1[0], 1); + Assert.AreEqual(list1[1], 2); + Assert.AreEqual(list1.Peek(), 2); + Assert.AreEqual(list1.Pop(), 2); + Assert.AreEqual(list1.Count, 1); + Assert.AreEqual(list1.Capacity, 4); + Assert.AreEqual(list1[0], 1); + Assert.AreEqual(list1.Peek(), 1); + Assert.AreEqual(list1.Pop(), 1); + Assert.AreEqual(list1.Count, 0); + Assert.AreEqual(list1.Capacity, 4); + } + + [Test] + public void Test03() { + var list1 = new IsoList(); + list1.Push(1); + list1.Push(2); + list1.Push(3); + list1.Clear(); + Assert.AreEqual(list1.Count, 0); + Assert.AreEqual(list1.Capacity, 4); + } + + [Test] + public void Test04() { + var list1 = new IsoList(); + list1.Push(1); + list1.Push(2); + list1.Push(3); + list1.Push(4); + Assert.AreEqual(list1.UnorderedRemoveAt(1), 4); + Assert.AreEqual(list1[0], 1); + Assert.AreEqual(list1[1], 4); + Assert.AreEqual(list1[2], 3); + Assert.AreEqual(list1.Count, 3); + Assert.AreEqual(list1.Capacity, 4); + Assert.AreEqual(list1.UnorderedRemoveAt(0), 3); + Assert.AreEqual(list1[0], 3); + Assert.AreEqual(list1[1], 4); + Assert.AreEqual(list1.Count, 2); + Assert.AreEqual(list1.Capacity, 4); + Assert.AreEqual(list1.UnorderedRemoveAt(1), 4); + Assert.AreEqual(list1[0], 3); + Assert.AreEqual(list1.Count, 1); + Assert.AreEqual(list1.Capacity, 4); + Assert.AreEqual(list1.UnorderedRemoveAt(0), 3); + Assert.AreEqual(list1.Count, 0); + Assert.AreEqual(list1.Capacity, 4); + } + + [Test] + public void Test05() { + var list = new IsoList(); + list.Capacity = 10; + Assert.AreEqual(list.Count, 0); + Assert.AreEqual(list.Capacity, 10); + list.Push(1); + list.Push(2); + list.Capacity = 20; + Assert.AreEqual(list[0], 1); + Assert.AreEqual(list[1], 2); + Assert.AreEqual(list.Count, 2); + Assert.AreEqual(list.Capacity, 20); + list.Capacity = 2; + Assert.AreEqual(list[0], 1); + Assert.AreEqual(list[1], 2); + Assert.AreEqual(list.Count, 2); + Assert.AreEqual(list.Capacity, 2); + } + + [Test] + public void Test06() { + Assert.Throws(() => { + new IsoList(-1); + }); + Assert.Throws(() => { + var list = new IsoList(); + list.Pop(); + }); + Assert.Throws(() => { + var list = new IsoList(); + list.Peek(); + }); + Assert.Throws(() => { + var list = new IsoList(); + list.UnorderedRemoveAt(0); + }); + Assert.Throws(() => { + var list = new IsoList(); + Assert.AreEqual(list[0], 100500); + }); + Assert.Throws(() => { + var list = new IsoList(); + list.Push(1); + list.Push(2); + list.Capacity = 1; + }); + } + } +} diff --git a/Assets/IsoTools/Scripts/Internal/Editor/IsoListTests.cs.meta b/Assets/IsoTools/Scripts/Internal/Editor/IsoListTests.cs.meta new file mode 100644 index 0000000..6f3d4de --- /dev/null +++ b/Assets/IsoTools/Scripts/Internal/Editor/IsoListTests.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: be01881a4a8e243219f6ceabae9b7876 +timeCreated: 1454601114 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/IsoTools/Scripts/Internal/IsoList.cs b/Assets/IsoTools/Scripts/Internal/IsoList.cs new file mode 100644 index 0000000..3ebf9e5 --- /dev/null +++ b/Assets/IsoTools/Scripts/Internal/IsoList.cs @@ -0,0 +1,110 @@ +using System; + +namespace IsoTools.Internal { + public class IsoList { + T[] _data; + int _size; + + static readonly T[] _emptyData = new T[0]; + const int _defaultCapacity = 4; + + public IsoList() { + _data = _emptyData; + _size = 0; + } + + public IsoList(int capacity) { + if ( capacity < 0 ) { + throw new ArgumentOutOfRangeException( + "capacity", "capacity must be >= 0"); + } else if ( capacity == 0 ) { + _data = _emptyData; + _size = 0; + } else { + _data = new T[capacity]; + _size = 0; + } + } + + public void Push(T value) { + if ( _size == _data.Length ) { + var new_capacity = _size == 0 + ? _defaultCapacity : _size * 2; + var new_data = new T[new_capacity]; + Array.Copy(_data, new_data, _size); + _data = new_data; + } + _data[_size++] = value; + } + + public T Pop() { + if ( _size == 0 ) { + throw new InvalidOperationException("empty list"); + } + var last = _data[--_size]; + _data[_size] = default(T); + return last; + } + + public T Peek() { + if ( _size == 0 ) { + throw new InvalidOperationException("empty list"); + } + return _data[_size - 1]; + } + + public void Clear() { + Array.Clear(_data, 0, _size); + _size = 0; + } + + public T UnorderedRemoveAt(int index) { + if ( (uint)index >= (uint)_size ) { + throw new IndexOutOfRangeException(); + } + var last = _data[_size - 1]; + _data[index] = last; + _data[--_size] = default(T); + return last; + } + + public T this[int index] { + get { + if ( (uint)index >= (uint)_size ) { + throw new IndexOutOfRangeException(); + } + return _data[index]; + } + set { + if ( (uint)index >= (uint)_size ) { + throw new IndexOutOfRangeException(); + } + _data[index] = value; + } + } + + public int Count { + get { return _size; } + } + + public int Capacity { + get { return _data.Length; } + set { + if ( value < _size ) { + throw new ArgumentOutOfRangeException("capacity"); + } + if ( value != _data.Length ) { + if ( value > 0 ) { + var new_data = new T[value]; + if ( _size > 0 ) { + Array.Copy(_data, new_data, _size); + } + _data = new_data; + } else { + _data = _emptyData; + } + } + } + } + } +} diff --git a/Assets/IsoTools/Scripts/Internal/IsoList.cs.meta b/Assets/IsoTools/Scripts/Internal/IsoList.cs.meta new file mode 100644 index 0000000..bdf2337 --- /dev/null +++ b/Assets/IsoTools/Scripts/Internal/IsoList.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 76d2adce009b1461aa61e3122c5fcc3d +timeCreated: 1454599127 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/IsoTools/Scripts/IsoObject.cs b/Assets/IsoTools/Scripts/IsoObject.cs index bd7ceae..e428465 100644 --- a/Assets/IsoTools/Scripts/IsoObject.cs +++ b/Assets/IsoTools/Scripts/IsoObject.cs @@ -166,14 +166,14 @@ namespace IsoTools { public class InternalState { public bool Dirty = false; - public bool Visited = false; + public bool Placed = false; public Rect ScreenRect = new Rect(); public float Offset3d = 0.0f; public IsoUtils.MinMax MinMax3d = IsoUtils.MinMax.zero; public Vector2 MinSector = Vector2.zero; public Vector2 MaxSector = Vector2.zero; public Dictionary SelfDependsD = new Dictionary(); - public List SelfDependsL = new List(); + public IsoList SelfDependsL = new IsoList(); public HashSet TheirDepends = new HashSet(); } @@ -279,7 +279,7 @@ namespace IsoTools { void Awake() { Internal.SelfDependsD = new Dictionary(47); - Internal.SelfDependsL = new List(47); + Internal.SelfDependsL = new IsoList(47); Internal.TheirDepends = new HashSet(new IsoObject[47]); Internal.TheirDepends.Clear(); FixLastProperties(); diff --git a/Assets/IsoTools/Scripts/IsoWorld.cs b/Assets/IsoTools/Scripts/IsoWorld.cs index 21ce2b9..93a52fd 100644 --- a/Assets/IsoTools/Scripts/IsoWorld.cs +++ b/Assets/IsoTools/Scripts/IsoWorld.cs @@ -21,17 +21,17 @@ namespace IsoTools { List _tmpRenderers = new List(); class Sector { - public List objects = new List(); + public IsoList objects = new IsoList(); public void Reset() { objects.Clear(); } } - List _sectors = new List(); - float _sectorsSize = 0.0f; - Vector2 _sectorsMinNumPos = Vector2.zero; - Vector2 _sectorsMaxNumPos = Vector2.zero; - Vector2 _sectorsNumPosCount = Vector2.zero; + IsoList _sectors = new IsoList(); + float _sectorsSize = 0.0f; + Vector2 _sectorsMinNumPos = Vector2.zero; + Vector2 _sectorsMaxNumPos = Vector2.zero; + Vector2 _sectorsNumPosCount = Vector2.zero; // --------------------------------------------------------------------- // @@ -445,7 +445,7 @@ namespace IsoTools { var a_depends_l = obj_a.Internal.SelfDependsL; if ( !a_depends_d.ContainsKey(obj_b) ) { a_depends_d.Add(obj_b, a_depends_l.Count); - a_depends_l.Add(obj_b); + a_depends_l.Push(obj_b); } obj_b.Internal.TheirDepends.Add(obj_a); } @@ -463,7 +463,7 @@ namespace IsoTools { var b_depends_l = obj_b.Internal.SelfDependsL; if ( !b_depends_d.ContainsKey(obj_a) ) { b_depends_d.Add(obj_a, b_depends_l.Count); - b_depends_l.Add(obj_a); + b_depends_l.Push(obj_a); } obj_a.Internal.TheirDepends.Add(obj_b); } @@ -501,7 +501,7 @@ namespace IsoTools { _sectors.Capacity = count; } while ( _sectors.Count < _sectors.Capacity ) { - _sectors.Add(new Sector()); + _sectors.Push(new Sector()); } } for ( int i = 0, e = _sectors.Count; i < e; ++i ) { @@ -521,7 +521,7 @@ namespace IsoTools { for ( var x = min.x; x < max.x; ++x ) { var sector = FindSector(new Vector2(x, y)); if ( sector != null ) { - sector.objects.Add(iso_object); + sector.objects.Push(iso_object); } }} } @@ -566,7 +566,7 @@ namespace IsoTools { while ( objects_iter.MoveNext() ) { var iso_object = objects_iter.Current; if ( IsIsoObjectVisible(iso_object) ) { - iso_object.Internal.Visited = false; + iso_object.Internal.Placed = false; _oldVisibles.Add(iso_object); } } @@ -609,12 +609,10 @@ namespace IsoTools { int index; if ( their_depends_d.TryGetValue(iso_object, out index) ) { their_depends_d.Remove(iso_object); - if ( index != their_depends_l.Count - 1 ) { - var last_obj = their_depends_l[their_depends_l.Count - 1]; - their_depends_d[last_obj] = index; - their_depends_l[index] = last_obj; + var reordered = their_depends_l.UnorderedRemoveAt(index); + if ( reordered != iso_object ) { + their_depends_d[reordered] = index; } - their_depends_l.RemoveAt(their_depends_l.Count - 1); } } } @@ -644,11 +642,10 @@ namespace IsoTools { } float RecursivePlaceIsoObject(IsoObject iso_object, float depth) { - if ( iso_object.Internal.Visited ) { + if ( iso_object.Internal.Placed ) { return depth; } - iso_object.Internal.Visited = true; - + iso_object.Internal.Placed = true; var depends_l = iso_object.Internal.SelfDependsL; for ( int i = 0, e = iso_object.Internal.SelfDependsL.Count; i < e; ++i ) { depth = RecursivePlaceIsoObject(depends_l[i], depth); diff --git a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapAssetEditor.cs b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapAssetEditor.cs index 1677a9f..ce520d2 100644 --- a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapAssetEditor.cs +++ b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapAssetEditor.cs @@ -8,7 +8,7 @@ using System.Linq; namespace IsoTools.Tiled.Internal { [CustomEditor(typeof(TiledMapAsset))] - public class TiledMapAssetEditor : Editor { + class TiledMapAssetEditor : Editor { TiledMapAsset _asset = null; // ------------------------------------------------------------------------ diff --git a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapEditor.cs b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapEditor.cs index 0e81901..79ffe36 100644 --- a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapEditor.cs +++ b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapEditor.cs @@ -5,7 +5,7 @@ using IsoTools.Internal; namespace IsoTools.Tiled.Internal { [CustomEditor(typeof(TiledMap)), CanEditMultipleObjects] - public class TiledMapMapEditor : Editor { + class TiledMapMapEditor : Editor { TiledMap _map = null; // ------------------------------------------------------------------------ diff --git a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapLayerEditor.cs b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapLayerEditor.cs index a1cf5ca..24e2a5c 100644 --- a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapLayerEditor.cs +++ b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapLayerEditor.cs @@ -5,7 +5,7 @@ using IsoTools.Internal; namespace IsoTools.Tiled.Internal { [CustomEditor(typeof(TiledMapLayer)), CanEditMultipleObjects] - public class TiledMapLayerEditor : Editor { + class TiledMapLayerEditor : Editor { TiledMapLayer _layer = null; // ------------------------------------------------------------------------ diff --git a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapPostprocessor.cs b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapPostprocessor.cs index 3a0ec9b..0550c4b 100644 --- a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapPostprocessor.cs +++ b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapPostprocessor.cs @@ -10,7 +10,7 @@ using System.Reflection; using System.Collections.Generic; namespace IsoTools.Tiled.Internal { - public class TiledMapPostprocessor : AssetPostprocessor { + class TiledMapPostprocessor : AssetPostprocessor { static void OnPostprocessAllAssets( string[] imported_assets, string[] deleted_assets, string[] moved_assets, string[] moved_from_asset_paths) diff --git a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapPropertiesTests.cs b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapPropertiesTests.cs index 4d82204..a96da72 100644 --- a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapPropertiesTests.cs +++ b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapPropertiesTests.cs @@ -3,7 +3,7 @@ using NUnit.Framework; using System.Collections.Generic; namespace IsoTools.Tiled.Internal { - public class TiledMapPropertiesTests { + class TiledMapPropertiesTests { [Test] public void Test00() { diff --git a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapTileEditor.cs b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapTileEditor.cs index 32097aa..5d1c18d 100644 --- a/Assets/IsoTools/Tiled/Internal/Editor/TiledMapTileEditor.cs +++ b/Assets/IsoTools/Tiled/Internal/Editor/TiledMapTileEditor.cs @@ -5,7 +5,7 @@ using IsoTools.Internal; namespace IsoTools.Tiled.Internal { [CustomEditor(typeof(TiledMapTile)), CanEditMultipleObjects] - public class TiledMapTileEditor : Editor { + class TiledMapTileEditor : Editor { TiledMapTile _tile = null; // ------------------------------------------------------------------------