This commit is contained in:
Mikhail 2024-01-11 00:48:39 +08:00
parent bf9809f3e6
commit 6ebda350a3
5 changed files with 132 additions and 59 deletions

View File

@ -1,7 +1,26 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static DCFApixels.DragonECS.Internal.DataInterfaceHalper;
namespace DCFApixels.DragonECS.Internal
{
#region DataInterfaceHalper
public static class DataInterfaceHalper
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CheckFakeInstanceValide<T>(T fakeInstnace)
{
#if DEBUG
if (fakeInstnace.Equals(default) == false)
{
throw new Exception("Не правильное применение интерфейса, менять нужно передаваемое по ref значение");
}
#endif
}
}
#endregion
}
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
#region IEcsWorldComponent #region IEcsWorldComponent
@ -34,13 +53,22 @@ 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> internal sealed class WorldComponentHandler<T> : IEcsWorldComponent<T>
where T : IEcsWorldComponent<T> where T : struct, IEcsWorldComponent<T>
{ {
private T _fakeInstnace = default; private T _fakeInstnace = default;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Init(ref T component, EcsWorld world) => _fakeInstnace.Init(ref component, world); public void Init(ref T component, EcsWorld world)
public void OnDestroy(ref T component, EcsWorld world) => _fakeInstnace.OnDestroy(ref component, world); {
_fakeInstnace.Init(ref component, world);
CheckFakeInstanceValide(_fakeInstnace);
}
public void OnDestroy(ref T component, EcsWorld world)
{
_fakeInstnace.OnDestroy(ref component, world);
CheckFakeInstanceValide(_fakeInstnace);
}
} }
#endregion #endregion
@ -77,7 +105,11 @@ namespace DCFApixels.DragonECS
{ {
private T _fakeInstnace = default; private T _fakeInstnace = default;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset(ref T component) => _fakeInstnace.Reset(ref component); public void Reset(ref T component)
{
_fakeInstnace.Reset(ref component);
CheckFakeInstanceValide(_fakeInstnace);
}
} }
#endregion #endregion
@ -114,7 +146,11 @@ namespace DCFApixels.DragonECS
{ {
private T _fakeInstnace = default; private T _fakeInstnace = default;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Copy(ref T from, ref T to) => _fakeInstnace.Copy(ref from, ref to); public void Copy(ref T from, ref T to)
{
_fakeInstnace.Copy(ref from, ref to);
CheckFakeInstanceValide(_fakeInstnace);
}
} }
#endregion #endregion
} }

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

@ -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

@ -81,9 +81,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)
{ {