IsoList for fast Pop

This commit is contained in:
2016-02-05 00:55:03 +06:00
parent ba1c51fcb7
commit 8c4b0eccac
14 changed files with 318 additions and 28 deletions

View File

@@ -0,0 +1,157 @@
using System;
using NUnit.Framework;
namespace IsoTools.Internal {
class IsoListTests {
[Test]
public void Test00() {
var list1 = new IsoList<int>();
Assert.AreEqual(list1.Count, 0);
Assert.AreEqual(list1.Capacity, 0);
var list2 = new IsoList<int>(0);
Assert.AreEqual(list2.Count, 0);
Assert.AreEqual(list2.Capacity, 0);
var list3 = new IsoList<int>(1);
Assert.AreEqual(list3.Count, 0);
Assert.AreEqual(list3.Capacity, 1);
var list4 = new IsoList<int>();
list4.Push(1);
Assert.AreEqual(list4.Count, 1);
Assert.AreEqual(list4.Capacity, 4);
}
[Test]
public void Test01() {
var list1 = new IsoList<int>(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<int>();
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<int>();
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<int>();
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<int>();
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<ArgumentOutOfRangeException>(() => {
new IsoList<int>(-1);
});
Assert.Throws<InvalidOperationException>(() => {
var list = new IsoList<int>();
list.Pop();
});
Assert.Throws<InvalidOperationException>(() => {
var list = new IsoList<int>();
list.Peek();
});
Assert.Throws<IndexOutOfRangeException>(() => {
var list = new IsoList<int>();
list.UnorderedRemoveAt(0);
});
Assert.Throws<IndexOutOfRangeException>(() => {
var list = new IsoList<int>();
Assert.AreEqual(list[0], 100500);
});
Assert.Throws<ArgumentOutOfRangeException>(() => {
var list = new IsoList<int>();
list.Push(1);
list.Push(2);
list.Capacity = 1;
});
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: be01881a4a8e243219f6ceabae9b7876
timeCreated: 1454601114
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,110 @@
using System;
namespace IsoTools.Internal {
public class IsoList<T> {
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;
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 76d2adce009b1461aa61e3122c5fcc3d
timeCreated: 1454599127
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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<IsoObject, int> SelfDependsD = new Dictionary<IsoObject, int>();
public List<IsoObject> SelfDependsL = new List<IsoObject>();
public IsoList<IsoObject> SelfDependsL = new IsoList<IsoObject>();
public HashSet<IsoObject> TheirDepends = new HashSet<IsoObject>();
}
@@ -279,7 +279,7 @@ namespace IsoTools {
void Awake() {
Internal.SelfDependsD = new Dictionary<IsoObject, int>(47);
Internal.SelfDependsL = new List<IsoObject>(47);
Internal.SelfDependsL = new IsoList<IsoObject>(47);
Internal.TheirDepends = new HashSet<IsoObject>(new IsoObject[47]);
Internal.TheirDepends.Clear();
FixLastProperties();

View File

@@ -21,17 +21,17 @@ namespace IsoTools {
List<Renderer> _tmpRenderers = new List<Renderer>();
class Sector {
public List<IsoObject> objects = new List<IsoObject>();
public IsoList<IsoObject> objects = new IsoList<IsoObject>();
public void Reset() {
objects.Clear();
}
}
List<Sector> _sectors = new List<Sector>();
float _sectorsSize = 0.0f;
Vector2 _sectorsMinNumPos = Vector2.zero;
Vector2 _sectorsMaxNumPos = Vector2.zero;
Vector2 _sectorsNumPosCount = Vector2.zero;
IsoList<Sector> _sectors = new IsoList<Sector>();
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);

View File

@@ -8,7 +8,7 @@ using System.Linq;
namespace IsoTools.Tiled.Internal {
[CustomEditor(typeof(TiledMapAsset))]
public class TiledMapAssetEditor : Editor {
class TiledMapAssetEditor : Editor {
TiledMapAsset _asset = null;
// ------------------------------------------------------------------------

View File

@@ -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;
// ------------------------------------------------------------------------

View File

@@ -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;
// ------------------------------------------------------------------------

View File

@@ -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)

View File

@@ -3,7 +3,7 @@ using NUnit.Framework;
using System.Collections.Generic;
namespace IsoTools.Tiled.Internal {
public class TiledMapPropertiesTests {
class TiledMapPropertiesTests {
[Test]
public void Test00() {

View File

@@ -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;
// ------------------------------------------------------------------------