messages + rearranging
							parent
							
								
									9032eff699
								
							
						
					
					
						commit
						3d2261f739
					
				|  | @ -60,12 +60,27 @@ namespace MoonTools.ECS.Collections | ||||||
| 				return false; | 				return false; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			/* | ||||||
| 			var lastElement = array[Count - 1]; | 			var lastElement = array[Count - 1]; | ||||||
| 			var index = indices[element]; | 			var index = indices[element]; | ||||||
| 			array[index] = lastElement; | 			array[index] = lastElement; | ||||||
| 			indices[lastElement] = index; | 			indices[lastElement] = index; | ||||||
| 			count -= 1; | 			count -= 1; | ||||||
| 			indices.Remove(element); | 			indices.Remove(element); | ||||||
|  | 			*/ | ||||||
|  | 
 | ||||||
|  | 			// FIXME: we can probably undo this change | ||||||
|  | 
 | ||||||
|  | 			var index = indices[element]; | ||||||
|  | 
 | ||||||
|  | 			for (var i = index; i < Count - 1; i += 1) | ||||||
|  | 			{ | ||||||
|  | 				array[i] = array[i + 1]; | ||||||
|  | 				indices[array[i]] = i; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			indices.Remove(element); | ||||||
|  | 			count -= 1; | ||||||
| 
 | 
 | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
|  | @ -0,0 +1,110 @@ | ||||||
|  | using System; | ||||||
|  | using System.Runtime.CompilerServices; | ||||||
|  | using System.Runtime.InteropServices; | ||||||
|  | 
 | ||||||
|  | namespace MoonTools.ECS.Collections; | ||||||
|  | 
 | ||||||
|  | public unsafe class NativeArray<T> : IDisposable where T : unmanaged | ||||||
|  | { | ||||||
|  | 	private T* Array; | ||||||
|  | 	private int count; | ||||||
|  | 	private int capacity; | ||||||
|  | 	private int elementSize; | ||||||
|  | 
 | ||||||
|  | 	public int Count => count; | ||||||
|  | 
 | ||||||
|  | 	public Span<T>.Enumerator GetEnumerator() => new Span<T>(Array, count).GetEnumerator(); | ||||||
|  | 
 | ||||||
|  | 	private bool disposed; | ||||||
|  | 
 | ||||||
|  | 	public NativeArray(int capacity = 16) | ||||||
|  | 	{ | ||||||
|  | 		this.capacity = capacity; | ||||||
|  | 		elementSize = Unsafe.SizeOf<T>(); | ||||||
|  | 		Array = (T*) NativeMemory.Alloc((nuint) (capacity * elementSize)); | ||||||
|  | 		count = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public ref T this[int i] => ref Array[i]; | ||||||
|  | 
 | ||||||
|  | 	public void Add(T item) | ||||||
|  | 	{ | ||||||
|  | 		if (count >= capacity) | ||||||
|  | 		{ | ||||||
|  | 			capacity *= 2; | ||||||
|  | 			Array = (T*) NativeMemory.Realloc(Array, (nuint) (capacity * Unsafe.SizeOf<T>())); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		Array[count] = item; | ||||||
|  | 		count += 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void RemoveLastElement() | ||||||
|  | 	{ | ||||||
|  | 		count -= 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public bool TryPop(out T element) | ||||||
|  | 	{ | ||||||
|  | 		if (count > 0) | ||||||
|  | 		{ | ||||||
|  | 			element = Array[count - 1]; | ||||||
|  | 			count -= 1; | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		element = default; | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void Clear() | ||||||
|  | 	{ | ||||||
|  | 		count = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private void ResizeTo(int size) | ||||||
|  | 	{ | ||||||
|  | 		capacity = size; | ||||||
|  | 		Array = (T*) NativeMemory.Realloc((void*) Array, (nuint) (elementSize * capacity)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void CopyTo(NativeArray<T> other) | ||||||
|  | 	{ | ||||||
|  | 		if (count >= other.capacity) | ||||||
|  | 		{ | ||||||
|  | 			other.ResizeTo(Count); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		NativeMemory.Copy( | ||||||
|  | 			(void*) Array, | ||||||
|  | 			(void*) other.Array, | ||||||
|  | 			(nuint) (elementSize * Count) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		other.count = count; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	protected virtual void Dispose(bool disposing) | ||||||
|  | 	{ | ||||||
|  | 		if (!disposed) | ||||||
|  | 		{ | ||||||
|  | 			NativeMemory.Free(Array); | ||||||
|  | 			Array = null; | ||||||
|  | 
 | ||||||
|  | 			disposed = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	~NativeArray() | ||||||
|  | 	{ | ||||||
|  | 		// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||||||
|  | 		Dispose(disposing: false); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void Dispose() | ||||||
|  | 	{ | ||||||
|  | 		// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||||||
|  | 		Dispose(disposing: true); | ||||||
|  | 		GC.SuppressFinalize(this); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,128 @@ | ||||||
|  | using System; | ||||||
|  | using System.Runtime.CompilerServices; | ||||||
|  | using System.Runtime.InteropServices; | ||||||
|  | 
 | ||||||
|  | namespace MoonTools.ECS.Collections; | ||||||
|  | 
 | ||||||
|  | internal unsafe class NativeArray : IDisposable | ||||||
|  | { | ||||||
|  | 	public nint Elements; | ||||||
|  | 	public int Count; | ||||||
|  | 
 | ||||||
|  | 	private int Capacity; | ||||||
|  | 	public readonly int ElementSize; | ||||||
|  | 
 | ||||||
|  | 	private bool IsDisposed; | ||||||
|  | 
 | ||||||
|  | 	public NativeArray(int elementSize) | ||||||
|  | 	{ | ||||||
|  | 		Capacity = 16; | ||||||
|  | 		Count = 0; | ||||||
|  | 		ElementSize = elementSize; | ||||||
|  | 
 | ||||||
|  | 		Elements = (nint) NativeMemory.Alloc((nuint) (ElementSize * Capacity)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public Span<T> ToSpan<T>() | ||||||
|  | 	{ | ||||||
|  | 		return new Span<T>((void*) Elements, Count); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||||||
|  | 	public ref T Get<T>(int i) where T : unmanaged | ||||||
|  | 	{ | ||||||
|  | 		return ref ((T*) Elements)[i]; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private void Resize() | ||||||
|  | 	{ | ||||||
|  | 		Capacity *= 2; | ||||||
|  | 		Elements = (nint) NativeMemory.Realloc((void*) Elements, (nuint) (ElementSize * Capacity)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private void ResizeTo(int capacity) | ||||||
|  | 	{ | ||||||
|  | 		Capacity = capacity; | ||||||
|  | 		Elements = (nint) NativeMemory.Realloc((void*) Elements, (nuint) (ElementSize * Capacity)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Fills gap by copying final element to the deleted index | ||||||
|  | 	public void Delete(int index) | ||||||
|  | 	{ | ||||||
|  | 		if (Count > 1) | ||||||
|  | 		{ | ||||||
|  | 			NativeMemory.Copy( | ||||||
|  | 				(void*) (Elements + ((Count - 1) * ElementSize)), | ||||||
|  | 				(void*) (Elements + (index * ElementSize)), | ||||||
|  | 				(nuint) ElementSize | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		Count -= 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void Append<T>(T component) where T : unmanaged | ||||||
|  | 	{ | ||||||
|  | 		if (Count >= Capacity) | ||||||
|  | 		{ | ||||||
|  | 			Resize(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		((T*) Elements)[Count] = component; | ||||||
|  | 		Count += 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void CopyElementToEnd(int index, NativeArray other) | ||||||
|  | 	{ | ||||||
|  | 		if (other.Count >= other.Capacity) | ||||||
|  | 		{ | ||||||
|  | 			other.Resize(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		NativeMemory.Copy( | ||||||
|  | 			(void*) (Elements + (index * ElementSize)), | ||||||
|  | 			(void*) (other.Elements + (other.Count * ElementSize)), | ||||||
|  | 			(nuint) ElementSize | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		other.Count += 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void CopyAllTo(NativeArray other) | ||||||
|  | 	{ | ||||||
|  | 		if (Count >= other.Capacity) | ||||||
|  | 		{ | ||||||
|  | 			other.ResizeTo(Count); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		NativeMemory.Copy( | ||||||
|  | 			(void*) Elements, | ||||||
|  | 			(void*) other.Elements, | ||||||
|  | 			(nuint) (ElementSize * Count) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		other.Count = Count; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	protected virtual void Dispose(bool disposing) | ||||||
|  | 	{ | ||||||
|  | 		if (!IsDisposed) | ||||||
|  | 		{ | ||||||
|  | 			NativeMemory.Free((void*) Elements); | ||||||
|  | 			IsDisposed = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	~NativeArray() | ||||||
|  | 	{ | ||||||
|  | 		// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||||||
|  | 		Dispose(disposing: false); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void Dispose() | ||||||
|  | 	{ | ||||||
|  | 		// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||||||
|  | 		Dispose(disposing: true); | ||||||
|  | 		GC.SuppressFinalize(this); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -43,7 +43,7 @@ namespace MoonTools.ECS | ||||||
| 			return Lookup<TComponent>().Any(); | 			return Lookup<TComponent>().Any(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public ref readonly TComponent Get<TComponent>(int entityID) where TComponent : unmanaged | 		public ref TComponent Get<TComponent>(int entityID) where TComponent : unmanaged | ||||||
| 		{ | 		{ | ||||||
| 			return ref Lookup<TComponent>().Get(entityID); | 			return ref Lookup<TComponent>().Get(entityID); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -41,7 +41,7 @@ namespace MoonTools.ECS | ||||||
| 			return count > 0; | 			return count > 0; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public ref readonly TComponent Get(int entityID) | 		public ref TComponent Get(int entityID) | ||||||
| 		{ | 		{ | ||||||
| 			return ref components[entityIDToStorageIndex[entityID]]; | 			return ref components[entityIDToStorageIndex[entityID]]; | ||||||
| 		} | 		} | ||||||
|  | @ -151,6 +151,7 @@ namespace MoonTools.ECS | ||||||
| 		{ | 		{ | ||||||
| 			return entityIDToStorageIndex.Keys; | 			return entityIDToStorageIndex.Keys; | ||||||
| 		} | 		} | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| 		protected virtual void Dispose(bool disposing) | 		protected virtual void Dispose(bool disposing) | ||||||
| 		{ | 		{ | ||||||
|  | @ -177,6 +178,5 @@ namespace MoonTools.ECS | ||||||
| 			Dispose(disposing: true); | 			Dispose(disposing: true); | ||||||
| 			GC.SuppressFinalize(this); | 			GC.SuppressFinalize(this); | ||||||
| 		} | 		} | ||||||
| #endif |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ namespace MoonTools.ECS | ||||||
| 			return Lookup<TMessage>().First(); | 			return Lookup<TMessage>().First(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public ReverseSpanEnumerator<TMessage> WithEntity<TMessage>(int entityID) where TMessage : unmanaged | 		public Span<TMessage>.Enumerator WithEntity<TMessage>(int entityID) where TMessage : unmanaged | ||||||
| 		{ | 		{ | ||||||
| 			return Lookup<TMessage>().WithEntity(entityID); | 			return Lookup<TMessage>().WithEntity(entityID); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -63,7 +63,7 @@ namespace MoonTools.ECS | ||||||
| 			return messages[0]; | 			return messages[0]; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public ReverseSpanEnumerator<TMessage> WithEntity(int entityID) | 		public Span<TMessage>.Enumerator WithEntity(int entityID) | ||||||
| 		{ | 		{ | ||||||
| 			if (entityToMessages.TryGetValue(entityID, out var messages)) | 			if (entityToMessages.TryGetValue(entityID, out var messages)) | ||||||
| 			{ | 			{ | ||||||
|  | @ -71,7 +71,7 @@ namespace MoonTools.ECS | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				return ReverseSpanEnumerator<TMessage>.Empty; | 				return Span<TMessage>.Empty.GetEnumerator(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,111 +0,0 @@ | ||||||
| using System; |  | ||||||
| using System.Runtime.CompilerServices; |  | ||||||
| using System.Runtime.InteropServices; |  | ||||||
| 
 |  | ||||||
| namespace MoonTools.ECS.Collections |  | ||||||
| { |  | ||||||
| 	public unsafe class NativeArray<T> : IDisposable where T : unmanaged |  | ||||||
| 	{ |  | ||||||
| 		private T* Array; |  | ||||||
| 		private int count; |  | ||||||
| 		private int capacity; |  | ||||||
| 		private int elementSize; |  | ||||||
| 
 |  | ||||||
| 		public int Count => count; |  | ||||||
| 
 |  | ||||||
| 		public Span<T>.Enumerator GetEnumerator() => new Span<T>(Array, count).GetEnumerator(); |  | ||||||
| 
 |  | ||||||
| 		private bool disposed; |  | ||||||
| 
 |  | ||||||
| 		public NativeArray(int capacity = 16) |  | ||||||
| 		{ |  | ||||||
| 			this.capacity = capacity; |  | ||||||
| 			elementSize = Unsafe.SizeOf<T>(); |  | ||||||
| 			Array = (T*) NativeMemory.Alloc((nuint) (capacity * elementSize)); |  | ||||||
| 			count = 0; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public ref T this[int i] => ref Array[i]; |  | ||||||
| 
 |  | ||||||
| 		public void Add(T item) |  | ||||||
| 		{ |  | ||||||
| 			if (count >= capacity) |  | ||||||
| 			{ |  | ||||||
| 				capacity *= 2; |  | ||||||
| 				Array = (T*) NativeMemory.Realloc(Array, (nuint) (capacity * Unsafe.SizeOf<T>())); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			Array[count] = item; |  | ||||||
| 			count += 1; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void RemoveLastElement() |  | ||||||
| 		{ |  | ||||||
| 			count -= 1; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public bool TryPop(out T element) |  | ||||||
| 		{ |  | ||||||
| 			if (count > 0) |  | ||||||
| 			{ |  | ||||||
| 				element = Array[count - 1]; |  | ||||||
| 				count -= 1; |  | ||||||
| 				return true; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			element = default; |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void Clear() |  | ||||||
| 		{ |  | ||||||
| 			count = 0; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		private void ResizeTo(int size) |  | ||||||
| 		{ |  | ||||||
| 			capacity = size; |  | ||||||
| 			Array = (T*) NativeMemory.Realloc((void*) Array, (nuint) (elementSize * capacity)); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void CopyTo(NativeArray<T> other) |  | ||||||
| 		{ |  | ||||||
| 			if (count >= other.capacity) |  | ||||||
| 			{ |  | ||||||
| 				other.ResizeTo(Count); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			NativeMemory.Copy( |  | ||||||
| 				(void*) Array, |  | ||||||
| 				(void*) other.Array, |  | ||||||
| 				(nuint) (elementSize * Count) |  | ||||||
| 			); |  | ||||||
| 
 |  | ||||||
| 			other.count = count; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		protected virtual void Dispose(bool disposing) |  | ||||||
| 		{ |  | ||||||
| 			if (!disposed) |  | ||||||
| 			{ |  | ||||||
| 				NativeMemory.Free(Array); |  | ||||||
| 				Array = null; |  | ||||||
| 
 |  | ||||||
| 				disposed = true; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		~NativeArray() |  | ||||||
| 		{ |  | ||||||
| 			// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method |  | ||||||
| 			Dispose(disposing: false); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void Dispose() |  | ||||||
| 		{ |  | ||||||
| 			// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method |  | ||||||
| 			Dispose(disposing: true); |  | ||||||
| 			GC.SuppressFinalize(this); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -7,7 +7,7 @@ internal class Archetype | ||||||
| { | { | ||||||
| 	public World World; | 	public World World; | ||||||
| 	public ArchetypeSignature Signature; | 	public ArchetypeSignature Signature; | ||||||
| 	public Column[] ComponentColumns; | 	public NativeArray[] ComponentColumns; | ||||||
| 	public NativeArray<Id> RowToEntity = new NativeArray<Id>(); | 	public NativeArray<Id> RowToEntity = new NativeArray<Id>(); | ||||||
| 
 | 
 | ||||||
| 	public Dictionary<Id, int> ComponentToColumnIndex = | 	public Dictionary<Id, int> ComponentToColumnIndex = | ||||||
|  | @ -20,7 +20,7 @@ internal class Archetype | ||||||
| 	{ | 	{ | ||||||
| 		World = world; | 		World = world; | ||||||
| 		Signature = signature; | 		Signature = signature; | ||||||
| 		ComponentColumns = new Column[signature.Count]; | 		ComponentColumns = new NativeArray[signature.Count]; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void ClearAll() | 	public void ClearAll() | ||||||
|  |  | ||||||
|  | @ -1,4 +1,3 @@ | ||||||
| namespace MoonTools.ECS.Rev2 | namespace MoonTools.ECS.Rev2; | ||||||
| { | 
 | ||||||
| 	internal readonly record struct ArchetypeEdge(Archetype Add, Archetype Remove); | internal readonly record struct ArchetypeEdge(Archetype Add, Archetype Remove); | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| 
 | 
 | ||||||
| namespace MoonTools.ECS.Rev2 | namespace MoonTools.ECS.Rev2; | ||||||
|  | 
 | ||||||
|  | internal class ArchetypeSignature : IEquatable<ArchetypeSignature> | ||||||
| { | { | ||||||
| 	internal class ArchetypeSignature : IEquatable<ArchetypeSignature> |  | ||||||
| 	{ |  | ||||||
| 	public static ArchetypeSignature Empty = new ArchetypeSignature(0); | 	public static ArchetypeSignature Empty = new ArchetypeSignature(0); | ||||||
| 
 | 
 | ||||||
| 	List<uint> Ids; | 	List<uint> Ids; | ||||||
|  | @ -88,5 +88,4 @@ namespace MoonTools.ECS.Rev2 | ||||||
| 
 | 
 | ||||||
| 		return hashcode; | 		return hashcode; | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,129 +0,0 @@ | ||||||
| using System; |  | ||||||
| using System.Runtime.CompilerServices; |  | ||||||
| using System.Runtime.InteropServices; |  | ||||||
| 
 |  | ||||||
| namespace MoonTools.ECS.Rev2 |  | ||||||
| { |  | ||||||
| 	internal unsafe class Column : IDisposable |  | ||||||
| 	{ |  | ||||||
| 		public nint Elements; |  | ||||||
| 		public int Count; |  | ||||||
| 
 |  | ||||||
| 		private int Capacity; |  | ||||||
| 		public readonly int ElementSize; |  | ||||||
| 
 |  | ||||||
| 		private bool IsDisposed; |  | ||||||
| 
 |  | ||||||
| 		public Column(int elementSize) |  | ||||||
| 		{ |  | ||||||
| 			Capacity = 16; |  | ||||||
| 			Count = 0; |  | ||||||
| 			ElementSize = elementSize; |  | ||||||
| 
 |  | ||||||
| 			Elements = (nint) NativeMemory.Alloc((nuint) (ElementSize * Capacity)); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public Span<T> ToSpan<T>() |  | ||||||
| 		{ |  | ||||||
| 			return new Span<T>((void*) Elements, Count); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		[MethodImpl(MethodImplOptions.AggressiveInlining)] |  | ||||||
| 		public ref T Get<T>(int i) where T : unmanaged |  | ||||||
| 		{ |  | ||||||
| 			return ref ((T*) Elements)[i]; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void Resize() |  | ||||||
| 		{ |  | ||||||
| 			Capacity *= 2; |  | ||||||
| 			Elements = (nint) NativeMemory.Realloc((void*) Elements, (nuint) (ElementSize * Capacity)); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void ResizeTo(int capacity) |  | ||||||
| 		{ |  | ||||||
| 			Capacity = capacity; |  | ||||||
| 			Elements = (nint) NativeMemory.Realloc((void*) Elements, (nuint) (ElementSize * Capacity)); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// Fills gap by copying final element to the deleted index |  | ||||||
| 		public void Delete(int index) |  | ||||||
| 		{ |  | ||||||
| 			if (Count > 1) |  | ||||||
| 			{ |  | ||||||
| 				NativeMemory.Copy( |  | ||||||
| 					(void*) (Elements + ((Count - 1) * ElementSize)), |  | ||||||
| 					(void*) (Elements + (index * ElementSize)), |  | ||||||
| 					(nuint) ElementSize |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			Count -= 1; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void Append<T>(T component) where T : unmanaged |  | ||||||
| 		{ |  | ||||||
| 			if (Count >= Capacity) |  | ||||||
| 			{ |  | ||||||
| 				Resize(); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			((T*) Elements)[Count] = component; |  | ||||||
| 			Count += 1; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void CopyElementToEnd(int index, Column other) |  | ||||||
| 		{ |  | ||||||
| 			if (other.Count >= other.Capacity) |  | ||||||
| 			{ |  | ||||||
| 				other.Resize(); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			NativeMemory.Copy( |  | ||||||
| 				(void*) (Elements + (index * ElementSize)), |  | ||||||
| 				(void*) (other.Elements + (other.Count * ElementSize)), |  | ||||||
| 				(nuint) ElementSize |  | ||||||
| 			); |  | ||||||
| 
 |  | ||||||
| 			other.Count += 1; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void CopyAllTo(Column other) |  | ||||||
| 		{ |  | ||||||
| 			if (Count >= other.Capacity) |  | ||||||
| 			{ |  | ||||||
| 				other.ResizeTo(Count); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			NativeMemory.Copy( |  | ||||||
| 				(void*) Elements, |  | ||||||
| 				(void*) other.Elements, |  | ||||||
| 				(nuint) (ElementSize * Count) |  | ||||||
| 			); |  | ||||||
| 
 |  | ||||||
| 			other.Count = Count; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		protected virtual void Dispose(bool disposing) |  | ||||||
| 		{ |  | ||||||
| 			if (!IsDisposed) |  | ||||||
| 			{ |  | ||||||
| 				NativeMemory.Free((void*) Elements); |  | ||||||
| 				IsDisposed = true; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		~Column() |  | ||||||
| 		{ |  | ||||||
| 		    // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method |  | ||||||
| 		    Dispose(disposing: false); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		public void Dispose() |  | ||||||
| 		{ |  | ||||||
| 			// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method |  | ||||||
| 			Dispose(disposing: true); |  | ||||||
| 			GC.SuppressFinalize(this); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| 
 | 
 | ||||||
| namespace MoonTools.ECS.Rev2 | namespace MoonTools.ECS.Rev2; | ||||||
|  | 
 | ||||||
|  | // TODO: do we want to get fancy with queries beyond Include and Exclude? | ||||||
|  | public class Filter | ||||||
| { | { | ||||||
| 	// TODO: do we want to get fancy with queries beyond Include and Exclude? |  | ||||||
| 	public class Filter |  | ||||||
| 	{ |  | ||||||
| 	private Archetype EmptyArchetype; | 	private Archetype EmptyArchetype; | ||||||
| 	private HashSet<Id> Included; | 	private HashSet<Id> Included; | ||||||
| 	private HashSet<Id> Excluded; | 	private HashSet<Id> Excluded; | ||||||
|  | @ -200,5 +200,4 @@ namespace MoonTools.ECS.Rev2 | ||||||
| 		public bool MoveNext() => LinearCongruentialEnumerator.MoveNext(); | 		public bool MoveNext() => LinearCongruentialEnumerator.MoveNext(); | ||||||
| 		public Id Current => Filter.NthEntity(LinearCongruentialEnumerator.Current); | 		public Id Current => Filter.NthEntity(LinearCongruentialEnumerator.Current); | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| 
 | 
 | ||||||
| namespace MoonTools.ECS.Rev2 | namespace MoonTools.ECS.Rev2; | ||||||
|  | 
 | ||||||
|  | public ref struct FilterBuilder | ||||||
| { | { | ||||||
| 	public ref struct FilterBuilder |  | ||||||
| 	{ |  | ||||||
| 	World World; | 	World World; | ||||||
| 	HashSet<Id> Included; | 	HashSet<Id> Included; | ||||||
| 	HashSet<Id> Excluded; | 	HashSet<Id> Excluded; | ||||||
|  | @ -24,14 +24,14 @@ namespace MoonTools.ECS.Rev2 | ||||||
| 
 | 
 | ||||||
| 	public FilterBuilder Include<T>() where T : unmanaged | 	public FilterBuilder Include<T>() where T : unmanaged | ||||||
| 	{ | 	{ | ||||||
| 			World.TryRegisterTypeId<T>(); | 		World.GetTypeId<T>(); | ||||||
| 		Included.Add(World.TypeToId[typeof(T)]); | 		Included.Add(World.TypeToId[typeof(T)]); | ||||||
| 		return new FilterBuilder(World, Included, Excluded); | 		return new FilterBuilder(World, Included, Excluded); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public FilterBuilder Exclude<T>() where T : unmanaged | 	public FilterBuilder Exclude<T>() where T : unmanaged | ||||||
| 	{ | 	{ | ||||||
| 			World.TryRegisterTypeId<T>(); | 		World.GetTypeId<T>(); | ||||||
| 		Excluded.Add(World.TypeToId[typeof(T)]); | 		Excluded.Add(World.TypeToId[typeof(T)]); | ||||||
| 		return new FilterBuilder(World, Included, Excluded); | 		return new FilterBuilder(World, Included, Excluded); | ||||||
| 	} | 	} | ||||||
|  | @ -40,5 +40,4 @@ namespace MoonTools.ECS.Rev2 | ||||||
| 	{ | 	{ | ||||||
| 		return new Filter(World.EmptyArchetype, Included, Excluded); | 		return new Filter(World.EmptyArchetype, Included, Excluded); | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +0,0 @@ | ||||||
| namespace MoonTools.ECS.Rev2; |  | ||||||
| 
 |  | ||||||
| public interface IHasId |  | ||||||
| { |  | ||||||
| 	public int Id { get; init; } |  | ||||||
| } |  | ||||||
|  | @ -0,0 +1,63 @@ | ||||||
|  | using System; | ||||||
|  | using MoonTools.ECS.Collections; | ||||||
|  | 
 | ||||||
|  | namespace MoonTools.ECS.Rev2; | ||||||
|  | 
 | ||||||
|  | public class MessageStorage : IDisposable | ||||||
|  | { | ||||||
|  | 	private NativeArray Messages; | ||||||
|  | 
 | ||||||
|  | 	private bool IsDisposed; | ||||||
|  | 
 | ||||||
|  | 	public MessageStorage(int elementSize) | ||||||
|  | 	{ | ||||||
|  | 		Messages = new NativeArray(elementSize); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void Add<T>(in T message) where T : unmanaged | ||||||
|  | 	{ | ||||||
|  | 		Messages.Append(message); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public bool Some() | ||||||
|  | 	{ | ||||||
|  | 		return Messages.Count > 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public ReadOnlySpan<T> All<T>() where T : unmanaged | ||||||
|  | 	{ | ||||||
|  | 		return Messages.ToSpan<T>(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public T First<T>() where T : unmanaged | ||||||
|  | 	{ | ||||||
|  | 		return Messages.Get<T>(0); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void Clear() | ||||||
|  | 	{ | ||||||
|  | 		Messages.Count = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	protected virtual void Dispose(bool disposing) | ||||||
|  | 	{ | ||||||
|  | 		if (!IsDisposed) | ||||||
|  | 		{ | ||||||
|  | 			Messages.Dispose(); | ||||||
|  | 			IsDisposed = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// ~MessageStorage() | ||||||
|  | 	// { | ||||||
|  | 	// 	// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||||||
|  | 	// 	Dispose(disposing: false); | ||||||
|  | 	// } | ||||||
|  | 
 | ||||||
|  | 	public void Dispose() | ||||||
|  | 	{ | ||||||
|  | 		// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||||||
|  | 		Dispose(disposing: true); | ||||||
|  | 		GC.SuppressFinalize(this); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -1,4 +1,3 @@ | ||||||
| namespace MoonTools.ECS.Rev2 | namespace MoonTools.ECS.Rev2; | ||||||
| { | 
 | ||||||
| 	internal readonly record struct Record(Archetype Archetype, int Row); | internal readonly record struct Record(Archetype Archetype, int Row); | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -8,8 +8,8 @@ namespace MoonTools.ECS.Rev2; | ||||||
| // TODO: implement this entire class with NativeMemory equivalents, can just memcpy for snapshots | // TODO: implement this entire class with NativeMemory equivalents, can just memcpy for snapshots | ||||||
| internal class RelationStorage | internal class RelationStorage | ||||||
| { | { | ||||||
| 	internal Column relations; | 	internal NativeArray relations; | ||||||
| 	internal Column relationDatas; | 	internal NativeArray relationDatas; | ||||||
| 	internal Dictionary<(Id, Id), int> indices = new Dictionary<(Id, Id), int>(16); | 	internal Dictionary<(Id, Id), int> indices = new Dictionary<(Id, Id), int>(16); | ||||||
| 	internal Dictionary<Id, IndexableSet<Id>> outRelations = new Dictionary<Id, IndexableSet<Id>>(16); | 	internal Dictionary<Id, IndexableSet<Id>> outRelations = new Dictionary<Id, IndexableSet<Id>>(16); | ||||||
| 	internal Dictionary<Id, IndexableSet<Id>> inRelations = new Dictionary<Id, IndexableSet<Id>>(16); | 	internal Dictionary<Id, IndexableSet<Id>> inRelations = new Dictionary<Id, IndexableSet<Id>>(16); | ||||||
|  | @ -19,8 +19,8 @@ internal class RelationStorage | ||||||
| 
 | 
 | ||||||
| 	public RelationStorage(int relationDataSize) | 	public RelationStorage(int relationDataSize) | ||||||
| 	{ | 	{ | ||||||
| 		relations = new Column(Unsafe.SizeOf<(Id, Id)>()); | 		relations = new NativeArray(Unsafe.SizeOf<(Id, Id)>()); | ||||||
| 		relationDatas = new Column(relationDataSize); | 		relationDatas = new NativeArray(relationDataSize); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public ReverseSpanEnumerator<(Id, Id)> All() | 	public ReverseSpanEnumerator<(Id, Id)> All() | ||||||
|  |  | ||||||
|  | @ -139,20 +139,20 @@ public class Snapshot | ||||||
| 
 | 
 | ||||||
| 	private class ArchetypeSnapshot | 	private class ArchetypeSnapshot | ||||||
| 	{ | 	{ | ||||||
| 		private readonly Column[] ComponentColumns; | 		private readonly NativeArray[] ComponentColumns; | ||||||
| 		private readonly NativeArray<Id> RowToEntity; | 		private readonly NativeArray<Id> RowToEntity; | ||||||
| 
 | 
 | ||||||
| 		public int Count => RowToEntity.Count; | 		public int Count => RowToEntity.Count; | ||||||
| 
 | 
 | ||||||
| 		public ArchetypeSnapshot(ArchetypeSignature signature) | 		public ArchetypeSnapshot(ArchetypeSignature signature) | ||||||
| 		{ | 		{ | ||||||
| 			ComponentColumns = new Column[signature.Count]; | 			ComponentColumns = new NativeArray[signature.Count]; | ||||||
| 			RowToEntity = new NativeArray<Id>(); | 			RowToEntity = new NativeArray<Id>(); | ||||||
| 
 | 
 | ||||||
| 			for (int i = 0; i < signature.Count; i += 1) | 			for (int i = 0; i < signature.Count; i += 1) | ||||||
| 			{ | 			{ | ||||||
| 				var componentId = signature[i]; | 				var componentId = signature[i]; | ||||||
| 				ComponentColumns[i] = new Column(World.ElementSizes[componentId]); | 				ComponentColumns[i] = new NativeArray(World.ElementSizes[componentId]); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -180,13 +180,13 @@ public class Snapshot | ||||||
| 
 | 
 | ||||||
| 	private class RelationSnapshot | 	private class RelationSnapshot | ||||||
| 	{ | 	{ | ||||||
| 		private Column Relations; | 		private NativeArray Relations; | ||||||
| 		private Column RelationDatas; | 		private NativeArray RelationDatas; | ||||||
| 
 | 
 | ||||||
| 		public RelationSnapshot(int elementSize) | 		public RelationSnapshot(int elementSize) | ||||||
| 		{ | 		{ | ||||||
| 			Relations = new Column(Unsafe.SizeOf<(Id, Id)>()); | 			Relations = new NativeArray(Unsafe.SizeOf<(Id, Id)>()); | ||||||
| 			RelationDatas = new Column(elementSize); | 			RelationDatas = new NativeArray(elementSize); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		public void Take(RelationStorage relationStorage) | 		public void Take(RelationStorage relationStorage) | ||||||
|  |  | ||||||
|  | @ -1,13 +1,12 @@ | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Runtime.CompilerServices; | using System.Runtime.CompilerServices; | ||||||
| using System.Runtime.InteropServices; |  | ||||||
| using MoonTools.ECS.Collections; | using MoonTools.ECS.Collections; | ||||||
| 
 | 
 | ||||||
| namespace MoonTools.ECS.Rev2 | namespace MoonTools.ECS.Rev2; | ||||||
|  | 
 | ||||||
|  | public class World : IDisposable | ||||||
| { | { | ||||||
| 	public class World : IDisposable |  | ||||||
| 	{ |  | ||||||
| 	// Get ComponentId from a Type | 	// Get ComponentId from a Type | ||||||
| 	internal static Dictionary<Type, Id> TypeToId = new Dictionary<Type, Id>(); | 	internal static Dictionary<Type, Id> TypeToId = new Dictionary<Type, Id>(); | ||||||
| 	// Get element size from a ComponentId | 	// Get element size from a ComponentId | ||||||
|  | @ -30,6 +29,10 @@ namespace MoonTools.ECS.Rev2 | ||||||
| 	internal Dictionary<Id, IndexableSet<Id>> EntityRelationIndex = | 	internal Dictionary<Id, IndexableSet<Id>> EntityRelationIndex = | ||||||
| 		new Dictionary<Id, IndexableSet<Id>>(); | 		new Dictionary<Id, IndexableSet<Id>>(); | ||||||
| 
 | 
 | ||||||
|  | 	// Message Storages | ||||||
|  | 	private Dictionary<Id, MessageStorage> MessageIndex = | ||||||
|  | 		new Dictionary<Id, MessageStorage>(); | ||||||
|  | 
 | ||||||
| 	// ID Management | 	// ID Management | ||||||
| 	// FIXME: Entity and Type Ids should be separated | 	// FIXME: Entity and Type Ids should be separated | ||||||
| 	internal IdAssigner IdAssigner = new IdAssigner(); | 	internal IdAssigner IdAssigner = new IdAssigner(); | ||||||
|  | @ -59,7 +62,7 @@ namespace MoonTools.ECS.Rev2 | ||||||
| 			var componentId = signature[i]; | 			var componentId = signature[i]; | ||||||
| 			ComponentIndex[componentId].Add(archetype); | 			ComponentIndex[componentId].Add(archetype); | ||||||
| 			archetype.ComponentToColumnIndex.Add(componentId, i); | 			archetype.ComponentToColumnIndex.Add(componentId, i); | ||||||
| 				archetype.ComponentColumns[i] = new Column(ElementSizes[componentId]); | 			archetype.ComponentColumns[i] = new NativeArray(ElementSizes[componentId]); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return archetype; | 		return archetype; | ||||||
|  | @ -79,29 +82,25 @@ namespace MoonTools.ECS.Rev2 | ||||||
| 		return entityId; | 		return entityId; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 		internal void TryRegisterTypeId<T>() where T : unmanaged | 	internal Id GetTypeId<T>() where T : unmanaged | ||||||
| 	{ | 	{ | ||||||
| 			if (!TypeToId.ContainsKey(typeof(T))) | 		if (TypeToId.ContainsKey(typeof(T))) | ||||||
| 		{ | 		{ | ||||||
|  | 			return TypeToId[typeof(T)]; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		var typeId = IdAssigner.Assign(); | 		var typeId = IdAssigner.Assign(); | ||||||
| 		TypeToId.Add(typeof(T), typeId); | 		TypeToId.Add(typeof(T), typeId); | ||||||
| 		ElementSizes.Add(typeId, Unsafe.SizeOf<T>()); | 		ElementSizes.Add(typeId, Unsafe.SizeOf<T>()); | ||||||
| 			} | 		return typeId; | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// FIXME: would be much more efficient to do all this at load time somehow |  | ||||||
| 		private void RegisterComponent(Id typeId) |  | ||||||
| 		{ |  | ||||||
| 			ComponentIndex.Add(typeId, new List<Archetype>()); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private void TryRegisterComponentId<T>() where T : unmanaged | 	private void TryRegisterComponentId<T>() where T : unmanaged | ||||||
| 	{ | 	{ | ||||||
| 			TryRegisterTypeId<T>(); | 		var typeId = GetTypeId<T>(); | ||||||
| 			var typeId = TypeToId[typeof(T)]; |  | ||||||
| 		if (!ComponentIndex.ContainsKey(typeId)) | 		if (!ComponentIndex.ContainsKey(typeId)) | ||||||
| 		{ | 		{ | ||||||
| 				RegisterComponent(typeId); | 			ComponentIndex.Add(typeId, new List<Archetype>()); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -118,8 +117,7 @@ namespace MoonTools.ECS.Rev2 | ||||||
| 
 | 
 | ||||||
| 	private void TryRegisterRelationType<T>() where T : unmanaged | 	private void TryRegisterRelationType<T>() where T : unmanaged | ||||||
| 	{ | 	{ | ||||||
| 			TryRegisterTypeId<T>(); | 		var typeId = GetTypeId<T>(); | ||||||
| 			var typeId = TypeToId[typeof(T)]; |  | ||||||
| 		if (!RelationIndex.ContainsKey(typeId)) | 		if (!RelationIndex.ContainsKey(typeId)) | ||||||
| 		{ | 		{ | ||||||
| 			RegisterRelationType(typeId); | 			RegisterRelationType(typeId); | ||||||
|  | @ -132,6 +130,53 @@ namespace MoonTools.ECS.Rev2 | ||||||
| 		return RelationIndex[TypeToId[typeof(T)]]; | 		return RelationIndex[TypeToId[typeof(T)]]; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// Messages | ||||||
|  | 
 | ||||||
|  | 	private Id GetMessageTypeId<T>() where T : unmanaged | ||||||
|  | 	{ | ||||||
|  | 		var typeId = GetTypeId<T>(); | ||||||
|  | 
 | ||||||
|  | 		if (!MessageIndex.ContainsKey(typeId)) | ||||||
|  | 		{ | ||||||
|  | 			MessageIndex.Add(typeId, new MessageStorage(Unsafe.SizeOf<T>())); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return typeId; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void Send<T>(in T message) where T : unmanaged | ||||||
|  | 	{ | ||||||
|  | 		var typeId = GetMessageTypeId<T>(); | ||||||
|  | 		MessageIndex[typeId].Add(message); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public bool SomeMessage<T>() where T : unmanaged | ||||||
|  | 	{ | ||||||
|  | 		var typeId = GetMessageTypeId<T>(); | ||||||
|  | 		return MessageIndex[typeId].Some(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public ReadOnlySpan<T> ReadMessages<T>() where T : unmanaged | ||||||
|  | 	{ | ||||||
|  | 		var typeId = GetMessageTypeId<T>(); | ||||||
|  | 		return MessageIndex[typeId].All<T>(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public T ReadMessage<T>() where T : unmanaged | ||||||
|  | 	{ | ||||||
|  | 		var typeId = GetMessageTypeId<T>(); | ||||||
|  | 		return MessageIndex[typeId].First<T>(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void ClearMessages() | ||||||
|  | 	{ | ||||||
|  | 		foreach (var (_, messageStorage) in MessageIndex) | ||||||
|  | 		{ | ||||||
|  | 			messageStorage.Clear(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Components | ||||||
| 	public bool Has<T>(Id entityId) where T : unmanaged | 	public bool Has<T>(Id entityId) where T : unmanaged | ||||||
| 	{ | 	{ | ||||||
| 		var componentId = GetComponentId<T>(); | 		var componentId = GetComponentId<T>(); | ||||||
|  | @ -474,5 +519,4 @@ namespace MoonTools.ECS.Rev2 | ||||||
| 		Dispose(disposing: true); | 		Dispose(disposing: true); | ||||||
| 		GC.SuppressFinalize(this); | 		GC.SuppressFinalize(this); | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ namespace MoonTools.ECS | ||||||
| 			return MessageDepot.Some<TMessage>(); | 			return MessageDepot.Some<TMessage>(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		protected ReverseSpanEnumerator<TMessage> ReadMessagesWithEntity<TMessage>(in Entity entity) where TMessage : unmanaged | 		protected Span<TMessage>.Enumerator ReadMessagesWithEntity<TMessage>(in Entity entity) where TMessage : unmanaged | ||||||
| 		{ | 		{ | ||||||
| 			return MessageDepot.WithEntity<TMessage>(entity.ID); | 			return MessageDepot.WithEntity<TMessage>(entity.ID); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -36,6 +36,11 @@ namespace MoonTools.ECS | ||||||
| 			return EntityStorage.Tag(entity); | 			return EntityStorage.Tag(entity); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		public ref TComponent Get<TComponent>(in Entity entity) where TComponent : unmanaged | ||||||
|  | 		{ | ||||||
|  | 			return ref ComponentDepot.Get<TComponent>(entity.ID); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		public void Set<TComponent>(Entity entity, in TComponent component) where TComponent : unmanaged | 		public void Set<TComponent>(Entity entity, in TComponent component) where TComponent : unmanaged | ||||||
| 		{ | 		{ | ||||||
| #if DEBUG | #if DEBUG | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue