Updated Context and Ticker Framework Added Datastructurestags/Rel1
@@ -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,5 +1,5 @@ | |||
fileFormatVersion: 2 | |||
guid: 88190f2317429cb49bfdf63e448efa52 | |||
guid: ec4bd87e898bf7c42823fb5ec2456b43 | |||
folderAsset: yes | |||
timeCreated: 1431630831 | |||
licenseType: Free | |||
@@ -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; | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
@@ -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(); | |||
} | |||
} | |||
@@ -5,7 +5,7 @@ namespace Svelto.Context | |||
void NotifyFrameworkInitialized(); | |||
void NotifyFrameworkDeinitialized(); | |||
void AddFrameworkInitializationListener(IWaitForFrameworkInitialization obj); | |||
void AddFrameworkInitializationListener(IWaitForFrameworkInitialization obj); | |||
void AddFrameworkDestructionListener(IWaitForFrameworkDestruction obj); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 5f61f9718491ceb498626e61ab9f48d4 | |||
folderAsset: yes | |||
timeCreated: 1434754873 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,5 +1,5 @@ | |||
fileFormatVersion: 2 | |||
guid: 403de662aab64bb4e917559caa6b7946 | |||
guid: 14144568b327bbe40876c12a777e5f05 | |||
folderAsset: yes | |||
timeCreated: 1434752394 | |||
licenseType: Free | |||
@@ -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); | |||
} | |||
} | |||
} |
@@ -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; | |||
} |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 6663fc83070cb0842b4665b38356feb2 | |||
folderAsset: yes | |||
timeCreated: 1463348260 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -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; | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
fileFormatVersion: 2 | |||
guid: 0859454e6e6d968498cea54757578eda | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -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(); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: e13aaf89d27048246bcf0d30c0993cf3 | |||
timeCreated: 1459332966 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -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(); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
fileFormatVersion: 2 | |||
guid: 905bfd795bede6d448694b23dd88e0be | |||
guid: 57d029cda5232f8468d50d4eb3bf5489 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] |
@@ -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) | |||
{ } | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 205cba76ee94d0e47aba9510ca92c540 | |||
timeCreated: 1452175408 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 2eae335fd33e33c4f951bf28bbf4914f | |||
folderAsset: yes | |||
timeCreated: 1462445195 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -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; | |||
} |
@@ -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); | |||
} | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
fileFormatVersion: 2 | |||
guid: 13278f0cd187d8d43acc6a02479e459b | |||
guid: 908688d3b784d644e88a06e20f9ea159 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] |
@@ -1,5 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: b1f3314cac8b8484f965651234415ca8 | |||
folderAsset: yes | |||
DefaultImporter: | |||
userData: |
@@ -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); | |||
} | |||
} |
@@ -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>()); | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: b8aebbeeaf3d65d438359008c1f5d351 | |||
timeCreated: 1459422025 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -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: | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 42ab9afd9889862468f4afdac4fffd8b | |||
timeCreated: 1457096903 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,6 @@ | |||
namespace Svelto.ES | |||
{ | |||
public interface IComponent | |||
{ | |||
} | |||
} |
@@ -1,6 +1,6 @@ | |||
fileFormatVersion: 2 | |||
guid: 103dfa72bd2486d46ac7e6927c805778 | |||
timeCreated: 1435956509 | |||
guid: 644f7615a18450b4e92f4dcab1f75e57 | |||
timeCreated: 1463519273 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 44c24b91989f46048abc15039fd070bc | |||
timeCreated: 1459422024 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -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); | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
namespace Svelto.ES | |||
{ | |||
/// <summary> | |||
/// please use [DisallowMultipleComponent] in your monobehaviours that implement IEntityDescriptorHolder | |||
/// </summary> | |||
public interface IEntityDescriptorHolder | |||
{ | |||
EntityDescriptor BuildDescriptorType(); | |||
} | |||
} |
@@ -1,6 +1,6 @@ | |||
fileFormatVersion: 2 | |||
guid: 2bf8d1cb161e6aa428300dba9323892e | |||
timeCreated: 1434750269 | |||
guid: 5a8db83410a8aaa40b824fdc3d968f67 | |||
timeCreated: 1463438461 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 |
@@ -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; | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
using System; | |||
namespace Svelto.ES | |||
{ | |||
public interface IRemoveEntityComponent | |||
{ | |||
Action removeEntity { get; set; } | |||
} | |||
} |
@@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: bb9e778a1f85b0d46a065bbd5b549acd | |||
timeCreated: 1462977663 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,5 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 8e3c19ee9185a664aa837e567c4db122 | |||
folderAsset: yes | |||
DefaultImporter: | |||
userData: |
@@ -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; } | |||
} | |||
} |
@@ -1,8 +0,0 @@ | |||
namespace Svelto.ES | |||
{ | |||
interface INodeHolder | |||
{ | |||
INode node { get; } | |||
INodeEnginesRoot engineRoot { set; } | |||
} | |||
} |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: a4c0061442f32644cb1e434b6544d56c | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,5 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: e369cc976007e884d92f906e4d1054d7 | |||
folderAsset: yes | |||
DefaultImporter: | |||
userData: |
@@ -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; | |||
} | |||
} | |||
} |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 50ed7d1adb836dd4786fef832cb4e808 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -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(); | |||
} | |||
} |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 6e4e1cde52e768148a0aaf8effbb9ba3 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -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. |
@@ -0,0 +1,4 @@ | |||
fileFormatVersion: 2 | |||
guid: 11a3defaf51bc2147904eb737af5efb7 | |||
TextScriptImporter: | |||
userData: |
@@ -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); | |||
} | |||
} |
@@ -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,5 +1,5 @@ | |||
fileFormatVersion: 2 | |||
guid: c2a9f8efc13196f40bdc41e36e9f78fb | |||
guid: e9d378efdf4e5dd439400d001b6775ec | |||
timeCreated: 1440356670 | |||
licenseType: Free | |||
MonoImporter: | |||
@@ -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,5 +1,5 @@ | |||
fileFormatVersion: 2 | |||
guid: 632ffa30ee5cc9d40af433bd31a2f57a | |||
guid: 7b4eff431179a5047a4b9110fe27ecf6 | |||
timeCreated: 1440352946 | |||
licenseType: Free | |||
MonoImporter: | |||
@@ -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 | |||
{ | |||
} | |||
} |
@@ -1,7 +1,10 @@ | |||
fileFormatVersion: 2 | |||
guid: b9ebca86eb6d1f64ba93813b675c4f88 | |||
guid: 8830537b810b3fa489b14e66327f0af2 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -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); | |||
} | |||
} | |||
} | |||
@@ -1,7 +1,10 @@ | |||
fileFormatVersion: 2 | |||
guid: 5a726e8ced6bca340b272e7bd64ebcad | |||
guid: 0bf92a08bb722064ab845dea9463933e | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -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>(); | |||
} | |||
} |
@@ -1,7 +1,10 @@ | |||
fileFormatVersion: 2 | |||
guid: b522dd9c9c9c5a941a49ff6a52222824 | |||
guid: 82d08d9d100803c47b036667fdc671cf | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -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; | |||
} | |||
} | |||
@@ -1,7 +1,10 @@ | |||
fileFormatVersion: 2 | |||
guid: 8972f22f09349484b8537133b3905062 | |||
guid: b62a08472017f914d9fc399eeb95108e | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -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; | |||
} | |||
@@ -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 | |||
} | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 1f5eede659a66c64a9af2ec703db2691 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -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; | |||
} | |||
} | |||
} |