tracking for non-immediate components

pull/5/head
Evan Hemsley 2019-12-28 13:53:02 -08:00
parent e3343e4a00
commit 41e9dd4451
7 changed files with 151 additions and 29 deletions

View File

@ -11,6 +11,8 @@ namespace Encompass
private readonly ComponentStore componentStore; private readonly ComponentStore componentStore;
private readonly HashSet<int> entitiesMarkedForRemoval = new HashSet<int>(); private readonly HashSet<int> entitiesMarkedForRemoval = new HashSet<int>();
internal ComponentBitSet ComponentBitSet { get { return componentStore.ComponentBitSet; } }
public ComponentManager(DrawLayerManager drawLayerManager, ComponentUpdateManager componentUpdateManager, Dictionary<Type, int> typeToIndex) public ComponentManager(DrawLayerManager drawLayerManager, ComponentUpdateManager componentUpdateManager, Dictionary<Type, int> typeToIndex)
{ {
this.drawLayerManager = drawLayerManager; this.drawLayerManager = drawLayerManager;

View File

@ -38,9 +38,13 @@ namespace Encompass
private ComponentManager componentManager; private ComponentManager componentManager;
private ComponentUpdateManager componentUpdateManager; private ComponentUpdateManager componentUpdateManager;
private TimeManager timeManager; private TimeManager timeManager;
private TrackingManager trackingManager;
private EntitySetQuery entityQuery; private EntitySetQuery entityQuery;
private HashSet<Entity> _trackedEntities = new HashSet<Entity>();
protected IEnumerable<Entity> TrackedEntities { get { return _trackedEntities; } }
protected Engine() protected Engine()
{ {
ID = Guid.NewGuid(); ID = Guid.NewGuid();
@ -146,6 +150,11 @@ namespace Encompass
this.timeManager = timeManager; this.timeManager = timeManager;
} }
internal void AssignTrackingManager(TrackingManager trackingManager)
{
this.trackingManager = trackingManager;
}
/// <summary> /// <summary>
/// Runs once per World update with the calculated delta-time. /// Runs once per World update with the calculated delta-time.
/// </summary> /// </summary>
@ -422,13 +431,18 @@ namespace Encompass
bool written; bool written;
if (writeImmediateTypes.Contains(typeof(TComponent))) if (writeImmediateTypes.Contains(typeof(TComponent)))
{ {
written = AddImmediateComponent(entity, component, priority); written = componentUpdateManager.AddImmediateComponent(entity, component, priority);
} }
else else
{ {
written = componentUpdateManager.UpdateComponent(entity, component, priority); written = componentUpdateManager.UpdateComponent(entity, component, priority);
} }
if (!componentUpdateManager.HasExistingComponent<TComponent>(entity))
{
trackingManager.RegisterAddition(entity, typeof(TComponent));
}
if (written && component is IDrawableComponent drawableComponent) if (written && component is IDrawableComponent drawableComponent)
{ {
componentManager.RegisterDrawableComponent(entity, component, drawableComponent.Layer); componentManager.RegisterDrawableComponent(entity, component, drawableComponent.Layer);
@ -474,11 +488,6 @@ namespace Encompass
componentUpdateManager.AddExistingComponent(entity, component); componentUpdateManager.AddExistingComponent(entity, component);
} }
internal bool AddImmediateComponent<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent
{
return componentUpdateManager.AddImmediateComponent(entity, component, priority);
}
/// <summary> /// <summary>
/// Reads all messages of the specified Type. /// Reads all messages of the specified Type.
/// </summary> /// </summary>
@ -574,6 +583,11 @@ namespace Encompass
{ {
componentManager.Remove<TComponent>(entity, priority); componentManager.Remove<TComponent>(entity, priority);
} }
if (componentUpdateManager.HasExistingComponent<TComponent>(entity))
{
trackingManager.RegisterRemoval(entity, typeof(TComponent));
}
} }
/// <summary> /// <summary>
@ -636,11 +650,19 @@ namespace Encompass
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, easeOutFunction); timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, easeOutFunction);
} }
protected IEnumerable<Entity> QueryEntities() internal void CheckTrackEntity(Entity entity)
{ {
foreach (var entity in entityQuery.FilterEntities(entityManager.Entities, componentUpdateManager.ImmediateBits, componentUpdateManager.ExistingBits)) if (entityQuery.CheckEntity(entity, componentManager.ComponentBitSet))
{ {
yield return entity; _trackedEntities.Add(entity);
}
}
internal void CheckUntrackEntity(Entity entity)
{
if (!entityQuery.CheckEntity(entity, componentManager.ComponentBitSet))
{
_trackedEntities.Remove(entity);
} }
} }

View File

@ -21,9 +21,17 @@ namespace Encompass
NotWithMask = notWithMask; NotWithMask = notWithMask;
} }
public IEnumerable<Entity> FilterEntities(IEnumerable<Entity> entities, ComponentBitSet immediateBitLookup, ComponentBitSet existingBitLookup) public bool CheckEntity(Entity entity, ComponentBitSet componentBitSet)
{ {
foreach (var entity in entities) var existingBits = componentBitSet.EntityBitArray(entity.ID);
var existing = WithExistingMask.And(existingBits).Or(NotWithMask);
var existingForbidden = WithoutExistingMask.And(existingBits).Not();
return existing.And(existingForbidden).AllTrue();
}
public bool CheckEntityImmediate(Entity entity, ComponentBitSet immediateBitLookup, ComponentBitSet existingBitLookup)
{ {
var immediateBits = immediateBitLookup.EntityBitArray(entity.ID); var immediateBits = immediateBitLookup.EntityBitArray(entity.ID);
var existingBits = existingBitLookup.EntityBitArray(entity.ID); var existingBits = existingBitLookup.EntityBitArray(entity.ID);
@ -36,8 +44,7 @@ namespace Encompass
var existingForbidden = WithoutExistingMask.And(existingBits).Not(); var existingForbidden = WithoutExistingMask.And(existingBits).Not();
var withoutCheck = immediateForbidden.And(existingForbidden); var withoutCheck = immediateForbidden.And(existingForbidden);
if (withCheck.And(withoutCheck).AllTrue()) { yield return entity; } return withCheck.And(withoutCheck).AllTrue();
}
} }
} }
} }

View File

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
namespace Encompass
{
internal class TrackingManager
{
private Dictionary<Type, HashSet<Engine>> _pendingComponentTypesToEngines = new Dictionary<Type, HashSet<Engine>>();
private Dictionary<Type, HashSet<Engine>> _componentTypesToEngines = new Dictionary<Type, HashSet<Engine>>();
private HashSet<(Entity, Type)> _additions = new HashSet<(Entity, Type)>();
private HashSet<(Entity, Type)> _removals = new HashSet<(Entity, Type)>();
public void RegisterComponentTypeToEngine(Type type, Engine engine)
{
if (!_componentTypesToEngines.ContainsKey(type)) { _componentTypesToEngines.Add(type, new HashSet<Engine>()); }
_componentTypesToEngines[type].Add(engine);
}
public void RegisterAddition(Entity entity, Type type)
{
_additions.Add((entity, type));
}
public void RegisterRemoval(Entity entity, Type type)
{
_removals.Add((entity, type));
}
public void InitializeTracking(IEnumerable<Entity> entities)
{
foreach (var entity in entities)
{
foreach (var engineSet in _componentTypesToEngines.Values)
{
foreach (var engine in engineSet)
{
engine.CheckTrackEntity(entity);
}
}
}
}
public void UpdateTracking()
{
// TODO: optimize so we only check each entity/engine pair once
foreach (var (entity, componentType) in _additions)
{
if (_componentTypesToEngines.ContainsKey(componentType))
{
foreach (var engine in _componentTypesToEngines[componentType])
{
engine.CheckTrackEntity(entity);
}
}
}
_additions.Clear();
foreach (var (entity, componentType) in _removals)
{
if (_componentTypesToEngines.ContainsKey(componentType))
{
foreach (var engine in _componentTypesToEngines[componentType])
{
engine.CheckUntrackEntity(entity);
}
}
}
_removals.Clear();
}
}
}

View File

@ -10,6 +10,7 @@ namespace Encompass
private readonly List<Engine> enginesInOrder; private readonly List<Engine> enginesInOrder;
private readonly EntityManager entityManager; private readonly EntityManager entityManager;
private readonly ComponentManager componentManager; private readonly ComponentManager componentManager;
private readonly TrackingManager trackingManager;
private readonly MessageManager messageManager; private readonly MessageManager messageManager;
private readonly ComponentUpdateManager componentUpdateManager; private readonly ComponentUpdateManager componentUpdateManager;
private readonly TimeManager timeManager; private readonly TimeManager timeManager;
@ -19,6 +20,7 @@ namespace Encompass
List<Engine> enginesInOrder, List<Engine> enginesInOrder,
EntityManager entityManager, EntityManager entityManager,
ComponentManager componentManager, ComponentManager componentManager,
TrackingManager trackingManager,
MessageManager messageManager, MessageManager messageManager,
ComponentUpdateManager componentUpdateManager, ComponentUpdateManager componentUpdateManager,
TimeManager timeManager, TimeManager timeManager,
@ -28,6 +30,7 @@ namespace Encompass
this.enginesInOrder = enginesInOrder; this.enginesInOrder = enginesInOrder;
this.entityManager = entityManager; this.entityManager = entityManager;
this.componentManager = componentManager; this.componentManager = componentManager;
this.trackingManager = trackingManager;
this.messageManager = messageManager; this.messageManager = messageManager;
this.componentUpdateManager = componentUpdateManager; this.componentUpdateManager = componentUpdateManager;
this.timeManager = timeManager; this.timeManager = timeManager;
@ -40,6 +43,7 @@ namespace Encompass
/// <param name="dt">The time in seconds that has passed since the previous frame.</param> /// <param name="dt">The time in seconds that has passed since the previous frame.</param>
public void Update(double dt) public void Update(double dt)
{ {
trackingManager.UpdateTracking();
messageManager.ProcessDelayedMessages(dt); messageManager.ProcessDelayedMessages(dt);
timeManager.Update(dt); timeManager.Update(dt);

View File

@ -31,6 +31,7 @@ namespace Encompass
private readonly TimeManager timeManager; private readonly TimeManager timeManager;
private readonly DrawLayerManager drawLayerManager; private readonly DrawLayerManager drawLayerManager;
private readonly RenderManager renderManager; private readonly RenderManager renderManager;
private readonly TrackingManager trackingManager;
private readonly Dictionary<Type, HashSet<Engine>> typeToReaders = new Dictionary<Type, HashSet<Engine>>(); private readonly Dictionary<Type, HashSet<Engine>> typeToReaders = new Dictionary<Type, HashSet<Engine>>();
@ -52,6 +53,7 @@ namespace Encompass
messageManager = new MessageManager(timeManager); messageManager = new MessageManager(timeManager);
entityManager = new EntityManager(componentManager, entityCapacity); entityManager = new EntityManager(componentManager, entityCapacity);
renderManager = new RenderManager(entityManager, drawLayerManager); renderManager = new RenderManager(entityManager, drawLayerManager);
trackingManager = new TrackingManager();
startingComponentStoreForComponentManager = new ComponentStore(typeToIndex); startingComponentStoreForComponentManager = new ComponentStore(typeToIndex);
startingComponentStoreForComponentUpdateManager = new ComponentStore(typeToIndex); startingComponentStoreForComponentUpdateManager = new ComponentStore(typeToIndex);
@ -132,6 +134,7 @@ namespace Encompass
engine.AssignMessageManager(messageManager); engine.AssignMessageManager(messageManager);
engine.AssignComponentUpdateManager(componentUpdateManager); engine.AssignComponentUpdateManager(componentUpdateManager);
engine.AssignTimeManager(timeManager); engine.AssignTimeManager(timeManager);
engine.AssignTrackingManager(trackingManager);
engines.Add(engine); engines.Add(engine);
engineGraph.AddNode(engine); engineGraph.AddNode(engine);
@ -156,6 +159,11 @@ namespace Encompass
senders.Add(engine); senders.Add(engine);
} }
foreach (var componentType in engine.queryWithTypes.Union(engine.queryWithoutTypes))
{
trackingManager.RegisterComponentTypeToEngine(componentType, engine);
}
foreach (var componentType in engine.readTypes.Union(engine.writeTypes).Union(engine.readImmediateTypes)) foreach (var componentType in engine.readTypes.Union(engine.writeTypes).Union(engine.readImmediateTypes))
{ {
AddComponentTypeToRegister(componentType); AddComponentTypeToRegister(componentType);
@ -381,6 +389,7 @@ namespace Encompass
engineOrder, engineOrder,
entityManager, entityManager,
componentManager, componentManager,
trackingManager,
messageManager, messageManager,
componentUpdateManager, componentUpdateManager,
timeManager, timeManager,
@ -390,6 +399,8 @@ namespace Encompass
componentUpdateManager.SetStartingComponentStore(startingComponentStoreForComponentUpdateManager); componentUpdateManager.SetStartingComponentStore(startingComponentStoreForComponentUpdateManager);
componentManager.SetComponentStore(startingComponentStoreForComponentManager); componentManager.SetComponentStore(startingComponentStoreForComponentManager);
trackingManager.InitializeTracking(entityManager.Entities);
return world; return world;
} }
@ -406,6 +417,7 @@ namespace Encompass
var dummyDrawLayerManager = new DrawLayerManager(typeToIndex); var dummyDrawLayerManager = new DrawLayerManager(typeToIndex);
var dummyComponentUpdateManager = new ComponentUpdateManager(typeToIndex); var dummyComponentUpdateManager = new ComponentUpdateManager(typeToIndex);
var dummyComponentManager = new ComponentManager(dummyDrawLayerManager, dummyComponentUpdateManager, typeToIndex); var dummyComponentManager = new ComponentManager(dummyDrawLayerManager, dummyComponentUpdateManager, typeToIndex);
var dummyTrackingManager = new TrackingManager();
var dummyEntityManager = new EntityManager(dummyComponentManager, entityCapacity); var dummyEntityManager = new EntityManager(dummyComponentManager, entityCapacity);
var dummyRenderManager = new RenderManager(dummyEntityManager, dummyDrawLayerManager); var dummyRenderManager = new RenderManager(dummyEntityManager, dummyDrawLayerManager);
@ -418,6 +430,7 @@ namespace Encompass
uberEngine.AssignMessageManager(dummyMessageManager); uberEngine.AssignMessageManager(dummyMessageManager);
uberEngine.AssignComponentUpdateManager(dummyComponentUpdateManager); uberEngine.AssignComponentUpdateManager(dummyComponentUpdateManager);
uberEngine.AssignTimeManager(dummyTimeManager); uberEngine.AssignTimeManager(dummyTimeManager);
uberEngine.AssignTrackingManager(dummyTrackingManager);
var uberRenderer = new UberRenderer(componentTypes); var uberRenderer = new UberRenderer(componentTypes);
uberRenderer.AssignComponentManager(dummyComponentManager); uberRenderer.AssignComponentManager(dummyComponentManager);
@ -446,6 +459,7 @@ namespace Encompass
emitterEngine.AssignMessageManager(dummyMessageManager); emitterEngine.AssignMessageManager(dummyMessageManager);
emitterEngine.AssignComponentUpdateManager(dummyComponentUpdateManager); emitterEngine.AssignComponentUpdateManager(dummyComponentUpdateManager);
emitterEngine.AssignTimeManager(dummyTimeManager); emitterEngine.AssignTimeManager(dummyTimeManager);
emitterEngine.AssignTrackingManager(dummyTrackingManager);
prepEngineOrder.Add(emitterEngine); prepEngineOrder.Add(emitterEngine);
} }
@ -456,6 +470,7 @@ namespace Encompass
prepEngineOrder, prepEngineOrder,
dummyEntityManager, dummyEntityManager,
dummyComponentManager, dummyComponentManager,
dummyTrackingManager,
dummyMessageManager, dummyMessageManager,
dummyComponentUpdateManager, dummyComponentUpdateManager,
dummyTimeManager, dummyTimeManager,

View File

@ -1116,7 +1116,7 @@ namespace Tests
public override void Update(double dt) public override void Update(double dt)
{ {
entities.Clear(); entities.Clear();
foreach (var entity in QueryEntities()) foreach (var entity in TrackedEntities)
{ {
entities.Add(entity); entities.Add(entity);
} }
@ -1164,7 +1164,7 @@ namespace Tests
public override void Update(double dt) public override void Update(double dt)
{ {
entities.Clear(); entities.Clear();
entities.AddRange(QueryEntities()); entities.AddRange(TrackedEntities);
} }
} }
@ -1211,7 +1211,7 @@ namespace Tests
{ {
entities.Clear(); entities.Clear();
entities.AddRange(QueryEntities()); entities.AddRange(TrackedEntities);
} }
} }
@ -1278,7 +1278,7 @@ namespace Tests
public override void Update(double dt) public override void Update(double dt)
{ {
entities.Clear(); entities.Clear();
entities.AddRange(QueryEntities()); entities.AddRange(TrackedEntities);
} }
} }
@ -1317,7 +1317,7 @@ namespace Tests
public override void Update(double dt) public override void Update(double dt)
{ {
entities.Clear(); entities.Clear();
entities.AddRange(QueryEntities()); entities.AddRange(TrackedEntities);
} }
} }
@ -1379,7 +1379,7 @@ namespace Tests
{ {
entities.Clear(); entities.Clear();
entities.AddRange(QueryEntities()); entities.AddRange(TrackedEntities);
} }
} }
@ -1435,7 +1435,7 @@ namespace Tests
public override void Update(double dt) public override void Update(double dt)
{ {
entities.Clear(); entities.Clear();
entities.AddRange(QueryEntities()); entities.AddRange(TrackedEntities);
} }
} }