update Copy/Clone(Entity) add Move/Remove(Components)

This commit is contained in:
Mikhail 2024-11-06 13:46:20 +08:00
parent ab06cbce58
commit ad2bcae5ad
4 changed files with 257 additions and 41 deletions

View File

@ -44,7 +44,7 @@ namespace DCFApixels.DragonECS
internal EcsWorld _source;
internal EcsMask _mask;
private bool _isBuilt = false;
private IEcsPool[] _pools;
//private IEcsPool[] _pools;
#region Properties
public EcsMask Mask
@ -59,10 +59,10 @@ namespace DCFApixels.DragonECS
{
get { return _isBuilt; }
}
public ReadOnlySpan<IEcsPool> Pools
{
get { return _pools; }
}
//public ReadOnlySpan<IEcsPool> Pools
//{
// get { return _pools; }
//}
/// <summary>
/// Статическая инициализация означет что каждый новый эекземпляр идентичен другому, инициализация стандартным путем создает идентичные экземпляры, поэтому значение по умолчанию true.
/// </summary>
@ -86,8 +86,8 @@ namespace DCFApixels.DragonECS
private EcsWorld _world;
private EcsStaticMask.Builder _maskBuilder;
private IEcsPool[] _poolsBuffer = new IEcsPool[8];
private int _poolsBufferCount;
//private IEcsPool[] _poolsBuffer = new IEcsPool[8];
//private int _poolsBufferCount;
#region Properties
public IncludeMarker Inc
@ -154,8 +154,8 @@ namespace DCFApixels.DragonECS
}
}
newAspect._mask = staticMask.ToMask(world);
var pools = new IEcsPool[builder._poolsBufferCount];
Array.Copy(builder._poolsBuffer, pools, pools.Length);
//var pools = new IEcsPool[builder._poolsBufferCount];
//Array.Copy(builder._poolsBuffer, pools, pools.Length);
newAspect._isBuilt = true;
_constructorBuildersStackIndex--;
@ -184,11 +184,11 @@ namespace DCFApixels.DragonECS
private TPool CachePool<TPool>() where TPool : IEcsPoolImplementation, new()
{
var pool = _world.GetPoolInstance<TPool>();
if (_poolsBufferCount >= _poolsBuffer.Length)
{
Array.Resize(ref _poolsBuffer, _poolsBuffer.Length << 1);
}
_poolsBuffer[_poolsBufferCount++] = pool;
//if (_poolsBufferCount >= _poolsBuffer.Length)
//{
// Array.Resize(ref _poolsBuffer, _poolsBuffer.Length << 1);
//}
//_poolsBuffer[_poolsBufferCount++] = pool;
return pool;
}
private void IncludeImplicit(Type type)

View File

@ -717,11 +717,11 @@ namespace DCFApixels.DragonECS
{
while (_span.MoveNext())
{
int chunck = _span.Current << _entityComponentMaskLengthBitShift;
int entityLineStartIndex = _span.Current << _entityComponentMaskLengthBitShift;
for (int i = 0; i < _sortIncChunckBuffer.Length; i++)
{
var bit = _sortIncChunckBuffer.ptr[i];
if ((_entityComponentMasks[chunck + bit.chunkIndex] & bit.mask) != bit.mask)
if ((_entityComponentMasks[entityLineStartIndex + bit.chunkIndex] & bit.mask) != bit.mask)
{
goto skip;
}
@ -729,7 +729,7 @@ namespace DCFApixels.DragonECS
for (int i = 0; i < _sortExcChunckBuffer.Length; i++)
{
var bit = _sortExcChunckBuffer.ptr[i];
if ((_entityComponentMasks[chunck + bit.chunkIndex] & bit.mask) != 0)
if ((_entityComponentMasks[entityLineStartIndex + bit.chunkIndex] & bit.mask) != 0)
{
goto skip;
}
@ -848,11 +848,11 @@ namespace DCFApixels.DragonECS
{
while (_span.MoveNext())
{
int chunck = _span.Current << _entityComponentMaskLengthBitShift;
int entityLineStartIndex = _span.Current << _entityComponentMaskLengthBitShift;
for (int i = 0; i < _sortIncChunckBuffer.Length; i++)
{
var bit = _sortIncChunckBuffer.ptr[i];
if ((_entityComponentMasks[chunck + bit.chunkIndex] & bit.mask) != bit.mask)
if ((_entityComponentMasks[entityLineStartIndex + bit.chunkIndex] & bit.mask) != bit.mask)
{
goto skip;
}

View File

@ -458,11 +458,59 @@ namespace DCFApixels.DragonECS
}
#endregion
#region Copy/Clone
public void CopyEntity(int fromEntityID, int toEntityID)
//TODO протестить Copy Clone Move Remove
#region CopyEntity
public unsafe void CopyEntity(int fromEntityID, int toEntityID)
{
foreach (var pool in _pools)
const int COMPONENT_MASK_CHUNK_SIZE_HALF = COMPONENT_MASK_CHUNK_SIZE / 2;
int entityLineStartIndex = fromEntityID << _entityComponentMaskLengthBitShift;
int poolIndexWithoutOffset = 0;
for (int i = 0; i < _entityComponentMaskLength; i++)
{
int chunk = _entityComponentMasks[i];
poolIndexWithoutOffset += COMPONENT_MASK_CHUNK_SIZE;
if (chunk != 0)
{
if ((chunk & 0x0000FFFF) != 0)
{
int bit = 1;
for (int j = 0; j < COMPONENT_MASK_CHUNK_SIZE_HALF; j++)
{
if ((bit & chunk) != 0)
{
_pools[poolIndexWithoutOffset + j].Copy(fromEntityID, toEntityID);
}
bit <<= 1;
}
}
if ((chunk & -0x7FFF0000) != 0)
{
int bit = 0x00010000;
for (int j = COMPONENT_MASK_CHUNK_SIZE_HALF; j < COMPONENT_MASK_CHUNK_SIZE; j++)
{
if ((bit & chunk) != 0)
{
_pools[poolIndexWithoutOffset + j].Copy(fromEntityID, toEntityID);
}
bit <<= 1;
}
}
}
}
//foreach (var pool in _pools)
//{
// if (pool.Has(fromEntityID))
// {
// pool.Copy(fromEntityID, toEntityID);
// }
//}
}
public void CopyEntity(int fromEntityID, int toEntityID, ReadOnlySpan<int> componentTypeIDs)
{
foreach (var poolID in componentTypeIDs)
{
var pool = _pools[poolID];
if (pool.Has(fromEntityID))
{
pool.Copy(fromEntityID, toEntityID);
@ -471,26 +519,89 @@ namespace DCFApixels.DragonECS
}
public void CopyEntity(int fromEntityID, EcsWorld toWorld, int toEntityID)
{
foreach (var pool in _pools)
const int COMPONENT_MASK_CHUNK_SIZE_HALF = COMPONENT_MASK_CHUNK_SIZE / 2;
int entityLineStartIndex = fromEntityID << _entityComponentMaskLengthBitShift;
int poolIndexWithoutOffset = 0;
for (int i = 0; i < _entityComponentMaskLength; i++)
{
int chunk = _entityComponentMasks[i];
poolIndexWithoutOffset += COMPONENT_MASK_CHUNK_SIZE;
if (chunk != 0)
{
if ((chunk & 0x0000FFFF) != 0)
{
int bit = 1;
for (int j = 0; j < COMPONENT_MASK_CHUNK_SIZE_HALF; j++)
{
if ((bit & chunk) != 0)
{
_pools[poolIndexWithoutOffset + j].Copy(fromEntityID, toWorld, toEntityID);
}
bit <<= 1;
}
}
if ((chunk & -0x7FFF0000) != 0)
{
int bit = 0x00010000;
for (int j = COMPONENT_MASK_CHUNK_SIZE_HALF; j < COMPONENT_MASK_CHUNK_SIZE; j++)
{
if ((bit & chunk) != 0)
{
_pools[poolIndexWithoutOffset + j].Copy(fromEntityID, toWorld, toEntityID);
}
bit <<= 1;
}
}
}
}
//foreach (var pool in _pools)
//{
// if (pool.Has(fromEntityID))
// {
// pool.Copy(fromEntityID, toWorld, toEntityID);
// }
//}
}
public void CopyEntity(int fromEntityID, EcsWorld toWorld, int toEntityID, ReadOnlySpan<int> componentTypeIDs)
{
foreach (var poolID in componentTypeIDs)
{
var pool = _pools[poolID];
if (pool.Has(fromEntityID))
{
pool.Copy(fromEntityID, toWorld, toEntityID);
}
}
}
public int CloneEntity(int fromEntityID)
#endregion
#region CloneEntity
public int CloneEntity(int entityID)
{
int newEntity = NewEntity();
CopyEntity(fromEntityID, newEntity);
CopyEntity(entityID, newEntity);
return newEntity;
}
public int CloneEntity(int fromEntityID, EcsWorld toWorld)
public int CloneEntity(int entityID, ReadOnlySpan<int> componentTypeIDs)
{
int newEntity = NewEntity();
CopyEntity(fromEntityID, toWorld, newEntity);
CopyEntity(entityID, newEntity, componentTypeIDs);
return newEntity;
}
public int CloneEntity(int entityID, EcsWorld toWorld)
{
int newEntity = NewEntity();
CopyEntity(entityID, toWorld, newEntity);
return newEntity;
}
public int CloneEntity(int entityID, EcsWorld toWorld, ReadOnlySpan<int> componentTypeIDs)
{
int newEntity = NewEntity();
CopyEntity(entityID, toWorld, newEntity, componentTypeIDs);
return newEntity;
}
public void CloneEntity(int fromEntityID, int toEntityID)
{
CopyEntity(fromEntityID, toEntityID);
@ -505,6 +616,116 @@ namespace DCFApixels.DragonECS
//public void CloneEntity(int fromEntityID, EcsWorld toWorld, int toEntityID)
#endregion
#region MoveComponents
public void MoveComponents(int fromEntityID, int toEntityID)
{
const int COMPONENT_MASK_CHUNK_SIZE_HALF = COMPONENT_MASK_CHUNK_SIZE / 2;
int entityLineStartIndex = fromEntityID << _entityComponentMaskLengthBitShift;
int poolIndexWithoutOffset = 0;
for (int i = 0; i < _entityComponentMaskLength; i++)
{
int chunk = _entityComponentMasks[i];
poolIndexWithoutOffset += COMPONENT_MASK_CHUNK_SIZE;
if (chunk != 0)
{
if ((chunk & 0x0000FFFF) != 0)
{
int bit = 1;
for (int j = 0; j < COMPONENT_MASK_CHUNK_SIZE_HALF; j++)
{
if ((bit & chunk) != 0)
{
var pool = _pools[poolIndexWithoutOffset + j];
pool.Copy(fromEntityID, toEntityID);
pool.Del(fromEntityID);
}
bit <<= 1;
}
}
if ((chunk & -0x7FFF0000) != 0)
{
int bit = 0x00010000;
for (int j = COMPONENT_MASK_CHUNK_SIZE_HALF; j < COMPONENT_MASK_CHUNK_SIZE; j++)
{
if ((bit & chunk) != 0)
{
var pool = _pools[poolIndexWithoutOffset + j];
pool.Copy(fromEntityID, toEntityID);
pool.Del(fromEntityID);
}
bit <<= 1;
}
}
}
}
}
public void MoveComponents(int fromEntityID, int toEntityID, ReadOnlySpan<int> componentTypeIDs)
{
foreach (var poolID in componentTypeIDs)
{
var pool = _pools[poolID];
if (pool.Has(fromEntityID))
{
pool.Copy(fromEntityID, toEntityID);
pool.Del(fromEntityID);
}
}
}
#endregion
#region RemoveComponents
public void RemoveComponents(int fromEntityID, int toEntityID)
{
const int COMPONENT_MASK_CHUNK_SIZE_HALF = COMPONENT_MASK_CHUNK_SIZE / 2;
int entityLineStartIndex = fromEntityID << _entityComponentMaskLengthBitShift;
int poolIndexWithoutOffset = 0;
for (int i = 0; i < _entityComponentMaskLength; i++)
{
int chunk = _entityComponentMasks[i];
poolIndexWithoutOffset += COMPONENT_MASK_CHUNK_SIZE;
if (chunk != 0)
{
if ((chunk & 0x0000FFFF) != 0)
{
int bit = 1;
for (int j = 0; j < COMPONENT_MASK_CHUNK_SIZE_HALF; j++)
{
if ((bit & chunk) != 0)
{
_pools[poolIndexWithoutOffset + j].Del(fromEntityID);
}
bit <<= 1;
}
}
if ((chunk & -0x7FFF0000) != 0)
{
int bit = 0x00010000;
for (int j = COMPONENT_MASK_CHUNK_SIZE_HALF; j < COMPONENT_MASK_CHUNK_SIZE; j++)
{
if ((bit & chunk) != 0)
{
_pools[poolIndexWithoutOffset + j].Del(fromEntityID);
}
bit <<= 1;
}
}
}
}
}
public void MoveComponents(int fromEntityID, int toEntityID, ReadOnlySpan<int> componentTypeIDs)
{
foreach (var poolID in componentTypeIDs)
{
var pool = _pools[poolID];
if (pool.Has(fromEntityID))
{
pool.Del(fromEntityID);
}
}
}
#endregion
#endregion
#region DelEntBuffer
@ -800,18 +1021,13 @@ namespace DCFApixels.DragonECS
#endregion
#region EntitySlot
[StructLayout(LayoutKind.Explicit, Pack = 4, Size = 4 * 3)]
[StructLayout(LayoutKind.Sequential)]
private struct EntitySlot
{
public static readonly EntitySlot Empty = new EntitySlot(SLEEPING_GEN_FLAG, 0, false);
[FieldOffset(0)]
public short gen;
[FieldOffset(2)]
public short componentsCount;
[FieldOffset(4)]
public bool isUsed;
//[FieldOffset(5)]
//public bool isLocked;
public EntitySlot(short gen, short componentsCount, bool isUsed)
{
this.gen = gen;

View File

@ -253,12 +253,12 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool TryRegisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
{
ref int chunk = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex];
int newChunk = chunk | maskBit.mask;
if (chunk != newChunk)
ref int entityLineStartIndex = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex];
int newChunk = entityLineStartIndex | maskBit.mask;
if (entityLineStartIndex != newChunk)
{
UpVersion();
chunk = newChunk;
entityLineStartIndex = newChunk;
ref PoolSlot slot = ref _poolSlots[componentTypeID];
slot.count++;
slot.version++;
@ -270,16 +270,16 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool TryUnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
{
ref int chunk = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex];
int newChunk = chunk & ~maskBit.mask;
if (chunk != newChunk)
ref int entityLineStartIndex = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex];
int newChunk = entityLineStartIndex & ~maskBit.mask;
if (entityLineStartIndex != newChunk)
{
UpVersion();
ref PoolSlot slot = ref _poolSlots[componentTypeID];
slot.count--;
slot.version++;
var count = --_entities[entityID].componentsCount;
chunk = newChunk;
entityLineStartIndex = newChunk;
if (count == 0 && IsUsed(entityID))
{