advanced query system
parent
728109bfc6
commit
50974c181a
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Encompass
|
||||
|
@ -6,7 +7,12 @@ namespace Encompass
|
|||
internal class ComponentStore
|
||||
{
|
||||
private Dictionary<Type, TypedComponentStore> Stores = new Dictionary<Type, TypedComponentStore>(512);
|
||||
private ComponentBitSet componentBitSet = new ComponentBitSet();
|
||||
private ComponentBitSet componentBitSet;
|
||||
|
||||
public ComponentStore(Dictionary<Type, int> typeToIndex)
|
||||
{
|
||||
componentBitSet = new ComponentBitSet(typeToIndex);
|
||||
}
|
||||
|
||||
public IEnumerable<(Type, TypedComponentStore)> StoresEnumerable()
|
||||
{
|
||||
|
@ -22,7 +28,6 @@ namespace Encompass
|
|||
{
|
||||
var store = new TypedComponentStore<TComponent>();
|
||||
Stores.Add(typeof(TComponent), store);
|
||||
componentBitSet.RegisterType<TComponent>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,9 +52,9 @@ namespace Encompass
|
|||
return Stores.ContainsKey(type) && Stores[type].Has(entity);
|
||||
}
|
||||
|
||||
public IEnumerable<Entity> EntitiesWithComponents(IEnumerable<Type> types)
|
||||
public BitArray EntityBitArray(Entity entity)
|
||||
{
|
||||
return componentBitSet.EntitiesWithComponents(types);
|
||||
return componentBitSet.EntityBitArray(entity);
|
||||
}
|
||||
|
||||
public TComponent Get<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
|
|
|
@ -8,21 +8,25 @@ namespace Encompass
|
|||
{
|
||||
BitArrayPool bitArrayPool = new BitArrayPool(32768); // todo: set entity cap
|
||||
Dictionary<Entity, BitArray> entities = new Dictionary<Entity, BitArray>();
|
||||
Dictionary<Type, int> typeToIndex = new Dictionary<Type, int>();
|
||||
BitArray queryArray;
|
||||
Dictionary<Type, int> TypeToIndex { get; set; }
|
||||
BitArray withQueryArray;
|
||||
BitArray withoutQueryArray;
|
||||
BitArray emptyArray;
|
||||
|
||||
public void RegisterType<TComponent>() where TComponent : struct, IComponent
|
||||
public ComponentBitSet(Dictionary<Type, int> typeToIndex)
|
||||
{
|
||||
typeToIndex.Add(typeof(TComponent), typeToIndex.Count);
|
||||
foreach (var kvp in entities)
|
||||
{
|
||||
kvp.Value.Length = typeToIndex.Count;
|
||||
}
|
||||
TypeToIndex = typeToIndex;
|
||||
}
|
||||
|
||||
public void FinishRegistering()
|
||||
{
|
||||
queryArray = new BitArray(typeToIndex.Count);
|
||||
withQueryArray = new BitArray(TypeToIndex.Count);
|
||||
withoutQueryArray = new BitArray(TypeToIndex.Count);
|
||||
emptyArray = new BitArray(TypeToIndex.Count);
|
||||
foreach (var kvp in entities)
|
||||
{
|
||||
kvp.Value.Length = TypeToIndex.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
|
@ -36,19 +40,19 @@ namespace Encompass
|
|||
|
||||
public void AddEntity(Entity entity)
|
||||
{
|
||||
var bitArray = bitArrayPool.Obtain(typeToIndex.Count);
|
||||
var bitArray = bitArrayPool.Obtain(TypeToIndex.Count);
|
||||
entities.Add(entity, bitArray);
|
||||
}
|
||||
|
||||
public void Set<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
if (!entities.ContainsKey(entity)) { AddEntity(entity); }
|
||||
entities[entity].Set(typeToIndex[typeof(TComponent)], true);
|
||||
entities[entity].Set(TypeToIndex[typeof(TComponent)], true);
|
||||
}
|
||||
|
||||
public void RemoveComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
entities[entity].Set(typeToIndex[typeof(TComponent)], false);
|
||||
entities[entity].Set(TypeToIndex[typeof(TComponent)], false);
|
||||
}
|
||||
|
||||
public void RemoveEntity(Entity entity)
|
||||
|
@ -60,26 +64,9 @@ namespace Encompass
|
|||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Entity> EntitiesWithComponents(IEnumerable<Type> types)
|
||||
public BitArray EntityBitArray(Entity entity)
|
||||
{
|
||||
foreach (var kvp in entities)
|
||||
{
|
||||
queryArray.SetAll(false);
|
||||
foreach (var type in types)
|
||||
{
|
||||
queryArray.Set(typeToIndex[type], true);
|
||||
}
|
||||
queryArray.And(kvp.Value);
|
||||
var hasComponents = true;
|
||||
foreach (var type in types)
|
||||
{
|
||||
if (!queryArray.Get(typeToIndex[type])) {
|
||||
hasComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasComponents) { yield return kvp.Key; }
|
||||
}
|
||||
return entities.ContainsKey(entity) ? entities[entity] : emptyArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,14 @@ namespace Encompass
|
|||
private readonly DrawLayerManager drawLayerManager;
|
||||
private readonly ComponentUpdateManager componentUpdateManager;
|
||||
|
||||
private readonly ComponentStore componentStore = new ComponentStore();
|
||||
private readonly ComponentStore componentStore;
|
||||
private readonly HashSet<Entity> entitiesMarkedForRemoval = new HashSet<Entity>();
|
||||
|
||||
public ComponentManager(DrawLayerManager drawLayerManager, ComponentUpdateManager componentUpdateManager)
|
||||
public ComponentManager(DrawLayerManager drawLayerManager, ComponentUpdateManager componentUpdateManager, Dictionary<Type, int> typeToIndex)
|
||||
{
|
||||
this.drawLayerManager = drawLayerManager;
|
||||
this.componentUpdateManager = componentUpdateManager;
|
||||
componentStore = new ComponentStore(typeToIndex);
|
||||
}
|
||||
|
||||
public void RegisterComponentType<TComponent>() where TComponent : struct, IComponent
|
||||
|
@ -96,10 +97,5 @@ namespace Encompass
|
|||
componentUpdateManager.Remove<TComponent>(entity);
|
||||
drawLayerManager.UnRegisterComponentWithLayer<TComponent>(entity);
|
||||
}
|
||||
|
||||
public IEnumerable<Entity> EntitiesWithComponents(IEnumerable<Type> types)
|
||||
{
|
||||
return componentStore.EntitiesWithComponents(types);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,27 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
internal class ComponentUpdateManager
|
||||
{
|
||||
private readonly ComponentStore existingAndPendingComponentStore = new ComponentStore();
|
||||
private readonly ComponentStore existingComponentStore = new ComponentStore();
|
||||
private readonly ComponentStore pendingComponentStore = new ComponentStore();
|
||||
private readonly ComponentStore existingAndPendingComponentStore;
|
||||
private readonly ComponentStore existingComponentStore;
|
||||
private readonly ComponentStore pendingComponentStore;
|
||||
private readonly Dictionary<Type, Dictionary<Entity, int>> typeToEntityToPendingComponentPriority = new Dictionary<Type, Dictionary<Entity, int>>(128);
|
||||
private Dictionary<Type, int> typeToIndex;
|
||||
public ComponentStore UpToDateComponentStore { get; private set; }
|
||||
|
||||
public ComponentStore UpToDateComponentStore { get; private set; } = new ComponentStore();
|
||||
public ComponentUpdateManager(Dictionary<Type, int> typeToIndex)
|
||||
{
|
||||
existingAndPendingComponentStore = new ComponentStore(typeToIndex);
|
||||
existingComponentStore = new ComponentStore(typeToIndex);
|
||||
pendingComponentStore = new ComponentStore(typeToIndex);
|
||||
UpToDateComponentStore = new ComponentStore(typeToIndex);
|
||||
this.typeToIndex = typeToIndex;
|
||||
}
|
||||
|
||||
public void RegisterComponentType<TComponent>() where TComponent : struct, IComponent
|
||||
{
|
||||
|
@ -183,5 +194,63 @@ namespace Encompass
|
|||
{
|
||||
UpToDateComponentStore.Remove<TComponent>(entity);
|
||||
}
|
||||
|
||||
internal IEnumerable<Entity> QueryEntities(IEnumerable<Entity> entities, HashSet<Type> readTypes, HashSet<Type> readPendingTypes, IEnumerable<Type> withTypes, IEnumerable<Type> withoutTypes)
|
||||
{
|
||||
var pendingMask = new BitArray(typeToIndex.Count);
|
||||
foreach (var type in readPendingTypes)
|
||||
{
|
||||
pendingMask.Set(typeToIndex[type], true);
|
||||
}
|
||||
|
||||
var readMask = new BitArray(typeToIndex.Count);
|
||||
foreach (var type in readTypes)
|
||||
{
|
||||
readMask.Set(typeToIndex[type], true);
|
||||
}
|
||||
|
||||
var withMask = new BitArray(typeToIndex.Count);
|
||||
foreach (var type in withTypes)
|
||||
{
|
||||
withMask.Set(typeToIndex[type], true);
|
||||
}
|
||||
|
||||
var withoutMask = new BitArray(typeToIndex.Count);
|
||||
foreach (var type in withoutTypes)
|
||||
{
|
||||
withoutMask.Set(typeToIndex[type], true);
|
||||
}
|
||||
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
var pendingEntity = pendingComponentStore.EntityBitArray(entity);
|
||||
var existingEntity = existingComponentStore.EntityBitArray(entity);
|
||||
|
||||
if (VerifyTypes(pendingEntity, existingEntity, readMask, pendingMask, withMask, withoutMask)) { yield return entity; }
|
||||
}
|
||||
}
|
||||
|
||||
internal bool VerifyTypes(BitArray pendingEntity, BitArray existingEntity, BitArray readMask, BitArray pendingMask, BitArray withMask, BitArray withoutMask)
|
||||
{
|
||||
var arrayA = new BitArray(typeToIndex.Count);
|
||||
var arrayB = new BitArray(typeToIndex.Count);
|
||||
var arrayC = new BitArray(typeToIndex.Count);
|
||||
|
||||
var notWithMask = new BitArray(typeToIndex.Count);
|
||||
notWithMask.Or(withMask).Not();
|
||||
|
||||
arrayA.Or(pendingMask).And(withMask).And(pendingEntity);
|
||||
arrayB.Or(readMask).And(withMask).And(existingEntity);
|
||||
arrayA.Or(arrayB).Or(notWithMask);
|
||||
|
||||
arrayB.SetAll(false);
|
||||
arrayB.Or(pendingMask).And(withoutMask).And(pendingEntity).Not();
|
||||
arrayC.Or(readMask).And(withoutMask).And(existingEntity).Not();
|
||||
arrayB.And(arrayC);
|
||||
|
||||
arrayA.And(arrayB);
|
||||
|
||||
return !arrayA.Cast<bool>().Contains(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,12 @@ namespace Encompass
|
|||
private readonly Dictionary<int, HashSet<GeneralRenderer>> layerIndexToGeneralRenderers = new Dictionary<int, HashSet<GeneralRenderer>>(512);
|
||||
|
||||
private readonly Dictionary<Type, Dictionary<Entity, int>> typeToEntityToLayer = new Dictionary<Type, Dictionary<Entity, int>>(512);
|
||||
|
||||
private Dictionary<Type, int> typeToIndex;
|
||||
public IEnumerable<int> LayerOrder { get { return layerOrder.Values; } }
|
||||
|
||||
public DrawLayerManager()
|
||||
public DrawLayerManager(Dictionary<Type, int> typeToIndex)
|
||||
{
|
||||
this.typeToIndex = typeToIndex;
|
||||
RegisterDrawLayer(0);
|
||||
}
|
||||
|
||||
|
@ -27,7 +28,15 @@ namespace Encompass
|
|||
{
|
||||
layerOrder.Add(layer, layer);
|
||||
layerIndexToGeneralRenderers.Add(layer, new HashSet<GeneralRenderer>());
|
||||
layerIndexToComponentStore.Add(layer, new ComponentStore());
|
||||
layerIndexToComponentStore.Add(layer, new ComponentStore(typeToIndex));
|
||||
}
|
||||
}
|
||||
|
||||
public void FinishRegistering()
|
||||
{
|
||||
foreach (var store in layerIndexToComponentStore.Values)
|
||||
{
|
||||
store.FinishRegistering();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -612,9 +612,12 @@ namespace Encompass
|
|||
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, easeOutFunction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty EntitySetQuery. Can be modified and iterated over to obtain Entities that fit the given criteria.
|
||||
/// </summary>
|
||||
protected EntitySetQuery QueryEntities()
|
||||
{
|
||||
return new EntitySetQuery(componentManager);
|
||||
return new EntitySetQuery(entityManager, componentUpdateManager, readTypes, readPendingTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,17 @@ namespace Encompass
|
|||
{
|
||||
private readonly int entityCapacity;
|
||||
private readonly IDManager idManager = new IDManager();
|
||||
private readonly HashSet<int> IDs = new HashSet<int>();
|
||||
private readonly Dictionary<int, Entity> IDs = new Dictionary<int, Entity>(32768);
|
||||
|
||||
private readonly HashSet<Entity> entitiesMarkedForDestroy = new HashSet<Entity>();
|
||||
|
||||
private readonly ComponentManager componentManager;
|
||||
|
||||
public IEnumerable<Entity> Entities
|
||||
{
|
||||
get { return IDs.Values; }
|
||||
}
|
||||
|
||||
public EntityManager(ComponentManager componentManager, int entityCapacity)
|
||||
{
|
||||
this.componentManager = componentManager;
|
||||
|
@ -30,7 +35,7 @@ namespace Encompass
|
|||
{
|
||||
var id = NextID();
|
||||
var entity = new Entity(id);
|
||||
IDs.Add(id);
|
||||
IDs.Add(id, entity);
|
||||
return entity;
|
||||
}
|
||||
else
|
||||
|
@ -41,7 +46,7 @@ namespace Encompass
|
|||
|
||||
public bool EntityExists(int id)
|
||||
{
|
||||
return IDs.Contains(id);
|
||||
return IDs.ContainsKey(id);
|
||||
}
|
||||
|
||||
public void MarkForDestroy(Entity entity)
|
||||
|
|
|
@ -5,39 +5,57 @@ using System.Collections.Immutable;
|
|||
|
||||
namespace Encompass
|
||||
{
|
||||
/// <summary>
|
||||
/// EntitySetQuery is used to efficiently obtain a set of Entities that have all required Components and do not have any forbidden Components.
|
||||
/// </summary>
|
||||
public struct EntitySetQuery : IEnumerable<Entity>
|
||||
{
|
||||
private EntitySetQuery(ComponentManager componentManager, ImmutableArray<Type> includes, ImmutableArray<Type> excludes)
|
||||
private EntitySetQuery(EntityManager entityManager, ComponentUpdateManager componentUpdateManager, HashSet<Type> readTypes, HashSet<Type> readPendingTypes, ImmutableArray<Type> includes, ImmutableArray<Type> excludes)
|
||||
{
|
||||
ComponentManager = componentManager;
|
||||
EntityManager = entityManager;
|
||||
ComponentUpdateManager = componentUpdateManager;
|
||||
ReadTypes = readTypes;
|
||||
ReadPendingTypes = readPendingTypes;
|
||||
Includes = includes;
|
||||
Excludes = excludes;
|
||||
}
|
||||
|
||||
internal EntitySetQuery(ComponentManager componentManager)
|
||||
internal EntitySetQuery(EntityManager entityManager, ComponentUpdateManager componentUpdateManager, HashSet<Type> readTypes, HashSet<Type> readPendingTypes)
|
||||
{
|
||||
ComponentManager = componentManager;
|
||||
EntityManager = entityManager;
|
||||
ComponentUpdateManager = componentUpdateManager;
|
||||
ReadTypes = readTypes;
|
||||
ReadPendingTypes = readPendingTypes;
|
||||
Includes = ImmutableArray.Create<Type>();
|
||||
Excludes = ImmutableArray.Create<Type>();
|
||||
}
|
||||
|
||||
private ComponentManager ComponentManager { get; }
|
||||
private EntityManager EntityManager { get; }
|
||||
private ComponentUpdateManager ComponentUpdateManager { get; }
|
||||
private HashSet<Type> ReadTypes { get; }
|
||||
private HashSet<Type> ReadPendingTypes { get; }
|
||||
private ImmutableArray<Type> Includes { get; }
|
||||
private ImmutableArray<Type> Excludes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Designates that the given component type is required.
|
||||
/// </summary>
|
||||
public EntitySetQuery With<TComponent>() where TComponent : struct, IComponent
|
||||
{
|
||||
return new EntitySetQuery(ComponentManager, Includes.Add(typeof(TComponent)), Excludes);
|
||||
return new EntitySetQuery(EntityManager, ComponentUpdateManager, ReadTypes, ReadPendingTypes, Includes.Add(typeof(TComponent)), Excludes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Designates that the given component type is forbidden.
|
||||
/// </summary>
|
||||
public EntitySetQuery Without<TComponent>() where TComponent : struct, IComponent
|
||||
{
|
||||
return new EntitySetQuery(ComponentManager, Includes, Excludes.Add(typeof(TComponent)));
|
||||
return new EntitySetQuery(EntityManager, ComponentUpdateManager, ReadTypes, ReadPendingTypes, Includes, Excludes.Add(typeof(TComponent)));
|
||||
}
|
||||
|
||||
public IEnumerator<Entity> GetEnumerator()
|
||||
{
|
||||
return ComponentManager.EntitiesWithComponents(Includes).GetEnumerator();
|
||||
return ComponentUpdateManager.QueryEntities(EntityManager.Entities, ReadTypes, ReadPendingTypes, Includes, Excludes).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
|
|
|
@ -21,8 +21,8 @@ namespace Encompass
|
|||
private readonly int entityCapacity;
|
||||
private readonly List<Engine> engines = new List<Engine>();
|
||||
private readonly DirectedGraph<Engine, Unit> engineGraph = GraphBuilder.DirectedGraph<Engine>();
|
||||
private readonly ComponentStore startingComponentStoreForComponentManager = new ComponentStore();
|
||||
private readonly ComponentStore startingComponentStoreForComponentUpdateManager = new ComponentStore();
|
||||
private readonly ComponentStore startingComponentStoreForComponentManager;
|
||||
private readonly ComponentStore startingComponentStoreForComponentUpdateManager;
|
||||
|
||||
private readonly ComponentManager componentManager;
|
||||
private readonly EntityManager entityManager;
|
||||
|
@ -40,16 +40,21 @@ namespace Encompass
|
|||
|
||||
private readonly HashSet<Type> messageTypes = new HashSet<Type>();
|
||||
|
||||
private readonly Dictionary<Type, int> typeToIndex = new Dictionary<Type, int>();
|
||||
|
||||
public WorldBuilder(int entityCapacity = 32768)
|
||||
{
|
||||
this.entityCapacity = entityCapacity;
|
||||
drawLayerManager = new DrawLayerManager();
|
||||
drawLayerManager = new DrawLayerManager(typeToIndex);
|
||||
timeManager = new TimeManager();
|
||||
componentUpdateManager = new ComponentUpdateManager();
|
||||
componentManager = new ComponentManager(drawLayerManager, componentUpdateManager);
|
||||
componentUpdateManager = new ComponentUpdateManager(typeToIndex);
|
||||
componentManager = new ComponentManager(drawLayerManager, componentUpdateManager, typeToIndex);
|
||||
messageManager = new MessageManager(timeManager);
|
||||
entityManager = new EntityManager(componentManager, entityCapacity);
|
||||
renderManager = new RenderManager(drawLayerManager);
|
||||
|
||||
startingComponentStoreForComponentManager = new ComponentStore(typeToIndex);
|
||||
startingComponentStoreForComponentUpdateManager = new ComponentStore(typeToIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -84,7 +89,9 @@ namespace Encompass
|
|||
RegisterComponentType<TComponent>();
|
||||
componentTypesToRegister.Add(typeof(TComponent));
|
||||
|
||||
startingComponentStoreForComponentManager.FinishRegistering();
|
||||
startingComponentStoreForComponentManager.Set(entity, component);
|
||||
startingComponentStoreForComponentUpdateManager.FinishRegistering();
|
||||
startingComponentStoreForComponentUpdateManager.Set(entity, component);
|
||||
|
||||
if (component is IDrawableComponent drawableComponent)
|
||||
|
@ -96,11 +103,15 @@ namespace Encompass
|
|||
|
||||
internal void RegisterComponentType<TComponent>() where TComponent : struct, IComponent
|
||||
{
|
||||
if (!typeToIndex.ContainsKey(typeof(TComponent)))
|
||||
{
|
||||
typeToIndex.Add(typeof(TComponent), typeToIndex.Count);
|
||||
componentManager.RegisterComponentType<TComponent>();
|
||||
componentUpdateManager.RegisterComponentType<TComponent>();
|
||||
startingComponentStoreForComponentManager.RegisterComponentType<TComponent>();
|
||||
startingComponentStoreForComponentUpdateManager.RegisterComponentType<TComponent>();
|
||||
}
|
||||
}
|
||||
|
||||
internal void RegisterMessageTypes(IEnumerable<Type> types)
|
||||
{
|
||||
|
@ -363,13 +374,14 @@ namespace Encompass
|
|||
engineOrder.Add(emitterEngine);
|
||||
}
|
||||
|
||||
PreloadJIT(componentTypesToRegister, messageTypes);
|
||||
|
||||
componentManager.FinishRegistering();
|
||||
componentUpdateManager.FinishRegistering();
|
||||
drawLayerManager.FinishRegistering();
|
||||
startingComponentStoreForComponentManager.FinishRegistering();
|
||||
startingComponentStoreForComponentUpdateManager.FinishRegistering();
|
||||
|
||||
PreloadJIT(componentTypesToRegister, messageTypes);
|
||||
|
||||
foreach (var engine in engineGraph.TopologicalSort())
|
||||
{
|
||||
engineOrder.Add(engine);
|
||||
|
@ -401,9 +413,9 @@ namespace Encompass
|
|||
{
|
||||
var dummyTimeManager = new TimeManager();
|
||||
var dummyMessageManager = new MessageManager(dummyTimeManager);
|
||||
var dummyDrawLayerManager = new DrawLayerManager();
|
||||
var dummyComponentUpdateManager = new ComponentUpdateManager();
|
||||
var dummyComponentManager = new ComponentManager(dummyDrawLayerManager, dummyComponentUpdateManager);
|
||||
var dummyDrawLayerManager = new DrawLayerManager(typeToIndex);
|
||||
var dummyComponentUpdateManager = new ComponentUpdateManager(typeToIndex);
|
||||
var dummyComponentManager = new ComponentManager(dummyDrawLayerManager, dummyComponentUpdateManager, typeToIndex);
|
||||
var dummyEntityManager = new EntityManager(dummyComponentManager, entityCapacity);
|
||||
var dummyRenderManager = new RenderManager(dummyDrawLayerManager);
|
||||
|
||||
|
|
|
@ -1088,15 +1088,27 @@ namespace Tests
|
|||
undilatedDeltaTime.Should().Be(0.5);
|
||||
}
|
||||
|
||||
struct MockComponentB : IComponent { }
|
||||
|
||||
static Entity[] queriedEntities;
|
||||
|
||||
class EntityQueryEngine : Engine
|
||||
public class QueryTests
|
||||
{
|
||||
struct MockComponentB : IComponent { }
|
||||
struct MockComponentC : IComponent { }
|
||||
struct MockComponentD : IComponent { }
|
||||
|
||||
[Reads(typeof(MockComponent), typeof(MockComponentB))]
|
||||
class EntityQueryWithComponentsEngine : Engine
|
||||
{
|
||||
private List<Entity> entities;
|
||||
|
||||
public EntityQueryWithComponentsEngine(List<Entity> entities)
|
||||
{
|
||||
this.entities = entities;
|
||||
}
|
||||
|
||||
public override void Update(double dt)
|
||||
{
|
||||
queriedEntities = QueryEntities().With<MockComponent>().With<MockComponentB>().ToArray();
|
||||
entities.Clear();
|
||||
|
||||
entities.AddRange(QueryEntities().With<MockComponent>().With<MockComponentB>());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1117,7 +1129,8 @@ namespace Tests
|
|||
|
||||
worldBuilder.SetComponent(entityC, new MockComponentB());
|
||||
|
||||
worldBuilder.AddEngine(new EntityQueryEngine());
|
||||
var queriedEntities = new List<Entity>();
|
||||
worldBuilder.AddEngine(new EntityQueryWithComponentsEngine(queriedEntities));
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
|
@ -1125,5 +1138,106 @@ namespace Tests
|
|||
|
||||
queriedEntities.Should().BeEquivalentTo(new Entity[] { entity, entityB });
|
||||
}
|
||||
|
||||
[Reads(typeof(MockComponent))]
|
||||
class EntityQueryWithoutComponentsEngine : Engine
|
||||
{
|
||||
private List<Entity> entities;
|
||||
|
||||
public EntityQueryWithoutComponentsEngine(List<Entity> entities)
|
||||
{
|
||||
this.entities = entities;
|
||||
}
|
||||
|
||||
public override void Update(double dt)
|
||||
{
|
||||
entities.Clear();
|
||||
|
||||
entities.AddRange(QueryEntities().Without<MockComponent>());
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntitiesWithoutComponents()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
var entityB = worldBuilder.CreateEntity();
|
||||
var entityC = worldBuilder.CreateEntity();
|
||||
|
||||
worldBuilder.SetComponent(entity, new MockComponent());
|
||||
worldBuilder.SetComponent(entity, new MockComponentB());
|
||||
|
||||
worldBuilder.SetComponent(entityB, new MockComponent());
|
||||
worldBuilder.SetComponent(entityB, new MockComponentB());
|
||||
|
||||
worldBuilder.SetComponent(entityC, new MockComponentB());
|
||||
|
||||
var queriedEntities = new List<Entity>();
|
||||
worldBuilder.AddEngine(new EntityQueryWithoutComponentsEngine(queriedEntities));
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
world.Update(0.01);
|
||||
|
||||
queriedEntities.ToArray().Should().BeEquivalentTo(new Entity[] { entityC });
|
||||
}
|
||||
|
||||
[Reads(typeof(MockComponent), typeof(MockComponentB), typeof(MockComponentD))]
|
||||
class EntityQueryWithandWithoutComponentsEngine : Engine
|
||||
{
|
||||
private List<Entity> entities;
|
||||
|
||||
public EntityQueryWithandWithoutComponentsEngine(List<Entity> entities)
|
||||
{
|
||||
this.entities = entities;
|
||||
}
|
||||
|
||||
public override void Update(double dt)
|
||||
{
|
||||
entities.Clear();
|
||||
|
||||
entities.AddRange(QueryEntities().With<MockComponent>()
|
||||
.With<MockComponentB>()
|
||||
.Without<MockComponentD>());
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntitiesWithAndWithoutComponents()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
var entityB = worldBuilder.CreateEntity();
|
||||
var entityC = worldBuilder.CreateEntity();
|
||||
var entityD = worldBuilder.CreateEntity();
|
||||
|
||||
worldBuilder.SetComponent(entity, new MockComponent());
|
||||
worldBuilder.SetComponent(entity, new MockComponentB());
|
||||
worldBuilder.SetComponent(entity, new MockComponentD());
|
||||
|
||||
worldBuilder.SetComponent(entityB, new MockComponent());
|
||||
|
||||
worldBuilder.SetComponent(entityC, new MockComponent());
|
||||
worldBuilder.SetComponent(entityC, new MockComponentB());
|
||||
worldBuilder.SetComponent(entityC, new MockComponentC());
|
||||
worldBuilder.SetComponent(entityC, new MockComponentD());
|
||||
|
||||
worldBuilder.SetComponent(entityD, new MockComponent());
|
||||
worldBuilder.SetComponent(entityD, new MockComponentB());
|
||||
worldBuilder.SetComponent(entityD, new MockComponentC());
|
||||
|
||||
var queriedEntities = new List<Entity>();
|
||||
worldBuilder.AddEngine(new EntityQueryWithandWithoutComponentsEngine(queriedEntities));
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
world.Update(0.01);
|
||||
|
||||
queriedEntities.ToArray().Should().BeEquivalentTo(new Entity[] { entityD });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue