This commit is contained in:
Mikhail 2023-12-24 15:40:19 +08:00
parent 18345109c6
commit 70cf1be408
10 changed files with 275 additions and 38 deletions

View File

@ -7,24 +7,28 @@ namespace DCFApixels.DragonECS
{
#region Interfaces
[MetaName(nameof(PreInit))]
[MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsPreInitProcessRunner))]
public interface IEcsPreInitProcess : IEcsProcess
{
void PreInit();
}
[MetaName(nameof(Init))]
[MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsInitProcessRunner))]
public interface IEcsInitProcess : IEcsProcess
{
void Init();
}
[MetaName(nameof(Run))]
[MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsRunProcessRunner))]
public interface IEcsRunProcess : IEcsProcess
{
void Run();
}
[MetaName(nameof(Destroy))]
[MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsDestroyProcessRunner))]
public interface IEcsDestroyProcess : IEcsProcess
{

View File

@ -23,6 +23,11 @@ namespace DCFApixels.DragonECS
#region Properties
public bool IsNull => _source == null;
public int WorldID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.World.id;
}
public EcsWorld World
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -116,6 +121,11 @@ namespace DCFApixels.DragonECS
internal bool _isReleased = true;
#region Properties
public int WorldID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.id;
}
public EcsWorld World
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -619,7 +629,7 @@ namespace DCFApixels.DragonECS
yield return _dense[i];
}
public LongsIterator GetLongs() => new LongsIterator(this);
public ref struct Enumerator
public struct Enumerator : IEnumerator<int>
{
private readonly int[] _dense;
private readonly int _count;
@ -636,8 +646,13 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _dense[_index];
}
object IEnumerator.Current => Current;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext() => ++_index <= _count; // <= потму что отсчет начинается с индекса 1 //_count < _dense.Length дает среде понять что проверки на выход за границы не нужны
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose() { }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset() { }
}
public readonly struct LongsIterator : IEnumerable<entlong>
{
@ -680,25 +695,6 @@ namespace DCFApixels.DragonECS
}
#endregion
#region Object
public override string ToString() => $"group{{{string.Join(", ", _dense.Skip(1).Take(_count))}}}";
#endregion
#region OtherMethods
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int First() => _dense[1];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Last() => _dense[_count];
#endregion
#region OnWorldResize
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void OnWorldResize(int newSize)
{
Array.Resize(ref _sparse, newSize);
}
#endregion
#region Convertions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator EcsReadonlyGroup(EcsGroup a) => a.Readonly;
@ -706,7 +702,26 @@ namespace DCFApixels.DragonECS
public static implicit operator ReadOnlySpan<int>(EcsGroup a) => a.ToSpan();
#endregion
#region DebuggerProxy
#region Other
public override string ToString()
{
return $"group{{{string.Join(", ", _dense.Skip(1).Take(_count))}}}";
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int First()
{
return _dense[1];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Last()
{
return _dense[_count];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void OnWorldResize(int newSize)
{
Array.Resize(ref _sparse, newSize);
}
internal class DebuggerProxy
{
private EcsGroup _group;
@ -726,7 +741,6 @@ namespace DCFApixels.DragonECS
public int Count => _group.Count;
public int CapacityDense => _group.CapacityDense;
public int CapacitySparce => _group.CapacitySparce;
public override string ToString() => _group.ToString();
public DebuggerProxy(EcsGroup group) => _group = group;
}

View File

@ -0,0 +1,81 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public readonly ref struct EcsSpan
{
private readonly int _worldID;
private readonly ReadOnlySpan<int> _values;
#region Properties
public int WorldID => _worldID;
public EcsWorld World => EcsWorld.GetWorld(_worldID);
public int Length => _values.Length;
public bool IsEmpty => _values.IsEmpty;
public readonly int this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _values[index];
}
#endregion
#region Constructors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EcsSpan(int worldID, ReadOnlySpan<int> span)
{
_worldID = worldID;
_values = span;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EcsSpan(int worldID, int[] array)
{
_worldID = worldID;
_values = array;
}
internal EcsSpan(int worldID, int[] array, int length)
{
_worldID = worldID;
_values = new ReadOnlySpan<int>(array, 0, length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EcsSpan(int worldID, int[] array, int start, int length)
{
_worldID = worldID;
_values = new ReadOnlySpan<int>(array, start, length);
}
#endregion
#region Object
#pragma warning disable CS0809 // Устаревший член переопределяет неустаревший член
[Obsolete($"Equals() on {nameof(EcsSpan)} will always throw an exception. Use the equality operator instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj) => throw new NotSupportedException();
[Obsolete($"GetHashCode() on {nameof(EcsSpan)} will always throw an exception.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => throw new NotSupportedException();
#pragma warning restore CS0809 // Устаревший член переопределяет неустаревший член
public override string ToString() => _values.ToString();
#endregion
#region operators
public static bool operator ==(EcsSpan left, EcsSpan right) => left._values == right._values;
public static bool operator !=(EcsSpan left, EcsSpan right) => left._values != right._values;
#endregion
#region Enumerator
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpan<int>.Enumerator GetEnumerator() => _values.GetEnumerator();
#endregion
#region Other
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan Slice(int start) => new EcsSpan(_worldID, _values.Slice(start));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan Slice(int start, int length) => new EcsSpan(_worldID, _values.Slice(start, length));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int[] ToArray() => _values.ToArray();
#endregion
}
}

View File

@ -334,13 +334,15 @@ namespace DCFApixels.DragonECS
#region Iterator
public ref struct EcsAspectIterator
{
public readonly int worldID;
public readonly EcsMask mask;
private EcsReadonlyGroup _sourceGroup;
private Enumerator _enumerator;
public EcsAspectIterator(EcsAspect aspect, EcsReadonlyGroup sourceGroup)
{
mask = aspect.mask;
worldID = aspect.World.id;
mask = aspect.mask;
_sourceGroup = sourceGroup;
_enumerator = default;
}
@ -361,6 +363,30 @@ namespace DCFApixels.DragonECS
while (enumerator.MoveNext())
group.AddInternal(enumerator.Current);
}
public int CopyTo(ref int[] array)
{
var enumerator = GetEnumerator();
int count = 0;
while (enumerator.MoveNext())
{
if(array.Length <= count)
Array.Resize(ref array, array.Length << 1);
array[count++] = enumerator.Current;
}
return count;
}
public EcsSpan CopyToSpan(ref int[] array)
{
var enumerator = GetEnumerator();
int count = 0;
while (enumerator.MoveNext())
{
if (array.Length <= count)
Array.Resize(ref array, array.Length << 1);
array[count++] = enumerator.Current;
}
return new EcsSpan(worldID, array, count);
}
#region object
public override string ToString()

View File

@ -239,7 +239,7 @@ namespace DCFApixels.DragonECS
_filter = null;
OnDestroy();
}
protected virtual void OnSetup() { }
protected virtual void OnSetup() { } //rename to OnInitialize
protected virtual void OnDestroy() { }
}
}

View File

@ -141,6 +141,10 @@ namespace DCFApixels.DragonECS
{
return GetExecutor<EcsWhereExecutor<TAspect>>().Execute();
}
public EcsSpan WhereSpan<TAspect>() where TAspect : EcsAspect
{
return GetExecutor<EcsWhereSpanExecutor<TAspect>>().Execute();
}
#endregion
#region Entity

View File

@ -1,16 +1,32 @@
namespace DCFApixels.DragonECS
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public abstract class EcsQueryExecutor
{
private EcsWorld _world;
public EcsWorld World => _world;
private EcsWorld _source;
public int WorldID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.id;
}
public EcsWorld World
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source;
}
public abstract long Version { get; }
internal void Initialize(EcsWorld world)
{
_world = world;
_source = world;
OnInitialize();
}
internal void Destroy() => OnDestroy();
internal void Destroy()
{
OnDestroy();
_source = null;
}
protected abstract void OnInitialize();
protected abstract void OnDestroy();
}
}
}

View File

@ -1,19 +1,29 @@
namespace DCFApixels.DragonECS
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public sealed class EcsWhereExecutor<TAspect> : EcsQueryExecutor where TAspect : EcsAspect
{
private TAspect _aspect;
private EcsGroup _filteredGroup;
private long _executeVersion;
private long _version;
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
private EcsProfilerMarker _executeWhere = new EcsProfilerMarker("Where");
private readonly EcsProfilerMarker _executeMarker = new EcsProfilerMarker("Where");
#endif
#region Properties
public TAspect Aspect => _aspect;
internal long ExecuteVersion => _executeVersion;
public TAspect Aspect
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _aspect;
}
public sealed override long Version
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _version;
}
#endregion
#region OnInitialize/OnDestroy
@ -29,19 +39,80 @@
#endregion
#region Methods
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsReadonlyGroup Execute() => ExecuteFor(_aspect.World.Entities);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsReadonlyGroup ExecuteFor(EcsReadonlyGroup sourceGroup)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
_executeWhere.Begin();
_executeMarker.Begin();
if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения.
if (sourceGroup.WorldID != WorldID) throw new System.ArgumentException();//TODO составить текст исключения.
#endif
unchecked { _version++; }
_aspect.GetIteratorFor(sourceGroup).CopyTo(_filteredGroup);
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
_executeWhere.End();
_executeMarker.End();
#endif
return _filteredGroup.Readonly;
}
#endregion
}
public sealed class EcsWhereSpanExecutor<TAspect> : EcsQueryExecutor where TAspect : EcsAspect
{
private TAspect _aspect;
private int[] _filteredEntities;
private long _version;
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
private readonly EcsProfilerMarker _executeMarker = new EcsProfilerMarker("Where");
#endif
#region Properties
public TAspect Aspect
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _aspect;
}
public sealed override long Version
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _version;
}
#endregion
#region OnInitialize/OnDestroy
protected sealed override void OnInitialize()
{
_aspect = World.GetAspect<TAspect>();
_filteredEntities = new int[32];
}
protected sealed override void OnDestroy() { }
#endregion
#region Methods
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan Execute() => ExecuteFor(_aspect.World.Entities);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan ExecuteFor(EcsReadonlyGroup sourceGroup)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
_executeMarker.Begin();
if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения.
if (sourceGroup.WorldID != WorldID) throw new System.ArgumentException();//TODO составить текст исключения.
#endif
unchecked { _version++; }
EcsSpan result = _aspect.GetIteratorFor(sourceGroup).CopyToSpan(ref _filteredEntities);
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
_executeMarker.End();
#endif
return result;
}
#endregion
}
}

View File

@ -0,0 +1,21 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS.Internal
{
public readonly struct GenericEnumerable<T, TEnumerator> : IEnumerable<T> where TEnumerator : IEnumerator<T>
{
public readonly TEnumerator _enumerator;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public GenericEnumerable(TEnumerator enumerator) => _enumerator = enumerator;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TEnumerator GetEnumerator() => _enumerator;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
IEnumerator<T> IEnumerable<T>.GetEnumerator() => _enumerator;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
IEnumerator IEnumerable.GetEnumerator() => _enumerator;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator GenericEnumerable<T, TEnumerator>(TEnumerator enumerator) => new GenericEnumerable<T, TEnumerator>(enumerator);
}
}

View File

@ -38,13 +38,13 @@ namespace DCFApixels.DragonECS
#endregion
#region Constructors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpan(T[] array)
{
_array = array ?? Array.Empty<T>();
_start = 0;
_length = array.Length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpan(T[] array, int start, int length)
{