refactoring

This commit is contained in:
Mikhail 2024-11-01 12:41:10 +08:00
parent 02834d6826
commit 45acde2db3
8 changed files with 542 additions and 487 deletions

View File

@ -1,10 +1,12 @@
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Core;
using DCFApixels.DragonECS.Internal;
using DCFApixels.DragonECS.PoolsCore; using DCFApixels.DragonECS.PoolsCore;
using System; using System;
using System.Collections.Generic;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public abstract class EcsAspect : ITemplateNode, IEcsComponentMask public abstract class EcsAspect : ITemplateNode, IComponentMask
{ {
#region Initialization Halpers #region Initialization Halpers
[ThreadStatic] [ThreadStatic]
@ -40,6 +42,9 @@ namespace DCFApixels.DragonECS
internal EcsMask _mask; internal EcsMask _mask;
private bool _isBuilt = false; private bool _isBuilt = false;
//Инициализация аспектов проходит в синхронизированном состоянии, поэтому использование _staticMaskCache потоко безопасно.
private static Dictionary<Type, EcsStaticMask> _staticMaskCache = new Dictionary<Type, EcsStaticMask>();
#region Properties #region Properties
public EcsMask Mask public EcsMask Mask
{ {
@ -53,6 +58,13 @@ namespace DCFApixels.DragonECS
{ {
get { return _isBuilt; } get { return _isBuilt; }
} }
/// <summary>
/// Статическая инициализация означет что каждый новый эекземпляр идентичен другому, инициализация стандартным путем создает идентичные экземпляры, поэтому значение по умолчанию true.
/// </summary>
protected virtual bool IsStaticInitialization
{
get { return true; }
}
#endregion #endregion
#region Methods #region Methods
@ -90,19 +102,14 @@ namespace DCFApixels.DragonECS
#region Constructors/New #region Constructors/New
private Builder() { } private Builder() { }
private void Reset(EcsWorld world)
{
_maskBuilder = EcsStaticMask.New();
_world = world;
}
internal static unsafe TAspect New<TAspect>(EcsWorld world) where TAspect : EcsAspect, new() internal static unsafe TAspect New<TAspect>(EcsWorld world) where TAspect : EcsAspect, new()
{ {
//Get Builder
if (_constructorBuildersStack == null) if (_constructorBuildersStack == null)
{ {
_constructorBuildersStack = new Builder[4]; _constructorBuildersStack = new Builder[4];
_constructorBuildersStackIndex = -1; _constructorBuildersStackIndex = -1;
} }
_constructorBuildersStackIndex++; _constructorBuildersStackIndex++;
if (_constructorBuildersStackIndex >= _constructorBuildersStack.Length) if (_constructorBuildersStackIndex >= _constructorBuildersStack.Length)
{ {
@ -114,16 +121,34 @@ namespace DCFApixels.DragonECS
builder = new Builder(); builder = new Builder();
_constructorBuildersStack[_constructorBuildersStackIndex] = builder; _constructorBuildersStack[_constructorBuildersStackIndex] = builder;
} }
builder.Reset(world);
//Setup Builder
EcsStaticMask staticMask = null;
if (_staticMaskCache.TryGetValue(typeof(TAspect), out staticMask) == false)
{
builder._maskBuilder = EcsStaticMask.New();
}
builder._world = world;
//Building
TAspect newAspect = new TAspect(); TAspect newAspect = new TAspect();
newAspect.Init(builder);
_constructorBuildersStackIndex--;
newAspect._source = world; newAspect._source = world;
builder.Build(out newAspect._mask); newAspect.Init(builder);
//Build Mask
if (staticMask == null)
{
staticMask = builder._maskBuilder.Build();
builder._maskBuilder = default;
if (newAspect.IsStaticInitialization)
{
_staticMaskCache.Add(typeof(TAspect), staticMask);
}
}
newAspect._mask = staticMask.ToMask(world);
newAspect._isBuilt = true; newAspect._isBuilt = true;
_constructorBuildersStackIndex--;
return newAspect; return newAspect;
} }
#endregion #endregion
@ -148,34 +173,38 @@ namespace DCFApixels.DragonECS
private void IncludeImplicit(Type type) private void IncludeImplicit(Type type)
{ {
_maskBuilder.Inc(type); if (_maskBuilder.IsNull == false)
{
_maskBuilder.Inc(type);
}
} }
private void ExcludeImplicit(Type type) private void ExcludeImplicit(Type type)
{ {
_maskBuilder.Exc(type); if (_maskBuilder.IsNull == false)
{
_maskBuilder.Exc(type);
}
} }
public TOtherAspect Combine<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect, new() public TOtherAspect Combine<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect, new()
{ {
var result = _world.GetAspect<TOtherAspect>(); var result = _world.GetAspect<TOtherAspect>();
_maskBuilder.Combine(result.Mask._staticMask); if (_maskBuilder.IsNull == false)
{
_maskBuilder.Combine(result.Mask._staticMask);
}
return result; return result;
} }
public TOtherAspect Except<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect, new() public TOtherAspect Except<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect, new()
{ {
var result = _world.GetAspect<TOtherAspect>(); var result = _world.GetAspect<TOtherAspect>();
_maskBuilder.Except(result.Mask._staticMask); if (_maskBuilder.IsNull == false)
{
_maskBuilder.Except(result.Mask._staticMask);
}
return result; return result;
} }
#endregion #endregion
#region Build
private void Build(out EcsMask mask)
{
mask = _maskBuilder.Build().ToMask(_world);
}
#endregion
#region SupportReflectionHack #region SupportReflectionHack
#if UNITY_2020_3_OR_NEWER #if UNITY_2020_3_OR_NEWER
[UnityEngine.Scripting.Preserve] [UnityEngine.Scripting.Preserve]
@ -205,7 +234,43 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
#region Iterator #region Template
public virtual void Apply(short worldID, int entityID)
{
EcsWorld world = EcsWorld.GetWorld(worldID);
foreach (var incTypeID in _mask._incs)
{
var pool = world.FindPoolInstance(incTypeID);
if (pool != null)
{
if (pool.Has(entityID) == false)
{
pool.AddRaw(entityID, null);
}
}
#if DEBUG
else
{
EcsDebug.PrintWarning("Component has not been added because the pool has not been initialized yet.");
}
#endif
}
foreach (var excTypeID in _mask._excs)
{
var pool = world.FindPoolInstance(excTypeID);
if (pool != null && pool.Has(entityID))
{
pool.Del(entityID);
}
}
}
#endregion
#region Other
EcsMask IComponentMask.ToMask(EcsWorld world) { return _mask; }
#endregion
#region Obsolete
[Obsolete("Use EcsMask.GetIterator()")] [Obsolete("Use EcsMask.GetIterator()")]
public Iterator GetIterator() public Iterator GetIterator()
{ {
@ -252,42 +317,6 @@ namespace DCFApixels.DragonECS
} }
} }
#endregion #endregion
#region Template
public virtual void Apply(short worldID, int entityID)
{
EcsWorld world = EcsWorld.GetWorld(worldID);
foreach (var incTypeID in _mask._inc)
{
var pool = world.FindPoolInstance(incTypeID);
if (pool != null)
{
if (pool.Has(entityID) == false)
{
pool.AddRaw(entityID, null);
}
}
#if DEBUG
else
{
EcsDebug.PrintWarning("Component has not been added because the pool has not been initialized yet.");
}
#endif
}
foreach (var excTypeID in _mask._exc)
{
var pool = world.FindPoolInstance(excTypeID);
if (pool != null && pool.Has(entityID))
{
pool.Del(entityID);
}
}
}
#endregion
#region Other
EcsMask IEcsComponentMask.ToMask(EcsWorld world) { return _mask; }
#endregion
} }
#region EcsAspectExtensions #region EcsAspectExtensions

View File

@ -1,6 +1,8 @@
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Core;
using DCFApixels.DragonECS.Internal;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -8,74 +10,69 @@ using System.Runtime.CompilerServices;
using Unity.IL2CPP.CompilerServices; using Unity.IL2CPP.CompilerServices;
#endif #endif
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS.Core
{ {
using static EcsMaskIteratorUtility; public interface IComponentMask
public interface IEcsComponentMask
{ {
EcsMask ToMask(EcsWorld world); EcsMask ToMask(EcsWorld world);
} }
}
namespace DCFApixels.DragonECS
{
using static EcsMaskIteratorUtility;
#if ENABLE_IL2CPP #if ENABLE_IL2CPP
[Il2CppSetOption (Option.NullChecks, false)] [Il2CppSetOption (Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif #endif
[DebuggerTypeProxy(typeof(DebuggerProxy))] [DebuggerTypeProxy(typeof(DebuggerProxy))]
public sealed class EcsMask : IEquatable<EcsMask>, IEcsComponentMask public sealed class EcsMask : IEquatable<EcsMask>, IComponentMask
{ {
public readonly int ID;
public readonly short WorldID;
internal readonly EcsStaticMask _staticMask; internal readonly EcsStaticMask _staticMask;
internal readonly int _id;
internal readonly short _worldID;
internal readonly EcsMaskChunck[] _incChunckMasks; internal readonly EcsMaskChunck[] _incChunckMasks;
internal readonly EcsMaskChunck[] _excChunckMasks; internal readonly EcsMaskChunck[] _excChunckMasks;
/// <summary> Sorted </summary> /// <summary> Sorted </summary>
internal readonly int[] _inc; internal readonly int[] _incs;
/// <summary> Sorted </summary> /// <summary> Sorted </summary>
internal readonly int[] _exc; internal readonly int[] _excs;
private EcsMaskIterator _iterator; private EcsMaskIterator _iterator;
#region Properties #region Properties
public int ID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _id; }
}
public short WorldID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _worldID; }
}
public EcsWorld World public EcsWorld World
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return EcsWorld.GetWorld(_worldID); } get { return EcsWorld.GetWorld(WorldID); }
}
/// <summary> Sorted set including constraints. </summary>
public ReadOnlySpan<int> Inc
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _inc; }
} }
/// <summary> Sorted set excluding constraints. </summary> /// <summary> Sorted set excluding constraints. </summary>
public ReadOnlySpan<int> Exc public ReadOnlySpan<int> Incs
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _exc; } get { return _incs; }
}
/// <summary> Sorted set excluding constraints. </summary>
public ReadOnlySpan<int> Excs
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _excs; }
} }
public bool IsEmpty public bool IsEmpty
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _inc.Length == 0 && _exc.Length == 0; } get { return _incs.Length == 0 && _excs.Length == 0; }
} }
public bool IsBroken public bool IsBroken
{ {
get { return (_inc.Length & _exc.Length) == 1 && _inc[0] == _exc[0]; } get { return (_incs.Length & _excs.Length) == 1 && _incs[0] == _excs[0]; }
} }
#endregion #endregion
#region Constructors #region Constructors
[Obsolete("")]//TODO написать новый сопсоб создания
public static Builder New(EcsWorld world) { return new Builder(world); } public static Builder New(EcsWorld world) { return new Builder(world); }
internal static EcsMask CreateEmpty(int id, short worldID) internal static EcsMask CreateEmpty(int id, short worldID)
{ {
@ -88,10 +85,10 @@ namespace DCFApixels.DragonECS
private EcsMask(EcsStaticMask staticMask, int id, short worldID, int[] inc, int[] exc) private EcsMask(EcsStaticMask staticMask, int id, short worldID, int[] inc, int[] exc)
{ {
_staticMask = staticMask; _staticMask = staticMask;
_id = id; ID = id;
_inc = inc; _incs = inc;
_exc = exc; _excs = exc;
_worldID = worldID; WorldID = worldID;
_incChunckMasks = MakeMaskChuncsArray(inc); _incChunckMasks = MakeMaskChuncsArray(inc);
_excChunckMasks = MakeMaskChuncsArray(exc); _excChunckMasks = MakeMaskChuncsArray(exc);
@ -131,114 +128,230 @@ namespace DCFApixels.DragonECS
#region Checks #region Checks
public bool IsSubmaskOf(EcsMask otherMask) public bool IsSubmaskOf(EcsMask otherMask)
{ {
return IsSubmask(otherMask, this); return _staticMask.IsSubmaskOf(otherMask._staticMask);
} }
public bool IsSupermaskOf(EcsMask otherMask) public bool IsSupermaskOf(EcsMask otherMask)
{ {
return IsSubmask(this, otherMask); return _staticMask.IsSupermaskOf(otherMask._staticMask);
} }
public bool IsConflictWith(EcsMask otherMask) public bool IsConflictWith(EcsMask otherMask)
{ {
return OverlapsArray(_inc, otherMask._exc) || OverlapsArray(_exc, otherMask._inc); return _staticMask.IsConflictWith(otherMask._staticMask);
}
private static bool OverlapsArray(int[] l, int[] r)
{
int li = 0;
int ri = 0;
while (li < l.Length && ri < r.Length)
{
if (l[li] == r[ri])
{
return true;
}
else if (l[li] < r[ri])
{
li++;
}
else
{
ri++;
}
}
return false;
}
private static bool IsSubmask(EcsMask super, EcsMask sub)
{
return IsSubarray(sub._inc, super._inc) && IsSuperarray(sub._exc, super._exc);
}
private static bool IsSubarray(int[] super, int[] sub)
{
if (super.Length < sub.Length)
{
return false;
}
int superI = 0;
int subI = 0;
while (superI < super.Length && subI < sub.Length)
{
if (super[superI] == sub[subI])
{
superI++;
}
subI++;
}
return subI == sub.Length;
}
private static bool IsSuperarray(int[] super, int[] sub)
{
if (super.Length < sub.Length)
{
return false;
}
int superI = 0;
int subI = 0;
while (superI < super.Length && subI < sub.Length)
{
if (super[superI] == sub[subI])
{
subI++;
}
superI++;
}
return subI == sub.Length;
} }
#endregion #endregion
#region Object #region Object
public override string ToString() public override string ToString()
{ {
return CreateLogString(_worldID, _inc, _exc); return CreateLogString(WorldID, _incs, _excs);
} }
public bool Equals(EcsMask mask) public bool Equals(EcsMask mask)
{ {
return _id == mask._id && _worldID == mask._worldID; return ID == mask.ID && WorldID == mask.WorldID;
} }
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return obj is EcsMask mask && _id == mask._id && Equals(mask); return obj is EcsMask mask && ID == mask.ID && Equals(mask);
} }
public override int GetHashCode() public override int GetHashCode()
{ {
return unchecked(_id ^ (_worldID * EcsConsts.MAGIC_PRIME)); return unchecked(ID ^ (WorldID * EcsConsts.MAGIC_PRIME));
} }
#endregion #endregion
#region Other #region Other
EcsMask IEcsComponentMask.ToMask(EcsWorld world) { return this; } public static EcsMask FromStatic(EcsWorld world, EcsStaticMask abstractMask)
{
return world.Get<WorldMaskComponent>().ConvertFromStatic(abstractMask);
}
EcsMask IComponentMask.ToMask(EcsWorld world) { return this; }
public EcsMaskIterator GetIterator() public EcsMaskIterator GetIterator()
{ {
if (_iterator == null) if (_iterator == null)
{ {
_iterator = new EcsMaskIterator(EcsWorld.GetWorld(_worldID), this); _iterator = new EcsMaskIterator(EcsWorld.GetWorld(WorldID), this);
} }
return _iterator; return _iterator;
} }
#endregion #endregion
#region Operators
public static EcsMask operator -(EcsMask a, EcsMask b)
{
return a.World.Get<WorldMaskComponent>().ExceptMask(a, b);
}
public static EcsMask operator -(EcsMask a, IComponentMask b)
{
return a.World.Get<WorldMaskComponent>().ExceptMask(a, b.ToMask(a.World));
}
public static EcsMask operator -(IComponentMask b, EcsMask a)
{
return a.World.Get<WorldMaskComponent>().ExceptMask(b.ToMask(a.World), a);
}
public static EcsMask operator +(EcsMask a, EcsMask b)
{
return a.World.Get<WorldMaskComponent>().CombineMask(a, b);
}
public static EcsMask operator +(EcsMask a, IComponentMask b)
{
return a.World.Get<WorldMaskComponent>().CombineMask(a, b.ToMask(a.World));
}
public static EcsMask operator +(IComponentMask b, EcsMask a)
{
return a.World.Get<WorldMaskComponent>().CombineMask(b.ToMask(a.World), a);
}
public static implicit operator EcsMask((IComponentMask mask, EcsWorld world) a)
{
return a.mask.ToMask(a.world);
}
public static implicit operator EcsMask((EcsWorld world, IComponentMask mask) a)
{
return a.mask.ToMask(a.world);
}
#endregion
#region OpMaskKey
private readonly struct OpMaskKey : IEquatable<OpMaskKey>
{
public readonly int leftMaskID;
public readonly int rightMaskID;
public readonly int operation;
public const int COMBINE_OP = 7;
public const int EXCEPT_OP = 32;
public OpMaskKey(int leftMaskID, int rightMaskID, int operation)
{
this.leftMaskID = leftMaskID;
this.rightMaskID = rightMaskID;
this.operation = operation;
}
public bool Equals(OpMaskKey other)
{
return leftMaskID == other.leftMaskID && rightMaskID == other.rightMaskID && operation == other.operation;
}
public override int GetHashCode()
{
return leftMaskID ^ (rightMaskID * operation);
}
}
#endregion
#region Builder
private readonly struct WorldMaskComponent : IEcsWorldComponent<WorldMaskComponent>
{
private readonly EcsWorld _world;
private readonly Dictionary<OpMaskKey, EcsMask> _opMasks;
private readonly SparseArray<EcsMask> _staticMasks;
public readonly EcsMask EmptyMask;
public readonly EcsMask BrokenMask;
#region Constructor/Destructor
public WorldMaskComponent(EcsWorld world)
{
_world = world;
_opMasks = new Dictionary<OpMaskKey, EcsMask>(256);
_staticMasks = new SparseArray<EcsMask>(256);
EmptyMask = CreateEmpty(_staticMasks.Count, world.ID);
_staticMasks.Add(EmptyMask._staticMask.ID, EmptyMask);
BrokenMask = CreateBroken(_staticMasks.Count, world.ID);
_staticMasks.Add(BrokenMask._staticMask.ID, BrokenMask);
}
public void Init(ref WorldMaskComponent component, EcsWorld world)
{
component = new WorldMaskComponent(world);
}
public void OnDestroy(ref WorldMaskComponent component, EcsWorld world)
{
component._opMasks.Clear();
component._staticMasks.Clear();
component = default;
}
#endregion
#region GetMask
internal EcsMask CombineMask(EcsMask a, EcsMask b)
{
int operation = OpMaskKey.COMBINE_OP;
if (_opMasks.TryGetValue(new OpMaskKey(a.ID, b.ID, operation), out EcsMask result) == false)
{
if (a.IsConflictWith(b))
{
return a.World.Get<WorldMaskComponent>().BrokenMask;
}
result = ConvertFromStatic(EcsStaticMask.New().Combine(a._staticMask).Combine(b._staticMask).Build());
_opMasks.Add(new OpMaskKey(a.ID, b.ID, operation), result);
}
return result;
}
internal EcsMask ExceptMask(EcsMask a, EcsMask b)
{
int operation = OpMaskKey.EXCEPT_OP;
if (_opMasks.TryGetValue(new OpMaskKey(a.ID, b.ID, operation), out EcsMask result) == false)
{
if (a.IsConflictWith(b))
{
return a.World.Get<WorldMaskComponent>().BrokenMask;
}
result = ConvertFromStatic(EcsStaticMask.New().Combine(a._staticMask).Except(b._staticMask).Build());
_opMasks.Add(new OpMaskKey(a.ID, b.ID, operation), result);
}
return result;
}
internal EcsMask ConvertFromStatic(EcsStaticMask staticMask)
{
int[] ConvertTypeCodeToComponentTypeID(ReadOnlySpan<EcsTypeCode> from, EcsWorld world)
{
int[] to = new int[from.Length];
for (int i = 0; i < to.Length; i++)
{
to[i] = world.DeclareOrGetComponentTypeID(from[i]);
}
Array.Sort(to);
return to;
}
if (_staticMasks.TryGetValue(staticMask.ID, out EcsMask result) == false)
{
int[] incs = ConvertTypeCodeToComponentTypeID(staticMask.IncTypeCodes, _world);
int[] excs = ConvertTypeCodeToComponentTypeID(staticMask.ExcTypeCodes, _world);
result = new EcsMask(staticMask, _staticMasks.Count, _world.ID, incs, excs);
_staticMasks.Add(staticMask.ID, result);
}
return result;
}
#endregion
}
public partial struct Builder
{
private readonly EcsStaticMask.Builder _builder;
private readonly EcsWorld _world;
public Builder(EcsWorld world)
{
_world = world;
_builder = EcsStaticMask.New();
}
public Builder Inc<T>() { _builder.Inc<T>(); return this; }
public Builder Exc<T>() { _builder.Exc<T>(); return this; }
public Builder Inc(Type type) { _builder.Inc(type); return this; }
public Builder Exc(Type type) { _builder.Exc(type); return this; }
public Builder Inc(EcsTypeCode typeCode) { _builder.Inc(typeCode); return this; }
public Builder Exc(EcsTypeCode typeCode) { _builder.Exc(typeCode); return this; }
public Builder Combine(EcsMask mask) { _builder.Combine(mask._staticMask); return this; }
public Builder Except(EcsMask mask) { _builder.Except(mask._staticMask); return this; }
public EcsMask Build() { return _world.Get<WorldMaskComponent>().ConvertFromStatic(_builder.Build()); }
}
#endregion
#region Debug utils #region Debug utils
private static string CreateLogString(short worldID, int[] inc, int[] exc) private static string CreateLogString(short worldID, int[] inc, int[] exc)
{ {
@ -271,13 +384,13 @@ namespace DCFApixels.DragonECS
{ {
_source = mask; _source = mask;
ID = mask._id; ID = mask.ID;
world = EcsWorld.GetWorld(mask._worldID); world = EcsWorld.GetWorld(mask.WorldID);
_worldID = mask._worldID; _worldID = mask.WorldID;
includedChunkMasks = mask._incChunckMasks; includedChunkMasks = mask._incChunckMasks;
excludedChunkMasks = mask._excChunckMasks; excludedChunkMasks = mask._excChunckMasks;
included = mask._inc; included = mask._incs;
excluded = mask._exc; excluded = mask._excs;
Type converter(int o) { return world.GetComponentType(o); } Type converter(int o) { return world.GetComponentType(o); }
includedTypes = included.Select(converter).ToArray(); includedTypes = included.Select(converter).ToArray();
excludedTypes = excluded.Select(converter).ToArray(); excludedTypes = excluded.Select(converter).ToArray();
@ -289,200 +402,31 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
#region Operators #region Obsolete
public static EcsMask operator -(EcsMask a, EcsMask b) /// <summary> Sorted set including constraints. </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use Incs")]
public ReadOnlySpan<int> Inc
{ {
return a.World.Get<WorldMaskComponent>().ExceptMask(a, b); [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _incs; }
} }
public static EcsMask operator -(EcsMask a, IEcsComponentMask b) /// <summary> Sorted set excluding constraints. </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use Excs")]
public ReadOnlySpan<int> Exc
{ {
return a.World.Get<WorldMaskComponent>().ExceptMask(a, b.ToMask(a.World)); [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _excs; }
} }
public static EcsMask operator -(IEcsComponentMask b, EcsMask a) public partial struct Builder
{ {
return a.World.Get<WorldMaskComponent>().ExceptMask(b.ToMask(a.World), a); [EditorBrowsable(EditorBrowsableState.Never)][Obsolete] public Builder Include<T>() { return Inc<T>(); }
} [EditorBrowsable(EditorBrowsableState.Never)][Obsolete] public Builder Exclude<T>() { return Exc<T>(); }
public static EcsMask operator +(EcsMask a, EcsMask b) [EditorBrowsable(EditorBrowsableState.Never)][Obsolete] public Builder Include(Type type) { return Inc(type); }
{ [EditorBrowsable(EditorBrowsableState.Never)][Obsolete] public Builder Exclude(Type type) { return Exc(type); }
return a.World.Get<WorldMaskComponent>().CombineMask(a, b); [EditorBrowsable(EditorBrowsableState.Never)][Obsolete] public Builder Inc(int componentTypeID) { Inc(_world.GetComponentType(componentTypeID)); return this; }
} [EditorBrowsable(EditorBrowsableState.Never)][Obsolete] public Builder Exc(int componentTypeID) { Exc(_world.GetComponentType(componentTypeID)); return this; }
public static EcsMask operator +(EcsMask a, IEcsComponentMask b)
{
return a.World.Get<WorldMaskComponent>().CombineMask(a, b.ToMask(a.World));
}
public static EcsMask operator +(IEcsComponentMask b, EcsMask a)
{
return a.World.Get<WorldMaskComponent>().CombineMask(b.ToMask(a.World), a);
}
public static implicit operator EcsMask((IEcsComponentMask mask, EcsWorld world) a)
{
return a.mask.ToMask(a.world);
}
public static implicit operator EcsMask((EcsWorld world, IEcsComponentMask mask) a)
{
return a.mask.ToMask(a.world);
}
#endregion
#region OpMaskKey
private readonly struct OpMaskKey : IEquatable<OpMaskKey>
{
public readonly int leftMaskID;
public readonly int rightMaskID;
public readonly int operation;
public const int COMBINE_OP = 7;
public const int EXCEPT_OP = 32;
public OpMaskKey(int leftMaskID, int rightMaskID, int operation)
{
this.leftMaskID = leftMaskID;
this.rightMaskID = rightMaskID;
this.operation = operation;
}
public bool Equals(OpMaskKey other)
{
return leftMaskID == other.leftMaskID &&
rightMaskID == other.rightMaskID &&
operation == other.operation;
}
public override int GetHashCode()
{
return leftMaskID ^ (rightMaskID * operation);
}
}
#endregion
#region StaticMask
public static EcsMask FromStatic(EcsWorld world, EcsStaticMask abstractMask)
{
return world.Get<WorldMaskComponent>().ConvertFromStatic(abstractMask);
}
#endregion
#region Builder
private readonly struct WorldMaskComponent : IEcsWorldComponent<WorldMaskComponent>
{
private readonly EcsWorld _world;
private readonly Dictionary<OpMaskKey, EcsMask> _opMasks;
private readonly SparseArray<EcsMask> _staticMasks;
public readonly EcsMask EmptyMask;
public readonly EcsMask BrokenMask;
#region Constructor/Destructor
public WorldMaskComponent(EcsWorld world)
{
_world = world;
_opMasks = new Dictionary<OpMaskKey, EcsMask>(256);
_staticMasks = new SparseArray<EcsMask>(256);
EmptyMask = CreateEmpty(_staticMasks.Count, world.ID);
_staticMasks.Add(EmptyMask._staticMask.ID, EmptyMask);
BrokenMask = CreateBroken(_staticMasks.Count, world.ID);
_staticMasks.Add(BrokenMask._staticMask.ID, BrokenMask);
}
public void Init(ref WorldMaskComponent component, EcsWorld world)
{
component = new WorldMaskComponent(world);
}
public void OnDestroy(ref WorldMaskComponent component, EcsWorld world)
{
component._opMasks.Clear();
component._staticMasks.Clear();
component = default;
}
#endregion
#region GetMask
internal EcsMask CombineMask(EcsMask a, EcsMask b)
{
int operation = OpMaskKey.COMBINE_OP;
if (_opMasks.TryGetValue(new OpMaskKey(a._id, b._id, operation), out EcsMask result) == false)
{
if (a.IsConflictWith(b))
{
return a.World.Get<WorldMaskComponent>().BrokenMask;
}
result = ConvertFromStatic(EcsStaticMask.New().Combine(a._staticMask).Combine(b._staticMask).Build());
_opMasks.Add(new OpMaskKey(a._id, b._id, operation), result);
}
return result;
}
internal EcsMask ExceptMask(EcsMask a, EcsMask b)
{
int operation = OpMaskKey.EXCEPT_OP;
if (_opMasks.TryGetValue(new OpMaskKey(a._id, b._id, operation), out EcsMask result) == false)
{
if (a.IsConflictWith(b))
{
return a.World.Get<WorldMaskComponent>().BrokenMask;
}
result = ConvertFromStatic(EcsStaticMask.New().Combine(a._staticMask).Except(b._staticMask).Build());
_opMasks.Add(new OpMaskKey(a._id, b._id, operation), result);
}
return result;
}
internal EcsMask ConvertFromStatic(EcsStaticMask staticMask)
{
int[] ConvertTypeCodeToComponentTypeID(ReadOnlySpan<EcsTypeCode> from, EcsWorld world)
{
int[] to = new int[from.Length];
for (int i = 0; i < to.Length; i++)
{
to[i] = world.DeclareOrGetComponentTypeID(from[i]);
}
Array.Sort(to);
return to;
}
if (_staticMasks.TryGetValue(staticMask.ID, out EcsMask result) == false)
{
int[] incs = ConvertTypeCodeToComponentTypeID(staticMask.IncTypeCodes, _world);
int[] excs = ConvertTypeCodeToComponentTypeID(staticMask.ExcTypeCodes, _world);
result = new EcsMask(staticMask, _staticMasks.Count, _world.ID, incs, excs);
_staticMasks.Add(staticMask.ID, result);
}
return result;
}
#endregion
}
[Obsolete("")]//TODO написать новый сопсоб создания
public struct Builder
{
private readonly EcsStaticMask.Builder _builder;
private readonly EcsWorld _world;
public Builder(EcsWorld world)
{
_world = world;
_builder = EcsStaticMask.Builder.New();
}
public Builder Include<T>() { return Inc<T>(); }
public Builder Exclude<T>() { return Exc<T>(); }
public Builder Include(Type type) { return Inc(type); }
public Builder Exclude(Type type) { return Exc(type); }
public Builder Inc<T>() { _builder.Inc<T>(); return this; }
public Builder Exc<T>() { _builder.Exc<T>(); return this; }
public Builder Inc(Type type) { _builder.Inc(type); return this; }
public Builder Exc(Type type) { _builder.Exc(type); return this; }
public Builder Inc(EcsTypeCode typeCode) { _builder.Inc(typeCode); return this; }
public Builder Exc(EcsTypeCode typeCode) { _builder.Exc(typeCode); return this; }
public Builder Combine(EcsMask mask) { _builder.Combine(mask._staticMask); return this; }
public Builder Except(EcsMask mask) { _builder.Except(mask._staticMask); return this; }
public Builder Inc(int componentTypeID) { Inc(_world.GetComponentType(componentTypeID)); return this; }
public Builder Exc(int componentTypeID) { Exc(_world.GetComponentType(componentTypeID)); return this; }
public EcsMask Build() { return _world.Get<WorldMaskComponent>().ConvertFromStatic(_builder.Build()); }
} }
#endregion #endregion
} }
@ -554,8 +498,8 @@ namespace DCFApixels.DragonECS
{ {
World = source; World = source;
Mask = mask; Mask = mask;
_sortIncBuffer = UnsafeArray<int>.FromArray(mask._inc); _sortIncBuffer = UnsafeArray<int>.FromArray(mask._incs);
_sortExcBuffer = UnsafeArray<int>.FromArray(mask._exc); _sortExcBuffer = UnsafeArray<int>.FromArray(mask._excs);
_sortIncChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._incChunckMasks); _sortIncChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._incChunckMasks);
_sortExcChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._excChunckMasks); _sortExcChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._excChunckMasks);
_isOnlyInc = _sortExcBuffer.Length <= 0; _isOnlyInc = _sortExcBuffer.Length <= 0;

View File

@ -1,4 +1,5 @@
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Core;
using DCFApixels.DragonECS.Internal;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -16,7 +17,7 @@ namespace DCFApixels.DragonECS
[Il2CppSetOption(Option.ArrayBoundsChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif #endif
[DebuggerTypeProxy(typeof(DebuggerProxy))] [DebuggerTypeProxy(typeof(DebuggerProxy))]
public sealed class EcsStaticMask : IEquatable<EcsStaticMask>, IEcsComponentMask public sealed class EcsStaticMask : IEquatable<EcsStaticMask>, IComponentMask
{ {
public static readonly EcsStaticMask Empty; public static readonly EcsStaticMask Empty;
public static readonly EcsStaticMask Broken; public static readonly EcsStaticMask Broken;
@ -32,42 +33,50 @@ namespace DCFApixels.DragonECS
Broken = CreateMask(new Key(new EcsTypeCode[1] { (EcsTypeCode)1 }, new EcsTypeCode[1] { (EcsTypeCode)1 })); Broken = CreateMask(new Key(new EcsTypeCode[1] { (EcsTypeCode)1 }, new EcsTypeCode[1] { (EcsTypeCode)1 }));
} }
private readonly int _id; public readonly int ID;
/// <summary> Sorted </summary> /// <summary> Sorted </summary>
private readonly EcsTypeCode[] _inc; private readonly EcsTypeCode[] _incs;
/// <summary> Sorted </summary> /// <summary> Sorted </summary>
private readonly EcsTypeCode[] _exc; private readonly EcsTypeCode[] _excs;
#region Properties #region Properties
public int ID
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _id; }
}
/// <summary> Sorted set including constraints presented as global type codes. </summary> /// <summary> Sorted set including constraints presented as global type codes. </summary>
public ReadOnlySpan<EcsTypeCode> IncTypeCodes public ReadOnlySpan<EcsTypeCode> IncTypeCodes
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _inc; } get { return _incs; }
} }
/// <summary> Sorted set excluding constraints presented as global type codes. </summary> /// <summary> Sorted set excluding constraints presented as global type codes. </summary>
public ReadOnlySpan<EcsTypeCode> ExcTypeCodes public ReadOnlySpan<EcsTypeCode> ExcTypeCodes
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _exc; } get { return _excs; }
} }
public bool IsEmpty public bool IsEmpty
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _inc.Length == 0 && _exc.Length == 0; } get { return _incs.Length == 0 && _excs.Length == 0; }
} }
public bool IsBroken public bool IsBroken
{ {
get { return (_inc.Length & _exc.Length) == 1 && _inc[0] == _exc[0]; } get { return (_incs.Length & _excs.Length) == 1 && _incs[0] == _excs[0]; }
} }
#endregion #endregion
#region Constrcutors #region Constrcutors
private EcsStaticMask(int id, Key key)
{
ID = id;
_incs = key.incs;
_excs = key.excs;
}
public static Builder New() { return Builder.New(); }
public static Builder Inc<T>() { return Builder.New().Inc<T>(); }
public static Builder Exc<T>() { return Builder.New().Exc<T>(); }
public static Builder Inc(Type type) { return Builder.New().Inc(type); }
public static Builder Exc(Type type) { return Builder.New().Exc(type); }
public static Builder Inc(EcsTypeCode typeCode) { return Builder.New().Inc(typeCode); }
public static Builder Exc(EcsTypeCode typeCode) { return Builder.New().Exc(typeCode); }
private static EcsStaticMask CreateMask(Key key) private static EcsStaticMask CreateMask(Key key)
{ {
if (_ids.TryGetValue(key, out EcsStaticMask result) == false) if (_ids.TryGetValue(key, out EcsStaticMask result) == false)
@ -83,46 +92,110 @@ namespace DCFApixels.DragonECS
} }
return result; return result;
} }
public static Builder New() { return Builder.New(); } #endregion
public static Builder Inc<T>() { return Builder.New().Inc<T>(); }
public static Builder Exc<T>() { return Builder.New().Exc<T>(); } #region Checks
public static Builder Inc(Type type) { return Builder.New().Inc(type); } public bool IsSubmaskOf(EcsStaticMask otherMask)
public static Builder Exc(Type type) { return Builder.New().Exc(type); }
public static Builder Inc(EcsTypeCode typeCode) { return Builder.New().Inc(typeCode); }
public static Builder Exc(EcsTypeCode typeCode) { return Builder.New().Exc(typeCode); }
private EcsStaticMask(int id, Key key)
{ {
_id = id; return IsSubmask(otherMask, this);
_inc = key.inc; }
_exc = key.exc; public bool IsSupermaskOf(EcsStaticMask otherMask)
{
return IsSubmask(this, otherMask);
}
public bool IsConflictWith(EcsStaticMask otherMask)
{
return OverlapsArray(_incs, otherMask._excs) || OverlapsArray(_excs, otherMask._incs);
}
private static bool IsSubmask(EcsStaticMask super, EcsStaticMask sub)
{
return IsSubarray(sub._incs, super._incs) && IsSuperarray(sub._excs, super._excs);
}
private static bool OverlapsArray(EcsTypeCode[] l, EcsTypeCode[] r)
{
int li = 0;
int ri = 0;
while (li < l.Length && ri < r.Length)
{
if (l[li] == r[ri])
{
return true;
}
else if (l[li] < r[ri])
{
li++;
}
else
{
ri++;
}
}
return false;
}
private static bool IsSubarray(EcsTypeCode[] super, EcsTypeCode[] sub)
{
if (super.Length < sub.Length)
{
return false;
}
int superI = 0;
int subI = 0;
while (superI < super.Length && subI < sub.Length)
{
if (super[superI] == sub[subI])
{
superI++;
}
subI++;
}
return subI == sub.Length;
}
private static bool IsSuperarray(EcsTypeCode[] super, EcsTypeCode[] sub)
{
if (super.Length < sub.Length)
{
return false;
}
int superI = 0;
int subI = 0;
while (superI < super.Length && subI < sub.Length)
{
if (super[superI] == sub[subI])
{
subI++;
}
superI++;
}
return subI == sub.Length;
} }
#endregion #endregion
#region Methods #region Methods
public EcsMask ToMask(EcsWorld world) public EcsMask ToMask(EcsWorld world) { return EcsMask.FromStatic(world, this); }
{
return EcsMask.FromStatic(world, this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(EcsStaticMask other) { return _id == other._id; } public bool Equals(EcsStaticMask other) { return ID == other.ID; }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() { return _id; } public override int GetHashCode() { return ID; }
public override bool Equals(object obj) { return Equals((EcsStaticMask)obj); } public override bool Equals(object obj) { return Equals((EcsStaticMask)obj); }
public override string ToString() { return CreateLogString(_inc, _exc); } public override string ToString() { return CreateLogString(_incs, _excs); }
#endregion #endregion
#region Builder #region Builder
private readonly struct Key : IEquatable<Key> private readonly struct Key : IEquatable<Key>
{ {
public readonly EcsTypeCode[] inc; public readonly EcsTypeCode[] incs;
public readonly EcsTypeCode[] exc; public readonly EcsTypeCode[] excs;
public readonly int hash; public readonly int hash;
#region Constructors #region Constructors
public Key(EcsTypeCode[] inc, EcsTypeCode[] exc) public Key(EcsTypeCode[] inc, EcsTypeCode[] exc)
{ {
this.inc = inc; this.incs = inc;
this.exc = exc; this.excs = exc;
unchecked unchecked
{ {
hash = inc.Length + exc.Length; hash = inc.Length + exc.Length;
@ -142,15 +215,15 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Key other) public bool Equals(Key other)
{ {
if (inc.Length != other.inc.Length) { return false; } if (incs.Length != other.incs.Length) { return false; }
if (exc.Length != other.exc.Length) { return false; } if (excs.Length != other.excs.Length) { return false; }
for (int i = 0; i < inc.Length; i++) for (int i = 0; i < incs.Length; i++)
{ {
if (inc[i] != other.inc[i]) { return false; } if (incs[i] != other.incs[i]) { return false; }
} }
for (int i = 0; i < exc.Length; i++) for (int i = 0; i < excs.Length; i++)
{ {
if (exc[i] != other.exc[i]) { return false; } if (excs[i] != other.excs[i]) { return false; }
} }
return true; return true;
} }
@ -164,6 +237,19 @@ namespace DCFApixels.DragonECS
private readonly BuilderInstance _builder; private readonly BuilderInstance _builder;
private readonly int _version; private readonly int _version;
#region Properties
public bool IsNull
{
get { return _builder == null || _builder._version != _version; }
}
#endregion
#region Constrcutors
private Builder(BuilderInstance builder)
{
_builder = builder;
_version = builder._version;
}
public static Builder New() public static Builder New()
{ {
lock (_lock) lock (_lock)
@ -175,11 +261,9 @@ namespace DCFApixels.DragonECS
return new Builder(builderInstance); return new Builder(builderInstance);
} }
} }
private Builder(BuilderInstance builder) #endregion
{
_builder = builder; #region Inc/Exc/Combine/Except
_version = builder._version;
}
public Builder Inc<T>() { return Inc(EcsTypeCodeManager.Get<T>()); } public Builder Inc<T>() { return Inc(EcsTypeCodeManager.Get<T>()); }
public Builder Exc<T>() { return Exc(EcsTypeCodeManager.Get<T>()); } public Builder Exc<T>() { return Exc(EcsTypeCodeManager.Get<T>()); }
public Builder Inc(Type type) { return Inc(EcsTypeCodeManager.Get(type)); } public Builder Inc(Type type) { return Inc(EcsTypeCodeManager.Get(type)); }
@ -208,7 +292,9 @@ namespace DCFApixels.DragonECS
_builder.Except(mask); _builder.Except(mask);
return this; return this;
} }
#endregion
#region Build/Cancel
public EcsStaticMask Build() public EcsStaticMask Build()
{ {
if (_version != _builder._version) { Throw.UndefinedException(); } if (_version != _builder._version) { Throw.UndefinedException(); }
@ -218,6 +304,15 @@ namespace DCFApixels.DragonECS
return _builder.Build(); return _builder.Build();
} }
} }
public void Cancel()
{
if (_version != _builder._version) { Throw.UndefinedException(); }
lock (_lock)
{
_buildersPool.Push(_builder);
}
}
#endregion
} }
private class BuilderInstance private class BuilderInstance
{ {
@ -280,10 +375,10 @@ namespace DCFApixels.DragonECS
foreach (var item in _combineds) foreach (var item in _combineds)
{ {
EcsStaticMask submask = item.mask; EcsStaticMask submask = item.mask;
combinedIncs.ExceptWith(submask._exc);//удаляю конфликтующие ограничения combinedIncs.ExceptWith(submask._excs);//удаляю конфликтующие ограничения
combinedExcs.ExceptWith(submask._inc);//удаляю конфликтующие ограничения combinedExcs.ExceptWith(submask._incs);//удаляю конфликтующие ограничения
combinedIncs.UnionWith(submask._inc); combinedIncs.UnionWith(submask._incs);
combinedExcs.UnionWith(submask._exc); combinedExcs.UnionWith(submask._excs);
} }
combinedIncs.ExceptWith(_exc);//удаляю конфликтующие ограничения combinedIncs.ExceptWith(_exc);//удаляю конфликтующие ограничения
combinedExcs.ExceptWith(_inc);//удаляю конфликтующие ограничения combinedExcs.ExceptWith(_inc);//удаляю конфликтующие ограничения
@ -305,8 +400,8 @@ namespace DCFApixels.DragonECS
//{ //{
// return _world.Get<WorldMaskComponent>().BrokenMask; // return _world.Get<WorldMaskComponent>().BrokenMask;
//} //}
combinedIncs.ExceptWith(item.mask._inc); combinedIncs.ExceptWith(item.mask._incs);
combinedExcs.ExceptWith(item.mask._exc); combinedExcs.ExceptWith(item.mask._excs);
} }
_excepteds.Clear(); _excepteds.Clear();
} }
@ -372,9 +467,9 @@ namespace DCFApixels.DragonECS
{ {
_source = mask; _source = mask;
ID = mask._id; ID = mask.ID;
included = mask._inc; included = mask._incs;
excluded = mask._exc; excluded = mask._excs;
Type converter(EcsTypeCode o) { return EcsTypeCodeManager.FindTypeOfCode(o); } Type converter(EcsTypeCode o) { return EcsTypeCodeManager.FindTypeOfCode(o); }
includedTypes = included.Select(converter).ToArray(); includedTypes = included.Select(converter).ToArray();
excludedTypes = excluded.Select(converter).ToArray(); excludedTypes = excluded.Select(converter).ToArray();
@ -391,33 +486,11 @@ namespace DCFApixels.DragonECS
{ {
if (CheckRepeats(incs)) { throw new EcsFrameworkException("The values in the Include constraints are repeated."); } if (CheckRepeats(incs)) { throw new EcsFrameworkException("The values in the Include constraints are repeated."); }
if (CheckRepeats(excs)) { throw new EcsFrameworkException("The values in the Exclude constraints are repeated."); } if (CheckRepeats(excs)) { throw new EcsFrameworkException("The values in the Exclude constraints are repeated."); }
if (HasCommonElements(incs, excs)) { throw new EcsFrameworkException("Conflicting Include and Exclude constraints."); } if (OverlapsArray(incs, excs)) { throw new EcsFrameworkException("Conflicting Include and Exclude constraints."); }
}
private static bool HasCommonElements(EcsTypeCode[] a, EcsTypeCode[] b)
{
int i = 0;
int j = 0;
while (i < a.Length && j < b.Length)
{
if (a[i] == b[j])
{
return true;
}
else if (a[i] < b[j])
{
i++;
}
else
{
j++;
}
}
return false;
} }
private static bool CheckRepeats(EcsTypeCode[] array) private static bool CheckRepeats(EcsTypeCode[] array)
{ {
if(array.Length <= 0) if (array.Length <= 1)
{ {
return false; return false;
} }
@ -425,7 +498,7 @@ namespace DCFApixels.DragonECS
for (int i = 1; i < array.Length; i++) for (int i = 1; i < array.Length; i++)
{ {
EcsTypeCode value = array[i]; EcsTypeCode value = array[i];
if(value == lastValue) if (value == lastValue)
{ {
return true; return true;
} }

View File

@ -1,4 +1,5 @@
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Core;
using DCFApixels.DragonECS.Internal;
using DCFApixels.DragonECS.PoolsCore; using DCFApixels.DragonECS.PoolsCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -73,12 +74,6 @@ namespace DCFApixels.DragonECS
private List<IEcsEntityEventListener> _entityListeners = new List<IEcsEntityEventListener>(); private List<IEcsEntityEventListener> _entityListeners = new List<IEcsEntityEventListener>();
#region Properties #region Properties
[Obsolete("Use EcsWorld.ID")]
public short id
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return ID; }
}
EcsWorld IEntityStorage.World EcsWorld IEntityStorage.World
{ {
get { return this; } get { return this; }
@ -391,25 +386,25 @@ namespace DCFApixels.DragonECS
return _entities[entityID].componentsCount; return _entities[entityID].componentsCount;
} }
public bool IsMatchesMask(IEcsComponentMask mask, int entityID) public bool IsMatchesMask(IComponentMask mask, int entityID)
{ {
return IsMatchesMask(mask.ToMask(this), entityID); return IsMatchesMask(mask.ToMask(this), entityID);
} }
public bool IsMatchesMask(EcsMask mask, int entityID) public bool IsMatchesMask(EcsMask mask, int entityID)
{ {
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (mask._worldID != ID) { Throw.World_MaskDoesntBelongWorld(); } if (mask.WorldID != ID) { Throw.World_MaskDoesntBelongWorld(); }
#endif #endif
for (int i = 0, iMax = mask._inc.Length; i < iMax; i++) for (int i = 0, iMax = mask._incs.Length; i < iMax; i++)
{ {
if (!_pools[mask._inc[i]].Has(entityID)) if (!_pools[mask._incs[i]].Has(entityID))
{ {
return false; return false;
} }
} }
for (int i = 0, iMax = mask._exc.Length; i < iMax; i++) for (int i = 0, iMax = mask._excs.Length; i < iMax; i++)
{ {
if (_pools[mask._exc[i]].Has(entityID)) if (_pools[mask._excs[i]].Has(entityID))
{ {
return false; return false;
} }

View File

@ -19,17 +19,6 @@ namespace DCFApixels.DragonECS
private EcsNullPool _nullPool = EcsNullPool.instance; private EcsNullPool _nullPool = EcsNullPool.instance;
#region FindPoolInstance #region FindPoolInstance
[Obsolete("The GetPoolInstance(int componentTypeID) method will be removed in future updates, use FindPoolInstance(Type componentType)")]
public IEcsPool GetPoolInstance(int componentTypeID)
{
return FindPoolInstance(componentTypeID);
}
[Obsolete("The GetPoolInstance(Type componentType) method will be removed in future updates, use FindPoolInstance(Type componentType)")]
public IEcsPool GetPoolInstance(Type componentType)
{
return FindPoolInstance(componentType);
}
public IEcsPool FindPoolInstance(int componentTypeID) public IEcsPool FindPoolInstance(int componentTypeID)
{ {
if (IsComponentTypeDeclared(componentTypeID)) if (IsComponentTypeDeclared(componentTypeID))

View File

@ -1,6 +1,7 @@
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Internal;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -173,5 +174,27 @@ namespace DCFApixels.DragonECS
{ {
internal NullWorld() : base(new EcsWorldConfig(4, 4, 4, 4, 4), 0) { } internal NullWorld() : base(new EcsWorldConfig(4, 4, 4, 4, 4), 0) { }
} }
#region Obsolete
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use EcsWorld.ID")]
public short id
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return ID; }
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("The GetPoolInstance(int componentTypeID) method will be removed in future updates, use FindPoolInstance(Type componentType)")]
public IEcsPool GetPoolInstance(int componentTypeID)
{
return FindPoolInstance(componentTypeID);
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("The GetPoolInstance(Type componentType) method will be removed in future updates, use FindPoolInstance(Type componentType)")]
public IEcsPool GetPoolInstance(Type componentType)
{
return FindPoolInstance(componentType);
}
#endregion
} }
} }

View File

@ -1,4 +1,5 @@
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Core;
using DCFApixels.DragonECS.Internal;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -8,7 +9,7 @@ namespace DCFApixels.DragonECS
public partial class EcsWorld public partial class EcsWorld
{ {
private readonly Dictionary<(Type, object), EcsQueryExecutor> _executorCoures = new Dictionary<(Type, object), EcsQueryExecutor>(256); private readonly Dictionary<(Type, object), EcsQueryExecutor> _executorCoures = new Dictionary<(Type, object), EcsQueryExecutor>(256);
public TExecutor GetExecutor<TExecutor>(IEcsComponentMask mask) public TExecutor GetExecutor<TExecutor>(IComponentMask mask)
where TExecutor : EcsQueryExecutor, new() where TExecutor : EcsQueryExecutor, new()
{ {
var coreType = typeof(TExecutor); var coreType = typeof(TExecutor);
@ -74,9 +75,9 @@ namespace DCFApixels.DragonECS
public WorldStateVersionsChecker(EcsMask mask) public WorldStateVersionsChecker(EcsMask mask)
{ {
_world = mask.World; _world = mask.World;
_maskInc = mask._inc; _maskInc = mask._incs;
_maskExc = mask._exc; _maskExc = mask._excs;
_versions = UnmanagedArrayUtility.New<long>(1 + mask._inc.Length + mask._exc.Length); _versions = UnmanagedArrayUtility.New<long>(1 + mask._incs.Length + mask._excs.Length);
} }
public bool Check() public bool Check()
{ {

View File

@ -1,4 +1,5 @@
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Core;
using DCFApixels.DragonECS.Internal;
using System; using System;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
@ -34,7 +35,7 @@ namespace DCFApixels.DragonECS
return executor.ExecuteFor(span); return executor.ExecuteFor(span);
} }
public static EcsSpan Where<TCollection>(this TCollection entities, IEcsComponentMask mask) public static EcsSpan Where<TCollection>(this TCollection entities, IComponentMask mask)
where TCollection : IEntityStorage where TCollection : IEntityStorage
{ {
if (ReferenceEquals(entities, entities.World)) if (ReferenceEquals(entities, entities.World))
@ -44,11 +45,11 @@ namespace DCFApixels.DragonECS
} }
return entities.ToSpan().Where(mask); return entities.ToSpan().Where(mask);
} }
public static EcsSpan Where(this EcsReadonlyGroup group, IEcsComponentMask mask) public static EcsSpan Where(this EcsReadonlyGroup group, IComponentMask mask)
{ {
return group.ToSpan().Where(mask); return group.ToSpan().Where(mask);
} }
public static EcsSpan Where(this EcsSpan span, IEcsComponentMask mask) public static EcsSpan Where(this EcsSpan span, IComponentMask mask)
{ {
var executor = span.World.GetExecutor<EcsWhereExecutor>(mask); var executor = span.World.GetExecutor<EcsWhereExecutor>(mask);
return executor.ExecuteFor(span); return executor.ExecuteFor(span);
@ -79,7 +80,7 @@ namespace DCFApixels.DragonECS
return executor.ExecuteFor(span, comparison); return executor.ExecuteFor(span, comparison);
} }
public static EcsSpan Where<TCollection>(this TCollection entities, IEcsComponentMask mask, Comparison<int> comparison) public static EcsSpan Where<TCollection>(this TCollection entities, IComponentMask mask, Comparison<int> comparison)
where TCollection : IEntityStorage where TCollection : IEntityStorage
{ {
if (ReferenceEquals(entities, entities.World)) if (ReferenceEquals(entities, entities.World))
@ -89,11 +90,11 @@ namespace DCFApixels.DragonECS
} }
return entities.ToSpan().Where(mask, comparison); return entities.ToSpan().Where(mask, comparison);
} }
public static EcsSpan Where(this EcsReadonlyGroup group, IEcsComponentMask mask, Comparison<int> comparison) public static EcsSpan Where(this EcsReadonlyGroup group, IComponentMask mask, Comparison<int> comparison)
{ {
return group.ToSpan().Where(mask, comparison); return group.ToSpan().Where(mask, comparison);
} }
public static EcsSpan Where(this EcsSpan span, IEcsComponentMask mask, Comparison<int> comparison) public static EcsSpan Where(this EcsSpan span, IComponentMask mask, Comparison<int> comparison)
{ {
var executor = span.World.GetExecutor<EcsWhereExecutor>(mask); var executor = span.World.GetExecutor<EcsWhereExecutor>(mask);
return executor.ExecuteFor(span); return executor.ExecuteFor(span);
@ -124,7 +125,7 @@ namespace DCFApixels.DragonECS
return executor.ExecuteFor(span); return executor.ExecuteFor(span);
} }
public static EcsReadonlyGroup WhereToGroup<TCollection>(this TCollection entities, IEcsComponentMask mask) public static EcsReadonlyGroup WhereToGroup<TCollection>(this TCollection entities, IComponentMask mask)
where TCollection : IEntityStorage where TCollection : IEntityStorage
{ {
if (ReferenceEquals(entities, entities.World)) if (ReferenceEquals(entities, entities.World))
@ -134,11 +135,11 @@ namespace DCFApixels.DragonECS
} }
return entities.ToSpan().WhereToGroup(mask); return entities.ToSpan().WhereToGroup(mask);
} }
public static EcsReadonlyGroup WhereToGroup(this EcsReadonlyGroup group, IEcsComponentMask mask) public static EcsReadonlyGroup WhereToGroup(this EcsReadonlyGroup group, IComponentMask mask)
{ {
return group.ToSpan().WhereToGroup(mask); return group.ToSpan().WhereToGroup(mask);
} }
public static EcsReadonlyGroup WhereToGroup(this EcsSpan span, IEcsComponentMask mask) public static EcsReadonlyGroup WhereToGroup(this EcsSpan span, IComponentMask mask)
{ {
var executor = span.World.GetExecutor<EcsWhereToGroupExecutor>(mask); var executor = span.World.GetExecutor<EcsWhereToGroupExecutor>(mask);
return executor.ExecuteFor(span); return executor.ExecuteFor(span);