DragonECS/src/Pools/EcsSinglePool.cs

158 lines
5.5 KiB
C#
Raw Normal View History

2023-04-21 03:16:05 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
2023-04-21 03:16:05 +08:00
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
using static EcsPoolThrowHalper;
public sealed class EcsSinglePool<T> : IEcsPoolImplementation<T>, IEnumerable<T> //IntelliSense hack
2023-04-21 14:21:24 +08:00
where T : struct, IEcsSingleComponent
2023-04-21 03:16:05 +08:00
{
private EcsWorld _source;
private int _id;
private int[] _mapping;
2023-04-21 03:16:05 +08:00
private int _count;
private T _component;
private PoolRunners _poolRunners;
#region Properites
2023-04-24 16:48:18 +08:00
public ref T Instance
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref _component;
}
2023-04-21 03:16:05 +08:00
public int Count => _count;
int IEcsPool.Capacity => -1;
public int ComponentID => _id;
public Type ComponentType => typeof(T);
public EcsWorld World => _source;
2023-04-21 03:16:05 +08:00
#endregion
#region Init
void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID)
2023-04-21 03:16:05 +08:00
{
_source = world;
_id = componentID;
2023-04-21 03:16:05 +08:00
_mapping = new int[world.Capacity];
_count = 0;
_poolRunners = new PoolRunners(world.Pipeline);
}
#endregion
#region Methods
2023-04-21 03:16:05 +08:00
public ref T Add(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (Has(entityID)) ThrowAlreadyHasComponent<T>(entityID);
#endif
_mapping[entityID] = ++_count;
this.IncrementEntityComponentCount(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID);
2023-04-21 03:16:05 +08:00
return ref _component;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T Write(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
#endif
2023-04-21 03:16:05 +08:00
_poolRunners.write.OnComponentWrite<T>(entityID);
return ref _component;
}
public ref T TryAddOrWrite(int entityID)
{
if (!Has(entityID))
return ref Add(entityID);
return ref Write(entityID);
}
2023-04-21 03:16:05 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref readonly T Read(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
#endif
2023-04-21 03:16:05 +08:00
return ref _component;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Has(int entityID)
2023-04-21 03:16:05 +08:00
{
return _mapping[entityID] > 0;
}
public void Del(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
#endif
2023-04-21 03:16:05 +08:00
_mapping[entityID] = 0;
_count--;
this.DecrementEntityComponentCount(entityID);
2023-04-21 03:16:05 +08:00
_poolRunners.del.OnComponentDel<T>(entityID);
}
public void TryDel(int entityID)
{
if (Has(entityID)) Del(entityID);
}
public void Copy(int fromEntityID, int toEntityID)
{
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (!Has(fromEntityID)) ThrowNotHaveComponent<T>(fromEntityID);
#endif
TryAddOrWrite(toEntityID);
2023-04-21 03:16:05 +08:00
}
#endregion
#region Callbacks
void IEcsPoolImplementation.OnWorldResize(int newSize)
2023-04-21 03:16:05 +08:00
{
Array.Resize(ref _mapping, newSize);
}
void IEcsPoolImplementation.OnWorldDestroy() { }
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
{
foreach (var entityID in buffer)
TryDel(entityID);
}
#endregion
#region Other
void IEcsPool.AddRaw(int entityID, object dataRaw) => Instance = (T)dataRaw;
object IEcsPool.GetRaw(int entityID) => Instance;
void IEcsPool.SetRaw(int entityID, object dataRaw) => Instance = (T)dataRaw;
#endregion
#region IEnumerator - IntelliSense hack
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
2023-04-21 03:16:05 +08:00
#endregion
}
/// <summary>Singleton component</summary>
2023-04-21 14:21:24 +08:00
public interface IEcsSingleComponent { }
2023-04-21 03:46:51 +08:00
public static class EcsSinglePoolExt
2023-04-21 03:16:05 +08:00
{
2023-04-21 03:46:51 +08:00
public static EcsSinglePool<TSingleComponent> GetPool<TSingleComponent>(this EcsWorld self)
2023-04-21 14:21:24 +08:00
where TSingleComponent : struct, IEcsSingleComponent
2023-04-21 03:16:05 +08:00
{
2023-04-21 03:46:51 +08:00
return self.GetPool<TSingleComponent, EcsSinglePool<TSingleComponent>>();
2023-04-21 16:03:50 +08:00
}
public static EcsSinglePool<TSingleComponent> Include<TSingleComponent>(this EcsSubjectBuilderBase self) where TSingleComponent : struct, IEcsSingleComponent
2023-04-21 16:03:50 +08:00
{
return self.Include<TSingleComponent, EcsSinglePool<TSingleComponent>>();
}
public static EcsSinglePool<TSingleComponent> Exclude<TSingleComponent>(this EcsSubjectBuilderBase self) where TSingleComponent : struct, IEcsSingleComponent
2023-04-21 16:03:50 +08:00
{
return self.Exclude<TSingleComponent, EcsSinglePool<TSingleComponent>>();
}
public static EcsSinglePool<TSingleComponent> Optional<TSingleComponent>(this EcsSubjectBuilderBase self) where TSingleComponent : struct, IEcsSingleComponent
2023-04-21 16:03:50 +08:00
{
return self.Optional<TSingleComponent, EcsSinglePool<TSingleComponent>>();
}
2023-04-21 03:16:05 +08:00
}
}