mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44:35 +08:00
add CombinedSubject
This commit is contained in:
parent
39ca9d7d74
commit
80ac00e887
228
src/Builtin/Subjects.cs
Normal file
228
src/Builtin/Subjects.cs
Normal 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
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user