tracking for non-immediate components
parent
e3343e4a00
commit
41e9dd4451
|
@ -11,6 +11,8 @@ namespace Encompass
|
|||
private readonly ComponentStore componentStore;
|
||||
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)
|
||||
{
|
||||
this.drawLayerManager = drawLayerManager;
|
||||
|
|
|
@ -38,9 +38,13 @@ namespace Encompass
|
|||
private ComponentManager componentManager;
|
||||
private ComponentUpdateManager componentUpdateManager;
|
||||
private TimeManager timeManager;
|
||||
private TrackingManager trackingManager;
|
||||
|
||||
private EntitySetQuery entityQuery;
|
||||
|
||||
private HashSet<Entity> _trackedEntities = new HashSet<Entity>();
|
||||
protected IEnumerable<Entity> TrackedEntities { get { return _trackedEntities; } }
|
||||
|
||||
protected Engine()
|
||||
{
|
||||
ID = Guid.NewGuid();
|
||||
|
@ -146,6 +150,11 @@ namespace Encompass
|
|||
this.timeManager = timeManager;
|
||||
}
|
||||
|
||||
internal void AssignTrackingManager(TrackingManager trackingManager)
|
||||
{
|
||||
this.trackingManager = trackingManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs once per World update with the calculated delta-time.
|
||||
/// </summary>
|
||||
|
@ -422,13 +431,18 @@ namespace Encompass
|
|||
bool written;
|
||||
if (writeImmediateTypes.Contains(typeof(TComponent)))
|
||||
{
|
||||
written = AddImmediateComponent(entity, component, priority);
|
||||
written = componentUpdateManager.AddImmediateComponent(entity, component, priority);
|
||||
}
|
||||
else
|
||||
{
|
||||
written = componentUpdateManager.UpdateComponent(entity, component, priority);
|
||||
}
|
||||
|
||||
if (!componentUpdateManager.HasExistingComponent<TComponent>(entity))
|
||||
{
|
||||
trackingManager.RegisterAddition(entity, typeof(TComponent));
|
||||
}
|
||||
|
||||
if (written && component is IDrawableComponent drawableComponent)
|
||||
{
|
||||
componentManager.RegisterDrawableComponent(entity, component, drawableComponent.Layer);
|
||||
|
@ -474,11 +488,6 @@ namespace Encompass
|
|||
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>
|
||||
/// Reads all messages of the specified Type.
|
||||
/// </summary>
|
||||
|
@ -574,6 +583,11 @@ namespace Encompass
|
|||
{
|
||||
componentManager.Remove<TComponent>(entity, priority);
|
||||
}
|
||||
|
||||
if (componentUpdateManager.HasExistingComponent<TComponent>(entity))
|
||||
{
|
||||
trackingManager.RegisterRemoval(entity, typeof(TComponent));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -636,11 +650,19 @@ namespace Encompass
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,23 +21,30 @@ namespace Encompass
|
|||
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 immediateBits = immediateBitLookup.EntityBitArray(entity.ID);
|
||||
var existingBits = existingBitLookup.EntityBitArray(entity.ID);
|
||||
var existingBits = componentBitSet.EntityBitArray(entity.ID);
|
||||
var existing = WithExistingMask.And(existingBits).Or(NotWithMask);
|
||||
|
||||
var immediate = WithImmediateMask.And(immediateBits);
|
||||
var existing = WithExistingMask.And(existingBits);
|
||||
var withCheck = immediate.Or(existing).Or(NotWithMask);
|
||||
var existingForbidden = WithoutExistingMask.And(existingBits).Not();
|
||||
|
||||
var immediateForbidden = WithoutImmediateMask.And(immediateBits).Not();
|
||||
var existingForbidden = WithoutExistingMask.And(existingBits).Not();
|
||||
var withoutCheck = immediateForbidden.And(existingForbidden);
|
||||
return existing.And(existingForbidden).AllTrue();
|
||||
}
|
||||
|
||||
if (withCheck.And(withoutCheck).AllTrue()) { yield return entity; }
|
||||
}
|
||||
public bool CheckEntityImmediate(Entity entity, ComponentBitSet immediateBitLookup, ComponentBitSet existingBitLookup)
|
||||
{
|
||||
var immediateBits = immediateBitLookup.EntityBitArray(entity.ID);
|
||||
var existingBits = existingBitLookup.EntityBitArray(entity.ID);
|
||||
|
||||
var immediate = WithImmediateMask.And(immediateBits);
|
||||
var existing = WithExistingMask.And(existingBits);
|
||||
var withCheck = immediate.Or(existing).Or(NotWithMask);
|
||||
|
||||
var immediateForbidden = WithoutImmediateMask.And(immediateBits).Not();
|
||||
var existingForbidden = WithoutExistingMask.And(existingBits).Not();
|
||||
var withoutCheck = immediateForbidden.And(existingForbidden);
|
||||
|
||||
return withCheck.And(withoutCheck).AllTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ namespace Encompass
|
|||
private readonly List<Engine> enginesInOrder;
|
||||
private readonly EntityManager entityManager;
|
||||
private readonly ComponentManager componentManager;
|
||||
private readonly TrackingManager trackingManager;
|
||||
private readonly MessageManager messageManager;
|
||||
private readonly ComponentUpdateManager componentUpdateManager;
|
||||
private readonly TimeManager timeManager;
|
||||
|
@ -19,6 +20,7 @@ namespace Encompass
|
|||
List<Engine> enginesInOrder,
|
||||
EntityManager entityManager,
|
||||
ComponentManager componentManager,
|
||||
TrackingManager trackingManager,
|
||||
MessageManager messageManager,
|
||||
ComponentUpdateManager componentUpdateManager,
|
||||
TimeManager timeManager,
|
||||
|
@ -28,6 +30,7 @@ namespace Encompass
|
|||
this.enginesInOrder = enginesInOrder;
|
||||
this.entityManager = entityManager;
|
||||
this.componentManager = componentManager;
|
||||
this.trackingManager = trackingManager;
|
||||
this.messageManager = messageManager;
|
||||
this.componentUpdateManager = componentUpdateManager;
|
||||
this.timeManager = timeManager;
|
||||
|
@ -40,6 +43,7 @@ namespace Encompass
|
|||
/// <param name="dt">The time in seconds that has passed since the previous frame.</param>
|
||||
public void Update(double dt)
|
||||
{
|
||||
trackingManager.UpdateTracking();
|
||||
messageManager.ProcessDelayedMessages(dt);
|
||||
timeManager.Update(dt);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace Encompass
|
|||
private readonly TimeManager timeManager;
|
||||
private readonly DrawLayerManager drawLayerManager;
|
||||
private readonly RenderManager renderManager;
|
||||
private readonly TrackingManager trackingManager;
|
||||
|
||||
private readonly Dictionary<Type, HashSet<Engine>> typeToReaders = new Dictionary<Type, HashSet<Engine>>();
|
||||
|
||||
|
@ -52,6 +53,7 @@ namespace Encompass
|
|||
messageManager = new MessageManager(timeManager);
|
||||
entityManager = new EntityManager(componentManager, entityCapacity);
|
||||
renderManager = new RenderManager(entityManager, drawLayerManager);
|
||||
trackingManager = new TrackingManager();
|
||||
|
||||
startingComponentStoreForComponentManager = new ComponentStore(typeToIndex);
|
||||
startingComponentStoreForComponentUpdateManager = new ComponentStore(typeToIndex);
|
||||
|
@ -132,6 +134,7 @@ namespace Encompass
|
|||
engine.AssignMessageManager(messageManager);
|
||||
engine.AssignComponentUpdateManager(componentUpdateManager);
|
||||
engine.AssignTimeManager(timeManager);
|
||||
engine.AssignTrackingManager(trackingManager);
|
||||
|
||||
engines.Add(engine);
|
||||
engineGraph.AddNode(engine);
|
||||
|
@ -156,6 +159,11 @@ namespace Encompass
|
|||
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))
|
||||
{
|
||||
AddComponentTypeToRegister(componentType);
|
||||
|
@ -381,6 +389,7 @@ namespace Encompass
|
|||
engineOrder,
|
||||
entityManager,
|
||||
componentManager,
|
||||
trackingManager,
|
||||
messageManager,
|
||||
componentUpdateManager,
|
||||
timeManager,
|
||||
|
@ -390,6 +399,8 @@ namespace Encompass
|
|||
componentUpdateManager.SetStartingComponentStore(startingComponentStoreForComponentUpdateManager);
|
||||
componentManager.SetComponentStore(startingComponentStoreForComponentManager);
|
||||
|
||||
trackingManager.InitializeTracking(entityManager.Entities);
|
||||
|
||||
return world;
|
||||
}
|
||||
|
||||
|
@ -406,6 +417,7 @@ namespace Encompass
|
|||
var dummyDrawLayerManager = new DrawLayerManager(typeToIndex);
|
||||
var dummyComponentUpdateManager = new ComponentUpdateManager(typeToIndex);
|
||||
var dummyComponentManager = new ComponentManager(dummyDrawLayerManager, dummyComponentUpdateManager, typeToIndex);
|
||||
var dummyTrackingManager = new TrackingManager();
|
||||
var dummyEntityManager = new EntityManager(dummyComponentManager, entityCapacity);
|
||||
var dummyRenderManager = new RenderManager(dummyEntityManager, dummyDrawLayerManager);
|
||||
|
||||
|
@ -418,6 +430,7 @@ namespace Encompass
|
|||
uberEngine.AssignMessageManager(dummyMessageManager);
|
||||
uberEngine.AssignComponentUpdateManager(dummyComponentUpdateManager);
|
||||
uberEngine.AssignTimeManager(dummyTimeManager);
|
||||
uberEngine.AssignTrackingManager(dummyTrackingManager);
|
||||
|
||||
var uberRenderer = new UberRenderer(componentTypes);
|
||||
uberRenderer.AssignComponentManager(dummyComponentManager);
|
||||
|
@ -446,6 +459,7 @@ namespace Encompass
|
|||
emitterEngine.AssignMessageManager(dummyMessageManager);
|
||||
emitterEngine.AssignComponentUpdateManager(dummyComponentUpdateManager);
|
||||
emitterEngine.AssignTimeManager(dummyTimeManager);
|
||||
emitterEngine.AssignTrackingManager(dummyTrackingManager);
|
||||
|
||||
prepEngineOrder.Add(emitterEngine);
|
||||
}
|
||||
|
@ -456,6 +470,7 @@ namespace Encompass
|
|||
prepEngineOrder,
|
||||
dummyEntityManager,
|
||||
dummyComponentManager,
|
||||
dummyTrackingManager,
|
||||
dummyMessageManager,
|
||||
dummyComponentUpdateManager,
|
||||
dummyTimeManager,
|
||||
|
|
|
@ -1116,7 +1116,7 @@ namespace Tests
|
|||
public override void Update(double dt)
|
||||
{
|
||||
entities.Clear();
|
||||
foreach (var entity in QueryEntities())
|
||||
foreach (var entity in TrackedEntities)
|
||||
{
|
||||
entities.Add(entity);
|
||||
}
|
||||
|
@ -1164,7 +1164,7 @@ namespace Tests
|
|||
public override void Update(double dt)
|
||||
{
|
||||
entities.Clear();
|
||||
entities.AddRange(QueryEntities());
|
||||
entities.AddRange(TrackedEntities);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1211,7 +1211,7 @@ namespace Tests
|
|||
{
|
||||
entities.Clear();
|
||||
|
||||
entities.AddRange(QueryEntities());
|
||||
entities.AddRange(TrackedEntities);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1278,7 +1278,7 @@ namespace Tests
|
|||
public override void Update(double dt)
|
||||
{
|
||||
entities.Clear();
|
||||
entities.AddRange(QueryEntities());
|
||||
entities.AddRange(TrackedEntities);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1317,7 +1317,7 @@ namespace Tests
|
|||
public override void Update(double dt)
|
||||
{
|
||||
entities.Clear();
|
||||
entities.AddRange(QueryEntities());
|
||||
entities.AddRange(TrackedEntities);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1379,7 +1379,7 @@ namespace Tests
|
|||
{
|
||||
entities.Clear();
|
||||
|
||||
entities.AddRange(QueryEntities());
|
||||
entities.AddRange(TrackedEntities);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1435,7 +1435,7 @@ namespace Tests
|
|||
public override void Update(double dt)
|
||||
{
|
||||
entities.Clear();
|
||||
entities.AddRange(QueryEntities());
|
||||
entities.AddRange(TrackedEntities);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue