immediate tracking

pull/5/head
Evan Hemsley 2019-12-28 14:30:26 -08:00
parent 41e9dd4451
commit 9b0bf34c73
5 changed files with 72 additions and 11 deletions

View File

@ -432,6 +432,10 @@ namespace Encompass
if (writeImmediateTypes.Contains(typeof(TComponent)))
{
written = componentUpdateManager.AddImmediateComponent(entity, component, priority);
if (written)
{
trackingManager.ImmediateUpdateTracking(entity, typeof(TComponent));
}
}
else
{
@ -577,7 +581,10 @@ namespace Encompass
if (writeImmediateTypes.Contains(typeof(TComponent)))
{
componentManager.RemoveImmediate<TComponent>(entity, priority);
if (componentManager.RemoveImmediate<TComponent>(entity, priority))
{
trackingManager.ImmediateUpdateTracking(entity, typeof(TComponent));
}
}
else
{
@ -650,20 +657,28 @@ namespace Encompass
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, easeOutFunction);
}
internal void CheckTrackEntity(Entity entity)
internal void CheckAndUpdateTracking(Entity entity)
{
if (entityQuery.CheckEntity(entity, componentManager.ComponentBitSet))
if (_trackedEntities.Contains(entity) && !entityQuery.CheckEntity(entity, componentManager.ComponentBitSet))
{
_trackedEntities.Remove(entity);
}
else if (!_trackedEntities.Contains(entity) && entityQuery.CheckEntity(entity, componentManager.ComponentBitSet))
{
_trackedEntities.Add(entity);
}
}
internal void CheckUntrackEntity(Entity entity)
internal void ImmediateCheckAndUpdateTracking(Entity entity)
{
if (!entityQuery.CheckEntity(entity, componentManager.ComponentBitSet))
if (_trackedEntities.Contains(entity) && !entityQuery.ImmediateCheckEntity(entity, componentUpdateManager.ImmediateBits, componentUpdateManager.ExistingBits))
{
_trackedEntities.Remove(entity);
}
else if (!_trackedEntities.Contains(entity) && entityQuery.ImmediateCheckEntity(entity, componentUpdateManager.ImmediateBits, componentUpdateManager.ExistingBits))
{
_trackedEntities.Add(entity);
}
}
/// <summary>

View File

@ -31,7 +31,7 @@ namespace Encompass
return existing.And(existingForbidden).AllTrue();
}
public bool CheckEntityImmediate(Entity entity, ComponentBitSet immediateBitLookup, ComponentBitSet existingBitLookup)
public bool ImmediateCheckEntity(Entity entity, ComponentBitSet immediateBitLookup, ComponentBitSet existingBitLookup)
{
var immediateBits = immediateBitLookup.EntityBitArray(entity.ID);
var existingBits = existingBitLookup.EntityBitArray(entity.ID);

View File

@ -5,18 +5,26 @@ namespace Encompass
{
internal class TrackingManager
{
private Dictionary<Type, HashSet<Engine>> _pendingComponentTypesToEngines = new Dictionary<Type, HashSet<Engine>>();
private Dictionary<Type, HashSet<Engine>> _immediateComponentTypesToEngines = 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)>();
private HashSet<(Entity, Engine)> _pairsToCheck = new HashSet<(Entity, Engine)>();
public void RegisterComponentTypeToEngine(Type type, Engine engine)
{
if (!_componentTypesToEngines.ContainsKey(type)) { _componentTypesToEngines.Add(type, new HashSet<Engine>()); }
_componentTypesToEngines[type].Add(engine);
}
public void RegisterImmediateComponentTypeToEngine(Type type, Engine engine)
{
if (!_immediateComponentTypesToEngines.ContainsKey(type)) { _immediateComponentTypesToEngines.Add(type, new HashSet<Engine>()); }
_immediateComponentTypesToEngines[type].Add(engine);
}
public void RegisterAddition(Entity entity, Type type)
{
_additions.Add((entity, type));
@ -35,12 +43,23 @@ namespace Encompass
{
foreach (var engine in engineSet)
{
engine.CheckTrackEntity(entity);
engine.CheckAndUpdateTracking(entity);
}
}
}
}
public void ImmediateUpdateTracking(Entity entity, Type componentType)
{
if (_immediateComponentTypesToEngines.ContainsKey(componentType))
{
foreach (var engine in _componentTypesToEngines[componentType])
{
engine.ImmediateCheckAndUpdateTracking(entity);
}
}
}
public void UpdateTracking()
{
// TODO: optimize so we only check each entity/engine pair once
@ -50,7 +69,8 @@ namespace Encompass
{
foreach (var engine in _componentTypesToEngines[componentType])
{
engine.CheckTrackEntity(entity);
_pairsToCheck.Add((entity, engine));
// engine.CheckTrackEntity(entity);
}
}
}
@ -62,11 +82,18 @@ namespace Encompass
{
foreach (var engine in _componentTypesToEngines[componentType])
{
engine.CheckUntrackEntity(entity);
_pairsToCheck.Add((entity, engine));
//engine.CheckUntrackEntity(entity);
}
}
}
_removals.Clear();
foreach (var (entity, engine) in _pairsToCheck)
{
engine.CheckAndUpdateTracking(entity);
}
_pairsToCheck.Clear();
}
}
}

View File

@ -162,6 +162,10 @@ namespace Encompass
foreach (var componentType in engine.queryWithTypes.Union(engine.queryWithoutTypes))
{
trackingManager.RegisterComponentTypeToEngine(componentType, engine);
if (engine.readImmediateTypes.Contains(componentType))
{
trackingManager.RegisterImmediateComponentTypeToEngine(componentType, engine);
}
}
foreach (var componentType in engine.readTypes.Union(engine.writeTypes).Union(engine.readImmediateTypes))

View File

@ -1103,6 +1103,7 @@ namespace Tests
struct MockComponentD : IComponent { }
[Reads(typeof(MockComponent), typeof(MockComponentB))]
[Writes(typeof(MockComponentB))]
[QueryWith(typeof(MockComponent), typeof(MockComponentB))]
class EntityQueryWithComponentsEngine : Engine
{
@ -1119,6 +1120,7 @@ namespace Tests
foreach (var entity in TrackedEntities)
{
entities.Add(entity);
RemoveComponent<MockComponentB>(entity);
}
}
}
@ -1148,9 +1150,14 @@ namespace Tests
world.Update(0.01);
queriedEntities.Should().BeEquivalentTo(new Entity[] { entity, entityB });
world.Update(0.01);
queriedEntities.Should().BeEmpty();
}
[Reads(typeof(MockComponent))]
[Writes(typeof(MockComponent))]
[QueryWithout(typeof(MockComponent))]
class EntityQueryWithoutComponentsEngine : Engine
{
@ -1164,7 +1171,11 @@ namespace Tests
public override void Update(double dt)
{
entities.Clear();
entities.AddRange(TrackedEntities);
foreach (var entity in TrackedEntities)
{
entities.Add(entity);
SetComponent(entity, new MockComponent());
}
}
}
@ -1193,6 +1204,10 @@ namespace Tests
world.Update(0.01);
queriedEntities.ToArray().Should().BeEquivalentTo(new Entity[] { entityC });
world.Update(0.01);
queriedEntities.Should().BeEmpty();
}
[Reads(typeof(MockComponent), typeof(MockComponentB), typeof(MockComponentD))]