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))) if (writeImmediateTypes.Contains(typeof(TComponent)))
{ {
written = componentUpdateManager.AddImmediateComponent(entity, component, priority); written = componentUpdateManager.AddImmediateComponent(entity, component, priority);
if (written)
{
trackingManager.ImmediateUpdateTracking(entity, typeof(TComponent));
}
} }
else else
{ {
@ -577,7 +581,10 @@ namespace Encompass
if (writeImmediateTypes.Contains(typeof(TComponent))) if (writeImmediateTypes.Contains(typeof(TComponent)))
{ {
componentManager.RemoveImmediate<TComponent>(entity, priority); if (componentManager.RemoveImmediate<TComponent>(entity, priority))
{
trackingManager.ImmediateUpdateTracking(entity, typeof(TComponent));
}
} }
else else
{ {
@ -650,20 +657,28 @@ namespace Encompass
timeManager.ActivateTimeDilation(factor, easeInTime, easeInFunction, activeTime, easeOutTime, easeOutFunction); 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); _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); _trackedEntities.Remove(entity);
} }
else if (!_trackedEntities.Contains(entity) && entityQuery.ImmediateCheckEntity(entity, componentUpdateManager.ImmediateBits, componentUpdateManager.ExistingBits))
{
_trackedEntities.Add(entity);
}
} }
/// <summary> /// <summary>

View File

@ -31,7 +31,7 @@ namespace Encompass
return existing.And(existingForbidden).AllTrue(); 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 immediateBits = immediateBitLookup.EntityBitArray(entity.ID);
var existingBits = existingBitLookup.EntityBitArray(entity.ID); var existingBits = existingBitLookup.EntityBitArray(entity.ID);

View File

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

View File

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