From 9b0bf34c7325fdaa4e597675b96cad7e52f51e0d Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Sat, 28 Dec 2019 14:30:26 -0800 Subject: [PATCH] immediate tracking --- encompass-cs/Engine.cs | 25 ++++++++++++++++++----- encompass-cs/EntitySetQuery.cs | 2 +- encompass-cs/TrackingManager.cs | 35 +++++++++++++++++++++++++++++---- encompass-cs/WorldBuilder.cs | 4 ++++ test/EngineTest.cs | 17 +++++++++++++++- 5 files changed, 72 insertions(+), 11 deletions(-) diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 8bda3e9..c37a54a 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -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(entity, priority); + if (componentManager.RemoveImmediate(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); + } } /// diff --git a/encompass-cs/EntitySetQuery.cs b/encompass-cs/EntitySetQuery.cs index 663766f..02f903b 100644 --- a/encompass-cs/EntitySetQuery.cs +++ b/encompass-cs/EntitySetQuery.cs @@ -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); diff --git a/encompass-cs/TrackingManager.cs b/encompass-cs/TrackingManager.cs index 35eaf2d..1651719 100644 --- a/encompass-cs/TrackingManager.cs +++ b/encompass-cs/TrackingManager.cs @@ -5,18 +5,26 @@ namespace Encompass { internal class TrackingManager { - private Dictionary> _pendingComponentTypesToEngines = new Dictionary>(); + private Dictionary> _immediateComponentTypesToEngines = new Dictionary>(); private Dictionary> _componentTypesToEngines = new Dictionary>(); 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()); } _componentTypesToEngines[type].Add(engine); } + public void RegisterImmediateComponentTypeToEngine(Type type, Engine engine) + { + if (!_immediateComponentTypesToEngines.ContainsKey(type)) { _immediateComponentTypesToEngines.Add(type, new HashSet()); } + _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(); } } } diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 98326e5..ec31c39 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -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)) diff --git a/test/EngineTest.cs b/test/EngineTest.cs index c1eb422..1836d1d 100644 --- a/test/EngineTest.cs +++ b/test/EngineTest.cs @@ -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(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))]