diff --git a/src/Builtin/Subjects.cs b/src/Builtin/Subjects.cs new file mode 100644 index 0000000..fbf8462 --- /dev/null +++ b/src/Builtin/Subjects.cs @@ -0,0 +1,228 @@ +namespace DCFApixels.DragonECS +{ + public class SingleSubject : EcsSubject where TPool : IEcsPoolImplementation, new() + { + public readonly TPool pool; + public SingleSubject(Builder b) + { + pool = b.Include(); + } + } + public class CombinedSubject : EcsSubject + where S0 : EcsSubject + where S1 : EcsSubject + { + public readonly S0 s0; + public readonly S1 s1; + public CombinedSubject(Builder b) + { + s0 = b.Combine(); + s1 = b.Combine(); + } + } + + public class CombinedSubject : EcsSubject + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + { + public readonly S0 s0; + public readonly S1 s1; + public readonly S2 s2; + public CombinedSubject(Builder b) + { + s0 = b.Combine(); + s1 = b.Combine(); + s2 = b.Combine(); + } + } + + public class CombinedSubject : EcsSubject + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + where S3 : EcsSubject + { + public readonly S0 s0; + public readonly S1 s1; + public readonly S2 s2; + public readonly S3 s3; + public CombinedSubject(Builder b) + { + s0 = b.Combine(); + s1 = b.Combine(); + s2 = b.Combine(); + s3 = b.Combine(); + } + } + + public class CombinedSubject : EcsSubject + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + where S3 : EcsSubject + where S4 : EcsSubject + { + public readonly S0 s0; + public readonly S1 s1; + public readonly S2 s2; + public readonly S3 s3; + public readonly S4 s4; + public CombinedSubject(Builder b) + { + s0 = b.Combine(); + s1 = b.Combine(); + s2 = b.Combine(); + s3 = b.Combine(); + s4 = b.Combine(); + } + } + + public class CombinedSubject : EcsSubject + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + where S3 : EcsSubject + where S4 : EcsSubject + where S5 : EcsSubject + { + public readonly S0 s0; + public readonly S1 s1; + public readonly S2 s2; + public readonly S3 s3; + public readonly S4 s4; + public readonly S5 s5; + public CombinedSubject(Builder b) + { + s0 = b.Combine(); + s1 = b.Combine(); + s2 = b.Combine(); + s3 = b.Combine(); + s4 = b.Combine(); + s5 = b.Combine(); + } + } + + public static class CombinedSubjectExtensions + { + #region 2 + public static EcsReadonlyGroup Where(this EcsWorld self, out S0 s0, out S1 s1) + where S0 : EcsSubject + where S1 : EcsSubject + { + return self.WhereFor(self.Entities, out s0, out s1); + } + public static EcsReadonlyGroup WhereFor(this EcsWorld self, EcsReadonlyGroup sourceGroup, out S0 s0, out S1 s1) + where S0 : EcsSubject + where S1 : EcsSubject + { + var combined = self.GetSubject>(); + s0 = combined.s0; + s1 = combined.s1; + return self.WhereFor>(sourceGroup); + } + #endregion + + #region 3 + public static EcsReadonlyGroup Where(this EcsWorld self, out S0 s0, out S1 s1, out S2 s2) + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + { + return self.WhereFor(self.Entities, out s0, out s1, out s2); + } + public static EcsReadonlyGroup WhereFor(this EcsWorld self, EcsReadonlyGroup sourceGroup, out S0 s0, out S1 s1, out S2 s2) + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + { + var combined = self.GetSubject>(); + s0 = combined.s0; + s1 = combined.s1; + s2 = combined.s2; + return self.WhereFor>(sourceGroup); + } + #endregion + + #region 4 + public static EcsReadonlyGroup Where(this EcsWorld self, out S0 s0, out S1 s1, out S2 s2, out S3 s3) + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + where S3 : EcsSubject + { + return self.WhereFor(self.Entities, out s0, out s1, out s2, out s3); + } + public static EcsReadonlyGroup WhereFor(this EcsWorld self, EcsReadonlyGroup sourceGroup, out S0 s0, out S1 s1, out S2 s2, out S3 s3) + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + where S3 : EcsSubject + { + var combined = self.GetSubject>(); + s0 = combined.s0; + s1 = combined.s1; + s2 = combined.s2; + s3 = combined.s3; + return self.WhereFor>(sourceGroup); + } + #endregion + + #region 5 + public static EcsReadonlyGroup Where(this EcsWorld self, out S0 s0, out S1 s1, out S2 s2, out S3 s3, out S4 s4) + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + where S3 : EcsSubject + where S4 : EcsSubject + { + return self.WhereFor(self.Entities, out s0, out s1, out s2, out s3, out s4); + } + public static EcsReadonlyGroup WhereFor(this EcsWorld self, EcsReadonlyGroup sourceGroup, out S0 s0, out S1 s1, out S2 s2, out S3 s3, out S4 s4) + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + where S3 : EcsSubject + where S4 : EcsSubject + { + var combined = self.GetSubject>(); + s0 = combined.s0; + s1 = combined.s1; + s2 = combined.s2; + s3 = combined.s3; + s4 = combined.s4; + return self.WhereFor>(sourceGroup); + } + #endregion + + #region 6 + public static EcsReadonlyGroup Where(this EcsWorld self, out S0 s0, out S1 s1, out S2 s2, out S3 s3, out S4 s4, out S5 s5) + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + where S3 : EcsSubject + where S4 : EcsSubject + where S5 : EcsSubject + { + return self.WhereFor(self.Entities, out s0, out s1, out s2, out s3, out s4, out s5); + } + public static EcsReadonlyGroup WhereFor(this EcsWorld self, EcsReadonlyGroup sourceGroup, out S0 s0, out S1 s1, out S2 s2, out S3 s3, out S4 s4, out S5 s5) + where S0 : EcsSubject + where S1 : EcsSubject + where S2 : EcsSubject + where S3 : EcsSubject + where S4 : EcsSubject + where S5 : EcsSubject + { + var combined = self.GetSubject>(); + s0 = combined.s0; + s1 = combined.s1; + s2 = combined.s2; + s3 = combined.s3; + s4 = combined.s4; + s5 = combined.s5; + return self.WhereFor>(sourceGroup); + } + #endregion + } +} diff --git a/src/EcsSubject.cs b/src/EcsSubject.cs index 0da9ce9..9fbfbf0 100644 --- a/src/EcsSubject.cs +++ b/src/EcsSubject.cs @@ -35,22 +35,22 @@ namespace DCFApixels.DragonECS public sealed class Builder : EcsSubjectBuilderBase { private EcsWorld _world; - private List _inc; - private List _exc; + private HashSet _inc; + private HashSet _exc; public EcsWorld World => _world; private Builder(EcsWorld world) { _world = world; - _inc = new List(8); - _exc = new List(4); + _inc = new HashSet(8); + _exc = new HashSet(4); } internal static TSubject Build(EcsWorld world) where TSubject : EcsSubject { Builder builder = new Builder(world); - Type queryType = typeof(TSubject); - ConstructorInfo constructorInfo = queryType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Builder) }, null); + Type subjectType = typeof(TSubject); + ConstructorInfo constructorInfo = subjectType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Builder) }, null); EcsSubject newSubject; if (constructorInfo != null) { @@ -100,11 +100,24 @@ namespace DCFApixels.DragonECS } #endregion + #region Combine + public TOtherSubject Combine() where TOtherSubject : EcsSubject + { + var result = _world.GetSubject(); + _inc.UnionWith(result.mask._inc); + _exc.UnionWith(result.mask._exc); + return result; + } + #endregion + private void End(out EcsMask mask) { - _inc.Sort(); - _exc.Sort(); - mask = new EcsMask(_world.Archetype, _inc.ToArray(), _exc.ToArray()); + var inc = _inc.ToArray(); + Array.Sort(inc); + var exc = _exc.ToArray(); + Array.Sort(exc); + + mask = new EcsMask(_world.Archetype, inc, exc); _world = null; _inc = null; _exc = null; @@ -161,12 +174,25 @@ namespace DCFApixels.DragonECS _exc = exc; } + public static EcsMask Union(EcsMask a, EcsMask b) + { + if(a._worldType != b._worldType) ThrowHelper.ThrowArgumentDifferentWorldsException(); + + HashSet incset = new HashSet(a._inc); + HashSet excset = new HashSet(a._exc); + incset.UnionWith(b._inc); + excset.UnionWith(b._exc); + return new EcsMask(a._worldType, incset.ToArray(), excset.ToArray()); + } + + #region Object public override string ToString() => CreateLogString(_worldType, _inc, _exc); + #endregion #region Debug utils private static string CreateLogString(Type worldType, int[] inc, int[] exc) { -#if DEBUG +#if (DEBUG && !DISABLE_DEBUG) int worldID = WorldMetaStorage.GetWorldID(worldType); string converter(int o) => EcsDebugUtility.GetGenericTypeName(WorldMetaStorage.GetComponentType(worldID, o), 1); return $"Inc({string.Join(", ", inc.Select(converter))}) Exc({string.Join(", ", exc.Select(converter))})"; @@ -194,6 +220,14 @@ namespace DCFApixels.DragonECS public override string ToString() => CreateLogString(worldType, inc, exc); } #endregion + + #region ThrowHelper + internal static class ThrowHelper + { + [MethodImpl(MethodImplOptions.NoInlining)] + public static void ThrowArgumentDifferentWorldsException() => throw new ArgumentException("The groups belong to different worlds."); + } + #endregion } #endregion