mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44:35 +08:00
update
This commit is contained in:
parent
18345109c6
commit
70cf1be408
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
81
src/Collections/EcsSpan.cs
Normal file
81
src/Collections/EcsSpan.cs
Normal 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
|
||||
}
|
||||
}
|
@ -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()
|
||||
|
@ -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() { }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
21
src/Utils/GenericEnumerable.cs
Normal file
21
src/Utils/GenericEnumerable.cs
Normal 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);
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user