polishing pools

This commit is contained in:
Mikhail 2024-02-24 02:26:42 +08:00
parent efed7dcdbd
commit c3ece37bf5
4 changed files with 120 additions and 57 deletions

View File

@ -30,11 +30,26 @@ namespace DCFApixels.DragonECS
private EcsWorld.PoolsMediator _mediator;
#region Properites
public int Count => _itemsCount;
public int Capacity => _items.Length;
public int ComponentID => _componentTypeID;
public Type ComponentType => typeof(T);
public EcsWorld World => _source;
public int Count
{
get { return _itemsCount; }
}
public int Capacity
{
get { return _items.Length; }
}
public int ComponentID
{
get { return _componentTypeID; }
}
public Type ComponentType
{
get { return typeof(T); }
}
public EcsWorld World
{
get { return _source; }
}
#endregion
#region Methods
@ -42,7 +57,7 @@ namespace DCFApixels.DragonECS
{
ref int itemIndex = ref _mapping[entityID];
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (itemIndex > 0) EcsPoolThrowHalper.ThrowAlreadyHasComponent<T>(entityID);
if (itemIndex > 0) { EcsPoolThrowHalper.ThrowAlreadyHasComponent<T>(entityID); }
#endif
if (_recycledItemsCount > 0)
{
@ -53,7 +68,9 @@ namespace DCFApixels.DragonECS
{
itemIndex = ++_itemsCount;
if (itemIndex >= _items.Length)
{
Array.Resize(ref _items, _items.Length << 1);
}
}
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
_listeners.InvokeOnAddAndGet(entityID);
@ -64,7 +81,7 @@ namespace DCFApixels.DragonECS
public ref T Get(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
if (!Has(entityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); }
#endif
_listeners.InvokeOnGet(entityID);
return ref _items[_mapping[entityID]];
@ -73,7 +90,7 @@ namespace DCFApixels.DragonECS
public ref readonly T Read(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
if (!Has(entityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); }
#endif
return ref _items[_mapping[entityID]];
}
@ -91,7 +108,9 @@ namespace DCFApixels.DragonECS
{
itemIndex = ++_itemsCount;
if (itemIndex >= _items.Length)
{
Array.Resize(ref _items, _items.Length << 1);
}
}
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
_listeners.InvokeOnAdd(entityID);
@ -107,36 +126,39 @@ namespace DCFApixels.DragonECS
}
public void Del(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
#endif
ref int itemIndex = ref _mapping[entityID];
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (itemIndex <= 0) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); }
#endif
ResetComponent(ref _items[itemIndex]);
if (_recycledItemsCount >= _recycledItems.Length)
{
Array.Resize(ref _recycledItems, _recycledItems.Length << 1);
}
_recycledItems[_recycledItemsCount++] = itemIndex;
_mapping[entityID] = 0;
itemIndex = 0;
_itemsCount--;
_mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit);
_listeners.InvokeOnDel(entityID);
}
public void TryDel(int entityID)
{
if (Has(entityID)) Del(entityID);
if (Has(entityID))
{
Del(entityID);
}
}
public void Copy(int fromEntityID, int toEntityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID);
if (!Has(fromEntityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID); }
#endif
CopyComponent(ref Get(fromEntityID), ref TryAddOrGet(toEntityID));
}
public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID);
if (!Has(fromEntityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID); }
#endif
CopyComponent(ref Get(fromEntityID), ref toWorld.GetPool<T>().TryAddOrGet(toEntityID));
}
@ -171,11 +193,9 @@ namespace DCFApixels.DragonECS
#endregion
#region Other
void IEcsPool.AddRaw(int entityID, object dataRaw) => Add(entityID) = (T)dataRaw;
object IEcsPool.GetRaw(int entityID) => Read(entityID);
void IEcsPool.SetRaw(int entityID, object dataRaw) => Get(entityID) = (T)dataRaw;
ref readonly T IEcsStructPool<T>.Read(int entityID) => ref Read(entityID);
ref T IEcsStructPool<T>.Get(int entityID) => ref Get(entityID);
void IEcsPool.AddRaw(int entityID, object dataRaw) { Add(entityID) = (T)dataRaw; }
object IEcsPool.GetRaw(int entityID) { return Get(entityID); }
void IEcsPool.SetRaw(int entityID, object dataRaw) { Get(entityID) = (T)dataRaw; }
#endregion
#region Listeners
@ -219,8 +239,8 @@ namespace DCFApixels.DragonECS
#endregion
#region IEnumerator - IntelliSense hack
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
IEnumerator<T> IEnumerable<T>.GetEnumerator() { throw new NotImplementedException(); }
IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
#endregion
}
/// <summary>Standard component</summary>

View File

@ -12,7 +12,7 @@ namespace DCFApixels.DragonECS
Type ComponentType { get; }
EcsWorld World { get; }
int Count { get; }
int Capacity { get; }
int Capacity { get; } //TODO удалить. не во всех реализация нужен, проще привести к типу
#endregion
#region Methods
@ -30,18 +30,21 @@ namespace DCFApixels.DragonECS
void RemoveListener(IEcsPoolEventListener listener);
#endregion
}
public interface IEcsStructPool<T> : IEcsPool
/// <summary>A pool for struct components.</summary>
public interface IEcsStructPool<T> : IEcsPool where T: struct
{
ref T Add(int entityID);
ref readonly T Read(int entityID);
ref T Get(int entityID);
}
public interface IEcsClassPool<T> : IEcsPool
/// <summary>A pool for reference components of type T that instantiates components itself.</summary>
public interface IEcsClassPool<T> : IEcsPool where T: class
{
T Add(int entityID);
T Get(int entityID);
}
public interface IEcsHybridPool<T> : IEcsPool
/// <summary>A pool for reference components of type T, which does not instantiate components itself but receives components from external sources..</summary>
public interface IEcsHybridPool<T> : IEcsPool where T: class
{
void Add(int entityID, T component);
T Get(int entityID);
@ -68,6 +71,14 @@ namespace DCFApixels.DragonECS
{
throw new EcsFrameworkException($"Entity({entityID}) has no component {EcsDebugUtility.GetGenericTypeName<T>()}.");
}
public static void ThrowAlreadyHasComponent(Type type, int entityID)
{
throw new EcsFrameworkException($"Entity({entityID}) already has component {EcsDebugUtility.GetGenericTypeName(type)}.");
}
public static void ThrowNotHaveComponent(Type type, int entityID)
{
throw new EcsFrameworkException($"Entity({entityID}) has no component {EcsDebugUtility.GetGenericTypeName(type)}.");
}
}
public static class IEcsPoolImplementationExtensions
{

View File

@ -33,24 +33,41 @@ namespace DCFApixels.DragonECS
public EcsTagPool()
{
if (_isInvalidType)
{
throw new EcsFrameworkException($"{typeof(T).Name} type must not contain any data.");
}
}
#endif
#endregion
#region Properites
public int Count => _count;
int IEcsPool.Capacity => -1;
public int ComponentID => _componentTypeID;
public Type ComponentType => typeof(T);
public EcsWorld World => _source;
public int Count
{
get { return _count; }
}
int IEcsPool.Capacity
{
get { return -1; }
}
public int ComponentID
{
get { return _componentTypeID; }
}
public Type ComponentType
{
get { return typeof(T); }
}
public EcsWorld World
{
get { return _source; }
}
#endregion
#region Method
public void Add(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (Has(entityID)) EcsPoolThrowHalper.ThrowAlreadyHasComponent<T>(entityID);
if (Has(entityID)) { EcsPoolThrowHalper.ThrowAlreadyHasComponent<T>(entityID); }
#endif
_count++;
_mapping[entityID] = true;
@ -59,12 +76,9 @@ namespace DCFApixels.DragonECS
}
public void TryAdd(int entityID)
{
if (!_mapping[entityID])
if (Has(entityID) == false)
{
_count++;
_mapping[entityID] = true;
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
_listeners.InvokeOnAdd(entityID);
Add(entityID);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -75,7 +89,7 @@ namespace DCFApixels.DragonECS
public void Del(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
if (!Has(entityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); }
#endif
_mapping[entityID] = false;
_count--;
@ -84,19 +98,22 @@ namespace DCFApixels.DragonECS
}
public void TryDel(int entityID)
{
if (Has(entityID)) Del(entityID);
if (Has(entityID))
{
Del(entityID);
}
}
public void Copy(int fromEntityID, int toEntityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID);
if (!Has(fromEntityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID); }
#endif
TryAdd(toEntityID);
}
public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID);
if (!Has(fromEntityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID); }
#endif
toWorld.GetPool<T>().TryAdd(toEntityID);
}
@ -105,20 +122,28 @@ namespace DCFApixels.DragonECS
if (isHas)
{
if (!Has(entityID))
{
Add(entityID);
}
}
else
{
if (Has(entityID))
{
Del(entityID);
}
}
}
public void Toggle(int entityID)
{
if (Has(entityID))
{
Del(entityID);
}
else
{
Add(entityID);
}
}
#endregion
@ -142,11 +167,27 @@ namespace DCFApixels.DragonECS
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
{
foreach (var entityID in buffer)
{
TryDel(entityID);
}
}
#endregion
#region Other
void IEcsPool.AddRaw(int entityID, object dataRaw) { Add(entityID); }
object IEcsPool.GetRaw(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (Has(entityID) == false) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); }
#endif
return _fakeComponent;
}
void IEcsPool.SetRaw(int entityID, object dataRaw)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (Has(entityID) == false) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); }
#endif
}
ref T IEcsStructPool<T>.Add(int entityID)
{
Add(entityID);
@ -155,31 +196,17 @@ namespace DCFApixels.DragonECS
ref readonly T IEcsStructPool<T>.Read(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
if (Has(entityID) == false) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); }
#endif
return ref _fakeComponent;
}
ref T IEcsStructPool<T>.Get(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
if (Has(entityID) == false) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); }
#endif
return ref _fakeComponent;
}
void IEcsPool.AddRaw(int entityID, object dataRaw) => Add(entityID);
object IEcsPool.GetRaw(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
#endif
return _fakeComponent;
}
void IEcsPool.SetRaw(int entityID, object dataRaw)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
#endif
}
#endregion
#region Listeners

View File

@ -123,6 +123,11 @@ namespace DCFApixels.DragonECS.Internal
{
throw new Exception();
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void Exception(string message)
{
throw new Exception(message);
}
}
}