Merge branch 'dev'

This commit is contained in:
Mikhail 2023-06-02 00:00:43 +08:00
commit 9f12b40ff6
3 changed files with 123 additions and 52 deletions

View File

@ -8,7 +8,7 @@
"displayName": "DragonECS",
"description": "C# Entity Component System Framework",
"unity": "2020.3",
"version": "0.7.0",
"version": "0.7.1",
"repository": {
"type": "git",
"url": "https://github.com/DCFApixels/DragonECS.git"

View File

@ -1,9 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
using static DCFApixels.DragonECS.EcsGroup.ThrowHalper;
using static DCFApixels.DragonECS.EcsGroup.ThrowHelper;
#endif
namespace DCFApixels.DragonECS
@ -57,9 +59,21 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Has(int entityID) => _source.Has(entityID);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int IndexOf(int entityID) => _source.IndexOf(entityID);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsGroup.Enumerator GetEnumerator() => _source.GetEnumerator();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsGroup Clone() => _source.Clone();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int[] Bake() => _source.Bake();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Bake(ref int[] entities) => _source.Bake(ref entities);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Bake(List<int> entities) => _source.Bake(entities);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<int> ToSpan() => _source.ToSpan();
public Span<int> ToSpan(int start, int length) => _source.ToSpan(start, length);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int First() => _source.First();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -95,7 +109,7 @@ namespace DCFApixels.DragonECS
}
[DebuggerTypeProxy(typeof(DebuggerProxy))]
public unsafe class EcsGroup : IDisposable, IEquatable<EcsGroup>
public unsafe class EcsGroup : IDisposable, IEquatable<EcsGroup>, IEnumerable<int>
{
private EcsWorld _source;
private int[] _dense;
@ -143,11 +157,11 @@ namespace DCFApixels.DragonECS
}
#endregion
#region Constrcutors/Finalizer
#region Constrcutors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static EcsGroup New(EcsWorld world)
{
return world.GetGroupFromPool();
return world.GetFreeGroup();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EcsGroup(EcsWorld world, int denseCapacity = 64)
@ -161,16 +175,12 @@ namespace DCFApixels.DragonECS
}
#endregion
#region Has
//TODO переименовать в Has
#region Has/IndexOf
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Has(int entityID)
{
return _sparse[entityID] > 0;
}
#endregion
#region IndexOf
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int IndexOf(int entityID)
{
@ -234,7 +244,7 @@ namespace DCFApixels.DragonECS
}
#endregion
#region CopyFrom/Clone
#region CopyFrom/Clone/Bake/ToSpan
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyFrom(EcsReadonlyGroup group) => CopyFrom(group.GetGroupInternal());
public void CopyFrom(EcsGroup group)
@ -249,10 +259,37 @@ namespace DCFApixels.DragonECS
}
public EcsGroup Clone()
{
EcsGroup result = _source.GetGroupFromPool();
EcsGroup result = _source.GetFreeGroup();
result.CopyFrom(this);
return result;
}
public int[] Bake()
{
int[] result = new int[_count];
Array.Copy(_dense, result, _count);
return result;
}
public int Bake(ref int[] entities)
{
if(entities.Length < _count)
entities = new int[_count];
Array.Copy(_dense, entities, _count);
return _count;
}
public void Bake(List<int> entities)
{
entities.Clear();
foreach (var e in this)
entities.Add(e);
}
public Span<int> ToSpan() => new Span<int>(_dense, 0, _count);
public Span<int> ToSpan(int start, int length)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (start + length > _count) ThrowArgumentOutOfRangeException();
#endif
return new Span<int>(_dense, start, length);
}
#endregion
#region Set operations
@ -263,7 +300,7 @@ namespace DCFApixels.DragonECS
public void UnionWith(EcsGroup group)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (_source != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex");
if (_source != group.World) ThrowArgumentDifferentWorldsException();
#endif
foreach (var item in group)
if (!Has(item))
@ -277,7 +314,7 @@ namespace DCFApixels.DragonECS
public void ExceptWith(EcsGroup group)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (_source != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex");
if (_source != group.World) ThrowArgumentDifferentWorldsException();
#endif
foreach (var item in this)
if (group.Has(item))
@ -291,7 +328,7 @@ namespace DCFApixels.DragonECS
public void AndWith(EcsGroup group)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (World != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex");
if (World != group.World) ThrowArgumentDifferentWorldsException();
#endif
foreach (var item in this)
if (!group.Has(item))
@ -305,7 +342,7 @@ namespace DCFApixels.DragonECS
public void XorWith(EcsGroup group)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (_source != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex");
if (_source != group.World) ThrowArgumentDifferentWorldsException();
#endif
foreach (var item in group)
if (Has(item))
@ -313,21 +350,42 @@ namespace DCFApixels.DragonECS
else
AddInternal(item);
}
public void Inverse()
{
foreach (var item in _source.Entities)
if (Has(item))
RemoveInternal(item);
else
AddInternal(item);
}
#endregion
#region Static Set operations
/// <summary>as Intersect sets</summary>
/// <returns>new group from pool</returns>
public static EcsGroup Union(EcsGroup a, EcsGroup b)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (a._source != b._source) ThrowArgumentDifferentWorldsException();
#endif
EcsGroup result = a._source.GetFreeGroup();
foreach (var item in a)
result.AddInternal(item);
foreach (var item in b)
result.Add(item);
return result;
}
/// <summary>as Except sets</summary>
/// <returns>new group from pool</returns>
public static EcsGroup Except(EcsGroup a, EcsGroup b)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (a._source != b._source) throw new ArgumentException("a.WorldIndex != b.WorldIndex");
if (a._source != b._source) ThrowArgumentDifferentWorldsException();
#endif
EcsGroup result = a._source.GetGroupFromPool();
EcsGroup result = a._source.GetFreeGroup();
foreach (var item in a)
if (!b.Has(item))
result.AddInternal(item);
a._source.ReleaseGroup(a);
return result;
}
/// <summary>as Intersect sets</summary>
@ -335,50 +393,66 @@ namespace DCFApixels.DragonECS
public static EcsGroup And(EcsGroup a, EcsGroup b)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (a._source != b._source) throw new ArgumentException("a.WorldIndex != b.WorldIndex");
if (a._source != b._source) ThrowArgumentDifferentWorldsException();
#endif
EcsGroup result = a._source.GetGroupFromPool();
EcsGroup result = a._source.GetFreeGroup();
foreach (var item in a)
if (b.Has(item))
result.AddInternal(item);
a._source.ReleaseGroup(a);
return result;
}
/// <summary>as Intersect sets</summary>
/// <summary>as Symmetric Except sets</summary>
/// <returns>new group from pool</returns>
public static EcsGroup Union(EcsGroup a, EcsGroup b)
public static EcsGroup Xor(EcsGroup a, EcsGroup b)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (a._source != b._source) throw new ArgumentException("a.WorldIndex != b.WorldIndex");
if (a._source != b._source) ThrowArgumentDifferentWorldsException();
#endif
EcsGroup result = a._source.GetGroupFromPool();
EcsGroup result = a._source.GetFreeGroup();
foreach (var item in a)
if (!b.Has(item))
result.AddInternal(item);
foreach (var item in b)
if (!a.Has(item))
result.AddInternal(item);
return result;
}
public static EcsGroup Inverse(EcsGroup a)
{
EcsGroup result = a._source.GetFreeGroup();
foreach (var item in a._source.Entities)
if (!a.Has(item))
result.AddInternal(item);
foreach (var item in a)
result.Add(item);
return result;
}
#endregion
#region GetEnumerator
#region Enumerator
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
#endregion
#region Enumerator
public ref struct Enumerator// : IDisposable
IEnumerator IEnumerable.GetEnumerator()
{
for (int i = 0; i < _count; i++)
yield return _dense[i];
}
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
for (int i = 0; i < _count; i++)
yield return _dense[i];
}
public ref struct Enumerator
{
// private readonly EcsGroup source;
private readonly int[] _dense;
private readonly int _count;
private int _index;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator(EcsGroup group)
{
// source = group;
_dense = group._dense;
_count = group._count;
_index = 0;
@ -390,8 +464,6 @@ namespace DCFApixels.DragonECS
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext() => ++_index <= _count && _count < _dense.Length; // <= потму что отсчет начинается с индекса 1 //_count < _dense.Length дает среде понять что проверки на выход за границы не нужны
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
//public void Dispose() => source.Unlock();
}
#endregion
@ -401,12 +473,10 @@ namespace DCFApixels.DragonECS
public bool Equals(EcsReadonlyGroup other) => Equals(other.GetGroupInternal());
public bool Equals(EcsGroup other)
{
if (ReferenceEquals(other, null))
if (other is null || other.Count != Count)
return false;
if (other.Count != Count)
return false;
foreach (var item in other)
if (!Has(item))
foreach (var e in other)
if (!Has(e))
return false;
return true;
}
@ -431,8 +501,7 @@ namespace DCFApixels.DragonECS
private static bool StaticEquals(EcsGroup a, EcsReadonlyGroup b) => StaticEquals(a, b.GetGroupInternal());
private static bool StaticEquals(EcsGroup a, EcsGroup b)
{
if (ReferenceEquals(a, null))
return false;
if (a is null) return false;
return a.Equals(b);
}
public static bool operator ==(EcsGroup a, EcsGroup b) => StaticEquals(a, b);
@ -451,15 +520,12 @@ namespace DCFApixels.DragonECS
#region IDisposable/Release
public void Dispose() => Release();
public void Release()
{
_source.ReleaseGroup(this);
}
public void Release() => _source.ReleaseGroup(this);
#endregion
#region ThrowHalper
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
internal static class ThrowHalper
internal static class ThrowHelper
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowAlreadyContains(int entityID) => throw new EcsFrameworkException($"This group already contains entity {entityID}.");
@ -467,6 +533,10 @@ namespace DCFApixels.DragonECS
public static void ThrowArgumentOutOfRange() => throw new ArgumentOutOfRangeException($"index is less than 0 or is equal to or greater than Count.");
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowDoesNotContain(int entityID) => throw new EcsFrameworkException($"This group does not contain entity {entityID}.");
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException();
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowArgumentDifferentWorldsException() => throw new ArgumentException("The groups belong to different worlds.");
}
#endif
#endregion
@ -492,6 +562,7 @@ namespace DCFApixels.DragonECS
public int CapacityDense => _group.CapacityDense;
public int CapacitySparce => _group.CapacitySparce;
public override string ToString() => _group.ToString();
public DebuggerProxy(EcsGroup group) => _group = group;
}
#endregion

View File

@ -83,7 +83,7 @@ namespace DCFApixels.DragonECS
_delEntBuffer = new int[_entitesCapacity >> DEL_ENT_BUFFER_SIZE_OFFSET];
_groups = new List<WeakReference<EcsGroup>>();
_allEntites = GetGroupFromPool();
_allEntites = GetFreeGroup();
_subjects = new EcsSubject[128];
_executors = new EcsQueryExecutor[128];
@ -337,7 +337,7 @@ namespace DCFApixels.DragonECS
{
_groups.Add(new WeakReference<EcsGroup>(group));
}
internal EcsGroup GetGroupFromPool()
internal EcsGroup GetFreeGroup()
{
EcsGroup result = _groupsPool.Count <= 0 ? new EcsGroup(this) : _groupsPool.Pop();
result._isReleased = false;