mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-11-12 16:45:55 +08:00
ReworkWorld
This commit is contained in:
parent
d64d4407c9
commit
b73652cb37
454
src/EcsFilter.cs
454
src/EcsFilter.cs
@ -6,196 +6,37 @@ namespace DCFApixels.DragonECS
|
||||
#region Incs/Excs base
|
||||
public interface ICondition
|
||||
{
|
||||
public int[] GetComponentsIDs();
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Incs
|
||||
public interface IInc : ICondition { }
|
||||
|
||||
public struct Inc : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype => Array.Empty<int>();
|
||||
}
|
||||
public struct Inc<T0> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
public int[] GetComponentsIDs<TWorldArchetype>()
|
||||
where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
public int[] GetComponentsIDs<TWorldArchetype>()
|
||||
where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID,
|
||||
ComponentType<T5>.globalID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID,
|
||||
ComponentType<T5>.globalID,
|
||||
ComponentType<T6>.globalID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID,
|
||||
ComponentType<T5>.globalID,
|
||||
ComponentType<T6>.globalID,
|
||||
ComponentType<T7>.globalID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID,
|
||||
ComponentType<T5>.globalID,
|
||||
ComponentType<T6>.globalID,
|
||||
ComponentType<T7>.globalID,
|
||||
ComponentType<T8>.globalID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID,
|
||||
ComponentType<T5>.globalID,
|
||||
ComponentType<T6>.globalID,
|
||||
ComponentType<T7>.globalID,
|
||||
ComponentType<T8>.globalID,
|
||||
ComponentType<T9>.globalID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID,
|
||||
ComponentType<T5>.globalID,
|
||||
ComponentType<T6>.globalID,
|
||||
ComponentType<T7>.globalID,
|
||||
ComponentType<T8>.globalID,
|
||||
ComponentType<T9>.globalID,
|
||||
ComponentType<T10>.globalID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID,
|
||||
ComponentType<T5>.globalID,
|
||||
ComponentType<T6>.globalID,
|
||||
ComponentType<T7>.globalID,
|
||||
ComponentType<T8>.globalID,
|
||||
ComponentType<T9>.globalID,
|
||||
ComponentType<T10>.globalID,
|
||||
ComponentType<T11>.globalID
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -204,112 +45,114 @@ namespace DCFApixels.DragonECS
|
||||
#region Excs
|
||||
public interface IExc : ICondition { }
|
||||
|
||||
public struct Exc : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype => Array.Empty<int>();
|
||||
}
|
||||
public struct Exc<T0> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
public int[] GetComponentsIDs<TWorldArchetype>()
|
||||
where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
public int[] GetComponentsIDs<TWorldArchetype>()
|
||||
where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2> : IExc
|
||||
#endregion
|
||||
|
||||
#region BakedMask
|
||||
public abstract class BakedMask
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
internal readonly int[] Inc;
|
||||
internal readonly int[] Exc;
|
||||
internal readonly Mask Mask;
|
||||
|
||||
internal int IncCount
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID
|
||||
};
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Inc.Length;
|
||||
}
|
||||
internal int ExcCount
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Exc.Length;
|
||||
}
|
||||
|
||||
//Уникальный айди в рамках одного архиетипа мира
|
||||
internal abstract int UniqueID { get; }
|
||||
internal abstract Type WorldArchetypeType { get; }
|
||||
|
||||
protected BakedMask(int[] inc, int[] exc, Mask mask)
|
||||
{
|
||||
Inc = inc;
|
||||
Exc = exc;
|
||||
Mask = mask;
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3> : IExc
|
||||
|
||||
public abstract class BakedMask<TWorldArchetype> : BakedMask
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID
|
||||
};
|
||||
}
|
||||
internal static int increment = 1;
|
||||
internal static int capacity = 512;
|
||||
|
||||
protected BakedMask(int[] inc, int[] exc, Mask mask) : base(inc, exc, mask) { }
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3, T4> : IExc
|
||||
|
||||
public sealed class BakedMask<TWorldArchetype, TMask> : BakedMask<TWorldArchetype>
|
||||
where TWorldArchetype : IWorldArchetype
|
||||
where TMask : MaskSingleton<TMask>
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
public static readonly int uniqueID;
|
||||
|
||||
static BakedMask()
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID
|
||||
};
|
||||
uniqueID = increment++;
|
||||
#if DEBUG || DCFAECS_NO_SANITIZE_CHECKS
|
||||
if (uniqueID >= ushort.MaxValue)
|
||||
throw new EcsFrameworkException($"No more room for new BakedMask for this {typeof(TWorldArchetype).FullName} IWorldArchetype");
|
||||
#endif
|
||||
if (increment > capacity)
|
||||
capacity <<= 1;
|
||||
_instance = new BakedMask<TWorldArchetype, TMask>();
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3, T4, T5> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
|
||||
private BakedMask() : base(
|
||||
MaskSingleton<TMask>.Instance.MakeInc<IWorldArchetype>(),
|
||||
MaskSingleton<TMask>.Instance.MakeExc<IWorldArchetype>(),
|
||||
MaskSingleton<TMask>.Instance)
|
||||
{ }
|
||||
|
||||
private static readonly BakedMask<TWorldArchetype, TMask> _instance = new BakedMask<TWorldArchetype, TMask>();
|
||||
public static BakedMask<TWorldArchetype, TMask> Instance
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID,
|
||||
ComponentType<T5>.globalID
|
||||
};
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _instance;
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3, T4, T5, T6> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
|
||||
internal override int UniqueID
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID,
|
||||
ComponentType<T5>.globalID,
|
||||
ComponentType<T6>.globalID
|
||||
};
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => uniqueID;
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3, T4, T5, T6, T7> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs()
|
||||
|
||||
internal override Type WorldArchetypeType
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
ComponentType<T0>.globalID,
|
||||
ComponentType<T1>.globalID,
|
||||
ComponentType<T2>.globalID,
|
||||
ComponentType<T3>.globalID,
|
||||
ComponentType<T4>.globalID,
|
||||
ComponentType<T5>.globalID,
|
||||
ComponentType<T6>.globalID,
|
||||
ComponentType<T7>.globalID
|
||||
};
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => typeof(IWorldArchetype);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@ -317,111 +160,76 @@ namespace DCFApixels.DragonECS
|
||||
#region Masks
|
||||
public abstract class Mask
|
||||
{
|
||||
protected internal static int _typeIDIncrement = 0;
|
||||
|
||||
internal abstract int[] Include { get; }
|
||||
internal abstract int[] Exclude { get; }
|
||||
|
||||
public abstract int ID { get; }
|
||||
|
||||
public int IncCount
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Include.Length;
|
||||
}
|
||||
public int ExcCount
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Exclude.Length;
|
||||
}
|
||||
internal abstract int[] MakeInc<TWorldArchetype>() where TWorldArchetype : IWorldArchetype;
|
||||
internal abstract int[] MakeExc<TWorldArchetype>() where TWorldArchetype : IWorldArchetype;
|
||||
public abstract BakedMask GetBaked<TWorldArchetype>() where TWorldArchetype : IWorldArchetype;
|
||||
}
|
||||
public sealed class Mask<TInc> : Mask
|
||||
where TInc : struct, IInc
|
||||
public abstract class MaskSingleton<TSelf> : Mask
|
||||
where TSelf : Mask
|
||||
{
|
||||
internal static readonly int[] include = new TInc().GetComponentsIDs();
|
||||
internal static readonly int[] exclude = Array.Empty<int>();
|
||||
public static readonly int id = _typeIDIncrement++;
|
||||
private static Mask<TInc> _instance = new Mask<TInc>();
|
||||
|
||||
private Mask() { }
|
||||
|
||||
public static Mask<TInc> Instance
|
||||
protected static TSelf _instance;
|
||||
internal static TSelf Instance
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _instance;
|
||||
}
|
||||
public override int ID
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => id;
|
||||
}
|
||||
internal override int[] Include
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => include;
|
||||
}
|
||||
internal override int[] Exclude
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => exclude;
|
||||
}
|
||||
}
|
||||
public sealed class Mask<TInc, TExc> : Mask
|
||||
|
||||
public class Mask<TInc> : MaskSingleton<Mask<TInc>>
|
||||
where TInc : struct, IInc
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal override int[] MakeInc<TWorldArchetype>() => new TInc().GetComponentsIDs<TWorldArchetype>();
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal override int[] MakeExc<TWorldArchetype>() => Array.Empty<int>();
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override BakedMask GetBaked<TWorldArchetype>()
|
||||
{
|
||||
return BakedMask<TWorldArchetype, Mask<TInc>>.Instance;
|
||||
}
|
||||
|
||||
static Mask() { _instance = new Mask<TInc>(); }
|
||||
}
|
||||
public class Mask<TInc, TExc> : MaskSingleton<Mask<TInc, TExc>>
|
||||
where TInc : struct, IInc
|
||||
where TExc : struct, IExc
|
||||
{
|
||||
internal static readonly int[] include = new TInc().GetComponentsIDs();
|
||||
internal static readonly int[] exclude = new TExc().GetComponentsIDs();
|
||||
public static readonly int id = _typeIDIncrement++;
|
||||
private static Mask<TInc, TExc> _instance = new Mask<TInc, TExc>();
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal override int[] MakeInc<TWorldArchetype>() => new TInc().GetComponentsIDs<TWorldArchetype>();
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal override int[] MakeExc<TWorldArchetype>() => new TExc().GetComponentsIDs<TWorldArchetype>();
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override BakedMask GetBaked<TWorldArchetype>()
|
||||
{
|
||||
return BakedMask<TWorldArchetype, Mask<TInc, TExc>>.Instance;
|
||||
}
|
||||
|
||||
private Mask() { }
|
||||
|
||||
public static Mask<TInc, TExc> Instance
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _instance;
|
||||
}
|
||||
public override int ID
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => id;
|
||||
}
|
||||
internal override int[] Include
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => include;
|
||||
}
|
||||
internal override int[] Exclude
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => exclude;
|
||||
}
|
||||
static Mask() { _instance = new Mask<TInc, TExc>(); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Filter
|
||||
public interface IEcsFilter
|
||||
{
|
||||
public EcsWorld World { get; }
|
||||
public Mask Mask { get; }
|
||||
public IEcsWorld World { get; }
|
||||
public BakedMask Mask { get; }
|
||||
public IEcsReadonlyGroup Entities { get; }
|
||||
public int EntitiesCount { get; }
|
||||
}
|
||||
|
||||
public class EcsFilter : IEcsFilter
|
||||
{
|
||||
private readonly EcsWorld _source;
|
||||
private readonly IEcsWorld _source;
|
||||
private readonly EcsGroup _entities;
|
||||
private readonly Mask _mask;
|
||||
private readonly BakedMask _mask;
|
||||
|
||||
#region Properties
|
||||
public EcsWorld World
|
||||
public IEcsWorld World
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _source;
|
||||
}
|
||||
public Mask Mask
|
||||
public BakedMask Mask
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _mask;
|
||||
@ -439,7 +247,7 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Constrcutors
|
||||
internal EcsFilter(EcsWorld source, Mask mask, int capasity)
|
||||
internal EcsFilter(IEcsWorld source, BakedMask mask, int capasity)
|
||||
{
|
||||
_source = source;
|
||||
_mask = mask;
|
||||
|
||||
@ -5,7 +5,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
public interface IEcsReadonlyGroup
|
||||
{
|
||||
public EcsWorld World { get; }
|
||||
public IEcsWorld World { get; }
|
||||
public int Count { get; }
|
||||
public EcsGroup.Enumerator GetEnumerator();
|
||||
}
|
||||
@ -17,7 +17,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
public class EcsGroup : IEcsGroup
|
||||
{
|
||||
private EcsWorld _source;
|
||||
private IEcsWorld _source;
|
||||
private SparseSet _entities;
|
||||
|
||||
private DelayedOp[] _delayedOps;
|
||||
@ -26,12 +26,12 @@ namespace DCFApixels.DragonECS
|
||||
private int _lockCount;
|
||||
|
||||
#region Properties
|
||||
public EcsWorld World => _source;
|
||||
public IEcsWorld World => _source;
|
||||
public int Count => _entities.Count;
|
||||
#endregion
|
||||
|
||||
#region Constrcutors
|
||||
public EcsGroup(EcsWorld world, int entitiesCapacity, int delayedOpsCapacity = 128)
|
||||
public EcsGroup(IEcsWorld world, int entitiesCapacity, int delayedOpsCapacity = 128)
|
||||
{
|
||||
_source = world;
|
||||
_entities = new SparseSet(entitiesCapacity);
|
||||
|
||||
@ -10,28 +10,34 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
public interface IEcsPool
|
||||
{
|
||||
public EcsWorld World { get; }
|
||||
public IEcsWorld World { get; }
|
||||
public int ID { get; }
|
||||
public bool Has(int index);
|
||||
public void Write(int index);
|
||||
public void Del(int index);
|
||||
}
|
||||
|
||||
public class EcsPool<T> : IEcsPool
|
||||
public interface IEcsPool<T> : IEcsPool
|
||||
where T : struct
|
||||
{
|
||||
public ref readonly T Read(int entity);
|
||||
public new ref T Write(int entity);
|
||||
}
|
||||
public class EcsPool<T> : IEcsPool<T>
|
||||
where T : struct
|
||||
{
|
||||
private readonly int _id;
|
||||
private readonly EcsWorld _source;
|
||||
private readonly IEcsWorld _source;
|
||||
private readonly SparseSet _sparseSet;
|
||||
private T[] _denseItems;
|
||||
|
||||
#region Properites
|
||||
public EcsWorld World => _source;
|
||||
public IEcsWorld World => _source;
|
||||
public int ID => _id;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public EcsPool(EcsWorld source, int capacity)
|
||||
public EcsPool(IEcsWorld source, int capacity)
|
||||
{
|
||||
_source = source;
|
||||
_sparseSet = new SparseSet(capacity);
|
||||
@ -42,34 +48,36 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Read/Write/Has/Del
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref readonly T Read(int index)
|
||||
public ref readonly T Read(int entity)
|
||||
{
|
||||
return ref _denseItems[_sparseSet[index]];
|
||||
return ref _denseItems[_sparseSet[entity]];
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T Write(int index)
|
||||
public ref T Write(int entity)
|
||||
{
|
||||
if (_sparseSet.Contains(index))
|
||||
if (_sparseSet.Contains(entity))
|
||||
{
|
||||
return ref _denseItems[_sparseSet[index]];
|
||||
return ref _denseItems[_sparseSet[entity]];
|
||||
}
|
||||
else
|
||||
{
|
||||
_sparseSet.Add(index);
|
||||
_sparseSet.Add(entity);
|
||||
_sparseSet.Normalize(ref _denseItems);
|
||||
return ref _denseItems[_sparseSet.IndexOf(index)];
|
||||
_source.OnEntityComponentAdded(entity, _id);
|
||||
return ref _denseItems[_sparseSet.IndexOf(entity)];
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Has(int index)
|
||||
public bool Has(int entity)
|
||||
{
|
||||
return _sparseSet.IndexOf(index) > 0;
|
||||
return _sparseSet.IndexOf(entity) > 0;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Del(int index)
|
||||
public void Del(int entity)
|
||||
{
|
||||
_sparseSet.RemoveAt(index);
|
||||
_sparseSet.RemoveAt(entity);
|
||||
_source.OnEntityComponentRemoved(entity, _id);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@ -19,8 +19,8 @@ namespace DCFApixels.DragonECS
|
||||
private bool _isDestoryed = false;
|
||||
|
||||
private int _worldIdIncrement;
|
||||
private Dictionary<string, EcsWorld> _worldsDict = new Dictionary<string, EcsWorld>();
|
||||
private List<EcsWorld> _worlds = new List<EcsWorld>();
|
||||
private Dictionary<string, IEcsWorld> _worldsDict = new Dictionary<string, IEcsWorld>();
|
||||
private List<IEcsWorld> _worlds = new List<IEcsWorld>();
|
||||
|
||||
private Dictionary<Type, IEcsProcessorsRunner> _runners;
|
||||
private Dictionary<Type, IEcsProcessorsMessenger> _messengers;
|
||||
@ -89,11 +89,12 @@ namespace DCFApixels.DragonECS
|
||||
_allProcessors.Add(system);
|
||||
return this;
|
||||
}
|
||||
public EcsSession AddWorld(string name)
|
||||
public EcsSession AddWorld<TArchetype>(EcsWorld<TArchetype> world, string name = "")
|
||||
where TArchetype : IWorldArchetype
|
||||
{
|
||||
CheckInitForMethod(nameof(AddWorld));
|
||||
|
||||
//_worlds.Add(new EcsWorld(_worldIdIncrement++));
|
||||
_worlds.Add(new EcsWorld(_worldIdIncrement++));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public abstract class EcsTable
|
||||
{
|
||||
internal EcsFilter _filter;
|
||||
|
||||
public EcsTable(ref TableBuilder builder) { }
|
||||
|
||||
public EcsFilter Filter
|
||||
{
|
||||
get => _filter;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce8e0e17f18931e4284946bddba80e02
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
215
src/EcsWorld.cs
215
src/EcsWorld.cs
@ -1,215 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
|
||||
public class EcsWorldMap
|
||||
{
|
||||
|
||||
}
|
||||
public class EcsWorld
|
||||
{
|
||||
public const int MAX_WORLDS = byte.MaxValue; //Номер последнего мира 254
|
||||
public const int DEAD_WORLD_ID = byte.MaxValue; //Зарезервированный номер мира для мертвых сущьностей
|
||||
|
||||
private byte _id = DEAD_WORLD_ID;
|
||||
|
||||
//private float _timeScale;//TODO реализовать собсвенныйтайм склей для разных миров
|
||||
|
||||
private IEcsPool[] _pools;
|
||||
private SparseSet _componentIDToPoolID;
|
||||
|
||||
private SparseSet _entities = new SparseSet();
|
||||
private short[] _gens;
|
||||
|
||||
private List<EcsFilter>[] _filtersByIncludedComponents;
|
||||
private List<EcsFilter>[] _filtersByExcludedComponents;
|
||||
|
||||
private EcsFilter[] _filters;
|
||||
private SparseSet _maskIDToFilterID;
|
||||
|
||||
#region Properties
|
||||
public int ID => _id;
|
||||
public bool IsAlive => _id != DEAD_WORLD_ID;
|
||||
public bool IsEmpty => _entities.Count < 0;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public EcsWorld()
|
||||
{
|
||||
_pools = new IEcsPool[512];
|
||||
_entities = new SparseSet(512);
|
||||
_componentIDToPoolID = new SparseSet(512);
|
||||
_maskIDToFilterID = new SparseSet(512);
|
||||
_filters = new EcsFilter[512];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Pools
|
||||
public EcsPool<T> GetPool<T>()
|
||||
where T : struct
|
||||
{
|
||||
int uniqueID = ComponentType<T>.globalID;
|
||||
int poolIndex = _componentIDToPoolID.IndexOf(uniqueID);
|
||||
if (poolIndex >= 0)
|
||||
{
|
||||
return (EcsPool<T>)_pools[poolIndex];
|
||||
}
|
||||
#if DEBUG
|
||||
if (_componentIDToPoolID.Count >= ushort.MaxValue)
|
||||
{
|
||||
throw new EcsFrameworkException("No more room for new component into this world.");
|
||||
}
|
||||
#endif
|
||||
var pool = new EcsPool<T>(this, 512);
|
||||
_componentIDToPoolID.Add(uniqueID);
|
||||
_componentIDToPoolID.Normalize(ref _pools);
|
||||
_componentIDToPoolID.Normalize(ref _filtersByIncludedComponents);
|
||||
_componentIDToPoolID.Normalize(ref _filtersByExcludedComponents);
|
||||
|
||||
_pools[_componentIDToPoolID.IndexOf(poolIndex)] = pool;
|
||||
return pool;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Filters
|
||||
public EcsFilter GetFilter<TMask>(TMask mask) where TMask : Mask
|
||||
{
|
||||
if (_maskIDToFilterID.TryAdd(mask.ID, ref _filters))
|
||||
{
|
||||
EcsFilter filter = new EcsFilter(this, mask, 512);
|
||||
_filters[_maskIDToFilterID.IndexOf(mask.ID)] = filter;
|
||||
return filter;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _filters[_maskIDToFilterID.IndexOf(mask.ID)];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region NewEntity
|
||||
public ent NewEntity()
|
||||
{
|
||||
int entityID = _entities.GetFree();
|
||||
_entities.Normalize(ref _gens);
|
||||
_gens[entityID]++;
|
||||
|
||||
|
||||
return new ent(entityID, _gens[entityID], _id);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Destroy
|
||||
public void Destroy()
|
||||
{
|
||||
_id = DEAD_WORLD_ID;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IsMaskCompatible/IsMaskCompatibleWithout
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsMaskCompatible(Mask mask, int entity)
|
||||
{
|
||||
for (int i = 0, iMax = mask.IncCount; i < iMax; i++)
|
||||
{
|
||||
if (!_pools[_componentIDToPoolID[mask.Include[i]]].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0, iMax = mask.ExcCount; i < iMax; i++)
|
||||
{
|
||||
if (_pools[_componentIDToPoolID[mask.Exclude[i]]].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool IsMaskCompatibleWithout(Mask mask, int entity, int otherPoolID)
|
||||
{
|
||||
for (int i = 0, iMax = mask.IncCount; i < iMax; i++)
|
||||
{
|
||||
int poolID = _componentIDToPoolID[mask.Include[i]];
|
||||
if (poolID == otherPoolID || !_pools[poolID].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0, iMax = mask.ExcCount; i < iMax; i++)
|
||||
{
|
||||
int poolID = _componentIDToPoolID[mask.Exclude[i]];
|
||||
if (poolID != otherPoolID && _pools[poolID].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EntityChangedReact
|
||||
internal void OnEntityComponentAdded(int entityID, int changedPoolID)
|
||||
{
|
||||
var includeList = _filtersByIncludedComponents[changedPoolID];
|
||||
var excludeList = _filtersByExcludedComponents[changedPoolID];
|
||||
|
||||
if (includeList != null)
|
||||
{
|
||||
foreach (var filter in includeList)
|
||||
{
|
||||
if (IsMaskCompatible(filter.Mask, entityID))
|
||||
{
|
||||
filter.Add(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (excludeList != null)
|
||||
{
|
||||
foreach (var filter in excludeList)
|
||||
{
|
||||
if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID))
|
||||
{
|
||||
filter.Remove(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnEntityComponentRemoved(int entityID, int changedPoolID)
|
||||
{
|
||||
var includeList = _filtersByIncludedComponents[changedPoolID];
|
||||
var excludeList = _filtersByExcludedComponents[changedPoolID];
|
||||
|
||||
if (includeList != null)
|
||||
{
|
||||
foreach (var filter in includeList)
|
||||
{
|
||||
if (IsMaskCompatible(filter.Mask, entityID))
|
||||
{
|
||||
filter.Remove(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (excludeList != null)
|
||||
{
|
||||
foreach (var filter in excludeList)
|
||||
{
|
||||
if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID))
|
||||
{
|
||||
filter.Add(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
260
src/IEcsWorld.cs
Normal file
260
src/IEcsWorld.cs
Normal file
@ -0,0 +1,260 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public interface IWorldArchetype { }
|
||||
public struct DefaultArchetype : IWorldArchetype { }
|
||||
|
||||
public interface IEcsWorld
|
||||
{
|
||||
public const int MAX_WORLDS = byte.MaxValue; //Номер последнего мира 254
|
||||
public const int DEAD_WORLD_ID = byte.MaxValue; //Зарезервированный номер мира для мертвых сущьностей
|
||||
|
||||
//private float _timeScale;//TODO реализовать собсвенныйтайм склей для разных миров
|
||||
|
||||
#region Properties
|
||||
public ushort ID { get; internal set; }
|
||||
public bool IsAlive { get; }
|
||||
public bool IsEmpty { get; }
|
||||
public Type ArchetypeType { get; }
|
||||
#endregion
|
||||
|
||||
public EcsPool<T> GetPool<T>() where T : struct;
|
||||
public EcsFilter GetFilter<TMask>() where TMask : MaskSingleton<TMask>;
|
||||
public ent NewEntity();
|
||||
public void Destroy();
|
||||
|
||||
public bool IsMaskCompatible(Mask mask, int entity);
|
||||
public bool IsMaskCompatibleWithout(Mask mask, int entity, int otherPoolID);
|
||||
|
||||
internal void OnEntityComponentAdded(int entityID, int changedPoolID);
|
||||
internal void OnEntityComponentRemoved(int entityID, int changedPoolID);
|
||||
}
|
||||
|
||||
public class EcsWorld<TArchetype> : IEcsWorld
|
||||
where TArchetype : IWorldArchetype
|
||||
{
|
||||
private ushort _id = IEcsWorld.DEAD_WORLD_ID;
|
||||
|
||||
private SparseSet _componentIDToPoolID;
|
||||
|
||||
private SparseSet _entities = new SparseSet();
|
||||
private short[] _gens;
|
||||
|
||||
private IEcsPool[] _pools;
|
||||
|
||||
private List<EcsFilter>[] _filtersByIncludedComponents;
|
||||
private List<EcsFilter>[] _filtersByExcludedComponents;
|
||||
|
||||
private EcsFilter[] _filters;
|
||||
|
||||
#region Properties
|
||||
public ushort ID => _id;
|
||||
ushort IEcsWorld.ID { get => _id; set => _id = value; }
|
||||
|
||||
public bool IsAlive => _id != IEcsWorld.DEAD_WORLD_ID;
|
||||
public bool IsEmpty => _entities.Count < 0;
|
||||
public Type ArchetypeType => typeof(TArchetype);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public EcsWorld()
|
||||
{
|
||||
_pools = new IEcsPool[512];
|
||||
_entities = new SparseSet(512);
|
||||
_componentIDToPoolID = new SparseSet(512);
|
||||
_filters = new EcsFilter[512];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetPool
|
||||
public EcsPool<T> GetPool<T>() where T : struct
|
||||
{
|
||||
int uniqueID = ComponentType<T>.uniqueID;
|
||||
|
||||
if (uniqueID >= _pools.Length)
|
||||
{
|
||||
Array.Resize(ref _pools, ComponentType.capacity);
|
||||
Array.Resize(ref _filtersByIncludedComponents, ComponentType.capacity);
|
||||
Array.Resize(ref _filtersByExcludedComponents, ComponentType.capacity);
|
||||
}
|
||||
|
||||
if (_pools[uniqueID] == null)
|
||||
{
|
||||
_pools[uniqueID] = new EcsPool<T>(this, 512);
|
||||
}
|
||||
return (EcsPool<T>)_pools[uniqueID];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetFilter
|
||||
public EcsFilter GetFilter<TMask>() where TMask : MaskSingleton<TMask>
|
||||
{
|
||||
var bakedmask = BakedMask<TArchetype, TMask>.Instance;
|
||||
|
||||
if (_filters.Length >= BakedMask<TArchetype>.capacity)
|
||||
{
|
||||
Array.Resize(ref _filters, BakedMask<TArchetype>.capacity);
|
||||
}
|
||||
|
||||
if (_filters[bakedmask.UniqueID] == null)
|
||||
{
|
||||
_filters[bakedmask.UniqueID] = new EcsFilter(this, bakedmask, 512);
|
||||
}
|
||||
return _filters[bakedmask.UniqueID];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IsMaskCompatible/IsMaskCompatibleWithout
|
||||
public bool IsMaskCompatible(Mask mask, int entity)
|
||||
{
|
||||
BakedMask bakedMask = mask.GetBaked<TArchetype>();
|
||||
for (int i = 0, iMax = bakedMask.IncCount; i < iMax; i++)
|
||||
{
|
||||
if (!_pools[_componentIDToPoolID[bakedMask.Inc[i]]].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0, iMax = bakedMask.ExcCount; i < iMax; i++)
|
||||
{
|
||||
if (_pools[_componentIDToPoolID[bakedMask.Exc[i]]].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsMaskCompatibleWithout(Mask mask, int entity, int otherPoolID)
|
||||
{
|
||||
BakedMask bakedMask = mask.GetBaked<TArchetype>();
|
||||
for (int i = 0, iMax = bakedMask.IncCount; i < iMax; i++)
|
||||
{
|
||||
int poolID = _componentIDToPoolID[bakedMask.Inc[i]];
|
||||
if (poolID == otherPoolID || !_pools[poolID].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0, iMax = bakedMask.ExcCount; i < iMax; i++)
|
||||
{
|
||||
int poolID = _componentIDToPoolID[bakedMask.Exc[i]];
|
||||
if (poolID != otherPoolID && _pools[poolID].Has(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EntityChangedReact
|
||||
void IEcsWorld.OnEntityComponentAdded(int entityID, int changedPoolID)
|
||||
{
|
||||
var includeList = _filtersByIncludedComponents[changedPoolID];
|
||||
var excludeList = _filtersByExcludedComponents[changedPoolID];
|
||||
|
||||
if (includeList != null)
|
||||
{
|
||||
foreach (var filter in includeList)
|
||||
{
|
||||
if (IsMaskCompatible(filter.Mask.Mask, entityID))
|
||||
{
|
||||
filter.Add(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (excludeList != null)
|
||||
{
|
||||
foreach (var filter in excludeList)
|
||||
{
|
||||
if (IsMaskCompatibleWithout(filter.Mask.Mask, entityID, changedPoolID))
|
||||
{
|
||||
filter.Remove(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IEcsWorld.OnEntityComponentRemoved(int entityID, int changedPoolID)
|
||||
{
|
||||
var includeList = _filtersByIncludedComponents[changedPoolID];
|
||||
var excludeList = _filtersByExcludedComponents[changedPoolID];
|
||||
|
||||
if (includeList != null)
|
||||
{
|
||||
foreach (var filter in includeList)
|
||||
{
|
||||
if (IsMaskCompatible(filter.Mask.Mask, entityID))
|
||||
{
|
||||
filter.Remove(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (excludeList != null)
|
||||
{
|
||||
foreach (var filter in excludeList)
|
||||
{
|
||||
if (IsMaskCompatibleWithout(filter.Mask.Mask, entityID, changedPoolID))
|
||||
{
|
||||
filter.Add(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region NewEntity
|
||||
public Entity NewEntity()
|
||||
{
|
||||
int entityID = _entities.GetFree();
|
||||
_entities.Normalize(ref _gens);
|
||||
_gens[entityID]++;
|
||||
|
||||
return new Entity(this, entityID);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Destroy
|
||||
public void Destroy()
|
||||
{
|
||||
_id = IEcsWorld.DEAD_WORLD_ID;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utils
|
||||
internal abstract class ComponentType
|
||||
{
|
||||
internal static int increment = 1;
|
||||
internal static int capacity = 512;
|
||||
}
|
||||
internal sealed class ComponentType<T> : ComponentType
|
||||
{
|
||||
internal static int uniqueID;
|
||||
|
||||
static ComponentType()
|
||||
{
|
||||
uniqueID = increment++;
|
||||
#if DEBUG || DCFAECS_NO_SANITIZE_CHECKS
|
||||
if (increment + 1 > ushort.MaxValue)
|
||||
{
|
||||
throw new EcsFrameworkException($"No more room for new component for this {typeof(TArchetype).FullName} IWorldArchetype");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (increment > capacity)
|
||||
{
|
||||
capacity <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,7 @@ namespace DCFApixels.DragonECS
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)]
|
||||
public readonly struct ent : IEquatable<long>, IEquatable<ent>
|
||||
{
|
||||
public static readonly long NULL = 0;
|
||||
public static readonly ent NULL = default;
|
||||
|
||||
// id - 32 bits
|
||||
// gen - 16 bits
|
||||
@ -23,25 +23,25 @@ namespace DCFApixels.DragonECS
|
||||
get => (int)(_full >> 32);
|
||||
}
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public short gen
|
||||
public ushort gen
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => (short)((_full << 32) >> 48);
|
||||
get => (ushort)((_full << 32) >> 48);
|
||||
|
||||
}
|
||||
// но чтобы значене default было NULL сульностью, мир хранится в виде ID + 1
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public short world
|
||||
public ushort world
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => (short)(((_full << 48) >> 48) - 1);
|
||||
get => (ushort)(((_full << 48) >> 48) - 1);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public ent(int id, short gen, short world)
|
||||
public ent(int id, short gen, ushort world)
|
||||
{
|
||||
_full = ((long)id) << 32;
|
||||
_full += ((long)gen) << 16;
|
||||
@ -112,11 +112,11 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
|
||||
public ref struct Entity
|
||||
public readonly ref struct Entity
|
||||
{
|
||||
internal EcsWorld world;
|
||||
internal int id;
|
||||
public Entity(EcsWorld world, int id)
|
||||
internal readonly IEcsWorld world;
|
||||
internal readonly int id;
|
||||
public Entity(IEcsWorld world, ent id)
|
||||
{
|
||||
this.world = world;
|
||||
this.id = id;
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public readonly ref struct TableBuilder
|
||||
{
|
||||
private readonly EcsWorld _world;
|
||||
private readonly EcsWorld.Mask _mask;
|
||||
|
||||
public TableBuilder(EcsWorld world, EcsWorld.Mask mask)
|
||||
{
|
||||
_world = world;
|
||||
_mask = mask;
|
||||
}
|
||||
|
||||
public EcsPool<T> Cache<T>(mem<T> member)
|
||||
where T : struct
|
||||
{
|
||||
return _world.GetPool(member);
|
||||
}
|
||||
public EcsPool<T> Inc<T>(mem<T> member)
|
||||
where T : struct
|
||||
{
|
||||
_mask.Inc(member);
|
||||
return _world.GetPool(member);
|
||||
}
|
||||
public EcsPool<T> Exc<T>(mem<T> member)
|
||||
where T : struct
|
||||
{
|
||||
_mask.Exc(member);
|
||||
return _world.GetPool(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/Utils/BitMask.cs
Normal file
38
src/Utils/BitMask.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class BitMask
|
||||
{
|
||||
private int[] data;
|
||||
|
||||
public int Length { get; private set; }
|
||||
|
||||
public BitMask(int length)
|
||||
{
|
||||
Length = length;
|
||||
data = new int[(length + 31) / 32];
|
||||
}
|
||||
|
||||
public void Resize(int newLength)
|
||||
{
|
||||
Length = newLength;
|
||||
Array.Resize(ref data, (newLength + 31) / 32);
|
||||
}
|
||||
|
||||
public void Set1(int index)
|
||||
{
|
||||
data[index / 32] |= 1 << (index % 32);
|
||||
}
|
||||
|
||||
public void Set0(int index)
|
||||
{
|
||||
data[index / 32] &= ~(1 << (index % 32));
|
||||
}
|
||||
|
||||
public bool Get(int index)
|
||||
{
|
||||
return (data[index / 32] & (1 << (index % 32))) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ae306a1fd41f78428c59018eeaf21f3
|
||||
guid: 88bc1ea51d98c0843a48314fbe00ad9e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@ -1,98 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
internal abstract class ComponentType
|
||||
{
|
||||
internal static int increment = 1;
|
||||
internal static int capacity = 512;
|
||||
}
|
||||
internal sealed class ComponentType<T> : ComponentType
|
||||
{
|
||||
internal static int globalID;
|
||||
|
||||
static ComponentType()
|
||||
{
|
||||
globalID = increment++;
|
||||
if (increment > capacity)
|
||||
{
|
||||
capacity <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ComponentTypeMap
|
||||
{
|
||||
private int[] _dense;
|
||||
private int[] _sparse;
|
||||
|
||||
private int _count;
|
||||
|
||||
#region Properties
|
||||
public int Count
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _count;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constrcutors
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ComponentTypeMap(int denseCapacity = 64)
|
||||
{
|
||||
_dense = new int[denseCapacity];
|
||||
_sparse = new int[ComponentType.capacity];
|
||||
|
||||
_count = 0;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Contains
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Contains<T>() => Contains(ComponentType<T>.globalID);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool Contains(int globalID)
|
||||
{
|
||||
return globalID > 0 && globalID < _sparse.Length && _sparse[globalID] > 0;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetID
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int GetID<T>()
|
||||
{
|
||||
int globalID = ComponentType<T>.globalID;
|
||||
|
||||
if (!Contains(globalID))
|
||||
{
|
||||
Add(globalID);
|
||||
}
|
||||
|
||||
return _dense[globalID];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Add
|
||||
private void Add(int entityID)
|
||||
{
|
||||
if (Contains(entityID))
|
||||
return;
|
||||
|
||||
if (++_count >= _dense.Length)
|
||||
Array.Resize(ref _dense, _dense.Length << 1);
|
||||
|
||||
if (entityID > _sparse.Length)
|
||||
{
|
||||
int neadedSpace = _sparse.Length;
|
||||
while (entityID >= neadedSpace)
|
||||
neadedSpace <<= 1;
|
||||
Array.Resize(ref _sparse, neadedSpace);
|
||||
}
|
||||
|
||||
_dense[_count] = entityID;
|
||||
_sparse[entityID] = _count;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cef3dbf379d584346bc8a9313c22c563
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1036
src/Utils/IntSet.cs
1036
src/Utils/IntSet.cs
File diff suppressed because it is too large
Load Diff
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cad30d5b37df1d48bc2abe5d1743649
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,63 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DCFApixels;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class TransformTable : EcsTable
|
||||
{
|
||||
public readonly EcsPool<Vector3> position;
|
||||
public readonly EcsPool<Quaternion> rotation;
|
||||
public readonly EcsPool<Vector3> scale;
|
||||
|
||||
public TransformTable(ref TableBuilder tableBuilder) : base(ref tableBuilder)
|
||||
{
|
||||
position = tableBuilder.Inc(Mems.position);
|
||||
rotation = tableBuilder.Inc(Mems.rotation);
|
||||
scale = tableBuilder.Inc(Mems.scale);
|
||||
}
|
||||
}
|
||||
|
||||
public class PositionTable : EcsTable
|
||||
{
|
||||
public readonly EcsPool<Vector3> position;
|
||||
public readonly EcsPool<Quaternion> rotation;
|
||||
public readonly EcsPool<Vector3> scale;
|
||||
|
||||
public PositionTable(ref TableBuilder tableBuilder) : base(ref tableBuilder)
|
||||
{
|
||||
position = tableBuilder.Inc(Mems.position);
|
||||
rotation = tableBuilder.Cache(Mems.rotation);
|
||||
scale = tableBuilder.Cache(Mems.scale);
|
||||
}
|
||||
}
|
||||
|
||||
public class RotationTable : EcsTable
|
||||
{
|
||||
public readonly EcsPool<Vector3> position;
|
||||
public readonly EcsPool<Quaternion> rotation;
|
||||
public readonly EcsPool<Vector3> scale;
|
||||
|
||||
public RotationTable(ref TableBuilder tableBuilder) : base(ref tableBuilder)
|
||||
{
|
||||
position = tableBuilder.Cache(Mems.position);
|
||||
rotation = tableBuilder.Inc(Mems.rotation);
|
||||
scale = tableBuilder.Cache(Mems.scale);
|
||||
}
|
||||
}
|
||||
|
||||
public class ScaleTable : EcsTable
|
||||
{
|
||||
public readonly EcsPool<Vector3> position;
|
||||
public readonly EcsPool<Quaternion> rotation;
|
||||
public readonly EcsPool<Vector3> scale;
|
||||
|
||||
public ScaleTable(ref TableBuilder tableBuilder) : base(ref tableBuilder)
|
||||
{
|
||||
position = tableBuilder.Cache(Mems.position);
|
||||
rotation = tableBuilder.Cache(Mems.rotation);
|
||||
scale = tableBuilder.Inc(Mems.scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6c6320184f942444b499e3f027a72a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
Reference in New Issue
Block a user