Browse Source

Svelto-ECS 1.0 Production Ready (Warning Breaking Changes)

Updated Context and Ticker Framework
Added Datastructures
tags/Rel1
sebas77 8 years ago
parent
commit
d0132bffe7
73 changed files with 2542 additions and 646 deletions
  1. +45
    -28
      Context/ContextNotifier.cs
  2. +1
    -1
      Context/Factories.meta
  3. +35
    -50
      Context/Factories/GameObjectFactory.cs
  4. +11
    -21
      Context/Factories/MonoBehaviourFactory.cs
  5. +5
    -6
      Context/ICompositionRoot.cs
  6. +1
    -1
      Context/IContextNotifer.cs
  7. +0
    -13
      Context/IUnityContextHierarchyChangedListener.cs
  8. +9
    -0
      Context/Legacy.meta
  9. +1
    -1
      Context/Unity.meta
  10. +0
    -28
      Context/Unity/NotifyComponentsRemoved.cs
  11. +32
    -52
      Context/UnityContext.cs
  12. +9
    -0
      DataStructures.meta
  13. +431
    -0
      DataStructures/FasterList.cs
  14. +10
    -0
      DataStructures/FasterList.cs.meta
  15. +655
    -0
      DataStructures/ReadOnlyDictionary.cs
  16. +12
    -0
      DataStructures/ReadOnlyDictionary.cs.meta
  17. +171
    -0
      DataStructures/ThreadSafeQueue.cs
  18. +1
    -1
      DataStructures/ThreadSafeQueue.cs.meta
  19. +56
    -0
      DataStructures/WeakReference.cs
  20. +12
    -0
      DataStructures/WeakReference.cs.meta
  21. +9
    -0
      ECS/Dispatcher.meta
  22. +19
    -0
      ECS/Dispatcher/Dispatcher.cs
  23. +0
    -0
      ECS/Dispatcher/Dispatcher.cs.meta
  24. +13
    -1
      ECS/Dispatcher/DispatcherOnChange.cs
  25. +1
    -1
      ECS/Dispatcher/DispatcherOnChange.cs.meta
  26. +0
    -5
      ECS/Engine.meta
  27. +0
    -14
      ECS/Engine/IEngine.cs
  28. +59
    -0
      ECS/EngineNodeDB.cs
  29. +12
    -0
      ECS/EngineNodeDB.cs.meta
  30. +138
    -34
      ECS/EnginesRoot.cs
  31. +97
    -0
      ECS/EntityDescriptor.cs
  32. +12
    -0
      ECS/EntityDescriptor.cs.meta
  33. +6
    -0
      ECS/IComponent.cs
  34. +2
    -2
      ECS/IComponent.cs.meta
  35. +37
    -0
      ECS/IEngine.cs
  36. +0
    -0
      ECS/IEngine.cs.meta
  37. +11
    -0
      ECS/IEngineNodeDB.cs
  38. +12
    -0
      ECS/IEngineNodeDB.cs.meta
  39. +2
    -3
      ECS/IEnginesRoot.cs
  40. +10
    -0
      ECS/IEntityDescriptorHolder.cs
  41. +2
    -2
      ECS/IEntityDescriptorHolder.cs.meta
  42. +17
    -0
      ECS/INode.cs
  43. +0
    -0
      ECS/INode.cs.meta
  44. +9
    -0
      ECS/IRemoveEntityComponent.cs
  45. +12
    -0
      ECS/IRemoveEntityComponent.cs.meta
  46. +0
    -5
      ECS/Node.meta
  47. +0
    -16
      ECS/Node/INode.cs
  48. +0
    -8
      ECS/Node/INodeHolder.cs
  49. +0
    -8
      ECS/Node/INodeHolder.cs.meta
  50. +0
    -5
      ECS/Unity.meta
  51. +0
    -64
      ECS/Unity/UnityNodeHolder.cs
  52. +0
    -8
      ECS/Unity/UnityNodeHolder.cs.meta
  53. +0
    -65
      ECS/UnityEnginesRoot.cs
  54. +0
    -8
      ECS/UnityEnginesRoot.cs.meta
  55. +111
    -0
      ECS/note.txt
  56. +4
    -0
      ECS/note.txt.meta
  57. +1
    -1
      Factories/IGameObjectFactory.cs
  58. +27
    -6
      Observer/Observable.cs
  59. +1
    -1
      Observer/Observable.cs.meta
  60. +72
    -19
      Observer/Observer.cs
  61. +1
    -1
      Observer/Observer.cs.meta
  62. +13
    -8
      Ticker/ITickable.cs
  63. +4
    -1
      Ticker/ITickable.cs.meta
  64. +4
    -8
      Ticker/ITicker.cs
  65. +4
    -1
      Ticker/ITicker.cs.meta
  66. +116
    -52
      Ticker/TickBehaviour.cs
  67. +4
    -1
      Ticker/TickBehaviour.cs.meta
  68. +26
    -25
      Ticker/UnityTicker.cs
  69. +4
    -1
      Ticker/UnityTicker.cs.meta
  70. +0
    -20
      Utilities/Dispatcher.cs
  71. +165
    -0
      Utilities/Print.cs
  72. +8
    -0
      Utilities/Print.cs.meta
  73. +0
    -50
      Utilities/WeakReference.cs

+ 45
- 28
Context/ContextNotifier.cs View File

@@ -1,28 +1,31 @@
using Svelto.DataStructures;
using System;
using System.Collections.Generic;

namespace Svelto.Context
{
class ContextNotifier: IContextNotifer
class ContextNotifier : IContextNotifer
{
public ContextNotifier()
{
_toInitialize = new List<WeakReference<IWaitForFrameworkInitialization>>();
_toDeinitialize = new List<WeakReference<IWaitForFrameworkDestruction>> ();
_toDeinitialize = new List<WeakReference<IWaitForFrameworkDestruction>>();
}

/// <summary>
/// A Context is meant to be initialized only once in its timelife
/// </summary>
public void NotifyFrameworkInitialized()
public void AddFrameworkDestructionListener(IWaitForFrameworkDestruction obj)
{
foreach (WeakReference<IWaitForFrameworkInitialization> obj in _toInitialize)
{
if (obj.IsAlive == true)
obj.Target.OnFrameworkInitialized();
}
if (_toDeinitialize != null)
_toDeinitialize.Add(new WeakReference<IWaitForFrameworkDestruction>(obj));
else
throw new Exception("An object is expected to be initialized after the framework has been deinitialized. Type: " + obj.GetType());
}

_toInitialize = null;
public void AddFrameworkInitializationListener(IWaitForFrameworkInitialization obj)
{
if (_toInitialize != null)
_toInitialize.Add(new WeakReference<IWaitForFrameworkInitialization>(obj));
else
throw new Exception("An object is expected to be initialized after the framework has been initialized. Type: " + obj.GetType());
}

/// <summary>
@@ -30,32 +33,46 @@ namespace Svelto.Context
/// </summary>
public void NotifyFrameworkDeinitialized()
{
foreach (WeakReference<IWaitForFrameworkDestruction> obj in _toDeinitialize)
for (int i = _toDeinitialize.Count - 1; i >= 0; --i)
{
if (obj.IsAlive == true)
obj.Target.OnFrameworkDestroyed();
try
{
var obj = _toDeinitialize[i];
if (obj.IsAlive == true)
(obj.Target as IWaitForFrameworkDestruction).OnFrameworkDestroyed();
}
catch (Exception e)
{
Utility.Console.LogException(e);
}
}

_toDeinitialize = null;
}

public void AddFrameworkInitializationListener(IWaitForFrameworkInitialization obj)
/// <summary>
/// A Context is meant to be initialized only once in its timelife
/// </summary>
public void NotifyFrameworkInitialized()
{
if (_toInitialize != null)
_toInitialize.Add(new WeakReference<IWaitForFrameworkInitialization>(obj));
else
throw new Exception("An object is expected to be initialized after the framework has been initialized. Type: " + obj.GetType());
}
for (int i = _toInitialize.Count - 1; i >= 0; --i)
{
try
{
var obj = _toInitialize[i];
if (obj.IsAlive == true)
(obj.Target as IWaitForFrameworkInitialization).OnFrameworkInitialized();
}
catch (Exception e)
{
Utility.Console.LogException(e);
}
}

public void AddFrameworkDestructionListener(IWaitForFrameworkDestruction obj)
{
if (_toDeinitialize != null)
_toDeinitialize.Add(new WeakReference<IWaitForFrameworkDestruction>(obj));
else
throw new Exception("An object is expected to be initialized after the framework has been deinitialized. Type: " + obj.GetType());
_toInitialize = null;
}

List<WeakReference<IWaitForFrameworkInitialization>> _toInitialize;
List<WeakReference<IWaitForFrameworkDestruction>> _toDeinitialize;
List<WeakReference<IWaitForFrameworkInitialization>> _toInitialize;
}
}

+ 1
- 1
Context/Factories.meta View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 88190f2317429cb49bfdf63e448efa52
guid: ec4bd87e898bf7c42823fb5ec2456b43
folderAsset: yes
timeCreated: 1431630831
licenseType: Free


+ 35
- 50
Context/Factories/GameObjectFactory.cs View File

@@ -7,37 +7,19 @@ using UnityEngine;

namespace Svelto.Context
{
public class GameObjectFactory: Factories.IGameObjectFactory
{
public GameObjectFactory(IUnityContextHierarchyChangedListener root)
{
_unityContext = root;

_prefabs = new Dictionary<string, GameObject[]>();
}
/// <summary>
/// Register a prefab to be built later using a string ID.
/// </summary>
/// <param name="prefab">original prefab</param>
/// <param name="prefabName">prefab name</param>
/// <param name="parent">optional gameobject to specify as parent later</param>

public void RegisterPrefab(GameObject prefab, string prefabName, GameObject parent = null)
{
var objects = new GameObject[2];
objects[0] = prefab; objects[1] = parent;
_prefabs.Add(prefabName, objects);
}
public GameObject Build(string prefabName)
{
DesignByContract.Check.Require(_prefabs.ContainsKey(prefabName), "Svelto.Factories.IGameObjectFactory - Invalid Prefab Type");
var go = Build(_prefabs[prefabName][0]);
public class GameObjectFactory : Factories.IGameObjectFactory
{
public GameObjectFactory()
{
_prefabs = new Dictionary<string, GameObject[]>();
}

public GameObject Build(string prefabName)
{
DesignByContract.Check.Require(_prefabs.ContainsKey(prefabName), "Svelto.Factories.IGameObjectFactory - Invalid Prefab Type");

var go = Build(_prefabs[prefabName][0]);

GameObject parent = _prefabs[prefabName][1];

if (parent != null)
@@ -54,31 +36,34 @@ namespace Svelto.Context

transform.localPosition = position;
transform.localRotation = rotation;
transform.localScale = scale;
transform.localScale = scale;
}
return go;
}

public GameObject Build(GameObject go)
{
var copy = Object.Instantiate(go) as GameObject;
var components = copy.GetComponentsInChildren<MonoBehaviour>(true);

for (var i = 0; i < components.Length; ++i)
if (components[i] != null)
_unityContext.OnMonobehaviourAdded(components[i]);
return go;
}

_unityContext.OnGameObjectAdded(copy);
/// <summary>
/// Register a prefab to be built later using a string ID.
/// </summary>
/// <param name="prefab">original prefab</param>
public GameObject Build(GameObject prefab)
{
Profiler.BeginSample("GameObject Factory Build");

copy.AddComponent<NotifyComponentsRemoved>().unityContext = _unityContext;
copy.AddComponent<NotifyEntityRemoved>().unityContext = _unityContext;
var copy = Object.Instantiate(prefab) as GameObject;

return copy;
}
}

public void RegisterPrefab(GameObject prefab, string prefabName, GameObject parent = null)
{
var objects = new GameObject[2];

IUnityContextHierarchyChangedListener _unityContext;
Dictionary<string, GameObject[]> _prefabs;
objects[0] = prefab; objects[1] = parent;

_prefabs.Add(prefabName, objects);
}

Dictionary<string, GameObject[]> _prefabs;
}
}


+ 11
- 21
Context/Factories/MonoBehaviourFactory.cs View File

@@ -1,34 +1,24 @@
#region

using System;
using Svelto.DataStructures;
using UnityEngine;

#endregion

namespace Svelto.Context
{
public class MonoBehaviourFactory: Factories.IMonoBehaviourFactory
{
IUnityContextHierarchyChangedListener _unityContext;
public class MonoBehaviourFactory : Factories.IMonoBehaviourFactory
{
public MonoBehaviourFactory()
{
}

public MonoBehaviourFactory(IUnityContextHierarchyChangedListener unityContext)
{
_unityContext = unityContext;
}
public M Build<M>(Func<M> constructor) where M:MonoBehaviour
{
var mb = constructor();
_unityContext.OnMonobehaviourAdded(mb);

GameObject go = mb.gameObject;

if (go.GetComponent<NotifyComponentsRemoved>() == null)
go.AddComponent<NotifyComponentsRemoved>().unityContext = _unityContext;
public M Build<M>(Func<M> constructor) where M : MonoBehaviour
{
var mb = constructor();

return mb;
}
}
}
}
}


+ 5
- 6
Context/ICompositionRoot.cs View File

@@ -1,12 +1,11 @@
using UnityEngine;

namespace Svelto.Context
{
public interface ICompositionRoot
public interface ICompositionRoot
{
void OnContextInitialized();
void OnContextDestroyed();
}
void OnContextCreated(UnityContext contextHolder);
void OnContextInitialized();
void OnContextDestroyed();
}
}



+ 1
- 1
Context/IContextNotifer.cs View File

@@ -5,7 +5,7 @@ namespace Svelto.Context
void NotifyFrameworkInitialized();
void NotifyFrameworkDeinitialized();

void AddFrameworkInitializationListener(IWaitForFrameworkInitialization obj);
void AddFrameworkInitializationListener(IWaitForFrameworkInitialization obj);
void AddFrameworkDestructionListener(IWaitForFrameworkDestruction obj);
}
}

+ 0
- 13
Context/IUnityContextHierarchyChangedListener.cs View File

@@ -1,13 +0,0 @@
using UnityEngine;

namespace Svelto.Context
{
public interface IUnityContextHierarchyChangedListener
{
void OnMonobehaviourAdded(MonoBehaviour component);
void OnMonobehaviourRemoved(MonoBehaviour component);

void OnGameObjectAdded(GameObject entity);
void OnGameObjectRemoved(GameObject entity);
}
}

+ 9
- 0
Context/Legacy.meta View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 5f61f9718491ceb498626e61ab9f48d4
folderAsset: yes
timeCreated: 1434754873
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

+ 1
- 1
Context/Unity.meta View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 403de662aab64bb4e917559caa6b7946
guid: 14144568b327bbe40876c12a777e5f05
folderAsset: yes
timeCreated: 1434752394
licenseType: Free


+ 0
- 28
Context/Unity/NotifyComponentsRemoved.cs View File

@@ -1,28 +0,0 @@
using UnityEngine;

namespace Svelto.Context
{
public class NotifyComponentsRemoved : MonoBehaviour
{
public IUnityContextHierarchyChangedListener unityContext { private get; set; }

void OnDestroy()
{
MonoBehaviour[] components = gameObject.GetComponentsInChildren<MonoBehaviour>(true);

for (int i = 0; i < components.Length; ++i)
if (components[i] != null)
unityContext.OnMonobehaviourRemoved(components[i]);
}
}

public class NotifyEntityRemoved : MonoBehaviour
{
public IUnityContextHierarchyChangedListener unityContext { private get; set; }

void OnDestroy()
{
unityContext.OnGameObjectRemoved(gameObject);
}
}
}

+ 32
- 52
Context/UnityContext.cs View File

@@ -1,64 +1,44 @@
using UnityEngine;
using Svelto.Context;
using System.Collections;
using Svelto.Context;
using UnityEngine;

public class UnityContext:MonoBehaviour
{}

public class UnityContext<T>: UnityContext where T:class, ICompositionRoot, IUnityContextHierarchyChangedListener, new()
public abstract class UnityContext:MonoBehaviour
{
virtual protected void Awake()
{
Init();
}

void Init()
{
_applicationRoot = new T();
MonoBehaviour[] behaviours = transform.GetComponentsInChildren<MonoBehaviour>(true);
protected abstract void OnAwake();

for (int i = 0; i < behaviours.Length; i++)
{
var component = behaviours[i];
void Awake()
{
OnAwake();
}
}

if (component != null)
_applicationRoot.OnMonobehaviourAdded(component);
}
public class UnityContext<T>: UnityContext where T:class, ICompositionRoot, new()
{
protected override void OnAwake()
{
_applicationRoot = new T();

Transform[] children = transform.GetComponentsInChildren<Transform>(true);
_applicationRoot.OnContextCreated(this);
}

for (int i = 0; i < children.Length; i++)
{
var child = children[i];
void OnDestroy()
{
_applicationRoot.OnContextDestroyed();
}

if (child != null)
_applicationRoot.OnGameObjectAdded(child.gameObject);
}
void Start()
{
if (Application.isPlaying == true)
StartCoroutine(WaitForFrameworkInitialization());
}
void OnDestroy()
{
FrameworkDestroyed();
}

void Start()
{
if (Application.isPlaying == true)
StartCoroutine(WaitForFrameworkInitialization());
}
IEnumerator WaitForFrameworkInitialization()
{
//let's wait until the end of the frame, so we are sure that all the awake and starts are called
yield return new WaitForEndOfFrame();

_applicationRoot.OnContextInitialized();
}

IEnumerator WaitForFrameworkInitialization()
{
yield return new WaitForEndOfFrame(); //let's wait until next frame, so we are sure that all the awake and starts are called
_applicationRoot.OnContextInitialized();
}
void FrameworkDestroyed()
{
_applicationRoot.OnContextDestroyed();
}
private T _applicationRoot = null;
T _applicationRoot;
}

+ 9
- 0
DataStructures.meta View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 6663fc83070cb0842b4665b38356feb2
folderAsset: yes
timeCreated: 1463348260
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

+ 431
- 0
DataStructures/FasterList.cs View File

@@ -0,0 +1,431 @@
/**
* Custom modified version of Michael Lyashenko's BetterList
**/

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Svelto.DataStructures
{
public struct FasterListEnumerator<T> : IEnumerator<T>
{
public T Current
{
get { return _current; }
}

object IEnumerator.Current
{
get { return _current; }
}

T IEnumerator<T>.Current
{
get { return _current; }
}

public FasterListEnumerator(T[] buffer, int size)
{
_size = size;
_counter = 0;
_buffer = buffer;
_current = default(T);
}

public void Dispose()
{
_buffer = null;
}

bool IEnumerator.MoveNext()
{
return MoveNext();
}

void IEnumerator.Reset()
{
Reset();
}

public bool MoveNext()
{
if (_counter < _size)
{
_current = _buffer[_counter++];

return true;
}

_current = default(T);

return false;
}

public void Reset()
{
_counter = 0;
}

T[] _buffer;
int _counter;
int _size;
T _current;
}

public struct FasterReadOnlyList<T> : IList<T>
{
public FasterReadOnlyList(FasterList<T> list)
{
_list = list;
}

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

public FasterListEnumerator<T> GetEnumerator()
{
return _list.GetEnumerator();
}

public void Add(T item)
{
throw new NotImplementedException();
}

public void Clear()
{
throw new NotImplementedException();
}

public bool Contains(T item)
{
return _list.Contains(item);
}

public void CopyTo(T[] array, int arrayIndex)
{
_list.CopyTo(array, arrayIndex);
}

public bool Remove(T item)
{
throw new NotImplementedException();
}

public int Count { get { return _list.Count; } }
public bool IsReadOnly { get { return true; } }

public int IndexOf(T item)
{
return _list.IndexOf(item);
}

public void Insert(int index, T item)
{
throw new NotImplementedException();
}

public void RemoveAt(int index)
{
throw new NotImplementedException();
}

public T this[int index] { get { return _list[index]; } set { throw new NotImplementedException(); } }

readonly FasterList<T> _list;
}

public class FasterList<T> : IList<T>
{
public int Count
{
get { return _count; }
}

public bool IsReadOnly
{
get { return false; }
}

public FasterList()
{
_count = 0;

_buffer = new T[MIN_SIZE];
}

public FasterList(int initialSize)
{
_count = 0;

_buffer = new T[initialSize];
}

public FasterList(ICollection<T> collection)
{
_buffer = new T[collection.Count];

collection.CopyTo(_buffer, 0);

_count = _buffer.Length;
}

public FasterList(FasterList<T> listCopy)
{
_buffer = new T[listCopy.Count];

listCopy.CopyTo(_buffer, 0);

_count = listCopy.Count;
}

public void Add(T item)
{
if (_count == _buffer.Length)
AllocateMore();

_buffer[_count++] = item;
}

public void AddRange(IEnumerable<T> items, int count)
{
if (_count + count >= _buffer.Length)
AllocateMore(_count + count);

for (var i = items.GetEnumerator(); i.MoveNext();)
{
var item = i.Current;
_buffer[_count++] = item;
}
}

public void AddRange(ICollection<T> items)
{
var count = items.Count;
if (_count + count >= _buffer.Length)
AllocateMore(_count + count);

for (var i = items.GetEnumerator(); i.MoveNext();)
{
var item = i.Current;
_buffer[_count++] = item;
}
}

public void AddRange(FasterList<T> items)
{
var count = items.Count;
if (_count + count >= _buffer.Length)
AllocateMore(_count + count);

Array.Copy(items._buffer, 0, _buffer, _count, count);
_count += count;
}

public void AddRange(T[] items)
{
var count = items.Length;
if (_count + count >= _buffer.Length)
AllocateMore(_count + count);

Array.Copy(items, 0, _buffer, _count, count);
_count += count;
}

public FasterReadOnlyList<T> AsReadOnly()
{
return new FasterReadOnlyList<T>(this);
}

public void Clear()
{
_count = 0;
}

public bool Contains(T item)
{
var index = IndexOf(item);

return index != -1;
}

public void CopyTo(T[] array, int arrayIndex)
{
Array.Copy(_buffer, 0, array, arrayIndex, Count);
}

public FasterListEnumerator<T> GetEnumerator()
{
return new FasterListEnumerator<T>(_buffer, Count);
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return GetEnumerator();
}

public int IndexOf(T item)
{
var comp = EqualityComparer<T>.Default;

for (var index = _count - 1; index >= 0; --index)
if (comp.Equals(_buffer[index], item))
return index;

return -1;
}

public void Insert(int index, T item)
{
DesignByContract.Check.Require(index < _count, "out of bound index");

if (_count == _buffer.Length) AllocateMore();

Array.Copy(_buffer, index, _buffer, index + 1, _count - index);

_buffer[index] = item;
++_count;
}

public void Release()
{
_count = 0;
_buffer = null;
}

public bool Remove(T item)
{
var index = IndexOf(item);

if (index == -1)
return false;

RemoveAt(index);

return true;
}

public void RemoveAt(int index)
{
DesignByContract.Check.Require(index < _count, "out of bound index");

--_count;

if (index == _count)
return;

Array.Copy(_buffer, index + 1, _buffer, index, _count - index);
}

public void Resize(int newSize)
{
Array.Resize(ref _buffer, newSize);

_count = newSize;
}

public void SetAt(int index, T value)
{
if (index >= _buffer.Length)
AllocateMore(index + 1);

if (_count <= index)
_count = index + 1;

this[index] = value;
}

public void Sort(Comparison<T> comparer)
{
Trim();
Array.Sort(_buffer, comparer);
}

public T[] ToArray()
{
T[] destinationArray = new T[_count];

Array.Copy(_buffer, 0, destinationArray, 0, _count);

return destinationArray;
}

/// <summary>
/// This function exists to allow fast iterations. The size of the array returned cannot be
/// used. The list count must be used instead.
/// </summary>
/// <returns></returns>
public T[] ToArrayFast()
{
return _buffer;
}

public bool UnorderredRemove(T item)
{
var index = IndexOf(item);

if (index == -1)
return false;

UnorderredRemoveAt(index);

return true;
}

public void UnorderredRemoveAt(int index)
{
DesignByContract.Check.Require(index < _count, "out of bound index");

_buffer[index] = _buffer[--_count];
}

private void AllocateMore()
{
var newList = new T[Mathf.Max(_buffer.Length << 1, MIN_SIZE)];
if (_count > 0) _buffer.CopyTo(newList, 0);
_buffer = newList;
}

private void AllocateMore(int newSize)
{
var oldLength = _buffer.Length;

while (oldLength < newSize)
oldLength <<= 1;

var newList = new T[oldLength];
if (_count > 0) _buffer.CopyTo(newList, 0);
_buffer = newList;
}

private void Trim()
{
if (_count < _buffer.Length)
Resize(_count);
}

public T this[int i]
{
get { DesignByContract.Check.Require(i < _count, "out of bound index"); return _buffer[i]; }
set { DesignByContract.Check.Require(i < _count, "out of bound index"); _buffer[i] = value; }
}

private const int MIN_SIZE = 32;
private T[] _buffer;
private int _count;
}
}

+ 10
- 0
DataStructures/FasterList.cs.meta View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 0859454e6e6d968498cea54757578eda
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 655
- 0
DataStructures/ReadOnlyDictionary.cs View File

@@ -0,0 +1,655 @@
//note: ripped from openstacknetsdk

using System;
using System.Collections;
using System.Collections.Generic;

namespace Svelto.DataStructures
{
public struct ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary
{
private readonly IDictionary<TKey, TValue> _dictionary;

/// <summary>
/// Initializes a new instance of the <see cref="ReadOnlyDictionary{TKey, TValue}"/> class
/// that is a wrapper around the specified dictionary.
/// </summary>
/// <param name="dictionary">The dictionary to wrap.</param>
public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");

_dictionary = dictionary;
}

public bool isInitialized { get { return _dictionary != null; } }

/// <summary>
/// Gets the element that has the specified key.
/// </summary>
/// <param name="key">The key of the element to get.</param>
/// <returns>The element that has the specified key.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="key"/> is <see langword="null"/>.</exception>
/// <exception cref="KeyNotFoundException">If property is retrieved and <paramref name="key"/> is not found.</exception>
public TValue this[TKey key]
{
get
{
return _dictionary[key];
}
}

/// <inheritdoc/>
/// <summary>
/// Gets the element that has the specified key.
/// </summary>
/// <exception cref="NotSupportedException">If the property is set.</exception>
TValue IDictionary<TKey, TValue>.this[TKey key]
{
get
{
return this[key];
}

set
{
throw new NotSupportedException();
}
}

/// <inheritdoc/>
/// <summary>
/// Gets the element that has the specified key.
/// </summary>
/// <exception cref="NotSupportedException">If the property is set.</exception>
object IDictionary.this[object key]
{
get
{
if (!(key is TKey))
return null;

return this[(TKey)key];
}

set
{
throw new NotSupportedException();
}
}

/// <summary>
/// Gets the number of items in the dictionary.
/// </summary>
/// <value>
/// The number of items in the dictionary.
/// </value>
public int Count
{
get
{
return _dictionary.Count;
}
}

/// <summary>
/// Gets a key collection that contains the keys of the dictionary.
/// </summary>
/// <value>
/// A key collection that contains the keys of the dictionary.
/// </value>
public KeyCollection Keys
{
get
{
return new KeyCollection(_dictionary.Keys);
}
}

/// <inheritdoc/>
ICollection<TKey> IDictionary<TKey, TValue>.Keys
{
get
{
return Keys;
}
}

/// <inheritdoc/>
ICollection IDictionary.Keys
{
get
{
return Keys;
}
}

/// <summary>
/// Gets a collection that contains the values in the dictionary.
/// </summary>
/// <value>
/// A collection that contains the values in the object that implements <see cref="ReadOnlyDictionary{TKey, TValue}"/>.
/// </value>
public ValueCollection Values
{
get
{
return new ValueCollection(_dictionary.Values);
}
}

/// <inheritdoc/>
ICollection<TValue> IDictionary<TKey, TValue>.Values
{
get
{
return Values;
}
}

/// <inheritdoc/>
ICollection IDictionary.Values
{
get
{
return Values;
}
}

/// <inheritdoc/>
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
{
get
{
return true;
}
}

/// <inheritdoc/>
bool IDictionary.IsFixedSize
{
get
{
return true;
}
}

/// <inheritdoc/>
bool IDictionary.IsReadOnly
{
get
{
return true;
}
}

/// <inheritdoc/>
bool ICollection.IsSynchronized
{
get
{
return false;
}
}

/// <inheritdoc/>
object ICollection.SyncRoot
{
get
{
ICollection collection = this as ICollection;
if (collection == null)
return collection.SyncRoot;

throw new NotSupportedException("The current object does not support the SyncRoot property.");
}
}

/// <summary>
/// Determines whether the dictionary contains an element that has the specified key.
/// </summary>
/// <param name="key">The key to locate in the dictionary.</param>
/// <returns><see langword="true"/> if the dictionary contains an element that has the specified key; otherwise, <see langword="false"/>.</returns>
public bool ContainsKey(TKey key)
{
return _dictionary.ContainsKey(key);
}

/// <inheritdoc/>
bool IDictionary.Contains(object key)
{
if (key == null)
throw new ArgumentNullException("key");

if (key is TKey)
return ContainsKey((TKey)key);

return false;
}

/// <summary>
/// Returns an enumerator that iterates through the <see cref="ReadOnlyDictionary{TKey, TValue}"/>.
/// </summary>
/// <returns>An enumerator that can be used to iterate through the collection.</returns>
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _dictionary.GetEnumerator();
}

/// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

/// <inheritdoc/>
IDictionaryEnumerator IDictionary.GetEnumerator()
{
IDictionary dictionary = _dictionary as IDictionary;
if (dictionary != null)
return dictionary.GetEnumerator();

return new DictionaryEnumerator(_dictionary);
}

/// <summary>
/// Retrieves the value that is associated with the specified key.
/// </summary>
/// <param name="key">The key whose value will be retrieved.</param>
/// <param name="value">When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.</param>
/// <returns><see langword="true"/> if the object that implements <see cref="ReadOnlyDictionary{TKey, TValue}"/> contains an element with the specified key; otherwise, <see langword="false"/>.</returns>
public bool TryGetValue(TKey key, out TValue value)
{
return _dictionary.TryGetValue(key, out value);
}

/// <inheritdoc/>
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
throw new NotSupportedException();
}

/// <inheritdoc/>
void IDictionary.Add(object key, object value)
{
throw new NotSupportedException();
}

/// <inheritdoc/>
bool IDictionary<TKey, TValue>.Remove(TKey key)
{
throw new NotSupportedException();
}

/// <inheritdoc/>
void IDictionary.Remove(object key)
{
throw new NotSupportedException();
}

/// <inheritdoc/>
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
throw new NotSupportedException();
}

/// <inheritdoc/>
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
throw new NotSupportedException();
}

/// <inheritdoc/>
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}

/// <inheritdoc/>
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
throw new NotImplementedException();
}

/// <inheritdoc/>
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
throw new NotSupportedException();
}

/// <inheritdoc/>
void IDictionary.Clear()
{
throw new NotSupportedException();
}

/// <inheritdoc/>
void ICollection.CopyTo(Array array, int index)
{
throw new NotImplementedException();
}

/// <summary>
/// Represents a read-only collection of the keys of a <see cref="ReadOnlyDictionary{TKey, TValue}"/> object.
/// </summary>
public struct KeyCollection : ICollection<TKey>, ICollection
{
/// <summary>
/// The wrapped collection of keys.
/// </summary>
private readonly ICollection<TKey> _keys;

/// <summary>
/// Initializes a new instance of the <see cref="KeyCollection"/> class
/// as a wrapper around the specified collection of keys.
/// </summary>
/// <param name="keys">The collection of keys to wrap.</param>
/// <exception cref="ArgumentNullException">If <paramref name="keys"/> is <see langword="null"/>.</exception>
internal KeyCollection(ICollection<TKey> keys)
{
if (keys == null)
throw new ArgumentNullException("keys");

_keys = keys;
}

/// <summary>
/// Gets the number of elements in the collection.
/// </summary>
/// <value>
/// The number of elements in the collection.
/// </value>
public int Count
{
get
{
return _keys.Count;
}
}

/// <inheritdoc/>
bool ICollection<TKey>.IsReadOnly
{
get
{
return true;
}
}

/// <inheritdoc/>
bool ICollection.IsSynchronized
{
get
{
return false;
}
}

/// <inheritdoc/>
object ICollection.SyncRoot
{
get
{
throw new NotImplementedException();
}
}

/// <summary>
/// Copies the elements of the collection to an array, starting at a specific array index.
/// </summary>
/// <param name="array">The one-dimensional array that is the destination of the elements copied from the collection. The array must have zero-based indexing.</param>
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
/// <exception cref="ArgumentNullException">If <paramref name="array"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="arrayIndex"/> is less than 0.</exception>
/// <exception cref="ArgumentException">
/// If <paramref name="array"/> is multidimensional.
/// <para>-or-</para>
/// <para>If the number of elements in the source collection is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.</para>
/// <para>-or-</para>
/// <para>If the type <typeparamref name="TKey"/> cannot be cast automatically to the type of the destination <paramref name="array"/>.</para>
/// </exception>
public void CopyTo(TKey[] array, int arrayIndex)
{
_keys.CopyTo(array, arrayIndex);
}

/// <inheritdoc/>
void ICollection.CopyTo(Array array, int index)
{
throw new NotImplementedException();
}

/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>An enumerator that can be used to iterate through the collection.</returns>
public IEnumerator<TKey> GetEnumerator()
{
return _keys.GetEnumerator();
}

/// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

/// <inheritdoc/>
bool ICollection<TKey>.Contains(TKey item)
{
return _keys.Contains(item);
}

/// <inheritdoc/>
void ICollection<TKey>.Add(TKey item)
{
throw new NotSupportedException();
}

/// <inheritdoc/>
bool ICollection<TKey>.Remove(TKey item)
{
throw new NotSupportedException();
}

/// <inheritdoc/>
void ICollection<TKey>.Clear()
{
throw new NotSupportedException();
}
}

/// <summary>
/// Represents a read-only collection of the values of a <see cref="ReadOnlyDictionary{TKey, TValue}"/> object.
/// </summary>
public struct ValueCollection : ICollection<TValue>, ICollection
{
/// <summary>
/// The wrapped collection of values.
/// </summary>
private readonly ICollection<TValue> _values;

/// <summary>
/// Initializes a new instance of the <see cref="ValueCollection"/> class
/// as a wrapper around the specified collection of values.
/// </summary>
/// <param name="values">The collection of values to wrap.</param>
/// <exception cref="ArgumentNullException">If <paramref name="values"/> is <see langword="null"/>.</exception>
internal ValueCollection(ICollection<TValue> values)
{
if (values == null)
throw new ArgumentNullException("values");

_values = values;
}

/// <summary>
/// Gets the number of elements in the collection.
/// </summary>
/// <value>
/// The number of elements in the collection.
/// </value>
public int Count
{
get
{
return _values.Count;
}
}

/// <inheritdoc/>
bool ICollection<TValue>.IsReadOnly
{
get
{
return true;
}
}

/// <inheritdoc/>
bool ICollection.IsSynchronized
{
get
{
return false;
}
}

/// <inheritdoc/>
object ICollection.SyncRoot
{
get
{
throw new NotImplementedException();
}
}

/// <summary>
/// Copies the elements of the collection to an array, starting at a specific array index.
/// </summary>
/// <param name="array">The one-dimensional array that is the destination of the elements copied from the collection. The array must have zero-based indexing.</param>
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
/// <exception cref="ArgumentNullException">If <paramref name="array"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="arrayIndex"/> is less than 0.</exception>
/// <exception cref="ArgumentException">
/// If <paramref name="array"/> is multidimensional.
/// <para>-or-</para>
/// <para>If the number of elements in the source collection is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.</para>
/// <para>-or-</para>
/// <para>If the type <typeparamref name="TValue"/> cannot be cast automatically to the type of the destination <paramref name="array"/>.</para>
/// </exception>
public void CopyTo(TValue[] array, int arrayIndex)
{
_values.CopyTo(array, arrayIndex);
}

/// <inheritdoc/>
void ICollection.CopyTo(Array array, int index)
{
throw new NotImplementedException();
}

/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>An enumerator that can be used to iterate through the collection.</returns>
public IEnumerator<TValue> GetEnumerator()
{
return _values.GetEnumerator();
}

/// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

/// <inheritdoc/>
bool ICollection<TValue>.Contains(TValue item)
{
return _values.Contains(item);
}

/// <inheritdoc/>
void ICollection<TValue>.Add(TValue item)
{
throw new NotSupportedException();
}

/// <inheritdoc/>
bool ICollection<TValue>.Remove(TValue item)
{
throw new NotSupportedException();
}

/// <inheritdoc/>
void ICollection<TValue>.Clear()
{
throw new NotSupportedException();
}
}

struct DictionaryEnumerator : IDictionaryEnumerator
{
private readonly IEnumerator<KeyValuePair<TKey, TValue>> _enumerator;

public DictionaryEnumerator(IDictionary<TKey, TValue> dictionary)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");

_enumerator = dictionary.GetEnumerator();
}

/// <inheritdoc/>
public DictionaryEntry Entry
{
get
{
KeyValuePair<TKey, TValue> current = _enumerator.Current;
return new DictionaryEntry(current.Key, current.Value);
}
}

/// <inheritdoc/>
public object Key
{
get
{
return _enumerator.Current.Key;
}
}

/// <inheritdoc/>
public object Value
{
get
{
return _enumerator.Current.Value;
}
}

/// <inheritdoc/>
public object Current
{
get
{
return Entry;
}
}

/// <inheritdoc/>
public bool MoveNext()
{
return _enumerator.MoveNext();
}

/// <inheritdoc/>
public void Reset()
{
_enumerator.Reset();
}
}
}
}

+ 12
- 0
DataStructures/ReadOnlyDictionary.cs.meta View File

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

+ 171
- 0
DataStructures/ThreadSafeQueue.cs View File

@@ -0,0 +1,171 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;

namespace Svelto.DataStructures
{
public class ThreadSafeQueue<T>
{
private readonly Queue<T> m_Queue;

private readonly ReaderWriterLockSlim LockQ = new ReaderWriterLockSlim();

public ThreadSafeQueue()
{
m_Queue = new Queue<T>();
}

public ThreadSafeQueue(int capacity)
{
m_Queue = new Queue<T>(capacity);
}

public ThreadSafeQueue(IEnumerable<T> collection)
{
m_Queue = new Queue<T>(collection);
}

public IEnumerator<T> GetEnumerator()
{
Queue<T> localQ;

LockQ.EnterReadLock();
try
{
localQ = new Queue<T>(m_Queue);
}

finally
{
LockQ.ExitReadLock();
}

foreach (T item in localQ)
yield return item;
}

public void Enqueue(T item)
{
LockQ.EnterWriteLock();
try
{
m_Queue.Enqueue(item);
}

finally
{
LockQ.ExitWriteLock();
}
}

public T Dequeue()
{
LockQ.EnterWriteLock();
try
{
return m_Queue.Dequeue();
}

finally
{
LockQ.ExitWriteLock();
}
}

public void EnqueueAll(IEnumerable<T> ItemsToQueue)
{
LockQ.EnterWriteLock();
try
{
foreach (T item in ItemsToQueue)
m_Queue.Enqueue(item);
}

finally
{
LockQ.ExitWriteLock();
}
}

public List<T> DequeueAll()
{
LockQ.EnterWriteLock();
try
{
List<T> returnList = new List<T>();

while (m_Queue.Count > 0)
returnList.Add(m_Queue.Dequeue());

return returnList;
}

finally
{
LockQ.ExitWriteLock();
}
}

public T Peek()
{
LockQ.EnterWriteLock();
try
{
T item = default(T);

if (m_Queue.Count > 0)
item = m_Queue.Peek();

return item;
}

finally
{
LockQ.ExitWriteLock();
}
}

public bool TryDequeue(out T item)
{
LockQ.EnterWriteLock();
try
{
if (m_Queue.Count > 0)
{
item = m_Queue.Dequeue();

return true;
}
else
{
item = default(T);

return false;
}
}

finally
{
LockQ.ExitWriteLock();
}
}

public int Count
{
get
{
LockQ.EnterWriteLock();
try
{
return m_Queue.Count;
}

finally
{
LockQ.ExitWriteLock();
}
}
}
}
}

Context/IUnityContextHierarchyChangedListener.cs.meta → DataStructures/ThreadSafeQueue.cs.meta View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 905bfd795bede6d448694b23dd88e0be
guid: 57d029cda5232f8468d50d4eb3bf5489
MonoImporter:
serializedVersion: 2
defaultReferences: []

+ 56
- 0
DataStructures/WeakReference.cs View File

@@ -0,0 +1,56 @@
using System;
using System.Runtime.Serialization;
/// <span class="code-SummaryComment"><summary></span>
/// Represents a weak reference, which references an object while still allowing
/// that object to be reclaimed by garbage collection.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><typeparam name="T">The type of the object that is referenced.</typeparam></span>

namespace Svelto.DataStructures
{
[Serializable]
public class WeakReference<T>
: WeakReference where T : class
{
/// <span class="code-SummaryComment"><summary></span>
/// Gets or sets the object (the target) referenced by the
/// current WeakReference{T} object.
/// <span class="code-SummaryComment"></summary></span>
public new T Target
{
get
{
return (T)base.Target;
}
set
{
base.Target = value;
}
}
/// <span class="code-SummaryComment"><summary></span>
/// Initializes a new instance of the WeakReference{T} class, referencing
/// the specified object.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="target">The object to reference.</param></span>
public WeakReference(T target)
: base(target)
{ }

/// <span class="code-SummaryComment"><summary></span>
/// Initializes a new instance of the WeakReference{T} class, referencing
/// the specified object and using the specified resurrection tracking.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="target">An object to track.</param></span>
/// <span class="code-SummaryComment"><param name="trackResurrection">Indicates when to stop tracking the object. </span>
/// If true, the object is tracked
/// after finalization; if false, the object is only tracked
/// until finalization.<span class="code-SummaryComment"></param></span>
public WeakReference(T target, bool trackResurrection)
: base(target, trackResurrection)
{ }

protected WeakReference(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
}
}

+ 12
- 0
DataStructures/WeakReference.cs.meta View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 205cba76ee94d0e47aba9510ca92c540
timeCreated: 1452175408
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 9
- 0
ECS/Dispatcher.meta View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2eae335fd33e33c4f951bf28bbf4914f
folderAsset: yes
timeCreated: 1462445195
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

+ 19
- 0
ECS/Dispatcher/Dispatcher.cs View File

@@ -0,0 +1,19 @@
public class Dispatcher<S, T>
{
public event System.Action<S, T> subscribers;

private Dispatcher() { }

public Dispatcher(S sender)
{
_sender = sender;
}

public void Dispatch(ref T value)
{
if (subscribers != null)
subscribers(_sender, value);
}

readonly S _sender;
}

Utilities/Dispatcher.cs.meta → ECS/Dispatcher/Dispatcher.cs.meta View File


Utilities/DispatcherOnChange.cs → ECS/Dispatcher/DispatcherOnChange.cs View File

@@ -12,7 +12,7 @@ public class DispatcherOnChange<S, T>: Dispatcher<S, T>
{
_value = value;

Dispatch(value);
Dispatch(ref value);
}
}
}
@@ -20,3 +20,15 @@ public class DispatcherOnChange<S, T>: Dispatcher<S, T>
T _value;
}

public class DispatcherOnSet<S, T>: Dispatcher<S, T>
{
public DispatcherOnSet(S sender) : base(sender) { }

public T value
{
set
{
Dispatch(ref value);
}
}
}

Context/Unity/NotifyComponentsRemoved.cs.meta → ECS/Dispatcher/DispatcherOnChange.cs.meta View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 13278f0cd187d8d43acc6a02479e459b
guid: 908688d3b784d644e88a06e20f9ea159
MonoImporter:
serializedVersion: 2
defaultReferences: []

+ 0
- 5
ECS/Engine.meta View File

@@ -1,5 +0,0 @@
fileFormatVersion: 2
guid: b1f3314cac8b8484f965651234415ca8
folderAsset: yes
DefaultImporter:
userData:

+ 0
- 14
ECS/Engine/IEngine.cs View File

@@ -1,14 +0,0 @@
namespace Svelto.ES
{
public interface IEngine
{}
public interface INodeEngine : IEngine
{
System.Type[] AcceptedNodes();

void Add(INode obj);
void Remove(INode obj);
}

}

+ 59
- 0
ECS/EngineNodeDB.cs View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using Svelto.DataStructures;

namespace Svelto.ES
{
class EngineNodeDB : IEngineNodeDB
{
internal EngineNodeDB(Dictionary<Type, FasterList<INode>> nodesDB, Dictionary<Type, Dictionary<int, INode>> nodesDBdic)
{
this._nodesDB = nodesDB;
this._nodesDBdic = nodesDBdic;
}

public FasterReadOnlyList<INode> QueryNodes<T>() where T:INode
{
var type = typeof(T);

if (_nodesDB.ContainsKey(type) == false)
return _defaultEmptyNodeList;

return new FasterReadOnlyList<INode>(_nodesDB[type]);
}

public ReadOnlyDictionary<int, INode> QueryIndexableNodes<T>() where T:INode
{
var type = typeof(T);

if (_nodesDBdic.ContainsKey(type) == false)
return _defaultEmptyNodeDict;

return new ReadOnlyDictionary<int, INode>(_nodesDBdic[type]);
}

public bool QueryNode<T>(int ID, out T node) where T:INode
{
var type = typeof(T);

INode internalNode;

if (_nodesDBdic.ContainsKey(type) && _nodesDBdic[type].TryGetValue(ID, out internalNode))
{
node = (T)internalNode;

return true;
}

node = default(T);

return false;
}

Dictionary<Type, FasterList<INode>> _nodesDB;
Dictionary<Type, Dictionary<int, INode>> _nodesDBdic;

FasterReadOnlyList<INode> _defaultEmptyNodeList = new FasterReadOnlyList<INode>(new FasterList<INode>());
ReadOnlyDictionary<int, INode> _defaultEmptyNodeDict = new ReadOnlyDictionary<int, INode>(new Dictionary<int, INode>());
}
}

+ 12
- 0
ECS/EngineNodeDB.cs.meta View File

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

+ 138
- 34
ECS/EnginesRoot.cs View File

@@ -1,69 +1,173 @@
using System;
using System.Collections.Generic;

using Svelto.DataStructures;
using Svelto.Ticker;

namespace Svelto.ES
{
public sealed class EnginesRoot: INodeEnginesRoot
{
public EnginesRoot()
{
_nodeEngines = new Dictionary<Type, List<INodeEngine>>();
}
public sealed class EnginesRoot: IEnginesRoot, IEndOfFrameTickable, IEntityFactory
{
const int _INITIAL_SIZE = 100;
const int _INITIAL_INTERNAL_SIZE = 10;

public void AddEngine(IEngine engine)
public EnginesRoot(ITicker ticker)
{
if (engine is INodeEngine)
AddNodeEngine(engine as INodeEngine);
ticker.Add(this);

_nodeEngines = new Dictionary<Type, FasterList<INodeEngine<INode>>>();
_engineRootWeakReference = new WeakReference<EnginesRoot>(this);
_otherEnginesReferences = new FasterList<IEngine>();
_nodesDB = new Dictionary<Type, FasterList<INode>>(_INITIAL_SIZE);
_nodesDBdic = new Dictionary<Type, Dictionary<int, INode>>(_INITIAL_SIZE);

_nodesToAdd = new Queue<INode>(_INITIAL_SIZE);
}

public void Add(INode node)
public void EndOfFrameTick(float deltaSec)
{
Type nodeType = node.GetType();
List<INodeEngine> value;
if (_nodeEngines.TryGetValue(nodeType, out value))
for (int j = 0; j < value.Count; j++)
value[j].Add(node);
while (_nodesToAdd.Count > 0) InternalAdd(_nodesToAdd.Dequeue());
}

public void Remove(INode node)
public void AddEngine(IEngine engine)
{
Type nodeType = node.GetType();
if (engine is IQueryableNodeEngine)
(engine as IQueryableNodeEngine).nodesDB = new EngineNodeDB(_nodesDB, _nodesDBdic);

if (engine is INodesEngine)
{
var nodesEngine = engine as INodesEngine;

List<INodeEngine> value;
if (_nodeEngines.TryGetValue(nodeType, out value))
for (int j = 0; j < value.Count; j++)
value[j].Remove(node);
AddEngine(nodesEngine, nodesEngine.AcceptedNodes(), _nodeEngines);

return;
}

var baseType = engine.GetType().BaseType;
if (baseType.IsGenericType)
{
var genericType = baseType.GetGenericTypeDefinition();
if (genericType == typeof(SingleManagedNodeEngine<>))
{
AddEngine(engine as INodeEngine<INode>, baseType.GetGenericArguments(), _nodeEngines);

return;
}
}

_otherEnginesReferences.Add(engine);
}

void AddNodeEngine(INodeEngine engine)
public void BuildEntity(int ID, EntityDescriptor ed)
{
AddEngine(engine, engine.AcceptedNodes(), _nodeEngines);
var entityNodes = ed.BuildNodes(ID, (node) => _engineRootWeakReference.Target.InternalRemove(node));
for (int i = 0; i < entityNodes.Count; i++)
_nodesToAdd.Enqueue(entityNodes[i]);
}

void AddEngine<T>(T engine, Type[] types, Dictionary<Type, List<T>> engines)
static void AddEngine<T>(T engine, Type[] types, Dictionary<Type, FasterList<INodeEngine<INode>>> engines) where T:INodeEngine<INode>
{
for (int i = 0; i < types.Length; i++)
{
List<T> value;
FasterList<INodeEngine<INode>> list;

var type = types[i];

if (engines.TryGetValue(type, out value) == false)
if (engines.TryGetValue(type, out list) == false)
{
List<T> list = new List<T>();

list.Add(engine);
list = new FasterList<INodeEngine<INode>>();

engines.Add(type, list);
}
else
value.Add(engine);
list.Add(engine);
}
}

Dictionary<Type, List<INodeEngine>> _nodeEngines;
void InternalAdd<T>(T node) where T:INode
{
Type nodeType = node.GetType();

AddNodeToTheSuitableEngines(node, nodeType);
AddNodeToTheDB(node, nodeType);
}

void InternalRemove<T>(T node) where T:INode
{
Type nodeType = node.GetType();

RemoveNodeFromEngines(node, nodeType);
RemoveNodeFromTheDB(node, nodeType);
}

void AddNodeToTheDB<T>(T node, Type nodeType) where T : INode
{
FasterList<INode> nodes;
if (_nodesDB.TryGetValue(nodeType, out nodes) == false)
nodes = _nodesDB[nodeType] = new FasterList<INode>(_INITIAL_INTERNAL_SIZE);

nodes.Add(node);

if (node is NodeWithID)
{
Dictionary<int, INode> nodesDic;
if (_nodesDBdic.TryGetValue(nodeType, out nodesDic) == false)
nodesDic = _nodesDBdic[nodeType] = new Dictionary<int, INode>(_INITIAL_INTERNAL_SIZE);
nodesDic[(node as NodeWithID).ID] = node;
}
}

void AddNodeToTheSuitableEngines<T>(T node, Type nodeType) where T : INode
{
FasterList<INodeEngine<INode>> enginesForNode;

if (_nodeEngines.TryGetValue(nodeType, out enginesForNode))
for (int j = 0; j < enginesForNode.Count; j++)
enginesForNode[j].Add(node);
}

void RemoveNodeFromTheDB<T>(T node, Type nodeType) where T : INode
{
FasterList<INode> nodes;
if (_nodesDB.TryGetValue(nodeType, out nodes) == true)
nodes.Remove(node); //should I remove it from the dictionary if length is zero?

if (node is NodeWithID)
{
Dictionary<int, INode> nodesDic;

if (_nodesDBdic.TryGetValue(nodeType, out nodesDic))
nodesDic.Remove((node as NodeWithID).ID);
}
}

void RemoveNodeFromEngines<T>(T node, Type nodeType) where T : INode
{
FasterList<INodeEngine<INode>> enginesForNode;

if (_nodeEngines.TryGetValue(nodeType, out enginesForNode))
for (int j = 0; j < enginesForNode.Count; j++)
enginesForNode[j].Remove(node);
}

Dictionary<Type, FasterList<INodeEngine<INode>>> _nodeEngines;
FasterList<IEngine> _otherEnginesReferences;

Dictionary<Type, FasterList<INode>> _nodesDB;
Dictionary<Type, Dictionary<int, INode>> _nodesDBdic;

Queue<INode> _nodesToAdd;

WeakReference<EnginesRoot> _engineRootWeakReference;
//integrated pooling system
//add debug panel like Entitas has
//GCHandle should be used to reduce the number of strong references
//datastructure could be thread safe

//future enhancements:
}
}


+ 97
- 0
ECS/EntityDescriptor.cs View File

@@ -0,0 +1,97 @@
using System;
using System.Reflection;
using Svelto.DataStructures;

namespace Svelto.ES
{
public class EntityDescriptor
{
EntityDescriptor()
{}

protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor)
{
_implementors = componentsImplementor; _nodesToBuild = nodesToBuild;
}

virtual public FasterList<INode> BuildNodes(int ID, Action<INode> removeAction)
{
var nodes = new FasterList<INode>();

for (int index = 0; index < _nodesToBuild.Length; index++)
{
var nodeBuilder = _nodesToBuild[index];
var node = FillNode(nodeBuilder.Build(ID), () =>
{
for (int i = 0; i < nodes.Count; i++)
removeAction(nodes[i]);
}
);

nodes.Add (node);
}

return nodes;
}

TNode FillNode<TNode>(TNode node, Action removeAction) where TNode: INode
{
var fields = node.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);

for (int i = fields.Length - 1; i >=0 ; --i)
{
var field = fields[i];
Type fieldType = field.FieldType;
object component = null;

for (int j = 0; j < _implementors.Length; j++)
{
var implementor = _implementors[j];

if (fieldType.IsAssignableFrom(implementor.GetType()))
{
component = implementor;

if (fieldType.IsAssignableFrom(typeof(IRemoveEntityComponent)))
(component as IRemoveEntityComponent).removeEntity = removeAction;

break;
}
}

if (component == null)
{
Exception e = new Exception("Svelto.ES: An Entity must hold all the components needed for a Node. " +
"Type: " + field.FieldType.Name + " Node: " + node.GetType().Name);

Utility.Console.LogException(e);

throw e;
}

field.SetValue(node, component);
}

return node;
}

readonly object[] _implementors;

INodeBuilder[] _nodesToBuild;
}

public interface INodeBuilder
{
NodeWithID Build(int ID);
}

public class NodeBuilder<NodeType> : INodeBuilder where NodeType:NodeWithID, new()
{
public NodeWithID Build(int ID)
{
NodeWithID node = NodeWithID.BuildNode<NodeType>(ID);

return (NodeType)node;
}
}
}

+ 12
- 0
ECS/EntityDescriptor.cs.meta View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 42ab9afd9889862468f4afdac4fffd8b
timeCreated: 1457096903
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 6
- 0
ECS/IComponent.cs View File

@@ -0,0 +1,6 @@
namespace Svelto.ES
{
public interface IComponent
{
}
}

Utilities/DispatcherOnChange.cs.meta → ECS/IComponent.cs.meta View File

@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: 103dfa72bd2486d46ac7e6927c805778
timeCreated: 1435956509
guid: 644f7615a18450b4e92f4dcab1f75e57
timeCreated: 1463519273
licenseType: Free
MonoImporter:
serializedVersion: 2

+ 37
- 0
ECS/IEngine.cs View File

@@ -0,0 +1,37 @@
namespace Svelto.ES
{
public interface IEngine
{}

public interface INodeEngine<in TNodeType>:IEngine where TNodeType:INode
{
void Add(TNodeType obj);
void Remove(TNodeType obj);
}

public interface INodesEngine : INodeEngine<INode>
{
System.Type[] AcceptedNodes();
}

public interface IQueryableNodeEngine:IEngine
{
IEngineNodeDB nodesDB { set; }
}

public abstract class SingleManagedNodeEngine<TNodeType> : INodeEngine<INode> where TNodeType:class, INode
{
void INodeEngine<INode>.Add(INode obj)
{
Add(obj as TNodeType);
}

void INodeEngine<INode>.Remove(INode obj)
{
Remove(obj as TNodeType);
}

protected abstract void Add(TNodeType node);
protected abstract void Remove(TNodeType node);
}
}

ECS/Engine/IEngine.cs.meta → ECS/IEngine.cs.meta View File


+ 11
- 0
ECS/IEngineNodeDB.cs View File

@@ -0,0 +1,11 @@
using Svelto.DataStructures;

namespace Svelto.ES
{
public interface IEngineNodeDB
{
ReadOnlyDictionary<int, INode> QueryIndexableNodes<T>() where T : INode;
bool QueryNode<T>(int ID, out T node) where T:INode;
FasterReadOnlyList<INode> QueryNodes<T>() where T : INode;
}
}

+ 12
- 0
ECS/IEngineNodeDB.cs.meta View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 44c24b91989f46048abc15039fd070bc
timeCreated: 1459422024
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 2
- 3
ECS/IEnginesRoot.cs View File

@@ -5,9 +5,8 @@ namespace Svelto.ES
void AddEngine(IEngine engine);
}

public interface INodeEnginesRoot: IEnginesRoot
public interface IEntityFactory
{
void Add(INode node);
void Remove(INode node);
void BuildEntity(int ID, EntityDescriptor ED);
}
}

+ 10
- 0
ECS/IEntityDescriptorHolder.cs View File

@@ -0,0 +1,10 @@
namespace Svelto.ES
{
/// <summary>
/// please use [DisallowMultipleComponent] in your monobehaviours that implement IEntityDescriptorHolder
/// </summary>
public interface IEntityDescriptorHolder
{
EntityDescriptor BuildDescriptorType();
}
}

Utilities/WeakReference.cs.meta → ECS/IEntityDescriptorHolder.cs.meta View File

@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: 2bf8d1cb161e6aa428300dba9323892e
timeCreated: 1434750269
guid: 5a8db83410a8aaa40b824fdc3d968f67
timeCreated: 1463438461
licenseType: Free
MonoImporter:
serializedVersion: 2

+ 17
- 0
ECS/INode.cs View File

@@ -0,0 +1,17 @@
namespace Svelto.ES
{
public interface INode
{}

public class NodeWithID: INode
{
public static TNodeType BuildNode<TNodeType>(int ID) where TNodeType: NodeWithID, new()
{
return new TNodeType { _ID = ID };
}

public int ID { get { return _ID; } }

protected int _ID;
}
}

ECS/Node/INode.cs.meta → ECS/INode.cs.meta View File


+ 9
- 0
ECS/IRemoveEntityComponent.cs View File

@@ -0,0 +1,9 @@
using System;

namespace Svelto.ES
{
public interface IRemoveEntityComponent
{
Action removeEntity { get; set; }
}
}

+ 12
- 0
ECS/IRemoveEntityComponent.cs.meta View File

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

+ 0
- 5
ECS/Node.meta View File

@@ -1,5 +0,0 @@
fileFormatVersion: 2
guid: 8e3c19ee9185a664aa837e567c4db122
folderAsset: yes
DefaultImporter:
userData:

+ 0
- 16
ECS/Node/INode.cs View File

@@ -1,16 +0,0 @@
namespace Svelto.ES
{
public interface INode
{
}

public interface INodeWithReferenceID<out T> : INode where T : class
{
T ID { get; }
}

public interface INodeWithValueID<out T> : INode where T : struct
{
T ID { get; }
}
}

+ 0
- 8
ECS/Node/INodeHolder.cs View File

@@ -1,8 +0,0 @@
namespace Svelto.ES
{
interface INodeHolder
{
INode node { get; }
INodeEnginesRoot engineRoot { set; }
}
}

+ 0
- 8
ECS/Node/INodeHolder.cs.meta View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: a4c0061442f32644cb1e434b6544d56c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

+ 0
- 5
ECS/Unity.meta View File

@@ -1,5 +0,0 @@
fileFormatVersion: 2
guid: e369cc976007e884d92f906e4d1054d7
folderAsset: yes
DefaultImporter:
userData:

+ 0
- 64
ECS/Unity/UnityNodeHolder.cs View File

@@ -1,64 +0,0 @@
using System;
using System.Reflection;
using UnityEngine;

namespace Svelto.ES
{
public abstract class BaseNodeHolder<NodeType>:MonoBehaviour, INodeHolder where NodeType : INode
{
public INode node { get { if (_node != null) return _node; else return _node = ReturnNode(); } }

public INodeEnginesRoot engineRoot { set { _engineRoot = value; } }

protected abstract NodeType ReturnNode();

void Start()
{
if (_engineRoot != null)
_engineRoot.Add(node);
}

NodeType _node;
INodeEnginesRoot _engineRoot;
}

public abstract class UnityNodeHolder<NodeType>:BaseNodeHolder<NodeType> where NodeType : INode
{
protected abstract NodeType GenerateNode();

override protected NodeType ReturnNode()
{
NodeType node = GenerateNode();

FieldInfo[] fields = typeof(NodeType).GetFields(BindingFlags.Public | BindingFlags.Instance);

for (int i = fields.Length - 1; i >=0 ; --i)
{
var field = fields[i];

var component = transform.GetComponentsInChildren(field.FieldType, true); //can't use inactive components

if (component.Length == 0)
{
Exception e = new Exception("Svelto.ES: An Entity must hold all the components needed for a Node. Type: " + field.FieldType.Name + "Entity name: " + name);

Debug.LogException(e, gameObject);

throw e;
}
if (component.Length > 1)
{
Exception e = new Exception("Svelto.ES: An Entity can hold only one component of the same type. Type: " + field.FieldType.Name + "Entity name: " + name);

Debug.LogException(e, gameObject);

throw e;
}

field.SetValue(node, component[0]);
}

return node;
}
}
}

+ 0
- 8
ECS/Unity/UnityNodeHolder.cs.meta View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 50ed7d1adb836dd4786fef832cb4e808
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

+ 0
- 65
ECS/UnityEnginesRoot.cs View File

@@ -1,65 +0,0 @@
using UnityEngine;

namespace Svelto.ES
{
public class UnityEnginesRoot : INodeEnginesRoot
{
public void AddEngine(IEngine engine)
{
_engineRoot.AddEngine(engine);
}

public void Add(INode node)
{
_engineRoot.Add(node);
}

public void Remove(INode node)
{
_engineRoot.Remove(node);
}

public void AddGameObjectEntity(GameObject entity)
{
#if UNITY_5_0
INodeHolder[] nodeHolders = entity.GetComponents<INodeHolder>();
for (int i = 0; i < nodeHolders.Length; i++)
nodeHolders[i].engineRoot = this;
#else
MonoBehaviour[] nodeHolders = entity.GetComponents<MonoBehaviour>();

for (int i = 0; i < nodeHolders.Length; i++)
{
var nodeHolder = nodeHolders[i];
if (nodeHolder is INodeHolder)
(nodeHolders[i] as INodeHolder).engineRoot = this;
}
#endif
}

public void RemoveGameObjectEntity(GameObject entity)
{
#if UNITY_5_0
INodeHolder[] nodeHolders = entity.GetComponents<INodeHolder>();

for (int i = 0; i < nodeHolders.Length; i++)
Remove(nodeHolders[i].node);
#else
MonoBehaviour[] nodeHolders = entity.GetComponents<MonoBehaviour>();

for (int i = 0; i < nodeHolders.Length; i++)
{
var nodeHolder = nodeHolders[i];
if (nodeHolder is INodeHolder)
Remove((nodeHolder as INodeHolder).node);
}
#endif
}

EnginesRoot _engineRoot = new EnginesRoot();
}
}

+ 0
- 8
ECS/UnityEnginesRoot.cs.meta View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 6e4e1cde52e768148a0aaf8effbb9ba3
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

+ 111
- 0
ECS/note.txt View File

@@ -0,0 +1,111 @@
systems do not hold component data, but only system states
systems cannot be injected
systems are SRP and OCP
systems communicates between component, mediators, producer/consumer, observers. producer/consumer and observers must be defined in the layer of the engine.
systems can have injected dependencies

components don't have logic
components can have only getter and setter
components cannot define patterns that requires logic.
components cannot issues commands

High Cohesion[edit]
Main article: Cohesion (computer science)
High Cohesion is an evaluative pattern that attempts to keep objects appropriately focused, manageable and understandable. High cohesion is generally used in support of Low Coupling. High cohesion means that the responsibilities of a given element are strongly related and highly focused. Breaking programs into classes and subsystems is an example of activities that increase the cohesive properties of a system. Alternatively, low cohesion is a situation in which a given element has too many unrelated responsibilities. Elements with low cohesion often suffer from being hard to comprehend, hard to reuse, hard to maintain and averse to change.[3]

Low Coupling[edit]
Main article: Loose coupling
Low Coupling is an evaluative pattern, which dictates how to assign responsibilities to support:

lower dependency between the classes,
change in one class having lower impact on other classes,
higher reuse potential.

events, observers and mediators have the inconvience to hold the reference to the engine, which forces to use cleanup if the engine must be removed.
Observers are easy to clean up from the engine. Mediators needs to be integrated to the framework to be simple to clean up. Component events need the clean up function.
producer/consumer has the inconvienent to force check the number of jobs available everyframe

Engine can't be removed, they can only be disabled, but the logic of disabling must be handled by the engine itself

Should components have just one element? Should engines use just nodes? Components are ditacted by the entities and Nodes by the engines

http://thelinuxlich.github.io/artemis_CSharp/

differences: components no events, everthing must be update
give more responsabiltiy to the user, semplicity

https://github.com/sschmid/Entitas-CSharp/wiki/Overview

no groups, no queries

http://entity-systems.wikidot.com/es-articles

http://www.ashframework.org/

it's very important to give a namespace to the engines. In this way it's impossible to create semantically wrong nodes (PlayerNode Vs TargetNode)

ToDo:

it's not safe to remove an engine without having called being denitialised internal states. A special ClearOnRemove function must be added for each engine

namespace GameFramework.RayCast
{
public class RayCastEngineEngine
{
public RayCastEngine(RayCastEmployer jobList)
{
jobList.onJobassigned += OnRaycastRequested;
}

public void Add(IComponent obj)
{}

public void Remove(IComponent obj)
{}

void OnRaycastRequested(RayCastJob job)
{
RaycastHit shootHit;

Physics.Raycast(job.rayVector, out shootHit, job.range, _enemyMask);

job.Done(shootHit);
}

RayCastEmployer _employer;
int _enemyMask;
}

public struct RayCastJob
{
readonly public Ray rayVector;
readonly public float range;
readonly public Action<RaycastHit> Done;

public RayCastJob(Ray direction, float distance, Action<RaycastHit> OnDone)
{
rayVector = direction;
range = distance;
Done = OnDone;
}
}

public class RayCastEmployer
{
public event Action<RayCastJob> onJobassigned;

public void AssignJob(RayCastJob data, Action<RaycastHit> onJobdone)
{
onJobassigned(data);
}
}
}

if your code can be read as

A tells B to do something is direct
A register B event is indirect
althoggh if B tells A something through event is direct again. B must say something like I don't know who you are, but this just happened. you say B.SomethingHappenedToMe() not B.YouMustDoThis();

un engine non deve mai avere concetti di un altro engine. dire all'engine sonoro suona morte � sbagliato. � l'engine death che triggera l'evento e l'engine sound ad ascoltarlo.

+ 4
- 0
ECS/note.txt.meta View File

@@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 11a3defaf51bc2147904eb737af5efb7
TextScriptImporter:
userData:

+ 1
- 1
Factories/IGameObjectFactory.cs View File

@@ -7,6 +7,6 @@ namespace Svelto.Factories
void RegisterPrefab(GameObject prefab, string type, GameObject parent = null);

GameObject Build(string type);
GameObject Build(GameObject go);
GameObject Build(GameObject prefab);
}
}

+ 27
- 6
Observer/Observable.cs View File

@@ -2,20 +2,41 @@ using System;

namespace Svelto.Observer
{
public delegate void ObserverAction<DispatchType>(ref DispatchType parameter);

public interface IObservable
{
event Action Notify;

void Dispatch();
}

public interface IObservable<DispatchType>
{
event Action<DispatchType> Notify;
{
event ObserverAction<DispatchType> Notify;

void Dispatch(DispatchType parameter);
void Dispatch(ref DispatchType parameter);
}

public class Observable<DispatchType>:IObservable<DispatchType>
{
public event Action<DispatchType> Notify;
public event ObserverAction<DispatchType> Notify;

public void Dispatch(ref DispatchType parameter)
{
if (Notify != null)
Notify(ref parameter);
}
}

public class Observable:IObservable
{
public event Action Notify;

public void Dispatch(DispatchType parameter)
public void Dispatch()
{
Notify(parameter);
if (Notify != null)
Notify();
}
}
}

+ 1
- 1
Observer/Observable.cs.meta View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c2a9f8efc13196f40bdc41e36e9f78fb
guid: e9d378efdf4e5dd439400d001b6775ec
timeCreated: 1440356670
licenseType: Free
MonoImporter:


+ 72
- 19
Observer/Observer.cs View File

@@ -1,24 +1,24 @@
using System;

namespace Svelto.Observer
namespace Svelto.Observer.InterNamespace
{
public abstract class Observer<DispatchType, ActionType>: IObserver<ActionType>
public abstract class Observer<DispatchType, ActionType> : IObserver<ActionType>
{
public Observer(Observable<DispatchType> observable)
protected Observer(Observable<DispatchType> observable)
{
observable.Notify += OnObservableDispatched;
observable.Notify += OnObservableDispatched;

_unsubscribe = () => observable.Notify -= OnObservableDispatched;
}

public void AddAction(Action<ActionType> action)
public void AddAction(ObserverAction<ActionType> action)
{
_actions += action;
}

public void RemoveAction(Action<ActionType> action)
public void RemoveAction(ObserverAction<ActionType> action)
{
_actions += action;
_actions -= action;
}

public void Unsubscribe()
@@ -26,33 +26,86 @@ namespace Svelto.Observer
_unsubscribe();
}

private void OnObservableDispatched(DispatchType dispatchNotification)
void OnObservableDispatched(ref DispatchType dispatchNotification)
{
_actions(TypeMap(dispatchNotification));
if (_actions != null)
{
var actionType = TypeMap(ref dispatchNotification);

_actions(ref actionType);
}
}

abstract protected ActionType TypeMap(DispatchType dispatchNotification);
protected abstract ActionType TypeMap(ref DispatchType dispatchNotification);

Action<ActionType> _actions;
Action _unsubscribe;
ObserverAction<ActionType> _actions;
Action _unsubscribe;
}
}

public class Observer<DispatchType>: Observer<DispatchType, DispatchType>
namespace Svelto.Observer.IntraNamespace
{
public class Observer<DispatchType> : InterNamespace.Observer<DispatchType, DispatchType>
{
public Observer(Observable<DispatchType> observable):base(observable)
{}
public Observer(Observable<DispatchType> observable) : base(observable)
{ }

protected override DispatchType TypeMap(DispatchType dispatchNotification)
protected override DispatchType TypeMap(ref DispatchType dispatchNotification)
{
return dispatchNotification;
}
}
}

namespace Svelto.Observer
{
public class Observer: IObserver
{
public Observer(Observable observable)
{
observable.Notify += OnObservableDispatched;

_unsubscribe = () => observable.Notify -= OnObservableDispatched;
}

public void AddAction(Action action)
{
_actions += action;
}

public void RemoveAction(Action action)
{
_actions -= action;
}

public void Unsubscribe()
{
_unsubscribe();
}

void OnObservableDispatched()
{
if (_actions != null)
_actions();
}

Action _actions;
readonly Action _unsubscribe;
}

public interface IObserver<WatchingType>
{
void AddAction(Action<WatchingType> action);
void RemoveAction(Action<WatchingType> action);
void AddAction(ObserverAction<WatchingType> action);
void RemoveAction(ObserverAction<WatchingType> action);

void Unsubscribe();
}
}

public interface IObserver
{
void AddAction(Action action);
void RemoveAction(Action action);

void Unsubscribe();
}
}

+ 1
- 1
Observer/Observer.cs.meta View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 632ffa30ee5cc9d40af433bd31a2f57a
guid: 7b4eff431179a5047a4b9110fe27ecf6
timeCreated: 1440352946
licenseType: Free
MonoImporter:


+ 13
- 8
Ticker/ITickable.cs View File

@@ -1,26 +1,31 @@
namespace Svelto.Ticker
{
public interface ITickableBase
public interface ILateTickable : ITickableBase
{
void LateTick(float deltaSec);
}

public interface ITickable: ITickableBase
public interface IPhysicallyTickable : ITickableBase
{
void Tick(float deltaSec);
void PhysicsTick(float deltaSec);
}

public interface ILateTickable : ITickableBase
public interface ITickable : ITickableBase
{
void LateTick(float deltaSec);
void Tick(float deltaSec);
}

public interface IPhysicallyTickable : ITickableBase
public interface IEndOfFrameTickable : ITickableBase
{
void PhysicsTick(float deltaSec);
}
void EndOfFrameTick(float deltaSec);
}

public interface IIntervaledTickable : ITickableBase
{
void IntervaledTick();
}

public interface ITickableBase
{
}
}

+ 4
- 1
Ticker/ITickable.cs.meta View File

@@ -1,7 +1,10 @@
fileFormatVersion: 2
guid: b9ebca86eb6d1f64ba93813b675c4f88
guid: 8830537b810b3fa489b14e66327f0af2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 4
- 8
Ticker/ITicker.cs View File

@@ -1,12 +1,8 @@
using System;

namespace Svelto.Ticker
{
public interface ITicker
{
void Add(ITickableBase tickable);
public interface ITicker
{
void Add(ITickableBase tickable);
void Remove(ITickableBase tickable);
}
}
}



+ 4
- 1
Ticker/ITicker.cs.meta View File

@@ -1,7 +1,10 @@
fileFormatVersion: 2
guid: 5a726e8ced6bca340b272e7bd64ebcad
guid: 0bf92a08bb722064ab845dea9463933e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 116
- 52
Ticker/TickBehaviour.cs View File

@@ -1,42 +1,118 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

namespace Svelto.Ticker
{
public class TickBehaviour:MonoBehaviour
{
internal void Add(ITickable tickable)
{
_ticked.Add(tickable);
}
internal void Remove(ITickable tickable)
{
_ticked.Remove(tickable);
}

internal void AddPhysic(IPhysicallyTickable tickable)
{
_physicallyTicked.Add(tickable);
}

internal void RemovePhysic(IPhysicallyTickable tickable)
{
_physicallyTicked.Remove(tickable);
}

internal void AddLate(ILateTickable tickable)
{
_lateTicked.Add(tickable);
}

internal void RemoveLate(ILateTickable tickable)
{
_lateTicked.Remove(tickable);
}
public class TickBehaviour : MonoBehaviour
{
IEnumerator Start ()
{
var waitForEndFrame = new WaitForEndOfFrame();

while (true)
{
yield return waitForEndFrame;

for (int i = _endOfFrameTicked.Count - 1; i >= 0; --i)
{
try
{
_endOfFrameTicked[i].EndOfFrameTick(Time.deltaTime);
}
catch (Exception e)
{
Utility.Console.LogException(e);
}
}
}
}
internal void Add(ITickable tickable)
{
_ticked.Add(tickable);
}

internal void AddLate(ILateTickable tickable)
{
_lateTicked.Add(tickable);
}

internal void AddPhysic(IPhysicallyTickable tickable)
{
_physicallyTicked.Add(tickable);
}

internal void AddEndOfFrame(IEndOfFrameTickable tickable)
{
_endOfFrameTicked.Add(tickable);
}

internal void Remove(ITickable tickable)
{
_ticked.Remove(tickable);
}

internal void RemoveLate(ILateTickable tickable)
{
_lateTicked.Remove(tickable);
}

internal void RemovePhysic(IPhysicallyTickable tickable)
{
_physicallyTicked.Remove(tickable);
}

internal void RemoveEndOfFrame(IEndOfFrameTickable tickable)
{
_endOfFrameTicked.Remove(tickable);
}

void FixedUpdate()
{
for (int i = _physicallyTicked.Count - 1; i >= 0; --i)
{
try
{
_physicallyTicked[i].PhysicsTick(Time.fixedDeltaTime);
}
catch (Exception e)
{
Utility.Console.LogException(e);
}
}
}

void LateUpdate()
{
for (int i = _lateTicked.Count - 1; i >= 0; --i)
{
try
{
_lateTicked[i].LateTick(Time.deltaTime);
}
catch (Exception e)
{
Utility.Console.LogException(e);
}
}
}

void Update()
{
for (int i = _ticked.Count - 1; i >= 0; --i)
{
try
{
_ticked[i].Tick(Time.deltaTime);
}
catch (Exception e)
{
Utility.Console.LogException(e);
}
}
}

internal void AddIntervaled(IIntervaledTickable tickable)
{
@@ -57,33 +133,21 @@ namespace Svelto.Ticker
if (_intervalledTicked.TryGetValue(tickable, out enumerator))
{
StopCoroutine(enumerator);

_intervalledTicked.Remove(tickable);
}
}

void Update()
{
for (int i = _ticked.Count - 1; i >= 0; --i)
_ticked[i].Tick(Time.deltaTime);
}
void LateUpdate()
{
for (int i = _lateTicked.Count - 1; i >= 0; --i)
_lateTicked[i].LateTick(Time.deltaTime);
}
void FixedUpdate()
{
for (int i = _physicallyTicked.Count - 1; i >= 0; --i)
_physicallyTicked[i].PhysicsTick(Time.deltaTime);
}
IEnumerator IntervaledUpdate(IIntervaledTickable tickable, float seconds)
{
while (true) { DateTime next = DateTime.UtcNow.AddSeconds(seconds); while (DateTime.UtcNow < next) yield return null; tickable.IntervaledTick(); }
}

private List<ITickable> _ticked = new List<ITickable>();
private List<ILateTickable> _lateTicked = new List<ILateTickable>();
private List<IPhysicallyTickable> _physicallyTicked = new List<IPhysicallyTickable>();
private Dictionary<IIntervaledTickable, IEnumerator> _intervalledTicked = new Dictionary<IIntervaledTickable, IEnumerator>();
}
List<ILateTickable> _lateTicked = new List<ILateTickable>();
List<IPhysicallyTickable> _physicallyTicked = new List<IPhysicallyTickable>();
List<ITickable> _ticked = new List<ITickable>();
List<IEndOfFrameTickable> _endOfFrameTicked = new List<IEndOfFrameTickable>();

Dictionary<IIntervaledTickable, IEnumerator> _intervalledTicked = new Dictionary<IIntervaledTickable, IEnumerator>();
}
}

+ 4
- 1
Ticker/TickBehaviour.cs.meta View File

@@ -1,7 +1,10 @@
fileFormatVersion: 2
guid: b522dd9c9c9c5a941a49ff6a52222824
guid: 82d08d9d100803c47b036667fdc671cf
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 26
- 25
Ticker/UnityTicker.cs View File

@@ -2,24 +2,24 @@ using UnityEngine;

namespace Svelto.Ticker
{
internal class UnityTicker: ITicker
{
public UnityTicker()
{
_ticker = GameObject.FindObjectOfType<TickBehaviour>();
class UnityTicker : ITicker
{
public UnityTicker()
{
_ticker = Object.FindObjectOfType<TickBehaviour>();

if (_ticker == null)
{
GameObject go = new GameObject("SveltoTicker");
_ticker = go.AddComponent<TickBehaviour>();
}
}
public void Add(ITickableBase tickable)
{
{
var go = new GameObject("SveltoTicker");
_ticker = go.AddComponent<TickBehaviour>();
}
}
public void Add(ITickableBase tickable)
{
if (tickable is ITickable)
_ticker.Add(tickable as ITickable);
_ticker.Add(tickable as ITickable);

if (tickable is IPhysicallyTickable)
_ticker.AddPhysic(tickable as IPhysicallyTickable);
@@ -27,12 +27,15 @@ namespace Svelto.Ticker
if (tickable is ILateTickable)
_ticker.AddLate(tickable as ILateTickable);

if (tickable is IEndOfFrameTickable)
_ticker.AddEndOfFrame(tickable as IEndOfFrameTickable);

if (tickable is IIntervaledTickable)
_ticker.AddIntervaled(tickable as IIntervaledTickable);
}
public void Remove(ITickableBase tickable)
{
public void Remove(ITickableBase tickable)
{
if (tickable is ITickable)
_ticker.Remove(tickable as ITickable);

@@ -42,15 +45,13 @@ namespace Svelto.Ticker
if (tickable is ILateTickable)
_ticker.RemoveLate(tickable as ILateTickable);

if (tickable is IEndOfFrameTickable)
_ticker.RemoveEndOfFrame(tickable as IEndOfFrameTickable);

if (tickable is IIntervaledTickable)
_ticker.RemoveIntervaled(tickable as IIntervaledTickable);
}

private TickBehaviour _ticker;
}
readonly TickBehaviour _ticker;
}
}




+ 4
- 1
Ticker/UnityTicker.cs.meta View File

@@ -1,7 +1,10 @@
fileFormatVersion: 2
guid: 8972f22f09349484b8537133b3905062
guid: b62a08472017f914d9fc399eeb95108e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 0
- 20
Utilities/Dispatcher.cs View File

@@ -1,20 +0,0 @@
public class Dispatcher<S, T>
{
public event System.Action<S, T> observers;

private Dispatcher() { }

public Dispatcher(S sender)
{
_sender = sender;
}

virtual public void Dispatch(T value)
{
if (observers != null)
observers(_sender, value);
}

S _sender;
}


+ 165
- 0
Utilities/Print.cs View File

@@ -0,0 +1,165 @@
using System;
using System.Diagnostics;
using System.Text;
using Debug = UnityEngine.Debug;

public static class FastConcatUtility
{
static readonly StringBuilder _stringBuilder = new StringBuilder(256);

public static string FastConcat(this string str1, string str2)
{
lock (_stringBuilder)
{
_stringBuilder.Length = 0;

_stringBuilder.Append(str1);
_stringBuilder.Append(str2);

return _stringBuilder.ToString();
}
}

public static string FastConcat(this string str1, string str2, string str3)
{
lock (_stringBuilder)
{
_stringBuilder.Length = 0;

_stringBuilder.Append(str1);
_stringBuilder.Append(str2);
_stringBuilder.Append(str3);

return _stringBuilder.ToString();
}
}

public static string FastConcat(this string str1, string str2, string str3, string str4)
{
lock (_stringBuilder)
{
_stringBuilder.Length = 0;

_stringBuilder.Append(str1);
_stringBuilder.Append(str2);
_stringBuilder.Append(str3);
_stringBuilder.Append(str4);


return _stringBuilder.ToString();
}
}

public static string FastConcat(this string str1, string str2, string str3, string str4, string str5)
{
lock (_stringBuilder)
{
_stringBuilder.Length = 0;

_stringBuilder.Append(str1);
_stringBuilder.Append(str2);
_stringBuilder.Append(str3);
_stringBuilder.Append(str4);
_stringBuilder.Append(str5);

return _stringBuilder.ToString();
}
}
}

namespace Utility
{
public static class Console
{
static StringBuilder _stringBuilder = new StringBuilder(256);

public static void Log(string txt)
{
Debug.Log(txt);
}

public static void LogError(string txt)
{
string toPrint;
lock (_stringBuilder)
{
_stringBuilder.Length = 0;
_stringBuilder.Append("-!!!!!!-> ");
_stringBuilder.Append(txt);

toPrint = _stringBuilder.ToString();
}
Debug.LogError(toPrint);
}

public static void LogException(Exception e)
{
LogException(e, null);
}

public static void LogException(Exception e, UnityEngine.Object obj)
{
string toPrint;

lock (_stringBuilder)
{
_stringBuilder.Length = 0;
_stringBuilder.Append("-!!!!!!-> ").Append(e);

toPrint = _stringBuilder.ToString();
}

Exception ex = new Exception(e.ToString());

Debug.Log(toPrint);
Debug.LogException(ex, obj);
}

public static void LogWarning(string txt)
{
string toPrint;

lock (_stringBuilder)
{
_stringBuilder.Length = 0;
_stringBuilder.Append("------> ");
_stringBuilder.Append(txt);

toPrint = _stringBuilder.ToString();
}

Debug.LogWarning(toPrint);
}

/// <summary>
/// This function should never be used explicitly
/// </summary>
/// <param name="txt"></param>
public static void SystemLog(string txt)
{
string toPrint;

lock (_stringBuilder)
{
string currentTimeString = DateTime.UtcNow.ToLongTimeString(); //ensure includes seconds
string processTimeString = (DateTime.Now - Process.GetCurrentProcess().StartTime).ToString();

_stringBuilder.Length = 0;
_stringBuilder.Append("[").Append(currentTimeString);
_stringBuilder.Append("][").Append(processTimeString);
_stringBuilder.Length = _stringBuilder.Length - 3; //remove some precision that we don't need
_stringBuilder.Append("] ").AppendLine(txt);

toPrint = _stringBuilder.ToString();
}

#if !UNITY_EDITOR
System.Console.WriteLine(toPrint);
#else
Debug.Log(toPrint);
#endif
}
}
}

+ 8
- 0
Utilities/Print.cs.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1f5eede659a66c64a9af2ec703db2691
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

+ 0
- 50
Utilities/WeakReference.cs View File

@@ -1,50 +0,0 @@
using System;
using System.Runtime.Serialization;
/// <span class="code-SummaryComment"><summary></span>
/// Represents a weak reference, which references an object while still allowing
/// that object to be reclaimed by garbage collection.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><typeparam name="T">The type of the object that is referenced.</typeparam></span>
[Serializable]
public class WeakReference<T>
: WeakReference where T : class
{
/// <span class="code-SummaryComment"><summary></span>
/// Initializes a new instance of the WeakReference{T} class, referencing
/// the specified object.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="target">The object to reference.</param></span>
public WeakReference(T target)
: base(target)
{ }
/// <span class="code-SummaryComment"><summary></span>
/// Initializes a new instance of the WeakReference{T} class, referencing
/// the specified object and using the specified resurrection tracking.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="target">An object to track.</param></span>
/// <span class="code-SummaryComment"><param name="trackResurrection">Indicates when to stop tracking the object. </span>
/// If true, the object is tracked
/// after finalization; if false, the object is only tracked
/// until finalization.<span class="code-SummaryComment"></param></span>
public WeakReference(T target, bool trackResurrection)
: base(target, trackResurrection)
{ }
protected WeakReference(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
/// <span class="code-SummaryComment"><summary></span>
/// Gets or sets the object (the target) referenced by the
/// current WeakReference{T} object.
/// <span class="code-SummaryComment"></summary></span>
public new T Target
{
get
{
return (T)base.Target;
}
set
{
base.Target = value;
}
}
}

Loading…
Cancel
Save