update New/DelEntity add densify free entityIDs

This commit is contained in:
Mikhail 2024-02-14 01:04:22 +08:00
parent d1374d72ca
commit 94a99e3121
4 changed files with 50 additions and 37 deletions

View File

@ -189,11 +189,8 @@ namespace DCFApixels.DragonECS
#endregion
#region Entity
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan ToSpan()
{
return _entityDispenser.UsedToEcsSpan(id);
}
#region New/Del
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int NewEntity()
{
@ -201,15 +198,37 @@ namespace DCFApixels.DragonECS
int entityID = _entityDispenser.UseFree();
_entitiesCount++;
if (_gens.Length <= entityID)
if (_entitesCapacity <= entityID)
{
Upsize_Internal(_gens.Length << 1);
}
_gens[entityID] &= GEN_BITS;
_gens[entityID] &= GEN_MASK;
_entityListeners.InvokeOnNewEntity(entityID);
return entityID;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void NewEntity(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (IsUsed(entityID))
{
Throw.World_EntityIsAlreadyСontained(entityID);
}
#endif
unchecked { _version++; }
_entityDispenser.Use(entityID);
_entitiesCount++;
if (_entitesCapacity <= entityID)
{
Upsize_Internal(_gens.Length << 1);
}
_gens[entityID] &= GEN_MASK;
_entityListeners.InvokeOnNewEntity(entityID);
}
public entlong NewEntityLong()
{
int e = NewEntity();
@ -238,6 +257,14 @@ namespace DCFApixels.DragonECS
_entitiesCount--;
_entityListeners.InvokeOnDelEntity(entityID);
}
#endregion
#region Other
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan ToSpan()
{
return _entityDispenser.UsedToEcsSpan(id);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe entlong GetEntityLong(int entityID)
{
@ -282,6 +309,11 @@ namespace DCFApixels.DragonECS
}
}
}
//public void Densify()
//{
// _entityDispenser.Sort();
//}
#endregion
#region Copy/Clone
public void CopyEntity(int fromEntityID, int toEntityID)
@ -374,6 +406,7 @@ namespace DCFApixels.DragonECS
unchecked { _gens[e]++; }//up gen
_gens[e] |= DEATH_GEN_BIT;
}
_entityDispenser.Sort(); //уплотнение свободных айдишников
}
#endregion

View File

@ -16,7 +16,7 @@ namespace DCFApixels.DragonECS
}
public abstract partial class EcsWorld
{
private const short GEN_BITS = 0x7fff;
private const short GEN_MASK = 0x7fff;
private const short DEATH_GEN_BIT = short.MinValue;
private const int DEL_ENT_BUFFER_SIZE_OFFSET = 5;
private const int DEL_ENT_BUFFER_MIN_SIZE = 64;

View File

@ -83,7 +83,11 @@ namespace DCFApixels.DragonECS.Internal
{
throw new EcsFrameworkException($"An entity with identifier {entityID} is not contained in this world");
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void World_EntityIsAlreadyСontained(int entityID)
{
throw new EcsFrameworkException($"An entity with identifier {entityID} is already contained in this world");
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void Ent_ThrowIsNotAlive(entlong entity)
@ -109,7 +113,6 @@ namespace DCFApixels.DragonECS
public EcsFrameworkException() { }
public EcsFrameworkException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { }
public EcsFrameworkException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { }
protected EcsFrameworkException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
[Serializable]
public class EcsRunnerImplementationException : EcsFrameworkException
@ -117,6 +120,5 @@ namespace DCFApixels.DragonECS
public EcsRunnerImplementationException() { }
public EcsRunnerImplementationException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { }
public EcsRunnerImplementationException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { }
protected EcsRunnerImplementationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}

View File

@ -13,14 +13,13 @@ namespace DCFApixels.DragonECS.Utils
{
private const int FREE_FLAG_BIT = ~INDEX_MASK;
private const int INDEX_MASK = 0x7FFF_FFFF;
private const int MIN_SIZE = 4;
private int[] _dense = Array.Empty<int>();
private int[] _sparse = Array.Empty<int>(); //hibit free flag
private int _usedCount; //[|uuuu| ]
private int _size; //[|uuuu|ffffff]
private int _usedCount; //[uuuu| ]
private int _size; //[uuuu|ffffff]
private int _nullID;
@ -312,27 +311,6 @@ namespace DCFApixels.DragonECS.Utils
}
#endregion
#region Spans
public readonly struct UsedSpan : IEnumerable<int>
{
private readonly IdDispenser _instance;
public int Count => _instance._usedCount;
internal UsedSpan(IdDispenser instance) => _instance = instance;
public Enumerator GetEnumerator() => new Enumerator(_instance._dense, 0, _instance._usedCount);
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public readonly struct FreeSpan : IEnumerable<int>
{
private readonly IdDispenser _instance;
public int Count => _instance._size - _instance._usedCount;
internal FreeSpan(IdDispenser instance) => _instance = instance;
public Enumerator GetEnumerator() => new Enumerator(_instance._dense, _instance._usedCount, Count);
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
#endregion
#region Utils
private enum IDState : byte
{
@ -340,7 +318,6 @@ namespace DCFApixels.DragonECS.Utils
Reserved = 1,
Used = 2,
}
private static class ThrowHalper
{
[MethodImpl(MethodImplOptions.NoInlining)]
@ -361,7 +338,7 @@ namespace DCFApixels.DragonECS.Utils
public static void UndefinedException() { throw new Exception(); }
}
internal class DebuggerProxy
private class DebuggerProxy
{
private IdDispenser _target;
public DebuggerProxy(IdDispenser dispenser)
@ -370,6 +347,7 @@ namespace DCFApixels.DragonECS.Utils
}
#if DEBUG
public ReadOnlySpan<int> Used => new ReadOnlySpan<int>(_target._dense, 0, _target._usedCount);
public ReadOnlySpan<int> Free => new ReadOnlySpan<int>(_target._dense, _target._usedCount, _target._size - _target._usedCount);
public Pair[] Pairs
{
get