add CombinedSubject

This commit is contained in:
Mikhail 2023-06-03 01:58:54 +08:00
parent 39ca9d7d74
commit 80ac00e887
2 changed files with 272 additions and 10 deletions

228
src/Builtin/Subjects.cs Normal file
View File

@ -0,0 +1,228 @@
namespace DCFApixels.DragonECS
{
public class SingleSubject<TComponent, TPool> : EcsSubject where TPool : IEcsPoolImplementation<TComponent>, new()
{
public readonly TPool pool;
public SingleSubject(Builder b)
{
pool = b.Include<TComponent, TPool>();
}
}
public class CombinedSubject<S0, S1> : EcsSubject
where S0 : EcsSubject
where S1 : EcsSubject
{
public readonly S0 s0;
public readonly S1 s1;
public CombinedSubject(Builder b)
{
s0 = b.Combine<S0>();
s1 = b.Combine<S1>();
}
}
public class CombinedSubject<S0, S1, S2> : 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<S0>();
s1 = b.Combine<S1>();
s2 = b.Combine<S2>();
}
}
public class CombinedSubject<S0, S1, S2, S3> : 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<S0>();
s1 = b.Combine<S1>();
s2 = b.Combine<S2>();
s3 = b.Combine<S3>();
}
}
public class CombinedSubject<S0, S1, S2, S3, S4> : 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<S0>();
s1 = b.Combine<S1>();
s2 = b.Combine<S2>();
s3 = b.Combine<S3>();
s4 = b.Combine<S4>();
}
}
public class CombinedSubject<S0, S1, S2, S3, S4, S5> : 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<S0>();
s1 = b.Combine<S1>();
s2 = b.Combine<S2>();
s3 = b.Combine<S3>();
s4 = b.Combine<S4>();
s5 = b.Combine<S5>();
}
}
public static class CombinedSubjectExtensions
{
#region 2
public static EcsReadonlyGroup Where<S0, S1>(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<S0, S1>(this EcsWorld self, EcsReadonlyGroup sourceGroup, out S0 s0, out S1 s1)
where S0 : EcsSubject
where S1 : EcsSubject
{
var combined = self.GetSubject<CombinedSubject<S0, S1>>();
s0 = combined.s0;
s1 = combined.s1;
return self.WhereFor<CombinedSubject<S0, S1>>(sourceGroup);
}
#endregion
#region 3
public static EcsReadonlyGroup Where<S0, S1, S2>(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<S0, S1, S2>(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<CombinedSubject<S0, S1, S2>>();
s0 = combined.s0;
s1 = combined.s1;
s2 = combined.s2;
return self.WhereFor<CombinedSubject<S0, S1, S2>>(sourceGroup);
}
#endregion
#region 4
public static EcsReadonlyGroup Where<S0, S1, S2, S3>(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<S0, S1, S2, S3>(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<CombinedSubject<S0, S1, S2, S3>>();
s0 = combined.s0;
s1 = combined.s1;
s2 = combined.s2;
s3 = combined.s3;
return self.WhereFor<CombinedSubject<S0, S1, S2, S3>>(sourceGroup);
}
#endregion
#region 5
public static EcsReadonlyGroup Where<S0, S1, S2, S3, S4>(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<S0, S1, S2, S3, S4>(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<CombinedSubject<S0, S1, S2, S3, S4>>();
s0 = combined.s0;
s1 = combined.s1;
s2 = combined.s2;
s3 = combined.s3;
s4 = combined.s4;
return self.WhereFor<CombinedSubject<S0, S1, S2, S3, S4>>(sourceGroup);
}
#endregion
#region 6
public static EcsReadonlyGroup Where<S0, S1, S2, S3, S4, S5>(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<S0, S1, S2, S3, S4, S5>(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<CombinedSubject<S0, S1, S2, S3, S4, S5>>();
s0 = combined.s0;
s1 = combined.s1;
s2 = combined.s2;
s3 = combined.s3;
s4 = combined.s4;
s5 = combined.s5;
return self.WhereFor<CombinedSubject<S0, S1, S2, S3, S4, S5>>(sourceGroup);
}
#endregion
}
}

View File

@ -35,22 +35,22 @@ namespace DCFApixels.DragonECS
public sealed class Builder : EcsSubjectBuilderBase
{
private EcsWorld _world;
private List<int> _inc;
private List<int> _exc;
private HashSet<int> _inc;
private HashSet<int> _exc;
public EcsWorld World => _world;
private Builder(EcsWorld world)
{
_world = world;
_inc = new List<int>(8);
_exc = new List<int>(4);
_inc = new HashSet<int>(8);
_exc = new HashSet<int>(4);
}
internal static TSubject Build<TSubject>(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<TOtherSubject>() where TOtherSubject : EcsSubject
{
var result = _world.GetSubject<TOtherSubject>();
_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<int> incset = new HashSet<int>(a._inc);
HashSet<int> excset = new HashSet<int>(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