Merge branch 'new_dev'

This commit is contained in:
Mikhail 2024-02-09 22:41:21 +08:00
commit 374afe75a9
22 changed files with 674 additions and 269 deletions

View File

@ -5,6 +5,23 @@ using System.Linq;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public readonly struct Injector
{
private readonly EcsPipeline _pipeline;
public Injector(EcsPipeline pipeline)
{
_pipeline = pipeline;
}
public void Inject<T>(T data)
{
_pipeline.Inject(data);
}
}
public interface IInjectionBlock
{
void InjectTo(Injector i);
}
[MetaName(nameof(PreInject))] [MetaName(nameof(PreInject))]
[BindWithEcsRunner(typeof(EcsPreInjectRunner))] [BindWithEcsRunner(typeof(EcsPreInjectRunner))]
public interface IEcsPreInject : IEcsProcess public interface IEcsPreInject : IEcsProcess
@ -56,7 +73,14 @@ namespace DCFApixels.DragonECS
{ {
void IEcsPreInject.PreInject(object obj) void IEcsPreInject.PreInject(object obj)
{ {
foreach (var item in targets) item.PreInject(obj); if (obj is IInjectionBlock container)
{
container.InjectTo(new Injector(Pipeline));
}
foreach (var item in targets)
{
item.PreInject(obj);
}
} }
} }
[MetaTags(MetaTags.HIDDEN)] [MetaTags(MetaTags.HIDDEN)]
@ -74,9 +98,9 @@ namespace DCFApixels.DragonECS
{ {
Type baseType = typeof(T).BaseType; Type baseType = typeof(T).BaseType;
if (baseType != typeof(object) && baseType != typeof(ValueType) && baseType != null) if (baseType != typeof(object) && baseType != typeof(ValueType) && baseType != null)
_baseTypeInjectRunner = (EcsBaseTypeInjectRunner)Activator.CreateInstance(typeof(EcsBaseTypeInjectRunner<>).MakeGenericType(baseType), Source); _baseTypeInjectRunner = (EcsBaseTypeInjectRunner)Activator.CreateInstance(typeof(EcsBaseTypeInjectRunner<>).MakeGenericType(baseType), Pipeline);
else else
_baseTypeInjectRunner = new EcsObjectTypePreInjectRunner(Source); _baseTypeInjectRunner = new EcsObjectTypePreInjectRunner(Pipeline);
} }
} }
internal abstract class EcsBaseTypeInjectRunner internal abstract class EcsBaseTypeInjectRunner
@ -155,7 +179,10 @@ namespace DCFApixels.DragonECS
public static partial class EcsPipelineExtensions public static partial class EcsPipelineExtensions
{ {
public static void Inject<T>(EcsPipeline self, T data) => self.GetRunner<IEcsInject<T>>().Inject(data); public static void Inject<T>(this EcsPipeline self, T data)
{
self.GetRunner<IEcsInject<T>>().Inject(data);
}
} }
public static partial class EcsPipelineBuilderExtensions public static partial class EcsPipelineBuilderExtensions
{ {
@ -167,33 +194,33 @@ namespace DCFApixels.DragonECS
self.AddModule(module); self.AddModule(module);
return self; return self;
} }
public static EcsPipeline.Builder Inject<A, B>(this EcsPipeline.Builder self, A a, B b) public static EcsPipeline.Builder Inject<T0, T1>(this EcsPipeline.Builder self, T0 d0, T1 d1)
{ {
return self.Inject(a).Inject(b); return self.Inject(d0).Inject(d1);
} }
public static EcsPipeline.Builder Inject<A, B, C>(this EcsPipeline.Builder self, A a, B b, C c) public static EcsPipeline.Builder Inject<T0, T1, T2>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2)
{ {
return self.Inject(a).Inject(b).Inject(c); return self.Inject(d0).Inject(d1).Inject(d2);
} }
public static EcsPipeline.Builder Inject<A, B, C, D>(this EcsPipeline.Builder self, A a, B b, C c, D d) public static EcsPipeline.Builder Inject<T0, T1, T2, T3>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3)
{ {
return self.Inject(a).Inject(b).Inject(c).Inject(d); return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3);
} }
public static EcsPipeline.Builder Inject<A, B, C, D, E>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e) public static EcsPipeline.Builder Inject<T0, T1, T2, T3, T4>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4)
{ {
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e); return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4);
} }
public static EcsPipeline.Builder Inject<A, B, C, D, E, F>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f) public static EcsPipeline.Builder Inject<T0, T1, T2, T3, T4, T5>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4, T5 f)
{ {
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f); return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4).Inject(f);
} }
public static EcsPipeline.Builder Inject<A, B, C, D, E, F, G>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f, G g) public static EcsPipeline.Builder Inject<T0, T1, T2, T3, T4, T5, T6>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4, T5 f, T6 d6)
{ {
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f).Inject(g); return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4).Inject(f).Inject(d6);
} }
public static EcsPipeline.Builder Inject<A, B, C, D, E, F, G, H>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f, G g, H h) public static EcsPipeline.Builder Inject<T0, T1, T2, T3, T4, T5, T6, T7>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4, T5 f, T6 d6, T7 d7)
{ {
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f).Inject(g).Inject(h); return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4).Inject(f).Inject(d6).Inject(d7);
} }
} }
} }

View File

@ -1,5 +1,13 @@
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public sealed class EcsDefaultWorld : EcsWorld { } public sealed class EcsDefaultWorld : EcsWorld
public sealed class EcsEventWorld : EcsWorld { } {
public EcsDefaultWorld() : base(null) { }
public EcsDefaultWorld(IEcsWorldConfig config) : base(config) { }
}
public sealed class EcsEventWorld : EcsWorld
{
public EcsEventWorld() : base(null) { }
public EcsEventWorld(IEcsWorldConfig config) : base(config) { }
}
} }

View File

@ -29,7 +29,7 @@ namespace DCFApixels.DragonECS
public int WorldID public int WorldID
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.World.id; get => _source.WorldID;
} }
public EcsWorld World public EcsWorld World
{ {
@ -106,17 +106,18 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsSubsetOf(EcsReadonlyGroup group) => _source.IsSubsetOf(group._source); public bool IsSubsetOf(EcsReadonlyGroup group) => _source.IsSubsetOf(group._source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsSubsetOf(EcsGroup group) => _source.IsSubsetOf(group); public bool IsSubsetOf(EcsGroup group) => _source.IsSubsetOf(group);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsSupersetOf(EcsReadonlyGroup group) => _source.IsSupersetOf(group._source); public bool IsSupersetOf(EcsReadonlyGroup group) => _source.IsSupersetOf(group._source);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsSupersetOf(EcsGroup group) => _source.IsSupersetOf(group); public bool IsSupersetOf(EcsGroup group) => _source.IsSupersetOf(group);
#endregion #endregion
#region Internal #region Internal
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EcsGroup GetGroupInternal() => _source; internal EcsGroup GetSource_Internal() => _source;
#endregion #endregion
#region Other #region Other
@ -293,7 +294,7 @@ namespace DCFApixels.DragonECS
#region CopyFrom/Clone/Bake/ToSpan #region CopyFrom/Clone/Bake/ToSpan
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyFrom(EcsReadonlyGroup group) => CopyFrom(group.GetGroupInternal()); public void CopyFrom(EcsReadonlyGroup group) => CopyFrom(group.GetSource_Internal());
public void CopyFrom(EcsGroup group) public void CopyFrom(EcsGroup group)
{ {
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
@ -347,7 +348,7 @@ namespace DCFApixels.DragonECS
#region UnionWith #region UnionWith
/// <summary>as Union sets</summary> /// <summary>as Union sets</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void UnionWith(EcsReadonlyGroup group) => UnionWith(group.GetGroupInternal()); public void UnionWith(EcsReadonlyGroup group) => UnionWith(group.GetSource_Internal());
/// <summary>as Union sets</summary> /// <summary>as Union sets</summary>
public void UnionWith(EcsGroup group) public void UnionWith(EcsGroup group)
{ {
@ -374,7 +375,7 @@ namespace DCFApixels.DragonECS
#region ExceptWith #region ExceptWith
/// <summary>as Except sets</summary> /// <summary>as Except sets</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ExceptWith(EcsReadonlyGroup group) => ExceptWith(group.GetGroupInternal()); public void ExceptWith(EcsReadonlyGroup group) => ExceptWith(group.GetSource_Internal());
/// <summary>as Except sets</summary> /// <summary>as Except sets</summary>
public void ExceptWith(EcsGroup group) public void ExceptWith(EcsGroup group)
{ {
@ -432,7 +433,7 @@ namespace DCFApixels.DragonECS
#region IntersectWith #region IntersectWith
/// <summary>as Intersect sets</summary> /// <summary>as Intersect sets</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void IntersectWith(EcsReadonlyGroup group) => IntersectWith(group.GetGroupInternal()); public void IntersectWith(EcsReadonlyGroup group) => IntersectWith(group.GetSource_Internal());
/// <summary>as Intersect sets</summary> /// <summary>as Intersect sets</summary>
public void IntersectWith(EcsGroup group) public void IntersectWith(EcsGroup group)
{ {
@ -451,7 +452,7 @@ namespace DCFApixels.DragonECS
#region SymmetricExceptWith #region SymmetricExceptWith
/// <summary>as Symmetric Except sets</summary> /// <summary>as Symmetric Except sets</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SymmetricExceptWith(EcsReadonlyGroup group) => SymmetricExceptWith(group.GetGroupInternal()); public void SymmetricExceptWith(EcsReadonlyGroup group) => SymmetricExceptWith(group.GetSource_Internal());
/// <summary>as Symmetric Except sets</summary> /// <summary>as Symmetric Except sets</summary>
public void SymmetricExceptWith(EcsGroup group) public void SymmetricExceptWith(EcsGroup group)
{ {
@ -479,7 +480,7 @@ namespace DCFApixels.DragonECS
#region SetEquals #region SetEquals
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool SetEquals(EcsReadonlyGroup group) => SetEquals(group.GetGroupInternal()); public bool SetEquals(EcsReadonlyGroup group) => SetEquals(group.GetSource_Internal());
public bool SetEquals(EcsGroup group) public bool SetEquals(EcsGroup group)
{ {
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
@ -508,7 +509,7 @@ namespace DCFApixels.DragonECS
#region Overlaps #region Overlaps
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Overlaps(EcsReadonlyGroup group) => Overlaps(group.GetGroupInternal()); public bool Overlaps(EcsReadonlyGroup group) => Overlaps(group.GetSource_Internal());
public bool Overlaps(EcsGroup group) public bool Overlaps(EcsGroup group)
{ {
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
@ -542,7 +543,7 @@ namespace DCFApixels.DragonECS
#region IsSubsetOf #region IsSubsetOf
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsSubsetOf(EcsReadonlyGroup group) => IsSubsetOf(group.GetGroupInternal()); public bool IsSubsetOf(EcsReadonlyGroup group) => IsSubsetOf(group.GetSource_Internal());
public bool IsSubsetOf(EcsGroup group) public bool IsSubsetOf(EcsGroup group)
{ {
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
@ -559,7 +560,7 @@ namespace DCFApixels.DragonECS
#region IsSupersetOf #region IsSupersetOf
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsSupersetOf(EcsReadonlyGroup group) => IsSupersetOf(group.GetGroupInternal()); public bool IsSupersetOf(EcsReadonlyGroup group) => IsSupersetOf(group.GetSource_Internal());
public bool IsSupersetOf(EcsGroup group) public bool IsSupersetOf(EcsGroup group)
{ {
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
@ -764,7 +765,7 @@ namespace DCFApixels.DragonECS
public int CapacitySparce => _group.CapacitySparce; public int CapacitySparce => _group.CapacitySparce;
public override string ToString() => _group.ToString(); public override string ToString() => _group.ToString();
public DebuggerProxy(EcsGroup group) => _group = group; public DebuggerProxy(EcsGroup group) => _group = group;
public DebuggerProxy(EcsReadonlyGroup group) : this(group.GetGroupInternal()) { } public DebuggerProxy(EcsReadonlyGroup group) : this(group.GetSource_Internal()) { }
} }
#endregion #endregion
} }

View File

@ -1,4 +1,4 @@
using DCFApixels.DragonECS.Utils; using DCFApixels.DragonECS.Internal;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;

View File

@ -1,5 +1,3 @@
using System;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
@ -16,14 +14,15 @@ namespace DCFApixels.DragonECS
public static readonly bool isHasHandler; public static readonly bool isHasHandler;
static EcsWorldComponentHandler() static EcsWorldComponentHandler()
{ {
Type targetType = typeof(T); T def = default;
isHasHandler = targetType.GetInterfaces().Contains(typeof(IEcsWorldComponent<>).MakeGenericType(targetType)); if (def is IEcsWorldComponent<T> intrf)
if (isHasHandler)
{ {
instance = (IEcsWorldComponent<T>)Activator.CreateInstance(typeof(WorldComponentHandler<>).MakeGenericType(targetType)); isHasHandler = true;
instance = intrf;
} }
else else
{ {
isHasHandler = false;
instance = new DummyHandler(); instance = new DummyHandler();
} }
} }
@ -34,14 +33,6 @@ namespace DCFApixels.DragonECS
public void OnDestroy(ref T component, EcsWorld world) { } public void OnDestroy(ref T component, EcsWorld world) { }
} }
} }
internal class WorldComponentHandler<T> : IEcsWorldComponent<T>
where T : IEcsWorldComponent<T>
{
private T _fakeInstnace = default;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Init(ref T component, EcsWorld world) => _fakeInstnace.Init(ref component, world);
public void OnDestroy(ref T component, EcsWorld world) => _fakeInstnace.OnDestroy(ref component, world);
}
#endregion #endregion
#region IEcsComponentReset #region IEcsComponentReset
@ -55,14 +46,15 @@ namespace DCFApixels.DragonECS
public static readonly bool isHasHandler; public static readonly bool isHasHandler;
static EcsComponentResetHandler() static EcsComponentResetHandler()
{ {
Type targetType = typeof(T); T def = default;
isHasHandler = targetType.GetInterfaces().Contains(typeof(IEcsComponentReset<>).MakeGenericType(targetType)); if (def is IEcsComponentReset<T> intrf)
if (isHasHandler)
{ {
instance = (IEcsComponentReset<T>)Activator.CreateInstance(typeof(ComponentResetHandler<>).MakeGenericType(targetType)); isHasHandler = true;
instance = intrf;
} }
else else
{ {
isHasHandler = false;
instance = new DummyHandler(); instance = new DummyHandler();
} }
} }
@ -72,13 +64,6 @@ namespace DCFApixels.DragonECS
public void Reset(ref T component) => component = default; public void Reset(ref T component) => component = default;
} }
} }
internal sealed class ComponentResetHandler<T> : IEcsComponentReset<T>
where T : IEcsComponentReset<T>
{
private T _fakeInstnace = default;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset(ref T component) => _fakeInstnace.Reset(ref component);
}
#endregion #endregion
#region IEcsComponentCopy #region IEcsComponentCopy
@ -92,14 +77,15 @@ namespace DCFApixels.DragonECS
public static readonly bool isHasHandler; public static readonly bool isHasHandler;
static EcsComponentCopyHandler() static EcsComponentCopyHandler()
{ {
Type targetType = typeof(T); T def = default;
isHasHandler = targetType.GetInterfaces().Contains(typeof(IEcsComponentCopy<>).MakeGenericType(targetType)); if (def is IEcsComponentCopy<T> intrf)
if (isHasHandler)
{ {
instance = (IEcsComponentCopy<T>)Activator.CreateInstance(typeof(ComponentCopyHandler<>).MakeGenericType(targetType)); isHasHandler = true;
instance = intrf;
} }
else else
{ {
isHasHandler = false;
instance = new DummyHandler(); instance = new DummyHandler();
} }
} }
@ -109,12 +95,5 @@ namespace DCFApixels.DragonECS
public void Copy(ref T from, ref T to) => to = from; public void Copy(ref T from, ref T to) => to = from;
} }
} }
internal sealed class ComponentCopyHandler<T> : IEcsComponentCopy<T>
where T : IEcsComponentCopy<T>
{
private T _fakeInstnace = default;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Copy(ref T from, ref T to) => _fakeInstnace.Copy(ref from, ref to);
}
#endregion #endregion
} }

View File

@ -41,6 +41,11 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void PrintWarning(object v) => Print(EcsConsts.DEBUG_WARNING_TAG, v); public static void PrintWarning(object v) => Print(EcsConsts.DEBUG_WARNING_TAG, v);
public static void PrintError(object v) => Print(EcsConsts.DEBUG_ERROR_TAG, v); public static void PrintError(object v) => Print(EcsConsts.DEBUG_ERROR_TAG, v);
public static void PrintErrorAndBreak(object v)
{
Print(EcsConsts.DEBUG_ERROR_TAG, v);
Break();
}
public static void PrintPass(object v) => Print(EcsConsts.DEBUG_PASS_TAG, v); public static void PrintPass(object v) => Print(EcsConsts.DEBUG_PASS_TAG, v);
public static void Print() public static void Print()
{ {
@ -176,7 +181,11 @@ namespace DCFApixels.DragonECS
} }
public override void ProfilerMarkBegin(int id) public override void ProfilerMarkBegin(int id)
{ {
var color = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.DarkGray;
_stopwatchs[id].Start(); _stopwatchs[id].Start();
Print("ProfilerMark", $"{_stopwatchsNames[id]} start <");
Console.ForegroundColor = color;
} }
public override void ProfilerMarkEnd(int id) public override void ProfilerMarkEnd(int id)
{ {
@ -185,7 +194,7 @@ namespace DCFApixels.DragonECS
_stopwatchs[id].Stop(); _stopwatchs[id].Stop();
var time = _stopwatchs[id].Elapsed; var time = _stopwatchs[id].Elapsed;
_stopwatchs[id].Reset(); _stopwatchs[id].Reset();
Print("ProfilerMark", _stopwatchsNames[id] + " s:" + time.TotalSeconds); Print("ProfilerMark", $"> {_stopwatchsNames[id]} s:{time.TotalSeconds}");
Console.ForegroundColor = color; Console.ForegroundColor = color;
} }
protected override void OnDelProfilerMark(int id) protected override void OnDelProfilerMark(int id)

View File

@ -49,6 +49,7 @@ namespace DCFApixels.DragonECS
} }
private static string AutoToString(object target, Type type, bool isWriteName) private static string AutoToString(object target, Type type, bool isWriteName)
{ {
//TODO сделать специальный вывод в виде названий констант для Enum-ов
var fields = type.GetFields(RFL_FLAGS); var fields = type.GetFields(RFL_FLAGS);
string[] values = new string[fields.Length]; string[] values = new string[fields.Length];
for (int i = 0; i < fields.Length; i++) for (int i = 0; i < fields.Length; i++)

View File

@ -40,7 +40,7 @@ namespace DCFApixels.DragonECS
private Builder(EcsWorld world) private Builder(EcsWorld world)
{ {
_world = world; _world = world;
_maskBuilder = new EcsMask.Builder(world); _maskBuilder = EcsMask.New(world);
} }
internal static unsafe TAspect New<TAspect>(EcsWorld world) where TAspect : EcsAspect internal static unsafe TAspect New<TAspect>(EcsWorld world) where TAspect : EcsAspect
{ {
@ -113,16 +113,11 @@ namespace DCFApixels.DragonECS
public TOtherAspect Combine<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect public TOtherAspect Combine<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect
{ {
var result = _world.GetAspect<TOtherAspect>(); var result = _world.GetAspect<TOtherAspect>();
_maskBuilder.CombineWith(result.Mask); _maskBuilder.Combine(result.Mask);
return result; return result;
} }
#endregion #endregion
public EcsWorldCmp<T> GetWorldData<T>() where T : struct
{
return new EcsWorldCmp<T>(_world.id);
}
private void Build(out EcsMask mask) private void Build(out EcsMask mask)
{ {
mask = _maskBuilder.Build(); mask = _maskBuilder.Build();

View File

@ -7,20 +7,6 @@ using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public abstract partial class EcsWorld
{
private Dictionary<EcsMask.BuilderMaskKey, EcsMask> _masks = new Dictionary<EcsMask.BuilderMaskKey, EcsMask>(256);
internal EcsMask GetMask_Internal(EcsMask.BuilderMaskKey maskKey)
{
if (!_masks.TryGetValue(maskKey, out EcsMask result))
{
result = new EcsMask(_masks.Count, id, maskKey.inc, maskKey.exc);
_masks.Add(maskKey, result);
}
return result;
}
}
[DebuggerTypeProxy(typeof(DebuggerProxy))] [DebuggerTypeProxy(typeof(DebuggerProxy))]
public sealed class EcsMask : IEquatable<EcsMask> public sealed class EcsMask : IEquatable<EcsMask>
{ {
@ -42,6 +28,10 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Constructors #region Constructors
public static Builder New(EcsWorld world)
{
return new Builder(world);
}
internal EcsMask(int id, int worldID, int[] inc, int[] exc) internal EcsMask(int id, int worldID, int[] inc, int[] exc)
{ {
#if DEBUG #if DEBUG
@ -168,19 +158,69 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Builder #region Builder
public readonly struct BuilderMaskKey : IEquatable<BuilderMaskKey> private readonly struct WorldMaskComponent : IEcsWorldComponent<WorldMaskComponent>
{
private readonly EcsWorld _world;
private readonly Dictionary<Key, EcsMask> _masks;
#region Constructor/Destructor
public WorldMaskComponent(EcsWorld world, Dictionary<Key, EcsMask> masks)
{
_world = world;
_masks = masks;
}
public void Init(ref WorldMaskComponent component, EcsWorld world)
{
component = new WorldMaskComponent(world, new Dictionary<Key, EcsMask>(256));
}
public void OnDestroy(ref WorldMaskComponent component, EcsWorld world)
{
component._masks.Clear();
component = default;
}
#endregion
#region GetMask
internal EcsMask GetMask(Key maskKey)
{
if (!_masks.TryGetValue(maskKey, out EcsMask result))
{
result = new EcsMask(_masks.Count, _world.id, maskKey.inc, maskKey.exc);
_masks.Add(maskKey, result);
}
return result;
}
#endregion
}
private readonly struct Key : IEquatable<Key>
{ {
public readonly int[] inc; public readonly int[] inc;
public readonly int[] exc; public readonly int[] exc;
public readonly int hash; public readonly int hash;
public BuilderMaskKey(int[] inc, int[] exc, int hash)
#region Constructors
public Key(int[] inc, int[] exc)
{ {
this.inc = inc; this.inc = inc;
this.exc = exc; this.exc = exc;
this.hash = hash; unchecked
{
hash = inc.Length + exc.Length;
for (int i = 0, iMax = inc.Length; i < iMax; i++)
{
hash = hash * EcsConsts.MAGIC_PRIME + inc[i];
}
for (int i = 0, iMax = exc.Length; i < iMax; i++)
{
hash = hash * EcsConsts.MAGIC_PRIME - exc[i];
}
}
} }
#endregion
#region Object
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(BuilderMaskKey other) public bool Equals(Key other)
{ {
if (inc.Length != other.inc.Length) if (inc.Length != other.inc.Length)
{ {
@ -204,16 +244,11 @@ namespace DCFApixels.DragonECS
return false; return false;
} }
} }
#if DEBUG
if (other.hash != hash)
{
throw new Exception("other.hash != hash");
}
#endif
return true; return true;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() => hash; public override int GetHashCode() => hash;
#endregion
} }
public class Builder public class Builder
@ -223,49 +258,58 @@ namespace DCFApixels.DragonECS
private readonly HashSet<int> _exc = new HashSet<int>(); private readonly HashSet<int> _exc = new HashSet<int>();
private readonly List<Combined> _combined = new List<Combined>(); private readonly List<Combined> _combined = new List<Combined>();
#region Constrcutors
internal Builder(EcsWorld world) internal Builder(EcsWorld world)
{ {
_world = world; _world = world;
} }
#endregion
public void Include<T>() #region Include/Exclude/Combine
public Builder Include<T>()
{ {
int id = _world.GetComponentID<T>(); int id = _world.GetComponentID<T>();
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (_inc.Contains(id) || _exc.Contains(id)) Throw.ConstraintIsAlreadyContainedInMask(typeof(T)); if (_inc.Contains(id) || _exc.Contains(id)) Throw.ConstraintIsAlreadyContainedInMask(typeof(T));
#endif #endif
_inc.Add(id); _inc.Add(id);
return this;
} }
public void Exclude<T>() public Builder Exclude<T>()
{ {
int id = _world.GetComponentID<T>(); int id = _world.GetComponentID<T>();
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (_inc.Contains(id) || _exc.Contains(id)) Throw.ConstraintIsAlreadyContainedInMask(typeof(T)); if (_inc.Contains(id) || _exc.Contains(id)) Throw.ConstraintIsAlreadyContainedInMask(typeof(T));
#endif #endif
_exc.Add(id); _exc.Add(id);
return this;
} }
public void Include(Type type) public Builder Include(Type type)
{ {
int id = _world.GetComponentID(type); int id = _world.GetComponentID(type);
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (_inc.Contains(id) || _exc.Contains(id)) Throw.ConstraintIsAlreadyContainedInMask(type); if (_inc.Contains(id) || _exc.Contains(id)) Throw.ConstraintIsAlreadyContainedInMask(type);
#endif #endif
_inc.Add(id); _inc.Add(id);
return this;
} }
public void Exclude(Type type) public Builder Exclude(Type type)
{ {
int id = _world.GetComponentID(type); int id = _world.GetComponentID(type);
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (_inc.Contains(id) || _exc.Contains(id)) Throw.ConstraintIsAlreadyContainedInMask(type); if (_inc.Contains(id) || _exc.Contains(id)) Throw.ConstraintIsAlreadyContainedInMask(type);
#endif #endif
_exc.Add(id); _exc.Add(id);
return this;
} }
public Builder Combine(EcsMask mask, int order = 0)
public void CombineWith(EcsMask mask, int order = 0)
{ {
_combined.Add(new Combined(mask, order)); _combined.Add(new Combined(mask, order));
return this;
} }
#endregion
#region Build
public EcsMask Build() public EcsMask Build()
{ {
HashSet<int> combinedInc; HashSet<int> combinedInc;
@ -296,24 +340,16 @@ namespace DCFApixels.DragonECS
var inc = combinedInc.ToArray(); var inc = combinedInc.ToArray();
Array.Sort(inc); Array.Sort(inc);
_inc.Clear();
var exc = combinedExc.ToArray(); var exc = combinedExc.ToArray();
Array.Sort(exc); Array.Sort(exc);
_exc.Clear();
unchecked _combined.Clear();
{
int keyHash = inc.Length + exc.Length; return _world.Get<WorldMaskComponent>().GetMask(new Key(inc, exc));
for (int i = 0, iMax = inc.Length; i < iMax; i++)
{
keyHash = keyHash * EcsConsts.MAGIC_PRIME + inc[i];
}
for (int i = 0, iMax = exc.Length; i < iMax; i++)
{
keyHash = keyHash * EcsConsts.MAGIC_PRIME - exc[i];
}
BuilderMaskKey key = new BuilderMaskKey(inc, exc, keyHash);
return _world.GetMask_Internal(key);
}
} }
#endregion
} }
private readonly struct Combined private readonly struct Combined

View File

@ -38,16 +38,21 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Runners #region Runners
public T[] GetSystems<T>() where T : IEcsProcess
{
return _allSystems.Where(o => o is T).Select(o => (T)o).ToArray();
}
public T GetRunner<T>() where T : IEcsProcess public T GetRunner<T>() where T : IEcsProcess
{ {
Type type = typeof(T); Type type = typeof(T);
if (_runners.TryGetValue(type, out IEcsRunner result)) if (_runners.TryGetValue(type, out IEcsRunner result))
{
return (T)result; return (T)result;
}
result = (IEcsRunner)EcsRunner<T>.Instantiate(this); result = (IEcsRunner)EcsRunner<T>.Instantiate(this);
_runners.Add(type, result); _runners.Add(type, result);
return (T)result; return (T)result;
} }
internal void OnRunnerDestroy(IEcsRunner runner) internal void OnRunnerDestroy(IEcsRunner runner)
{ {
_runners.Remove(runner.Interface); _runners.Remove(runner.Interface);

View File

@ -54,9 +54,9 @@ namespace DCFApixels.DragonECS
{ {
public interface IEcsRunner public interface IEcsRunner
{ {
EcsPipeline Source { get; } EcsPipeline Pipeline { get; }
Type Interface { get; } Type Interface { get; }
IList Targets { get; } IList TargetsRaw { get; }
object Filter { get; } object Filter { get; }
bool IsHasFilter { get; } bool IsHasFilter { get; }
bool IsDestroyed { get; } bool IsDestroyed { get; }
@ -203,9 +203,10 @@ namespace DCFApixels.DragonECS
private bool _isDestroyed; private bool _isDestroyed;
#region Properties #region Properties
public EcsPipeline Source => _source; public EcsPipeline Pipeline => _source;
public Type Interface => typeof(TInterface); public Type Interface => typeof(TInterface);
public IList Targets => _targetsSealed; public IList TargetsRaw => _targetsSealed;
public ReadOnlySpan<TInterface> Targets => targets;
public object Filter => _filter; public object Filter => _filter;
public bool IsHasFilter => _isHasFilter; public bool IsHasFilter => _isHasFilter;
public bool IsDestroyed => _isDestroyed; public bool IsDestroyed => _isDestroyed;
@ -225,9 +226,13 @@ namespace DCFApixels.DragonECS
internal void Rebuild() internal void Rebuild()
{ {
if (_isHasFilter) if (_isHasFilter)
{
Set(_source, FilterSystems(_source.AllSystems), _isHasFilter, _filter); Set(_source, FilterSystems(_source.AllSystems), _isHasFilter, _filter);
}
else else
{
Set(_source, FilterSystems(_source.AllSystems, _filter), _isHasFilter, _filter); Set(_source, FilterSystems(_source.AllSystems, _filter), _isHasFilter, _filter);
}
} }
public void Destroy() public void Destroy()
{ {

View File

@ -9,6 +9,7 @@ namespace DCFApixels.DragonECS
public abstract partial class EcsWorld public abstract partial class EcsWorld
{ {
public readonly short id; public readonly short id;
private IEcsWorldConfig _config;
private bool _isDestroyed; private bool _isDestroyed;
@ -23,7 +24,7 @@ namespace DCFApixels.DragonECS
private int _delEntBufferCount; private int _delEntBufferCount;
private int _delEntBufferMinCount; private int _delEntBufferMinCount;
private int _freeSpace; private int _freeSpace;
private bool _isEnableReleaseDelEntBuffer = true; private bool _isEnableAutoReleaseDelEntBuffer = true;
private List<WeakReference<EcsGroup>> _groups = new List<WeakReference<EcsGroup>>(); private List<WeakReference<EcsGroup>> _groups = new List<WeakReference<EcsGroup>>();
private Stack<EcsGroup> _groupsPool = new Stack<EcsGroup>(64); private Stack<EcsGroup> _groupsPool = new Stack<EcsGroup>(64);
@ -36,41 +37,88 @@ namespace DCFApixels.DragonECS
private readonly PoolsMediator _poolsMediator; private readonly PoolsMediator _poolsMediator;
#region Properties #region Properties
public bool IsDestroyed => _isDestroyed; public IEcsWorldConfig Config
public int Count => _entitiesCount; {
public int Capacity => _entitesCapacity; //_denseEntities.Length; [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _config; }
}
public bool IsDestroyed
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _isDestroyed; }
}
public int Count
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _entitiesCount; }
}
public int Capacity
{
//_denseEntities.Length;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _entitesCapacity; }
}
public int DelEntBufferCount
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _delEntBufferCount; }
}
public bool IsEnableReleaseDelEntBuffer
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _isEnableAutoReleaseDelEntBuffer; }
}
public int DelEntBufferCount => _delEntBufferCount; public EcsReadonlyGroup Entities
public bool IsEnableReleaseDelEntBuffer => _isEnableReleaseDelEntBuffer; {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsReadonlyGroup Entities => _allEntites.Readonly; get
public ReadOnlySpan<IEcsPoolImplementation> AllPools => _pools;// new ReadOnlySpan<IEcsPoolImplementation>(pools, 0, _poolsCount); {
if (_isEnableAutoReleaseDelEntBuffer)
{
ReleaseDelEntityBufferAll();
}
return _allEntites.Readonly;
}
}
public ReadOnlySpan<IEcsPoolImplementation> AllPools
{
// new ReadOnlySpan<IEcsPoolImplementation>(pools, 0, _poolsCount);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _pools; }
}
#endregion #endregion
#region Constructors/Destroy #region Constructors/Destroy
public EcsWorld() : this(true) { } public EcsWorld(IEcsWorldConfig config) : this(config, true) { }
internal EcsWorld(bool isIndexable) private EcsWorld(IEcsWorldConfig config, bool isIndexable)
{ {
const int POOLS_CAPACITY = 512; if (config == null)
_poolsMediator = new PoolsMediator(this); {
config = EmptyConfig.Instance;
_entitesCapacity = 512; }
config.Lock();
_config = config;
if (isIndexable) if (isIndexable)
{ {
id = (short)_worldIdDispenser.UseFree(); id = (short)_worldIdDispenser.UseFree();
if (id >= Worlds.Length) if (id >= Worlds.Length)
{
Array.Resize(ref Worlds, Worlds.Length << 1); Array.Resize(ref Worlds, Worlds.Length << 1);
}
Worlds[id] = this; Worlds[id] = this;
} }
_poolsMediator = new PoolsMediator(this);
_entityDispenser = new IntDispenser(0); _entityDispenser = new IntDispenser(0);
_pools = new IEcsPoolImplementation[POOLS_CAPACITY];
_poolComponentCounts = new int[POOLS_CAPACITY]; int poolsCapacity = ArrayUtility.NormalizeSizeToPowerOfTwo(config.Get_PoolsCapacity());
//_sortedPoolIds = new int[POOLS_CAPACITY]; _pools = new IEcsPoolImplementation[poolsCapacity];
//_sortedPoolIdsMapping = new int[POOLS_CAPACITY]; _poolComponentCounts = new int[poolsCapacity];
ArrayUtility.Fill(_pools, _nullPool); ArrayUtility.Fill(_pools, _nullPool);
_entitesCapacity = ArrayUtility.NormalizeSizeToPowerOfTwo(config.Get_EntitiesCapacity());
_gens = new short[_entitesCapacity]; _gens = new short[_entitesCapacity];
_componentCounts = new short[_entitesCapacity]; _componentCounts = new short[_entitesCapacity];
@ -78,9 +126,11 @@ namespace DCFApixels.DragonECS
_delEntBufferCount = 0; _delEntBufferCount = 0;
_delEntBuffer = new int[_entitesCapacity]; _delEntBuffer = new int[_entitesCapacity];
_entitiesComponentMasks = new int[_entitesCapacity][]; _entitiesComponentMasks = new int[_entitesCapacity][];
int maskLength = _pools.Length / 32 + 1;
for (int i = 0; i < _entitesCapacity; i++) for (int i = 0; i < _entitesCapacity; i++)
{ {
_entitiesComponentMasks[i] = new int[_pools.Length / 32 + 1]; _entitiesComponentMasks[i] = new int[maskLength];
} }
_delEntBufferMinCount = Math.Max(_delEntBuffer.Length >> DEL_ENT_BUFFER_SIZE_OFFSET, DEL_ENT_BUFFER_MIN_SIZE); _delEntBufferMinCount = Math.Max(_delEntBuffer.Length >> DEL_ENT_BUFFER_SIZE_OFFSET, DEL_ENT_BUFFER_MIN_SIZE);
@ -142,7 +192,7 @@ namespace DCFApixels.DragonECS
#region Where Query #region Where Query
public EcsReadonlyGroup WhereToGroupFor<TAspect>(EcsSpan span, out TAspect aspect) where TAspect : EcsAspect public EcsReadonlyGroup WhereToGroupFor<TAspect>(EcsSpan span, out TAspect aspect) where TAspect : EcsAspect
{ {
if (_isEnableReleaseDelEntBuffer) if (_isEnableAutoReleaseDelEntBuffer)
{ {
ReleaseDelEntityBufferAll(); ReleaseDelEntityBufferAll();
} }
@ -152,7 +202,7 @@ namespace DCFApixels.DragonECS
} }
public EcsReadonlyGroup WhereToGroupFor<TAspect>(EcsSpan span) where TAspect : EcsAspect public EcsReadonlyGroup WhereToGroupFor<TAspect>(EcsSpan span) where TAspect : EcsAspect
{ {
if (_isEnableReleaseDelEntBuffer) if (_isEnableAutoReleaseDelEntBuffer)
{ {
ReleaseDelEntityBufferAll(); ReleaseDelEntityBufferAll();
} }
@ -160,7 +210,7 @@ namespace DCFApixels.DragonECS
} }
public EcsReadonlyGroup WhereToGroup<TAspect>(out TAspect aspect) where TAspect : EcsAspect public EcsReadonlyGroup WhereToGroup<TAspect>(out TAspect aspect) where TAspect : EcsAspect
{ {
if (_isEnableReleaseDelEntBuffer) if (_isEnableAutoReleaseDelEntBuffer)
{ {
ReleaseDelEntityBufferAll(); ReleaseDelEntityBufferAll();
} }
@ -170,7 +220,7 @@ namespace DCFApixels.DragonECS
} }
public EcsReadonlyGroup WhereToGroup<TAspect>() where TAspect : EcsAspect public EcsReadonlyGroup WhereToGroup<TAspect>() where TAspect : EcsAspect
{ {
if (_isEnableReleaseDelEntBuffer) if (_isEnableAutoReleaseDelEntBuffer)
{ {
ReleaseDelEntityBufferAll(); ReleaseDelEntityBufferAll();
} }
@ -179,7 +229,7 @@ namespace DCFApixels.DragonECS
public EcsSpan WhereFor<TAspect>(EcsSpan span, out TAspect aspect) where TAspect : EcsAspect public EcsSpan WhereFor<TAspect>(EcsSpan span, out TAspect aspect) where TAspect : EcsAspect
{ {
if (_isEnableReleaseDelEntBuffer) if (_isEnableAutoReleaseDelEntBuffer)
{ {
ReleaseDelEntityBufferAll(); ReleaseDelEntityBufferAll();
} }
@ -189,7 +239,7 @@ namespace DCFApixels.DragonECS
} }
public EcsSpan WhereFor<TAspect>(EcsSpan span) where TAspect : EcsAspect public EcsSpan WhereFor<TAspect>(EcsSpan span) where TAspect : EcsAspect
{ {
if (_isEnableReleaseDelEntBuffer) if (_isEnableAutoReleaseDelEntBuffer)
{ {
ReleaseDelEntityBufferAll(); ReleaseDelEntityBufferAll();
} }
@ -197,7 +247,7 @@ namespace DCFApixels.DragonECS
} }
public EcsSpan Where<TAspect>(out TAspect aspect) where TAspect : EcsAspect public EcsSpan Where<TAspect>(out TAspect aspect) where TAspect : EcsAspect
{ {
if (_isEnableReleaseDelEntBuffer) if (_isEnableAutoReleaseDelEntBuffer)
{ {
ReleaseDelEntityBufferAll(); ReleaseDelEntityBufferAll();
} }
@ -207,7 +257,7 @@ namespace DCFApixels.DragonECS
} }
public EcsSpan Where<TAspect>() where TAspect : EcsAspect public EcsSpan Where<TAspect>() where TAspect : EcsAspect
{ {
if (_isEnableReleaseDelEntBuffer) if (_isEnableAutoReleaseDelEntBuffer)
{ {
ReleaseDelEntityBufferAll(); ReleaseDelEntityBufferAll();
} }
@ -216,20 +266,20 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Entity #region Entity
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int NewEntity() public int NewEntity()
{ {
//if (_isEnableReleaseDelEntBuffer && _freeSpace <= 1 && _delEntBufferCount > _delEntBufferMinCount)
// ReleaseDelEntityBufferAll();
int entityID = _entityDispenser.GetFree(); int entityID = _entityDispenser.GetFree();
_freeSpace--; _freeSpace--;
_entitiesCount++; _entitiesCount++;
if (_gens.Length <= entityID) if (_gens.Length <= entityID)
Upsize(); {
Upsize_Internal(_gens.Length << 1);
}
_gens[entityID] &= GEN_BITS; _gens[entityID] &= GEN_BITS;
_allEntites.Add(entityID); _allEntites.AddUnchecked(entityID);
_entityListeners.InvokeOnNewEntity(entityID); _entityListeners.InvokeOnNewEntity(entityID);
return entityID; return entityID;
} }
@ -238,8 +288,23 @@ namespace DCFApixels.DragonECS
int e = NewEntity(); int e = NewEntity();
return GetEntityLong(e); return GetEntityLong(e);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDelEntity(int entityID)
{
if (IsUsed(entityID))
{
DelEntity(entityID);
}
}
public void DelEntity(int entityID) public void DelEntity(int entityID)
{ {
#if DEBUG
if(IsUsed(entityID) == false)
{
Throw.UndefinedException();
}
#endif
_allEntites.Remove(entityID); _allEntites.Remove(entityID);
_delEntBuffer[_delEntBufferCount++] = entityID; _delEntBuffer[_delEntBufferCount++] = entityID;
_gens[entityID] |= DEATH_GEN_BIT; _gens[entityID] |= DEATH_GEN_BIT;
@ -339,12 +404,12 @@ namespace DCFApixels.DragonECS
#region DelEntBuffer #region DelEntBuffer
public AutoReleaseDelEntBufferLonkUnloker DisableAutoReleaseDelEntBuffer() public AutoReleaseDelEntBufferLonkUnloker DisableAutoReleaseDelEntBuffer()
{ {
_isEnableReleaseDelEntBuffer = false; _isEnableAutoReleaseDelEntBuffer = false;
return new AutoReleaseDelEntBufferLonkUnloker(this); return new AutoReleaseDelEntBufferLonkUnloker(this);
} }
public void EnableAutoReleaseDelEntBuffer() public void EnableAutoReleaseDelEntBuffer()
{ {
_isEnableReleaseDelEntBuffer = true; _isEnableAutoReleaseDelEntBuffer = true;
} }
public readonly struct AutoReleaseDelEntBufferLonkUnloker : IDisposable public readonly struct AutoReleaseDelEntBufferLonkUnloker : IDisposable
{ {
@ -393,25 +458,29 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Upsize #region Upsize
[MethodImpl(MethodImplOptions.NoInlining)] public void Upsize(int minSize)
private void Upsize()
{ {
Array.Resize(ref _gens, _gens.Length << 1); Upsize_Internal(ArrayUtility.NormalizeSizeToPowerOfTwo(minSize));
Array.Resize(ref _componentCounts, _gens.Length); }
Array.Resize(ref _delEntBuffer, _gens.Length); [MethodImpl(MethodImplOptions.NoInlining)]
Array.Resize(ref _entitiesComponentMasks, _gens.Length); private void Upsize_Internal(int newSize)
for (int i = _entitesCapacity; i < _gens.Length; i++) {
Array.Resize(ref _gens, newSize);
Array.Resize(ref _componentCounts, newSize);
Array.Resize(ref _delEntBuffer, newSize);
Array.Resize(ref _entitiesComponentMasks, newSize);
for (int i = _entitesCapacity; i < newSize; i++)
_entitiesComponentMasks[i] = new int[_pools.Length / 32 + 1]; _entitiesComponentMasks[i] = new int[_pools.Length / 32 + 1];
_delEntBufferMinCount = Math.Max(_delEntBuffer.Length >> DEL_ENT_BUFFER_SIZE_OFFSET, DEL_ENT_BUFFER_MIN_SIZE); _delEntBufferMinCount = Math.Max(_delEntBuffer.Length >> DEL_ENT_BUFFER_SIZE_OFFSET, DEL_ENT_BUFFER_MIN_SIZE);
ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitesCapacity); ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitesCapacity);
_entitesCapacity = _gens.Length; _entitesCapacity = newSize;
for (int i = 0; i < _groups.Count; i++) for (int i = 0; i < _groups.Count; i++)
{ {
if (_groups[i].TryGetTarget(out EcsGroup group)) if (_groups[i].TryGetTarget(out EcsGroup group))
{ {
group.OnWorldResize(_gens.Length); group.OnWorldResize(newSize);
} }
else else
{ {
@ -421,9 +490,11 @@ namespace DCFApixels.DragonECS
} }
} }
foreach (var item in _pools) foreach (var item in _pools)
item.OnWorldResize(_gens.Length); {
item.OnWorldResize(newSize);
}
_listeners.InvokeOnWorldResize(_gens.Length); _listeners.InvokeOnWorldResize(newSize);
} }
#endregion #endregion
@ -500,6 +571,21 @@ namespace DCFApixels.DragonECS
} }
} }
#endregion #endregion
#region EmptyConfig
private class EmptyConfig : IEcsWorldConfig
{
public static readonly EmptyConfig Instance = new EmptyConfig();
private EmptyConfig() { }
public bool IsLocked => true;
public T Get<T>(string valueName) { return default; }
public bool Has(string valueName) { return false; }
public void Lock() { }
public void Remove(string valueName) { }
public void Set<T>(string valueName, T value) { }
public bool TryGet<T>(string valueName, out T value) { value = default; return false; }
}
#endregion
} }
#region Callbacks Interface #region Callbacks Interface
@ -551,4 +637,4 @@ namespace DCFApixels.DragonECS
public static entlong ToEntityLong(this int self, EcsWorld world) => world.GetEntityLong(self); public static entlong ToEntityLong(this int self, EcsWorld world) => world.GetEntityLong(self);
} }
#endregion #endregion
} }

View File

@ -23,6 +23,14 @@ namespace DCFApixels.DragonECS
public int GetComponentID(Type type) => DeclareComponentType(EcsTypeCode.Get(type)); public int GetComponentID(Type type) => DeclareComponentType(EcsTypeCode.Get(type));
public bool IsComponentTypeDeclared<T>() => _componentIds.Contains(EcsTypeCode.Get<T>()); public bool IsComponentTypeDeclared<T>() => _componentIds.Contains(EcsTypeCode.Get<T>());
public bool IsComponentTypeDeclared(Type type) => _componentIds.Contains(EcsTypeCode.Get(type)); public bool IsComponentTypeDeclared(Type type) => _componentIds.Contains(EcsTypeCode.Get(type));
public bool IsComponentTypeDeclared(int componentTypeID)
{
if (componentTypeID >= 0 && componentTypeID < _pools.Length)
{
return _pools[componentTypeID] != _nullPool;
}
return false;
}
public Type GetComponentType(int componentID) => _pools[componentID].ComponentType; public Type GetComponentType(int componentID) => _pools[componentID].ComponentType;
#endregion #endregion

View File

@ -22,13 +22,14 @@ namespace DCFApixels.DragonECS
private const int DEL_ENT_BUFFER_MIN_SIZE = 64; private const int DEL_ENT_BUFFER_MIN_SIZE = 64;
private static EcsWorld[] Worlds = new EcsWorld[4]; private static EcsWorld[] Worlds = new EcsWorld[4];
private static IdDispenser _worldIdDispenser = new IdDispenser(0); private static IdDispenser _worldIdDispenser = new IdDispenser(4);
private static List<DataReleaser> _dataReleaseres = new List<DataReleaser>(); private static List<DataReleaser> _dataReleaseres = new List<DataReleaser>();
//public static int Copacity => Worlds.Length;
static EcsWorld() static EcsWorld()
{ {
Worlds[0] = new EcsNullWorld(); Worlds[0] = new NullWorld();
} }
private static void ReleaseData(int worldID) private static void ReleaseData(int worldID)
{ {
@ -41,7 +42,7 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T GetData<T>(int worldID) => ref WorldComponentPool<T>.GetForWorld(worldID); public static ref T GetData<T>(int worldID) => ref WorldComponentPool<T>.GetForWorld(worldID);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T UncheckedGetData<T>(int worldID) => ref WorldComponentPool<T>.GetForWorldUnchecked(worldID); public static ref T GetDataUnchecked<T>(int worldID) => ref WorldComponentPool<T>.GetForWorldUnchecked(worldID);
private abstract class DataReleaser private abstract class DataReleaser
{ {
@ -81,9 +82,7 @@ namespace DCFApixels.DragonECS
if (_mapping.Length < Worlds.Length) if (_mapping.Length < Worlds.Length)
{ {
Array.Resize(ref _mapping, Worlds.Length); Array.Resize(ref _mapping, Worlds.Length);
} }
ref short itemIndex = ref _mapping[worldID]; ref short itemIndex = ref _mapping[worldID];
if (itemIndex <= 0) if (itemIndex <= 0)
{ {
@ -122,9 +121,9 @@ namespace DCFApixels.DragonECS
} }
} }
} }
} private sealed class NullWorld : EcsWorld
internal sealed class EcsNullWorld : EcsWorld {
{ internal NullWorld() : base(EmptyConfig.Instance, false) { }
internal EcsNullWorld() : base(false) { } }
} }
} }

128
src/EcsWorldConfig.cs Normal file
View File

@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
namespace DCFApixels.DragonECS
{
public interface IEcsWorldConfig
{
bool IsLocked { get; }
void Lock();
void Set<T>(string valueName, T value);
bool Has(string valueName);
T Get<T>(string valueName);
bool TryGet<T>(string valueName, out T value);
void Remove(string valueName);
}
public class EcsWorldConfig : IEcsWorldConfig
{
private Dictionary<string, object> _storage = new Dictionary<string, object>();
private bool _isLocked = false;
public bool IsLocked { get { return _isLocked; } }
public void Lock()
{
_isLocked = true;
}
public T Get<T>(string valueName)
{
return (T)_storage[valueName];
}
public bool Has(string valueName)
{
return _storage.ContainsKey(valueName);
}
public void Remove(string valueName)
{
if (_isLocked)
{
throw new InvalidOperationException();
}
_storage.Remove(valueName);
}
public void Set<T>(string valueName, T value)
{
if (_isLocked)
{
throw new InvalidOperationException();
}
_storage[valueName] = value;
}
public bool TryGet<T>(string valueName, out T value)
{
bool result = _storage.TryGetValue(valueName, out object rawValue);
value = rawValue == null ? default : (T)rawValue;
return result;
}
}
public static class EcsWorldConfigExtensions
{
public static T GetOrDefault<T>(this IEcsWorldConfig self, string valueName, T defaultValue)
{
if (self.TryGet(valueName, out T value))
{
return value;
}
return defaultValue;
}
private const string ENTITIES_CAPACITY = nameof(ENTITIES_CAPACITY);
private const int ENTITIES_CAPACITY_DEFAULT = 512;
public static TConfig Set_EntitiesCapacity<TConfig>(this TConfig self, int value)
where TConfig : IEcsWorldConfig
{
self.Set(ENTITIES_CAPACITY, value);
return self;
}
public static int Get_EntitiesCapacity(this IEcsWorldConfig self)
{
return self.GetOrDefault(ENTITIES_CAPACITY, ENTITIES_CAPACITY_DEFAULT);
}
//private const string RECYCLED_ENTITIES_CAPACITY = nameof(RECYCLED_ENTITIES_CAPACITY);
//public static void Set_RecycledEntitiesCapacity(this IEcsWorldConfig self, int value)
//{
// self.Set(RECYCLED_ENTITIES_CAPACITY, value);
//}
//public static int Get_RecycledEntitiesCapacity(this IEcsWorldConfig self)
//{
// return self.GetOrDefault(RECYCLED_ENTITIES_CAPACITY, self.Get_EntitiesCapacity() / 2);
//}
private const string POOLS_CAPACITY = nameof(POOLS_CAPACITY);
private const int POOLS_CAPACITY_DEFAULT = 512;
public static TConfig Set_PoolsCapacity<TConfig>(this TConfig self, int value)
where TConfig : IEcsWorldConfig
{
self.Set(POOLS_CAPACITY, value);
return self;
}
public static int Get_PoolsCapacity(this IEcsWorldConfig self)
{
return self.GetOrDefault(POOLS_CAPACITY, POOLS_CAPACITY_DEFAULT);
}
private const string COMPONENT_POOL_CAPACITY = nameof(COMPONENT_POOL_CAPACITY);
private const int COMPONENT_POOL_CAPACITY_DEFAULT = 512;
public static TConfig Set_PoolComponentsCapacity<TConfig>(this TConfig self, int value)
where TConfig : IEcsWorldConfig
{
self.Set(COMPONENT_POOL_CAPACITY, value);
return self;
}
public static int Get_PoolComponentsCapacity(this IEcsWorldConfig self)
{
return self.GetOrDefault(COMPONENT_POOL_CAPACITY, COMPONENT_POOL_CAPACITY_DEFAULT);
}
private const string POOL_RECYCLED_COMPONENTS_CAPACITY = nameof(POOL_RECYCLED_COMPONENTS_CAPACITY);
public static TConfig Set_PoolRecycledComponentsCapacity<TConfig>(this TConfig self, int value)
where TConfig : IEcsWorldConfig
{
self.Set(POOL_RECYCLED_COMPONENTS_CAPACITY, value);
return self;
}
public static int Get_PoolRecycledComponentsCapacity(this IEcsWorldConfig self)
{
return self.GetOrDefault(POOL_RECYCLED_COMPONENTS_CAPACITY, self.Get_PoolComponentsCapacity() / 2);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0bd5947405343044b9e716c787ad4945
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -71,7 +71,9 @@ namespace DCFApixels.DragonECS
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
_listeners.InvokeOnAdd(entityID); _listeners.InvokeOnAdd(entityID);
if (isMain) if (isMain)
{
component.OnAddToPool(_source.GetEntityLong(entityID)); component.OnAddToPool(_source.GetEntityLong(entityID));
}
_items[itemIndex] = component; _items[itemIndex] = component;
_entities[itemIndex] = entityID; _entities[itemIndex] = entityID;
} }
@ -122,9 +124,13 @@ namespace DCFApixels.DragonECS
ref int itemIndex = ref _mapping[entityID]; ref int itemIndex = ref _mapping[entityID];
T component = _items[itemIndex]; T component = _items[itemIndex];
if (isMain) if (isMain)
{
component.OnDelFromPool(_source.GetEntityLong(entityID)); component.OnDelFromPool(_source.GetEntityLong(entityID));
}
if (_recycledItemsCount >= _recycledItems.Length) if (_recycledItemsCount >= _recycledItems.Length)
{
Array.Resize(ref _recycledItems, _recycledItems.Length << 1); Array.Resize(ref _recycledItems, _recycledItems.Length << 1);
}
_recycledItems[_recycledItemsCount++] = itemIndex; _recycledItems[_recycledItemsCount++] = itemIndex;
_mapping[entityID] = 0; _mapping[entityID] = 0;
_entities[itemIndex] = 0; _entities[itemIndex] = 0;
@ -138,7 +144,9 @@ namespace DCFApixels.DragonECS
HybridMapping mapping = _source.GetHybridMapping(component.GetType()); HybridMapping mapping = _source.GetHybridMapping(component.GetType());
mapping.GetTargetTypePool().DelInternal(entityID, true); mapping.GetTargetTypePool().DelInternal(entityID, true);
foreach (var pool in mapping.GetPools()) foreach (var pool in mapping.GetPools())
{
pool.DelInternal(entityID, false); pool.DelInternal(entityID, false);
}
} }
public void TryDel(int entityID) public void TryDel(int entityID)
{ {

View File

@ -1,3 +1,4 @@
using DCFApixels.DragonECS.Internal;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
@ -20,7 +21,9 @@ namespace DCFApixels.DragonECS
private int _recycledItemsCount; private int _recycledItemsCount;
private IEcsComponentReset<T> _componentResetHandler = EcsComponentResetHandler<T>.instance; private IEcsComponentReset<T> _componentResetHandler = EcsComponentResetHandler<T>.instance;
private bool _isHasComponentResetHandler = EcsComponentResetHandler<T>.isHasHandler;
private IEcsComponentCopy<T> _componentCopyHandler = EcsComponentCopyHandler<T>.instance; private IEcsComponentCopy<T> _componentCopyHandler = EcsComponentCopyHandler<T>.instance;
private bool _isHasComponentCopyHandler = EcsComponentCopyHandler<T>.isHasHandler;
private List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>(); private List<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
@ -54,6 +57,7 @@ namespace DCFApixels.DragonECS
} }
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
_listeners.InvokeOnAddAndGet(entityID); _listeners.InvokeOnAddAndGet(entityID);
ResetComponent(ref _items[itemIndex]);
return ref _items[itemIndex]; return ref _items[itemIndex];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -93,6 +97,7 @@ namespace DCFApixels.DragonECS
_listeners.InvokeOnAdd(entityID); _listeners.InvokeOnAdd(entityID);
} }
_listeners.InvokeOnGet(entityID); _listeners.InvokeOnGet(entityID);
ResetComponent(ref _items[itemIndex]);
return ref _items[itemIndex]; return ref _items[itemIndex];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -106,9 +111,11 @@ namespace DCFApixels.DragonECS
if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); if (!Has(entityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID);
#endif #endif
ref int itemIndex = ref _mapping[entityID]; ref int itemIndex = ref _mapping[entityID];
_componentResetHandler.Reset(ref _items[itemIndex]); ResetComponent(ref _items[itemIndex]);
if (_recycledItemsCount >= _recycledItems.Length) if (_recycledItemsCount >= _recycledItems.Length)
{
Array.Resize(ref _recycledItems, _recycledItems.Length << 1); Array.Resize(ref _recycledItems, _recycledItems.Length << 1);
}
_recycledItems[_recycledItemsCount++] = itemIndex; _recycledItems[_recycledItemsCount++] = itemIndex;
_mapping[entityID] = 0; _mapping[entityID] = 0;
_itemsCount--; _itemsCount--;
@ -124,14 +131,14 @@ namespace DCFApixels.DragonECS
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID); if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID);
#endif #endif
_componentCopyHandler.Copy(ref Get(fromEntityID), ref TryAddOrGet(toEntityID)); CopyComponent(ref Get(fromEntityID), ref TryAddOrGet(toEntityID));
} }
public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID)
{ {
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID); if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent<T>(fromEntityID);
#endif #endif
_componentCopyHandler.Copy(ref Get(fromEntityID), ref toWorld.GetPool<T>().TryAddOrGet(toEntityID)); CopyComponent(ref Get(fromEntityID), ref toWorld.GetPool<T>().TryAddOrGet(toEntityID));
} }
#endregion #endregion
@ -143,12 +150,10 @@ namespace DCFApixels.DragonECS
_componentTypeID = componentTypeID; _componentTypeID = componentTypeID;
_maskBit = EcsMaskChunck.FromID(componentTypeID); _maskBit = EcsMaskChunck.FromID(componentTypeID);
const int capacity = 512;
_mapping = new int[world.Capacity]; _mapping = new int[world.Capacity];
_recycledItems = new int[128]; _recycledItems = new int[world.Config.Get_PoolRecycledComponentsCapacity()];
_recycledItemsCount = 0; _recycledItemsCount = 0;
_items = new T[capacity]; _items = new T[ArrayUtility.NormalizeSizeToPowerOfTwo(world.Config.Get_PoolComponentsCapacity())];
_itemsCount = 0; _itemsCount = 0;
} }
void IEcsPoolImplementation.OnWorldResize(int newSize) void IEcsPoolImplementation.OnWorldResize(int newSize)
@ -159,7 +164,9 @@ namespace DCFApixels.DragonECS
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
{ {
foreach (var entityID in buffer) foreach (var entityID in buffer)
{
TryDel(entityID); TryDel(entityID);
}
} }
#endregion #endregion
@ -184,6 +191,33 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
#region Reset/Copy
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ResetComponent(ref T component)
{
if (_isHasComponentResetHandler)
{
_componentResetHandler.Reset(ref component);
}
else
{
component = default;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void CopyComponent(ref T from, ref T to)
{
if (_isHasComponentCopyHandler)
{
_componentCopyHandler.Copy(ref from, ref to);
}
else
{
to = from;
}
}
#endregion
#region IEnumerator - IntelliSense hack #region IEnumerator - IntelliSense hack
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException(); IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();

View File

@ -5,18 +5,61 @@ using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace DCFApixels.DragonECS.Utils namespace DCFApixels.DragonECS.Internal
{ {
internal static class ArrayUtility internal static class ArrayUtility
{ {
private static int GetHighBitNumber(uint bits)
{
if (bits == 0)
{
return -1;
}
int bit = 0;
if ((bits & 0xFFFF0000) != 0)
{
bits >>= 16;
bit |= 16;
}
if ((bits & 0xFF00) != 0)
{
bits >>= 8;
bit |= 8;
}
if ((bits & 0xF0) != 0)
{
bits >>= 4;
bit |= 4;
}
if ((bits & 0xC) != 0)
{
bits >>= 2;
bit |= 2;
}
if ((bits & 0x2) != 0)
{
bit |= 1;
}
return bit;
}
public static int NormalizeSizeToPowerOfTwo(int minSize)
{
return 1 << (GetHighBitNumber((uint)minSize - 1u) + 1);
}
public static void Fill<T>(T[] array, T value, int startIndex = 0, int length = -1) public static void Fill<T>(T[] array, T value, int startIndex = 0, int length = -1)
{ {
if (length < 0) if (length < 0)
{
length = array.Length; length = array.Length;
}
else else
{
length = startIndex + length; length = startIndex + length;
}
for (int i = startIndex; i < length; i++) for (int i = startIndex; i < length; i++)
{
array[i] = value; array[i] = value;
}
} }
} }
internal readonly struct EnumerableInt : IEnumerable<int> internal readonly struct EnumerableInt : IEnumerable<int>
@ -113,7 +156,9 @@ namespace DCFApixels.DragonECS.Utils
{ {
T* clone = New<T>(length); T* clone = New<T>(length);
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{
clone[i] = sourcePtr[i]; clone[i] = sourcePtr[i];
}
return clone; return clone;
} }

View File

@ -2,89 +2,95 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Serialization; using System.Runtime.Serialization;
namespace DCFApixels.DragonECS
namespace DCFApixels.DragonECS.Internal
{ {
namespace Internal internal static class Throw
{ {
internal static class Throw [MethodImpl(MethodImplOptions.NoInlining)]
internal static void ArgumentNull()
{ {
[MethodImpl(MethodImplOptions.NoInlining)] throw new ArgumentNullException();
internal static void ArgumentNull() }
{
throw new ArgumentNullException();
}
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void ConstraintIsAlreadyContainedInMask(Type type) internal static void ConstraintIsAlreadyContainedInMask(Type type)
{ {
throw new EcsFrameworkException($"The {EcsDebugUtility.GetGenericTypeName(type)} constraint is already contained in the mask."); throw new EcsFrameworkException($"The {EcsDebugUtility.GetGenericTypeName(type)} constraint is already contained in the mask.");
} }
//[MethodImpl(MethodImplOptions.NoInlining)] //[MethodImpl(MethodImplOptions.NoInlining)]
//public static void ArgumentDifferentWorldsException() //public static void ArgumentDifferentWorldsException()
//{ //{
// throw new ArgumentException("The groups belong to different worlds."); // throw new ArgumentException("The groups belong to different worlds.");
//} //}
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void ArgumentOutOfRange() internal static void ArgumentOutOfRange()
{ {
throw new ArgumentOutOfRangeException($"index is less than 0 or is equal to or greater than Count."); throw new ArgumentOutOfRangeException($"index is less than 0 or is equal to or greater than Count.");
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void Group_AlreadyContains(int entityID) internal static void Group_AlreadyContains(int entityID)
{ {
throw new EcsFrameworkException($"This group already contains entity {entityID}."); throw new EcsFrameworkException($"This group already contains entity {entityID}.");
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void Group_DoesNotContain(int entityID) internal static void Group_DoesNotContain(int entityID)
{ {
throw new EcsFrameworkException($"This group does not contain entity {entityID}."); throw new EcsFrameworkException($"This group does not contain entity {entityID}.");
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void Group_ArgumentDifferentWorldsException() internal static void Group_ArgumentDifferentWorldsException()
{ {
throw new ArgumentException("The groups belong to different worlds."); throw new ArgumentException("The groups belong to different worlds.");
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void Pipeline_MethodCalledAfterInitialisation(string methodName) internal static void Pipeline_MethodCalledAfterInitialisation(string methodName)
{ {
throw new MethodAccessException($"It is forbidden to call {methodName}, after initialization {nameof(EcsPipeline)}."); throw new MethodAccessException($"It is forbidden to call {methodName}, after initialization {nameof(EcsPipeline)}.");
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void Pipeline_MethodCalledBeforeInitialisation(string methodName) internal static void Pipeline_MethodCalledBeforeInitialisation(string methodName)
{ {
throw new MethodAccessException($"It is forbidden to call {methodName}, before initialization {nameof(EcsPipeline)}."); throw new MethodAccessException($"It is forbidden to call {methodName}, before initialization {nameof(EcsPipeline)}.");
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void Pipeline_MethodCalledAfterDestruction(string methodName) internal static void Pipeline_MethodCalledAfterDestruction(string methodName)
{ {
throw new MethodAccessException($"It is forbidden to call {methodName}, after destroying {nameof(EcsPipeline)}."); throw new MethodAccessException($"It is forbidden to call {methodName}, after destroying {nameof(EcsPipeline)}.");
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void World_InvalidIncrementComponentsBalance() internal static void World_InvalidIncrementComponentsBalance()
{ {
throw new MethodAccessException("Invalid increment components balance."); throw new MethodAccessException("Invalid increment components balance.");
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void World_GroupDoesNotBelongWorld() internal static void World_GroupDoesNotBelongWorld()
{ {
throw new MethodAccessException("The Group does not belong in this world."); throw new MethodAccessException("The Group does not belong in this world.");
} }
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
internal static void Ent_ThrowIsNotAlive(entlong entity) internal static void Ent_ThrowIsNotAlive(entlong entity)
{ {
if (entity.IsNull) if (entity.IsNull)
throw new EcsFrameworkException($"The {entity} is null."); throw new EcsFrameworkException($"The {entity} is null.");
else else
throw new EcsFrameworkException($"The {entity} is not alive."); throw new EcsFrameworkException($"The {entity} is not alive.");
} }
[MethodImpl(MethodImplOptions.NoInlining)]
internal static void UndefinedException()
{
throw new Exception();
} }
} }
}
namespace DCFApixels.DragonECS
{
[Serializable] [Serializable]
public class EcsFrameworkException : Exception public class EcsFrameworkException : Exception
{ {

View File

@ -14,12 +14,7 @@ namespace DCFApixels.DragonECS.Utils
#endregion #endregion
#region Constructor #region Constructor
public IntDispenser() public IntDispenser(int startIncrement = 0)
{
_freeInts = new ConcurrentQueue<int>();
_increment = 0;
}
public IntDispenser(int startIncrement)
{ {
_freeInts = new ConcurrentQueue<int>(); _freeInts = new ConcurrentQueue<int>();
_increment = startIncrement; _increment = startIncrement;

View File

@ -1,4 +1,5 @@
#pragma warning disable IDE1006 #pragma warning disable IDE1006
#pragma warning disable CS8981
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Internal;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -154,9 +155,27 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator entlong(long a) => new entlong(a); public static explicit operator entlong(long a) => new entlong(a);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator int(entlong a) => a.ID; public static explicit operator int(entlong a) => a.ID;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Deconstruct(out int id, out int gen, out int world)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!IsAlive) Throw.Ent_ThrowIsNotAlive(this);
#endif
id = this.id;
gen = this.gen;
world = this.world;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Deconstruct(out int id, out int world)
{
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (!IsAlive) Throw.Ent_ThrowIsNotAlive(this);
#endif
id = this.id;
world = this.world;
}
#endregion #endregion
#region Other #region Other