mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-11-13 17:15:54 +08:00
Update
This commit is contained in:
parent
9a8e4a6995
commit
e2ebe33b57
8
src/Attributes.meta
Normal file
8
src/Attributes.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 269d1f5d46517e14a8563d7f239fa559
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
78
src/Attributes/DebugColorAttribute.cs
Normal file
78
src/Attributes/DebugColorAttribute.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class DebugColorAttribute : Attribute
|
||||
{
|
||||
private ColorRecord color;
|
||||
public byte r => color.r;
|
||||
public byte g => color.g;
|
||||
public byte b => color.b;
|
||||
|
||||
public DebugColorAttribute(byte r, byte g, byte b)
|
||||
{
|
||||
color = new ColorRecord(r, g, b);
|
||||
}
|
||||
|
||||
public DebugColorAttribute(DebugColor color)
|
||||
{
|
||||
this.color = new ColorRecord((int)color);
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 4)]
|
||||
private readonly struct ColorRecord
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public readonly int full;
|
||||
[FieldOffset(3)]
|
||||
public readonly byte r;
|
||||
[FieldOffset(2)]
|
||||
public readonly byte g;
|
||||
[FieldOffset(1)]
|
||||
public readonly byte b;
|
||||
|
||||
public ColorRecord(byte r, byte g, byte b) : this()
|
||||
{
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
}
|
||||
public ColorRecord(int full) : this()
|
||||
{
|
||||
this.full = full;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum DebugColor
|
||||
{
|
||||
/// <summary> Red. RGB is (255, 0, 0)</summary>
|
||||
Red = 255 << 8 * 3 + 000 << 8 * 2 + 000 << 8,
|
||||
/// <summary> Green. RGB is (0, 255, 0)</summary>
|
||||
Green = 000 << 8 * 3 + 255 << 8 * 2 + 000 << 8,
|
||||
/// <summary> Blue. RGB is (0, 0, 255)</summary>
|
||||
Blue = 000 << 8 * 3 + 000 << 8 * 2 + 255 << 8,
|
||||
|
||||
/// <summary> Yellow. RGB is (255, 255, 0)</summary>
|
||||
Yellow = 255 << 8 * 3 + 255 << 8 * 2 + 000 << 8,
|
||||
/// <summary> Cyan. RGB is (0, 255, 255)</summary>
|
||||
Cyan = 000 << 8 * 3 + 255 << 8 * 2 + 255 << 8,
|
||||
/// <summary> Magenta. RGB is (255, 0, 255)</summary>
|
||||
Magenta = 255 << 8 * 3 + 000 << 8 * 2 + 000 << 8,
|
||||
|
||||
/// <summary> Yellow. RGB is (255, 127, 0)</summary>
|
||||
Orange = (255 << 24) + (127 << 16) + (000 << 8),
|
||||
|
||||
/// <summary> Grey/Gray. RGB is (127, 127, 127)</summary>
|
||||
Gray = 127 << 8 * 3 + 127 << 8 * 2 + 127 << 8,
|
||||
/// <summary> Grey/Gray. RGB is (127, 127, 127)</summary>
|
||||
Grey = Gray,
|
||||
/// <summary> White. RGB is (255, 255, 255)</summary>
|
||||
White = -1,
|
||||
/// <summary> Black. RGB is (0, 0, 0)</summary>
|
||||
Black = 0,
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ae31658c78bbf04cb755ac72be367dd
|
||||
guid: 4b96ad0ff9cf7124d8539afccec8f1ae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@ -2,53 +2,49 @@
|
||||
{
|
||||
public interface IEcsPreInitSystem : IEcsSystem
|
||||
{
|
||||
public void PreInit(EcsSession session);
|
||||
public void PreInit(EcsSystems systems);
|
||||
}
|
||||
public interface IEcsInitSystem : IEcsSystem
|
||||
{
|
||||
public void Init(EcsSession session);
|
||||
public void Init(EcsSystems systems);
|
||||
}
|
||||
public interface IEcsRunSystem : IEcsSystem
|
||||
{
|
||||
public void Run(EcsSession session);
|
||||
public void Run(EcsSystems systems);
|
||||
}
|
||||
public interface IEcsDestroySystem : IEcsSystem
|
||||
{
|
||||
public void Destroy(EcsSession session);
|
||||
public void Destroy(EcsSystems systems);
|
||||
}
|
||||
|
||||
public interface IEcsBaseSystem :
|
||||
IEcsInitSystem,
|
||||
IEcsRunSystem,
|
||||
IEcsDestroySystem
|
||||
{ }
|
||||
public interface IEcsBaseSystem : IEcsInitSystem, IEcsRunSystem, IEcsDestroySystem { }
|
||||
|
||||
public sealed class EcsPreInitRunner : EcsRunner<IEcsPreInitSystem>, IEcsPreInitSystem
|
||||
{
|
||||
void IEcsPreInitSystem.PreInit(EcsSession session)
|
||||
void IEcsPreInitSystem.PreInit(EcsSystems systems)
|
||||
{
|
||||
foreach (var item in targets) item.PreInit(session);
|
||||
foreach (var item in targets) item.PreInit(systems);
|
||||
}
|
||||
}
|
||||
public sealed class EcsInitRunner : EcsRunner<IEcsInitSystem>, IEcsInitSystem
|
||||
{
|
||||
void IEcsInitSystem.Init(EcsSession session)
|
||||
void IEcsInitSystem.Init(EcsSystems systems)
|
||||
{
|
||||
foreach (var item in targets) item.Init(session);
|
||||
foreach (var item in targets) item.Init(systems);
|
||||
}
|
||||
}
|
||||
public sealed class EcsRunRunner : EcsRunner<IEcsRunSystem>, IEcsRunSystem
|
||||
{
|
||||
void IEcsRunSystem.Run(EcsSession session)
|
||||
void IEcsRunSystem.Run(EcsSystems systems)
|
||||
{
|
||||
foreach (var item in targets) item.Run(session);
|
||||
foreach (var item in targets) item.Run(systems);
|
||||
}
|
||||
}
|
||||
public sealed class EcsDestroyRunner : EcsRunner<IEcsDestroySystem>, IEcsDestroySystem
|
||||
{
|
||||
void IEcsDestroySystem.Destroy(EcsSession session)
|
||||
void IEcsDestroySystem.Destroy(EcsSystems systems)
|
||||
{
|
||||
foreach (var item in targets) item.Destroy(session);
|
||||
foreach (var item in targets) item.Destroy(systems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
{
|
||||
public void Inject(T obj);
|
||||
}
|
||||
[DebugColor(DebugColor.Gray)]
|
||||
public sealed class InjectRunner<T> : EcsRunner<IEcsInject<T>>, IEcsInject<T>
|
||||
{
|
||||
void IEcsInject<T>.Inject(T obj)
|
||||
@ -15,6 +16,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
[DebugColor(DebugColor.Gray)]
|
||||
public class InjectSystem<T> : IEcsPreInitSystem
|
||||
{
|
||||
private T _injectedData;
|
||||
@ -24,37 +26,38 @@
|
||||
_injectedData = injectedData;
|
||||
}
|
||||
|
||||
public void PreInit(EcsSession session)
|
||||
public void PreInit(EcsSystems systems)
|
||||
{
|
||||
var injector = session.GetRunner<IEcsInject<T>>();
|
||||
var injector = systems.GetRunner<IEcsInject<T>>();
|
||||
injector.Inject(_injectedData);
|
||||
}
|
||||
}
|
||||
|
||||
public static class InjectSystemExstensions
|
||||
{
|
||||
public static EcsSession Inject<T>(this EcsSession self, T data)
|
||||
public static EcsSystems.Builder Inject<T>(this EcsSystems.Builder self, T data)
|
||||
{
|
||||
self.Add(new InjectSystem<T>(data));
|
||||
return self;
|
||||
}
|
||||
|
||||
public static EcsSession Inject<A, B>(this EcsSession self, A dataA, B dataB)
|
||||
public static EcsSystems.Builder Inject<A, B>(this EcsSystems.Builder self, A a, B b)
|
||||
{
|
||||
self.Inject(dataA).Inject(dataB);
|
||||
self.Inject(a).Inject(b);
|
||||
return self;
|
||||
}
|
||||
|
||||
public static EcsSession Inject<A, B, C, D>(this EcsSession self, A dataA, B dataB, C dataC, D dataD)
|
||||
public static EcsSystems.Builder Inject<A, B, C, D>(this EcsSystems.Builder self, A a, B b, C c, D d)
|
||||
{
|
||||
self.Inject(dataA).Inject(dataB).Inject(dataC).Inject(dataD);
|
||||
self.Inject(a).Inject(b).Inject(c).Inject(d);
|
||||
return self;
|
||||
}
|
||||
|
||||
public static EcsSession Inject<A, B, C, D, E>(this EcsSession self,
|
||||
A dataA, B dataB, C dataC, D dataD, E dataE)
|
||||
public static EcsSystems.Builder Inject<A, B, C, D, E>(this EcsSystems.Builder self, A a, B b, C c, D d, E e)
|
||||
{
|
||||
self.Inject(dataA).Inject(dataB).Inject(dataC).Inject(dataD).Inject(dataE);
|
||||
self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e);
|
||||
return self;
|
||||
}
|
||||
public static EcsSystems.Builder Inject<A, B, C, D, E, F>(this EcsSystems.Builder self, A a, B b, C c, D d, E e, F f)
|
||||
{
|
||||
self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f);
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
||||
8
src/Consts.cs
Normal file
8
src/Consts.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class EcsConsts
|
||||
{
|
||||
public const string EXCEPTION_MESSAGE_PREFIX = "[DragonECS] ";
|
||||
public const string DEBUG_PREFIX = "[DEBUG] ";
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f04087406e09f6042a341cf8fc41fabf
|
||||
guid: 3c30dd6d8ecfdbd4aaceccd22bfb85c4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
254
src/EcsFilter.cs
254
src/EcsFilter.cs
@ -13,31 +13,193 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Incs
|
||||
public interface IInc : IMaskCondition { }
|
||||
|
||||
public struct Inc : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype => Array.Empty<int>();
|
||||
}
|
||||
public struct Inc<T0> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>()
|
||||
where TWorldArchetype : IWorldArchetype
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>()
|
||||
where TWorldArchetype : IWorldArchetype
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T7>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T7>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T8>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T7>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T8>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T9>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T7>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T8>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T9>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T10>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Inc<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> : IInc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T6>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T7>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T8>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T9>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T10>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T11>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -45,15 +207,13 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Excs
|
||||
public interface IExc : IMaskCondition { }
|
||||
|
||||
public struct Exc : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype => Array.Empty<int>();
|
||||
}
|
||||
public struct Exc<T0> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>()
|
||||
where TWorldArchetype : IWorldArchetype
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
@ -63,13 +223,66 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
public struct Exc<T0, T1> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>()
|
||||
where TWorldArchetype : IWorldArchetype
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3, T4> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
public struct Exc<T0, T1, T2, T3, T4, T5> : IExc
|
||||
{
|
||||
public int[] GetComponentsIDs<TWorldArchetype>() where TWorldArchetype : IWorldArchetype
|
||||
{
|
||||
return new int[]
|
||||
{
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T0>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T1>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T2>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T3>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T4>.uniqueID,
|
||||
EcsWorld<TWorldArchetype>.ComponentType<T5>.uniqueID,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -238,19 +451,4 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utils
|
||||
internal static class ArrayExt
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static T[] Sort<T>(this T[] self)
|
||||
{
|
||||
Array.Sort(self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Constrcutors
|
||||
public EcsGroup(IEcsWorld world, int entitiesCapacity, int delayedOpsCapacity = 128)
|
||||
public EcsGroup(IEcsWorld world, int entitiesCapacity, int delayedOpsCapacity = 32)
|
||||
{
|
||||
_source = world;
|
||||
_entities = new SparseSet(entitiesCapacity, entitiesCapacity);
|
||||
@ -67,6 +67,11 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Contains
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Contains(int entityID) => _entities.Contains(entityID);
|
||||
#endregion
|
||||
|
||||
#region AddGroup/RemoveGroup
|
||||
public void AddGroup(IEcsReadonlyGroup group)
|
||||
{
|
||||
@ -124,44 +129,28 @@ namespace DCFApixels.DragonECS
|
||||
private readonly EcsGroup _source;
|
||||
private readonly SparseSet _entities;
|
||||
private int _index;
|
||||
private Entity _currentEntity;
|
||||
|
||||
public Enumerator(EcsGroup group)
|
||||
{
|
||||
_source = group;
|
||||
_entities = group._entities;
|
||||
_index = -1;
|
||||
_currentEntity = new Entity(group.World, -1);
|
||||
}
|
||||
|
||||
public Entity Current
|
||||
public ent Current
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
_currentEntity.id = _entities[_index];
|
||||
return _currentEntity;
|
||||
}
|
||||
get { return _source.World.GetEntity(_entities[_index]); }
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool MoveNext()
|
||||
{
|
||||
return ++_index < _entities.Count;
|
||||
}
|
||||
public bool MoveNext() => ++_index < _entities.Count;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Dispose()
|
||||
{
|
||||
_source.Unlock();
|
||||
}
|
||||
public void Dispose() => _source.Unlock();
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Reset()
|
||||
{
|
||||
_index = -1;
|
||||
_currentEntity.id = -1;
|
||||
}
|
||||
public void Reset() => _index = -1;
|
||||
}
|
||||
|
||||
private struct DelayedOp
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq.Expressions;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
@ -25,7 +28,12 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
public interface IEcsSystem { }
|
||||
public interface IEcsRunner { }
|
||||
public interface IEcsRunner
|
||||
{
|
||||
public IList Targets { get; }
|
||||
public object Filter { get; }
|
||||
public bool IsHasFilter { get; }
|
||||
}
|
||||
|
||||
|
||||
public static class IEcsProcessorExtensions
|
||||
@ -36,10 +44,9 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal static class EcsRunnerActivator
|
||||
{
|
||||
private static Dictionary<Guid, Type> _runnerTypes; //interface guid/ Runner type pairs;
|
||||
private static Dictionary<Guid, Type> _runnerHandlerTypes; //interface guid/Runner handler type pairs;
|
||||
|
||||
static EcsRunnerActivator()
|
||||
{
|
||||
@ -47,28 +54,28 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
Type runnerBaseType = typeof(EcsRunner<>);
|
||||
|
||||
List<Type> newRunnerTypes = new List<Type>();
|
||||
newRunnerTypes = Assembly.GetAssembly(runnerBaseType)
|
||||
List<Type> runnerHandlerTypes = new List<Type>();
|
||||
runnerHandlerTypes = Assembly.GetAssembly(runnerBaseType)
|
||||
.GetTypes()
|
||||
.Where(type => type.BaseType != null && type.BaseType.IsGenericType && runnerBaseType == type.BaseType.GetGenericTypeDefinition())
|
||||
.ToList();
|
||||
|
||||
#if DEBUG
|
||||
for (int i = 0; i < newRunnerTypes.Count; i++)
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
for (int i = 0; i < runnerHandlerTypes.Count; i++)
|
||||
{
|
||||
var e = CheckRunnerValide(newRunnerTypes[i]);
|
||||
var e = CheckRunnerValide(runnerHandlerTypes[i]);
|
||||
if (e != null)
|
||||
{
|
||||
newRunnerTypes.RemoveAt(i--);
|
||||
runnerHandlerTypes.RemoveAt(i--);
|
||||
exceptions.Add(e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
_runnerTypes = new Dictionary<Guid, Type>();
|
||||
foreach (var item in newRunnerTypes)
|
||||
_runnerHandlerTypes = new Dictionary<Guid, Type>();
|
||||
foreach (var item in runnerHandlerTypes)
|
||||
{
|
||||
Type intrf = item.GetInterfaces().Where(o => o != typeof(IEcsRunner) && o != typeof(IEcsSystem)).First(); //TODO оптимизировать это место
|
||||
_runnerTypes.Add(intrf.GUID, item);
|
||||
Type interfaceType = item.GetInterfaces().Where(o => o != typeof(IEcsRunner) && o != typeof(IEcsSystem)).First(); //TODO оптимизировать это место
|
||||
_runnerHandlerTypes.Add(interfaceType.GUID, item);
|
||||
}
|
||||
|
||||
if (exceptions.Count > 0)
|
||||
@ -102,7 +109,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
Guid interfaceGuid = nonGenericInterfaceType.GUID;
|
||||
|
||||
if (!_runnerTypes.TryGetValue(interfaceGuid, out Type runnerType))
|
||||
if (!_runnerHandlerTypes.TryGetValue(interfaceGuid, out Type runnerType))
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
@ -111,16 +118,17 @@ namespace DCFApixels.DragonECS
|
||||
Type[] genericTypes = interfaceType.GetGenericArguments();
|
||||
runnerType = runnerType.MakeGenericType(genericTypes);
|
||||
}
|
||||
EcsRunner<TInterface>.Init(runnerType);
|
||||
EcsRunner<TInterface>.Register(runnerType);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class EcsRunner<TInterface> : IEcsSystem, IEcsRunner
|
||||
where TInterface : IEcsSystem
|
||||
{
|
||||
internal static void Init(Type subclass)
|
||||
#region Register
|
||||
private static Type _subclass;
|
||||
internal static void Register(Type subclass)
|
||||
{
|
||||
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
if (_subclass != null)
|
||||
{
|
||||
@ -141,8 +149,14 @@ namespace DCFApixels.DragonECS
|
||||
#endif
|
||||
_subclass = subclass;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static TInterface Instantiate(IEnumerable<IEcsSystem> targets, object filter)
|
||||
#region FilterSystems
|
||||
private static TInterface[] FilterSystems(IEnumerable<IEcsSystem> targets)
|
||||
{
|
||||
return targets.Where(o => o is TInterface).Select(o => (TInterface)o).ToArray();
|
||||
}
|
||||
private static TInterface[] FilterSystems(IEnumerable<IEcsSystem> targets, object filter)
|
||||
{
|
||||
Type interfaceType = typeof(TInterface);
|
||||
|
||||
@ -166,32 +180,52 @@ namespace DCFApixels.DragonECS
|
||||
return atr == null || atr.interfaceType == interfaceType && atr.filter == null;
|
||||
});
|
||||
}
|
||||
return newTargets.Select(o => (TInterface)o).ToArray();
|
||||
}
|
||||
#endregion
|
||||
|
||||
return Instantiate(newTargets.Select(o => (TInterface)o).ToArray());
|
||||
}
|
||||
public static TInterface Instantiate(IEnumerable<IEcsSystem> targets)
|
||||
{
|
||||
return Instantiate(targets.Where(o => o is TInterface).Select(o => (TInterface)o).ToArray());
|
||||
}
|
||||
internal static TInterface Instantiate(TInterface[] targets)
|
||||
#region Instantiate
|
||||
private static TInterface Instantiate(TInterface[] targets, bool isHasFilter, object filter)
|
||||
{
|
||||
if (_subclass == null)
|
||||
EcsRunnerActivator.InitFor<TInterface>();
|
||||
|
||||
var instance = (EcsRunner<TInterface>)Activator.CreateInstance(_subclass);
|
||||
return (TInterface)(IEcsSystem)instance.Set(targets);
|
||||
return (TInterface)(IEcsSystem)instance.Set(targets, isHasFilter, filter);
|
||||
}
|
||||
|
||||
private static Type _subclass;
|
||||
|
||||
protected static void SetSublcass(Type type) => _subclass = type;
|
||||
public static TInterface Instantiate(IEnumerable<IEcsSystem> targets)
|
||||
{
|
||||
return Instantiate(FilterSystems(targets), false, null);
|
||||
}
|
||||
public static TInterface Instantiate(IEnumerable<IEcsSystem> targets, object filter)
|
||||
{
|
||||
return Instantiate(FilterSystems(targets, filter), true, filter);
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected TInterface[] targets;
|
||||
private ReadOnlyCollection<TInterface> _targetsSealed;
|
||||
private object _filter;
|
||||
private bool _isHasFilter;
|
||||
|
||||
private EcsRunner<TInterface> Set(TInterface[] targets)
|
||||
public IList Targets => _targetsSealed;
|
||||
public object Filter => _filter;
|
||||
public bool IsHasFilter => _isHasFilter;
|
||||
private EcsRunner<TInterface> Set(TInterface[] targets, bool isHasFilter, object filter)
|
||||
{
|
||||
this.targets = targets;
|
||||
_targetsSealed = new ReadOnlyCollection<TInterface>(targets);
|
||||
_filter = filter;
|
||||
_isHasFilter = isHasFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
internal void Rebuild(IEnumerable<IEcsSystem> targets)
|
||||
{
|
||||
if(_isHasFilter)
|
||||
Set(FilterSystems(targets), _isHasFilter, _filter);
|
||||
else
|
||||
Set(FilterSystems(targets, _filter), _isHasFilter, _filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,160 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public class EcsWorldMap
|
||||
{
|
||||
private Dictionary<(Type, string), IEcsWorld> _worlds = new Dictionary<(Type, string), IEcsWorld>(8);
|
||||
private bool _built = false;
|
||||
|
||||
public void Add<TArchetype>(EcsWorld<TArchetype> world, string name = "")
|
||||
where TArchetype : IWorldArchetype
|
||||
{
|
||||
if(_built) { throw new Exception($"Cant change built {nameof(EcsWorldMap)}"); }
|
||||
_worlds.Add((typeof(TArchetype), name), world);
|
||||
}
|
||||
|
||||
public EcsWorld<TArchetype> Get<TArchetype>(string name ="")
|
||||
where TArchetype : IWorldArchetype
|
||||
{
|
||||
return (EcsWorld<TArchetype>)_worlds[(typeof(TArchetype), name)];
|
||||
}
|
||||
|
||||
public IEcsWorld Get(Type type, string name = "")
|
||||
{
|
||||
return _worlds[(type, name)];
|
||||
}
|
||||
|
||||
public void Build()
|
||||
{
|
||||
_built = true;
|
||||
}
|
||||
}
|
||||
|
||||
public class EcsSession
|
||||
{
|
||||
private int _id;
|
||||
|
||||
|
||||
private readonly List<IEcsSystem> _allSystems;
|
||||
private ReadOnlyCollection<IEcsSystem> _allSystemsSealed;
|
||||
|
||||
private bool _isInit = false;
|
||||
private bool _isDestoryed = false;
|
||||
|
||||
|
||||
private readonly Dictionary<Type, IEcsRunner> _runners;
|
||||
private IEcsRunSystem _runRunnerCache;
|
||||
|
||||
private readonly EcsWorldMap _worldMap;
|
||||
|
||||
#region Properties
|
||||
public ReadOnlyCollection<IEcsSystem> AllProcessors => _allSystemsSealed;
|
||||
|
||||
#endregion
|
||||
|
||||
public EcsSession()
|
||||
{
|
||||
_allSystems = new List<IEcsSystem>(128);
|
||||
_runners = new Dictionary<Type, IEcsRunner>();
|
||||
_worldMap = new EcsWorldMap();
|
||||
}
|
||||
|
||||
#region Runners
|
||||
public T GetRunner<T>() where T : IEcsSystem
|
||||
{
|
||||
Type type = typeof(T);
|
||||
if (_runners.TryGetValue(type, out IEcsRunner result))
|
||||
{
|
||||
return (T)result;
|
||||
}
|
||||
result = (IEcsRunner)EcsRunner<T>.Instantiate(_allSystems);
|
||||
_runners.Add(type, result);
|
||||
return (T)result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Configuration
|
||||
public EcsSession Add(IEcsSystem system)
|
||||
{
|
||||
CheckInitForMethod(nameof(AddWorld));
|
||||
_allSystems.Add(system);
|
||||
return this;
|
||||
}
|
||||
public EcsSession AddWorld<TArchetype>(EcsWorld<TArchetype> world, string name = "")
|
||||
where TArchetype : IWorldArchetype
|
||||
{
|
||||
CheckInitForMethod(nameof(AddWorld));
|
||||
_worldMap.Add(world, name);
|
||||
return this;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LifeCycle
|
||||
public EcsSession Init()
|
||||
{
|
||||
CheckInitForMethod(nameof(Init));
|
||||
_worldMap.Build();
|
||||
_allSystemsSealed = _allSystems.AsReadOnly();
|
||||
_isInit = true;
|
||||
|
||||
GetRunner<IEcsInject<EcsWorldMap>>().Inject(_worldMap);
|
||||
|
||||
GetRunner<IEcsPreInitSystem>().PreInit(this);
|
||||
GetRunner<IEcsInitSystem>().Init(this);
|
||||
|
||||
_runRunnerCache = GetRunner<IEcsRunSystem>();
|
||||
|
||||
return this;
|
||||
}
|
||||
public void Run()
|
||||
{
|
||||
CheckDestroyForMethod(nameof(Run));
|
||||
|
||||
_runRunnerCache.Run(this);
|
||||
}
|
||||
public void Destroy()
|
||||
{
|
||||
CheckDestroyForMethod(nameof(Destroy));
|
||||
_isDestoryed = true;
|
||||
|
||||
GetRunner<IEcsDestroySystem>().Destroy(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region StateChecks
|
||||
private void CheckInitForMethod(string methodName)
|
||||
{
|
||||
if (_isInit)
|
||||
throw new MethodAccessException($"Запрещено вызывать метод {methodName}, после инициализации {nameof(EcsSession)}");
|
||||
}
|
||||
private void CheckDestroyForMethod(string methodName)
|
||||
{
|
||||
if (_isDestoryed)
|
||||
throw new MethodAccessException($"Запрещено вызывать метод {methodName}, после уничтожения {nameof(EcsSession)}");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EntityConvert
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Entity ToEntity(in ent target)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// return new Entity(null, target.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ent ToEnt(in Entity target)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// return new ent(target.id, target.world._gens[target.id], -1000);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utils
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
196
src/EcsSystems.cs
Normal file
196
src/EcsSystems.cs
Normal file
@ -0,0 +1,196 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public sealed class EcsSystems
|
||||
{
|
||||
private IEcsSystem[] _allSystems;
|
||||
private Dictionary<Type, IEcsRunner> _runners;
|
||||
private IEcsRunSystem _runRunnerCache;
|
||||
|
||||
private ReadOnlyCollection<IEcsSystem> _allSystemsSealed;
|
||||
private ReadOnlyDictionary<Type, IEcsRunner> _allRunnersSealed;
|
||||
|
||||
private bool _isDestoryed;
|
||||
|
||||
#region Properties
|
||||
public ReadOnlyCollection<IEcsSystem> AllSystems => _allSystemsSealed;
|
||||
public ReadOnlyDictionary<Type, IEcsRunner> AllRunners => _allRunnersSealed;
|
||||
public bool IsDestoryed => _isDestoryed;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
private EcsSystems(IEcsSystem[] systems)
|
||||
{
|
||||
_allSystems = systems;
|
||||
_runners = new Dictionary<Type, IEcsRunner>();
|
||||
|
||||
_allSystemsSealed = new ReadOnlyCollection<IEcsSystem>(_allSystems);
|
||||
_allRunnersSealed = new ReadOnlyDictionary<Type, IEcsRunner>(_runners);
|
||||
|
||||
_isDestoryed = false;
|
||||
|
||||
GetRunner<IEcsPreInitSystem>().PreInit(this);
|
||||
GetRunner<IEcsInitSystem>().Init(this);
|
||||
|
||||
_runRunnerCache = GetRunner<IEcsRunSystem>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Runners
|
||||
public T GetRunner<T>() where T : IEcsSystem
|
||||
{
|
||||
Type type = typeof(T);
|
||||
if (_runners.TryGetValue(type, out IEcsRunner result))
|
||||
return (T)result;
|
||||
result = (IEcsRunner)EcsRunner<T>.Instantiate(_allSystems);
|
||||
_runners.Add(type, result);
|
||||
return (T)result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LifeCycle
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Run()
|
||||
{
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
CheckAfterDestroyForMethod(nameof(Run));
|
||||
#endif
|
||||
_runRunnerCache.Run(this);
|
||||
}
|
||||
public void Destroy()
|
||||
{
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
CheckAfterDestroyForMethod(nameof(Destroy));
|
||||
#endif
|
||||
_isDestoryed = true;
|
||||
GetRunner<IEcsDestroySystem>().Destroy(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region StateChecks
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
private void CheckAfterDestroyForMethod(string methodName)
|
||||
{
|
||||
if (_isDestoryed)
|
||||
throw new MethodAccessException($"It is forbidden to call method {methodName}, after destroying {nameof(EcsSystems)}");
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region Builder
|
||||
public static Builder New()
|
||||
{
|
||||
return new Builder();
|
||||
}
|
||||
public class Builder
|
||||
{
|
||||
private const int KEYS_CAPACITY = 4;
|
||||
private readonly HashSet<object> _declaredBlockKeys;
|
||||
private readonly List<object> _blockExecutionOrder;
|
||||
private readonly Dictionary<object, List<IEcsSystem>> _systems;
|
||||
private readonly object _basicBlocKey;
|
||||
private bool _isBasicBlockDeclared;
|
||||
private bool _isOnlyBasicBlock;
|
||||
public Builder()
|
||||
{
|
||||
_basicBlocKey = new object();
|
||||
_declaredBlockKeys = new HashSet<object>(KEYS_CAPACITY);
|
||||
_blockExecutionOrder = new List<object>(KEYS_CAPACITY);
|
||||
_systems = new Dictionary<object, List<IEcsSystem>>(KEYS_CAPACITY);
|
||||
_isBasicBlockDeclared = false;
|
||||
_isOnlyBasicBlock = true;
|
||||
}
|
||||
|
||||
public Builder Add(IEcsSystem system, object blockKey = null)
|
||||
{
|
||||
if (blockKey == null) blockKey = _basicBlocKey;
|
||||
List<IEcsSystem> list;
|
||||
if (!_systems.TryGetValue(blockKey, out list))
|
||||
{
|
||||
list = new List<IEcsSystem>();
|
||||
_systems.Add(blockKey, list);
|
||||
}
|
||||
list.Add(system);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder Add(IEcsModule module)
|
||||
{
|
||||
module.ImportSystems(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder BasicSystemsBlock()
|
||||
{
|
||||
_isBasicBlockDeclared = true;
|
||||
_blockExecutionOrder.Add(_basicBlocKey);
|
||||
return this;
|
||||
}
|
||||
public Builder SystemsBlock(object blockKey)
|
||||
{
|
||||
if (blockKey == null)
|
||||
return BasicSystemsBlock();
|
||||
|
||||
_isOnlyBasicBlock = false;
|
||||
_blockExecutionOrder.Add(blockKey);
|
||||
return this;
|
||||
}
|
||||
|
||||
public EcsSystems Build()
|
||||
{
|
||||
if (_isOnlyBasicBlock)
|
||||
{
|
||||
return new EcsSystems(_systems[_basicBlocKey].ToArray());
|
||||
}
|
||||
|
||||
if(_isBasicBlockDeclared == false)
|
||||
_blockExecutionOrder.Insert(0, _basicBlocKey);
|
||||
|
||||
List<IEcsSystem> result = new List<IEcsSystem>(32);
|
||||
|
||||
List<IEcsSystem> basicBlockList = _systems[_basicBlocKey];
|
||||
|
||||
foreach (var item in _systems)
|
||||
{
|
||||
if (!_blockExecutionOrder.Contains(item.Key))
|
||||
{
|
||||
basicBlockList.AddRange(item.Value);
|
||||
}
|
||||
}
|
||||
foreach (var item in _blockExecutionOrder)
|
||||
{
|
||||
result.AddRange(_systems[item]);
|
||||
}
|
||||
|
||||
return new EcsSystems(result.ToArray());
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public interface IEcsModule
|
||||
{
|
||||
public void ImportSystems(EcsSystems.Builder builder);
|
||||
}
|
||||
|
||||
public static class EcsSystemsExt
|
||||
{
|
||||
public static bool IsNullOrDestroyed(this EcsSystems self)
|
||||
{
|
||||
return self == null || self.IsDestoryed;
|
||||
}
|
||||
public static EcsSystems.Builder Add(this EcsSystems.Builder self, IEnumerable<IEcsSystem> range, object blockKey = null)
|
||||
{
|
||||
foreach (var item in range)
|
||||
{
|
||||
self.Add(item, blockKey);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/EcsSystems.cs.meta
Normal file
11
src/EcsSystems.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb5d6e45240ecad428d33758c4cc4c49
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -21,9 +21,11 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Methods
|
||||
public EcsPool<T> GetPool<T>() where T : struct;
|
||||
public EcsFilter GetFilter<TInc>() where TInc : struct, IInc;
|
||||
public EcsFilter Filter<TInc>() where TInc : struct, IInc;
|
||||
public EcsFilter GetFilter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc;
|
||||
public ent NewEntity();
|
||||
public bool EntityIsAlive(int entityID, short gen);
|
||||
public ent GetEntity(int entityID);
|
||||
public void DelEntity(int entityID);
|
||||
public void Destroy();
|
||||
|
||||
@ -64,7 +66,7 @@ namespace DCFApixels.DragonECS
|
||||
private EcsGroup _entities;
|
||||
|
||||
private short[] _gens;
|
||||
private short[] _componentCounts;
|
||||
//private short[] _componentCounts; //TODO
|
||||
|
||||
private IEcsPool[] _pools;
|
||||
private EcsNullPool _nullPool;
|
||||
@ -86,7 +88,8 @@ namespace DCFApixels.DragonECS
|
||||
_entityDispenser = new IntDispenser();
|
||||
_nullPool = new EcsNullPool(this);
|
||||
_pools = new IEcsPool[512];
|
||||
Array.Fill(_pools, _nullPool);
|
||||
FillArray(_pools, _nullPool);
|
||||
//Array.Fill(_pools, _nullPool); //TODO Fix it
|
||||
_gens = new short[512];
|
||||
_filters = new EcsFilter[64];
|
||||
_entities = new EcsGroup(this, 512);
|
||||
@ -104,7 +107,8 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
int oldCapacity = _pools.Length;
|
||||
Array.Resize(ref _pools, ComponentType.Capacity);
|
||||
Array.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length);
|
||||
FillArray(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length);
|
||||
//Array.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length); //TODO Fix it
|
||||
|
||||
Array.Resize(ref _filtersByIncludedComponents, ComponentType.Capacity);
|
||||
Array.Resize(ref _filtersByExcludedComponents, ComponentType.Capacity);
|
||||
@ -121,7 +125,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region GetFilter
|
||||
|
||||
public EcsFilter GetFilter<TInc>() where TInc : struct, IInc => GetFilter<TInc, Exc>();
|
||||
public EcsFilter Filter<TInc>() where TInc : struct, IInc => GetFilter<TInc, Exc>();
|
||||
public EcsFilter GetFilter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc
|
||||
{
|
||||
var mask = EcsMaskMap<TArchetype>.GetMask<TInc, Exc>();
|
||||
@ -277,19 +281,32 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region NewEntity/DelEntity
|
||||
#region Entity
|
||||
public ent NewEntity()
|
||||
{
|
||||
int entid = _entityDispenser.GetFree();
|
||||
_entities.Add(entid);
|
||||
if (_gens.Length < entid) Array.Resize(ref _gens, _gens.Length << 1);
|
||||
return new ent(entid, _gens[entid]++, id);
|
||||
int entityID = _entityDispenser.GetFree();
|
||||
_entities.Add(entityID);
|
||||
if (_gens.Length <= entityID)
|
||||
Array.Resize(ref _gens, _gens.Length << 1);
|
||||
return new ent(entityID, _gens[entityID]++, id);
|
||||
}
|
||||
public ent GetEntity(int entityID)
|
||||
{
|
||||
if (_entities.Contains(entityID) == false)
|
||||
return ent.NULL;
|
||||
|
||||
return new ent(entityID, _gens[entityID], id);
|
||||
}
|
||||
public void DelEntity(int entityID)
|
||||
{
|
||||
_entityDispenser.Release(entityID);
|
||||
_entities.Remove(entityID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool EntityIsAlive(int entityID, short gen)
|
||||
{
|
||||
return _entities.Contains(entityID) && _gens[entityID] == gen;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Destroy
|
||||
@ -329,6 +346,22 @@ namespace DCFApixels.DragonECS
|
||||
ComponentType.types[uniqueID] = typeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
private void FillArray<T>(T[] array, T value, int startIndex = 0, int length = -1)
|
||||
{
|
||||
if (length < 0)
|
||||
{
|
||||
length = array.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = startIndex + length;
|
||||
}
|
||||
for (int i = startIndex; i < length; i++)
|
||||
{
|
||||
array[i] = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
130
src/Entity.cs
130
src/Entity.cs
@ -5,52 +5,34 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)]
|
||||
// id - 32 bits
|
||||
// gen - 16 bits
|
||||
// world - 16 bits
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 2, Size = 8)]
|
||||
public readonly struct ent : IEquatable<long>, IEquatable<ent>
|
||||
{
|
||||
public static readonly ent NULL = default;
|
||||
|
||||
// id - 32 bits
|
||||
// gen - 16 bits
|
||||
// world - 16 bits
|
||||
public readonly long _full;
|
||||
|
||||
#region Properties
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public int id
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => (int)(_full >> 32);
|
||||
}
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public ushort gen
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => (ushort)((_full << 32) >> 48);
|
||||
|
||||
}
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public short world
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => (short)((_full << 48) >> 48);
|
||||
|
||||
}
|
||||
#endregion
|
||||
[FieldOffset(0)]
|
||||
private readonly long _full;
|
||||
[FieldOffset(3)]
|
||||
public readonly int id;
|
||||
[FieldOffset(1)]
|
||||
public readonly short gen;
|
||||
[FieldOffset(0)]
|
||||
public readonly short world;
|
||||
|
||||
#region Constructors
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public ent(int id, short gen, short world)
|
||||
public ent(int id, short gen, short world): this()
|
||||
{
|
||||
_full = ((long)id) << 32;
|
||||
_full += ((long)gen) << 16;
|
||||
_full += world;
|
||||
this.id = id;
|
||||
this.gen = gen;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ent(long value)
|
||||
internal ent(long full) : this()
|
||||
{
|
||||
_full = value;
|
||||
_full = full;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -64,14 +46,9 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Equals
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(in ent other)
|
||||
{
|
||||
return _full == other._full;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is ent other && Equals(in other);
|
||||
return obj is ent other && _full == other._full;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(ent other)
|
||||
@ -85,26 +62,39 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override string ToString() => $"ent(id:{id} gen:{gen} world:{world})";
|
||||
#endregion
|
||||
|
||||
#region operators
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(in ent left, in ent right) => left.Equals(in right);
|
||||
public static bool operator ==(in ent a, in ent b) => a._full == b._full;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(in ent left, in ent right) => !left.Equals(in right);
|
||||
public static bool operator !=(in ent a, in ent b) => a._full != b._full;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator long(in ent eent) => eent._full;
|
||||
public static explicit operator long(in ent a) => a._full;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator int(in ent eent) => eent.id;
|
||||
public static explicit operator int(in ent a) => a.id;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator ent(in long value) => new ent(value);
|
||||
public static explicit operator ent(in long a) => new ent(a);
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static partial class entExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsAlive(this ref ent self)
|
||||
{
|
||||
bool result = EcsWorld.Worlds[self.world].EntityIsAlive(self.id, self.gen);
|
||||
if (!result) self = ent.NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNull(this in ent self)
|
||||
{
|
||||
@ -136,50 +126,4 @@ namespace DCFApixels.DragonECS
|
||||
EcsWorld.Worlds[self.world].GetPool<T>().Del(self.id);
|
||||
}
|
||||
}
|
||||
|
||||
public struct Entity
|
||||
{
|
||||
public IEcsWorld world;
|
||||
public int id;
|
||||
|
||||
public Entity(IEcsWorld world, int id)
|
||||
{
|
||||
this.world = world;
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
public static partial class EntityExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNull(this in Entity self)
|
||||
{
|
||||
return self.world == null;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref readonly T Read<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
return ref self.world.GetPool<T>().Read(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref T Write<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
return ref self.world.GetPool<T>().Write(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool Has<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
return self.world.GetPool<T>().Has(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Del<T>(this in Entity self)
|
||||
where T : struct
|
||||
{
|
||||
self.world.GetPool<T>().Del(self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,8 +7,8 @@ namespace DCFApixels.DragonECS
|
||||
public class EcsFrameworkException : Exception
|
||||
{
|
||||
public EcsFrameworkException() { }
|
||||
public EcsFrameworkException(string message) : base(Exceptions.MESSAGE_SUFFIX + message) { }
|
||||
public EcsFrameworkException(string message, Exception inner) : base(Exceptions.MESSAGE_SUFFIX + message, inner) { }
|
||||
public EcsFrameworkException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { }
|
||||
public EcsFrameworkException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { }
|
||||
protected EcsFrameworkException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
internal static class Exceptions
|
||||
{
|
||||
public const string MESSAGE_SUFFIX = "[DragonECS] ";
|
||||
}
|
||||
}
|
||||
@ -8,3 +8,9 @@ DCFAECS_NO_SANITIZE_CHECKS - отвключение дополнительных
|
||||
|
||||
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
|
||||
|
||||
// [EditorBrowsable(EditorBrowsableState.Never)]
|
||||
|
||||
|
||||
//throw new EcsFrameworkException($"There is no suitable EcsRunner implementation for the {typeof(T).FullName} interface");
|
||||
|
||||
@ -80,7 +80,7 @@ namespace DCFApixels.DragonECS
|
||||
if (_count >= _dense.Length)
|
||||
Array.Resize(ref _dense, _dense.Length << 1);
|
||||
|
||||
if (value > _sparse.Length)
|
||||
if (value >= _sparse.Length)
|
||||
{
|
||||
int neadedSpace = _sparse.Length;
|
||||
while (value >= neadedSpace)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user