DragonECS/src/EcsQuery.cs

163 lines
5.6 KiB
C#
Raw Normal View History

2023-04-07 18:16:13 +08:00
using System;
using System.Collections.Generic;
using System.Reflection;
2023-04-09 02:52:39 +08:00
using Unity.Profiling;
namespace DCFApixels.DragonECS
{
2023-04-17 22:58:52 +08:00
public abstract class EcsQueryBase
2023-04-07 15:11:48 +08:00
{
internal EcsWorld source;
2023-04-09 02:52:39 +08:00
internal EcsGroup groupFilter;
2023-04-07 15:11:48 +08:00
internal EcsQueryMask mask;
public EcsWorld World => source;
#region Builder
2023-04-17 22:58:52 +08:00
protected virtual void Init(Builder b) { }
2023-04-18 19:35:42 +08:00
protected abstract void OnBuildAfter();
2023-04-17 22:58:52 +08:00
public abstract void Execute();
public sealed class Builder : EcsQueryBuilderBase
{
private EcsWorld _world;
private List<int> _inc;
private List<int> _exc;
private Builder(EcsWorld world)
2023-04-17 22:58:52 +08:00
{
_world = world;
_inc = new List<int>(8);
_exc = new List<int>(4);
}
internal static TQuery Build<TQuery>(EcsWorld world) where TQuery : EcsQueryBase
{
Builder builder = new Builder(world);
Type queryType = typeof(TQuery);
ConstructorInfo constructorInfo = queryType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Builder) }, null);
2023-04-17 22:58:52 +08:00
EcsQueryBase newQuery;
if (constructorInfo != null)
{
2023-04-17 22:58:52 +08:00
newQuery = (EcsQueryBase)constructorInfo.Invoke(new object[] { builder });
}
else
{
2023-04-17 22:58:52 +08:00
newQuery = (EcsQueryBase)Activator.CreateInstance(typeof(TQuery));
newQuery.Init(builder);
}
2023-04-15 00:23:46 +08:00
newQuery.groupFilter = EcsGroup.New(world);
2023-04-17 22:58:52 +08:00
newQuery.source = world;
builder.End(out newQuery.mask);
2023-04-18 19:35:42 +08:00
newQuery.OnBuildAfter();
return (TQuery)(object)newQuery;
}
2023-04-17 22:58:52 +08:00
public override inc_<TComponent> Include<TComponent>() where TComponent : struct
{
_inc.Add(_world.GetComponentID<TComponent>());
2023-04-21 01:05:06 +08:00
return new inc_<TComponent>(_world.GetOrCreatePool<TComponent>());
}
2023-04-17 22:58:52 +08:00
public override exc_<TComponent> Exclude<TComponent>() where TComponent : struct
{
_exc.Add(_world.GetComponentID<TComponent>());
2023-04-21 01:05:06 +08:00
return new exc_<TComponent>(_world.GetOrCreatePool<TComponent>());
}
2023-04-17 22:58:52 +08:00
public override opt_<TComponent> Optional<TComponent>() where TComponent : struct
{
2023-04-21 01:05:06 +08:00
return new opt_<TComponent>(_world.GetOrCreatePool<TComponent>());
}
private void End(out EcsQueryMask mask)
{
_inc.Sort();
_exc.Sort();
2023-04-20 19:23:58 +08:00
mask = new EcsQueryMask(_world.Archetype, _inc.ToArray(), _exc.ToArray());
_world = null;
_inc = null;
_exc = null;
}
}
#endregion
}
2023-04-20 18:23:23 +08:00
public abstract class EcsHierarchyQuery : EcsQueryBase
{
private ProfilerMarker _getEnumerator = new ProfilerMarker("EcsHierarchyQuery.Execute");
2023-04-20 18:23:23 +08:00
protected override void OnBuildAfter() { }
public override void Execute()
{
}
}
public abstract class EcsGraphQuery : EcsQueryBase
2023-04-17 22:58:52 +08:00
{
2023-04-18 19:35:42 +08:00
private EcsPool<Edge> attachPool;
2023-04-17 22:58:52 +08:00
2023-04-20 18:23:23 +08:00
private ProfilerMarker _getEnumerator = new ProfilerMarker("EcsGraphQuery.Execute");
2023-04-18 19:35:42 +08:00
protected sealed override void OnBuildAfter()
2023-04-17 22:58:52 +08:00
{
2023-04-21 01:05:06 +08:00
attachPool = World.GetOrCreatePool<Edge>();
2023-04-17 22:58:52 +08:00
}
public sealed override void Execute()
{
using (_getEnumerator.Auto())
{
throw new NotImplementedException();
}
}
public EcsGroup.Enumerator GetEnumerator()
{
return groupFilter.GetEnumerator();
}
}
public abstract class EcsQuery : EcsQueryBase
{
2023-04-20 18:23:23 +08:00
private ProfilerMarker _getEnumerator = new ProfilerMarker("EcsQuery.Execute");
2023-04-18 19:35:42 +08:00
protected sealed override void OnBuildAfter() { }
2023-04-17 22:58:52 +08:00
public sealed override void Execute()
{
using (_getEnumerator.Auto())
{
var pools = World.GetAllPools();
EcsReadonlyGroup all = World.Entities;
groupFilter.Clear();
foreach (var e in all)
{
int entityID = e.id;
for (int i = 0, iMax = mask.Inc.Length; i < iMax; i++)
{
if (!pools[mask.Inc[i]].Has(entityID))
continue;
}
for (int i = 0, iMax = mask.Exc.Length; i < iMax; i++)
{
if (pools[mask.Exc[i]].Has(entityID))
continue;
}
groupFilter.AggressiveAdd(entityID);
}
groupFilter.Sort();
}
}
public EcsGroup.Enumerator GetEnumerator()
{
return groupFilter.GetEnumerator();
}
}
2023-04-07 18:16:13 +08:00
public class EcsQueryMask : EcsComponentMask
{
2023-04-07 14:03:29 +08:00
public EcsQueryMask(Type worldArchetypeType, int[] inc, int[] exc)
{
2023-04-20 19:23:58 +08:00
WorldArchetype = worldArchetypeType;
Inc = inc;
Exc = exc;
}
}
2023-04-17 22:58:52 +08:00
public abstract class EcsQueryBuilderBase
2023-04-07 17:15:31 +08:00
{
2023-04-17 22:58:52 +08:00
public abstract inc_<TComponent> Include<TComponent>() where TComponent : struct;
public abstract exc_<TComponent> Exclude<TComponent>() where TComponent : struct;
public abstract opt_<TComponent> Optional<TComponent>() where TComponent : struct;
2023-04-07 17:15:31 +08:00
}
}