DragonECS/src/EcsQuery.cs

135 lines
4.6 KiB
C#
Raw Normal View History

2023-04-07 18:16:13 +08:00
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
2023-04-09 02:52:39 +08:00
using Unity.Profiling;
using UnityEngine;
using UnityEngine.UI;
namespace DCFApixels.DragonECS
{
2023-04-12 23:09:50 +08:00
public abstract class EcsQuery
2023-04-07 15:11:48 +08:00
{
2023-04-09 02:52:39 +08:00
internal EcsGroup groupFilter;
2023-04-07 15:11:48 +08:00
internal EcsQueryMask mask;
2023-04-09 02:52:39 +08:00
public IEcsWorld World => groupFilter.World;
2023-04-09 02:52:39 +08:00
private ProfilerMarker _getEnumerator = new ProfilerMarker("EcsQuery.GetEnumerator");
2023-04-15 00:23:46 +08:00
2023-04-09 02:52:39 +08:00
public EcsGroup.Enumerator GetEnumerator()
{
using (_getEnumerator.Auto())
{
2023-04-15 00:23:46 +08:00
var pools = World.GetAllPools();
EcsReadonlyGroup all = World.Entities;
groupFilter.Clear();
foreach (var e in all)
2023-04-09 02:52:39 +08:00
{
2023-04-15 00:23:46 +08:00
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);
2023-04-09 02:52:39 +08:00
}
2023-04-15 00:23:46 +08:00
groupFilter.Sort();
return groupFilter.GetEnumerator();
2023-04-09 02:52:39 +08:00
}
}
protected virtual void Init(Builder b) { }
#region Builder
2023-04-07 14:03:29 +08:00
public sealed class Builder : EcsQueryBuilder
{
private IEcsWorld _world;
private List<int> _inc;
private List<int> _exc;
2023-04-12 23:09:50 +08:00
internal static TQuery Build<TQuery>(IEcsWorld world) where TQuery : EcsQuery
{
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-12 23:09:50 +08:00
EcsQuery newQuery;
if (constructorInfo != null)
{
2023-04-12 23:09:50 +08:00
newQuery = (EcsQuery)constructorInfo.Invoke(new object[] { builder });
}
else
{
2023-04-12 23:09:50 +08:00
newQuery = (EcsQuery)Activator.CreateInstance(typeof(TQuery));
newQuery.Init(builder);
}
builder.End(out newQuery.mask);
2023-04-15 00:23:46 +08:00
// newQuery.groupFilter = new EcsGroup(world);
newQuery.groupFilter = EcsGroup.New(world);
return (TQuery)(object)newQuery;
}
private Builder(IEcsWorld world)
{
_world = world;
_inc = new List<int>(8);
_exc = new List<int>(4);
}
public override inc<TComponent> Include<TComponent>() where TComponent : struct
{
_inc.Add(_world.GetComponentID<TComponent>());
return new inc<TComponent>(_world.GetPool<TComponent>());
}
public override exc<TComponent> Exclude<TComponent>() where TComponent : struct
{
_exc.Add(_world.GetComponentID<TComponent>());
return new exc<TComponent>(_world.GetPool<TComponent>());
}
public override opt<TComponent> Optional<TComponent>() where TComponent : struct
{
return new opt<TComponent>(_world.GetPool<TComponent>());
}
private void End(out EcsQueryMask mask)
{
_inc.Sort();
_exc.Sort();
2023-04-07 14:03:29 +08:00
mask = new EcsQueryMask(_world.ArchetypeType, _inc.ToArray(), _exc.ToArray());
_world = null;
_inc = null;
_exc = null;
}
}
#endregion
}
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)
{
WorldArchetypeType = worldArchetypeType;
Inc = inc;
Exc = exc;
}
}
2023-04-07 17:15:31 +08:00
public abstract class EcsQueryBuilder
{
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;
}
}