mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44:35 +08:00
Merge branch 'new_dev'
This commit is contained in:
commit
374afe75a9
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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++)
|
||||||
|
@ -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();
|
||||||
|
124
src/EcsMask.cs
124
src/EcsMask.cs
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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()
|
||||||
{
|
{
|
||||||
|
180
src/EcsWorld.cs
180
src/EcsWorld.cs
@ -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
|
||||||
}
|
}
|
@ -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
|
||||||
|
|
||||||
|
@ -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
128
src/EcsWorldConfig.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/EcsWorldConfig.cs.meta
Normal file
11
src/EcsWorldConfig.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0bd5947405343044b9e716c787ad4945
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user