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 #region Interfaces
[MetaName(nameof(PreInit))] [MetaName(nameof(PreInit))]
[MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsPreInitProcessRunner))] [BindWithEcsRunner(typeof(EcsPreInitProcessRunner))]
public interface IEcsPreInitProcess : IEcsProcess public interface IEcsPreInitProcess : IEcsProcess
{ {
void PreInit(); void PreInit();
} }
[MetaName(nameof(Init))] [MetaName(nameof(Init))]
[MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsInitProcessRunner))] [BindWithEcsRunner(typeof(EcsInitProcessRunner))]
public interface IEcsInitProcess : IEcsProcess public interface IEcsInitProcess : IEcsProcess
{ {
void Init(); void Init();
} }
[MetaName(nameof(Run))] [MetaName(nameof(Run))]
[MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsRunProcessRunner))] [BindWithEcsRunner(typeof(EcsRunProcessRunner))]
public interface IEcsRunProcess : IEcsProcess public interface IEcsRunProcess : IEcsProcess
{ {
void Run(); void Run();
} }
[MetaName(nameof(Destroy))] [MetaName(nameof(Destroy))]
[MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsDestroyProcessRunner))] [BindWithEcsRunner(typeof(EcsDestroyProcessRunner))]
public interface IEcsDestroyProcess : IEcsProcess public interface IEcsDestroyProcess : IEcsProcess
{ {

View File

@ -23,6 +23,11 @@ namespace DCFApixels.DragonECS
#region Properties #region Properties
public bool IsNull => _source == null; public bool IsNull => _source == null;
public int WorldID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.World.id;
}
public EcsWorld World public EcsWorld World
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -116,6 +121,11 @@ namespace DCFApixels.DragonECS
internal bool _isReleased = true; internal bool _isReleased = true;
#region Properties #region Properties
public int WorldID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.id;
}
public EcsWorld World public EcsWorld World
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -619,7 +629,7 @@ namespace DCFApixels.DragonECS
yield return _dense[i]; yield return _dense[i];
} }
public LongsIterator GetLongs() => new LongsIterator(this); public LongsIterator GetLongs() => new LongsIterator(this);
public ref struct Enumerator public struct Enumerator : IEnumerator<int>
{ {
private readonly int[] _dense; private readonly int[] _dense;
private readonly int _count; private readonly int _count;
@ -636,8 +646,13 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _dense[_index]; get => _dense[_index];
} }
object IEnumerator.Current => Current;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext() => ++_index <= _count; // <= потму что отсчет начинается с индекса 1 //_count < _dense.Length дает среде понять что проверки на выход за границы не нужны 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> public readonly struct LongsIterator : IEnumerable<entlong>
{ {
@ -680,25 +695,6 @@ namespace DCFApixels.DragonECS
} }
#endregion #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 #region Convertions
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator EcsReadonlyGroup(EcsGroup a) => a.Readonly; 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(); public static implicit operator ReadOnlySpan<int>(EcsGroup a) => a.ToSpan();
#endregion #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 internal class DebuggerProxy
{ {
private EcsGroup _group; private EcsGroup _group;
@ -726,7 +741,6 @@ namespace DCFApixels.DragonECS
public int Count => _group.Count; public int Count => _group.Count;
public int CapacityDense => _group.CapacityDense; public int CapacityDense => _group.CapacityDense;
public int CapacitySparce => _group.CapacitySparce; public int CapacitySparce => _group.CapacitySparce;
public override string ToString() => _group.ToString(); public override string ToString() => _group.ToString();
public DebuggerProxy(EcsGroup group) => _group = group; 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,12 +334,14 @@ namespace DCFApixels.DragonECS
#region Iterator #region Iterator
public ref struct EcsAspectIterator public ref struct EcsAspectIterator
{ {
public readonly int worldID;
public readonly EcsMask mask; public readonly EcsMask mask;
private EcsReadonlyGroup _sourceGroup; private EcsReadonlyGroup _sourceGroup;
private Enumerator _enumerator; private Enumerator _enumerator;
public EcsAspectIterator(EcsAspect aspect, EcsReadonlyGroup sourceGroup) public EcsAspectIterator(EcsAspect aspect, EcsReadonlyGroup sourceGroup)
{ {
worldID = aspect.World.id;
mask = aspect.mask; mask = aspect.mask;
_sourceGroup = sourceGroup; _sourceGroup = sourceGroup;
_enumerator = default; _enumerator = default;
@ -361,6 +363,30 @@ namespace DCFApixels.DragonECS
while (enumerator.MoveNext()) while (enumerator.MoveNext())
group.AddInternal(enumerator.Current); 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 #region object
public override string ToString() public override string ToString()

View File

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

View File

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

View File

@ -1,15 +1,31 @@
namespace DCFApixels.DragonECS using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{ {
public abstract class EcsQueryExecutor public abstract class EcsQueryExecutor
{ {
private EcsWorld _world; private EcsWorld _source;
public EcsWorld World => _world; 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) internal void Initialize(EcsWorld world)
{ {
_world = world; _source = world;
OnInitialize(); OnInitialize();
} }
internal void Destroy() => OnDestroy(); internal void Destroy()
{
OnDestroy();
_source = null;
}
protected abstract void OnInitialize(); protected abstract void OnInitialize();
protected abstract void OnDestroy(); 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 public sealed class EcsWhereExecutor<TAspect> : EcsQueryExecutor where TAspect : EcsAspect
{ {
private TAspect _aspect; private TAspect _aspect;
private EcsGroup _filteredGroup; private EcsGroup _filteredGroup;
private long _executeVersion; private long _version;
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
private EcsProfilerMarker _executeWhere = new EcsProfilerMarker("Where"); private readonly EcsProfilerMarker _executeMarker = new EcsProfilerMarker("Where");
#endif #endif
#region Properties #region Properties
public TAspect Aspect => _aspect; public TAspect Aspect
internal long ExecuteVersion => _executeVersion; {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _aspect;
}
public sealed override long Version
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _version;
}
#endregion #endregion
#region OnInitialize/OnDestroy #region OnInitialize/OnDestroy
@ -29,19 +39,80 @@
#endregion #endregion
#region Methods #region Methods
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsReadonlyGroup Execute() => ExecuteFor(_aspect.World.Entities); public EcsReadonlyGroup Execute() => ExecuteFor(_aspect.World.Entities);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsReadonlyGroup ExecuteFor(EcsReadonlyGroup sourceGroup) public EcsReadonlyGroup ExecuteFor(EcsReadonlyGroup sourceGroup)
{ {
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
_executeWhere.Begin(); _executeMarker.Begin();
if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения. if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения.
if (sourceGroup.WorldID != WorldID) throw new System.ArgumentException();//TODO составить текст исключения.
#endif #endif
unchecked { _version++; }
_aspect.GetIteratorFor(sourceGroup).CopyTo(_filteredGroup); _aspect.GetIteratorFor(sourceGroup).CopyTo(_filteredGroup);
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
_executeWhere.End(); _executeMarker.End();
#endif #endif
return _filteredGroup.Readonly; return _filteredGroup.Readonly;
} }
#endregion #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 #endregion
#region Constructors #region Constructors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpan(T[] array) public ReadOnlySpan(T[] array)
{ {
_array = array ?? Array.Empty<T>(); _array = array ?? Array.Empty<T>();
_start = 0; _start = 0;
_length = array.Length; _length = array.Length;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpan(T[] array, int start, int length) public ReadOnlySpan(T[] array, int start, int length)
{ {