From cf6d59bb5bd6d022c869971bb28cb8cffdac9f21 Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+ehemsley@users.noreply.github.com> Date: Wed, 19 Jun 2019 17:40:01 -0700 Subject: [PATCH] draw layer manager and final entity renderer tests --- encompass-cs/ComponentManager.cs | 50 ++++++++++-- encompass-cs/DrawLayerManager.cs | 98 ++++++++++++++++++++++++ encompass-cs/Entity.cs | 15 ++++ encompass-cs/IEntityTracker.cs | 2 +- encompass-cs/RenderManager.cs | 84 +++----------------- encompass-cs/World.cs | 6 +- encompass-cs/WorldBuilder.cs | 12 +-- encompass-cs/renderers/EntityRenderer.cs | 8 +- test/EntityRendererTest.cs | 76 +++++++++++++++++- test/EntityTest.cs | 23 +++++- 10 files changed, 280 insertions(+), 94 deletions(-) create mode 100644 encompass-cs/DrawLayerManager.cs diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index 78ef122..4b76712 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -6,6 +6,8 @@ namespace Encompass { internal class ComponentManager { + private DrawLayerManager drawLayerManager; + private Dictionary componentIDToType = new Dictionary(); private Dictionary IDToComponent = new Dictionary(); private Dictionary> entityIDToComponentIDs = new Dictionary>(); @@ -25,10 +27,12 @@ namespace Encompass private List entitiesWithRemovedComponents; public ComponentManager( + DrawLayerManager drawLayerManager, List entitiesWithAddedComponents, List entitiesWithRemovedComponents ) { + this.drawLayerManager = drawLayerManager; this.entitiesWithAddedComponents = entitiesWithAddedComponents; this.entitiesWithRemovedComponents = entitiesWithRemovedComponents; } @@ -60,12 +64,24 @@ namespace Encompass entitiesWithAddedComponents.Add(entityID); + if (component is IDrawComponent) + { + drawLayerManager.RegisterComponentWithLayer(componentID, (component as IDrawComponent).Layer); + } + return componentID; } + internal IEnumerable GetComponentIDsByEntityID(Guid entityID) + { + return entityIDToComponentIDs.ContainsKey(entityID) ? + entityIDToComponentIDs[entityID] : + Enumerable.Empty(); + } + internal IEnumerable> GetComponentsByEntity(Guid entityID) { - return entityIDToComponentIDs[entityID].Intersect(activeComponents).Select((id) => new KeyValuePair(id, IDToComponent[id])); + return GetComponentIDsByEntityID(entityID).Intersect(activeComponents).Select((id) => new KeyValuePair(id, IDToComponent[id])); } internal IEnumerable> GetActiveComponentsByType() where TComponent : struct, IComponent @@ -103,7 +119,7 @@ namespace Encompass internal IEnumerable GetAllComponentTypesOfEntity(Guid entityID) { - return entityIDToComponentIDs[entityID].Select((id) => componentIDToType[id]); + return GetComponentIDsByEntityID(entityID).Select((id) => componentIDToType[id]); } internal bool EntityHasComponentOfType(Guid entityID) where TComponent : struct, IComponent @@ -152,19 +168,28 @@ namespace Encompass internal void MarkForActivation(Guid componentID) { componentsToActivate.Add(componentID); + + var entityID = GetEntityIDFromComponentID(componentID); + entitiesWithAddedComponents.Add(entityID); } internal void MarkForDeactivation(Guid componentID) { componentsToDeactivate.Add(componentID); + + var entityID = GetEntityIDFromComponentID(componentID); + entitiesWithRemovedComponents.Add(entityID); } internal void MarkForRemoval(Guid componentID) { componentsToRemove.Add(componentID); + + var entityID = GetEntityIDFromComponentID(componentID); + entitiesWithRemovedComponents.Add(entityID); } - internal void ActivateComponents() + internal void ActivateMarkedComponents() { foreach (var componentID in componentsToActivate) { @@ -178,7 +203,7 @@ namespace Encompass componentsToActivate.Clear(); } - internal void DeactivateComponents() + internal void DeactivateMarkedComponents() { foreach (var componentID in componentsToDeactivate) { @@ -192,13 +217,28 @@ namespace Encompass componentsToDeactivate.Clear(); } - internal void RemoveComponents() + internal void RemoveMarkedComponents() { foreach (var componentID in componentsToRemove) { var component = IDToComponent[componentID]; + var type = componentIDToType[componentID]; + activeComponents.Remove(componentID); inactiveComponents.Remove(componentID); + + var entityID = componentIDToEntityID[componentID]; + entityIDToComponentIDs[entityID].Remove(componentID); + + IDToComponent.Remove(componentID); + componentIDToType.Remove(componentID); + componentIDToEntityID.Remove(componentID); + typeToComponentIDs[type].Remove(componentID); + + if (component is IDrawComponent) + { + drawLayerManager.UnRegisterComponentWithLayer(componentID, (component as IDrawComponent).Layer); + } } componentsToRemove.Clear(); diff --git a/encompass-cs/DrawLayerManager.cs b/encompass-cs/DrawLayerManager.cs new file mode 100644 index 0000000..bec81b6 --- /dev/null +++ b/encompass-cs/DrawLayerManager.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Encompass +{ + internal class DrawLayerManager + { + private SortedList layerOrder = new SortedList(); + + private Dictionary> layerIndexToComponentIDs = new Dictionary>(); + private Dictionary> layerIndexToGeneralRenderers = new Dictionary>(); + + public IEnumerable LayerOrder { get { return layerOrder.Values; } } + + public void RegisterGeneralRendererWithLayer(GeneralRenderer renderer, int layer) + { + if (layerIndexToGeneralRenderers.ContainsKey(layer)) + { + var set = layerIndexToGeneralRenderers[layer]; + set.Add(renderer); + } + else + { + var set = new HashSet(); + layerIndexToGeneralRenderers.Add(layer, set); + set.Add(renderer); + } + + if (!layerOrder.ContainsKey(layer)) + { + layerOrder.Add(layer, layer); + } + } + + public void UnregisterGeneralRendererWithLayer(GeneralRenderer renderer, int layer) + { + if (layerIndexToGeneralRenderers.ContainsKey(layer)) + { + layerIndexToGeneralRenderers[layer].Remove(renderer); + } + } + + public void AdjustRendererLayer(GeneralRenderer renderer, int oldLayer, int newLayer) + { + UnregisterGeneralRendererWithLayer(renderer, oldLayer); + RegisterGeneralRendererWithLayer(renderer, newLayer); + } + + public void RegisterComponentWithLayer(Guid id, int layer) + { + if (layerIndexToComponentIDs.ContainsKey(layer)) + { + var set = layerIndexToComponentIDs[layer]; + set.Add(id); + } + else + { + var set = new HashSet(); + layerIndexToComponentIDs.Add(layer, set); + set.Add(id); + } + + if (!layerOrder.ContainsKey(layer)) + { + layerOrder.Add(layer, layer); + } + } + + public void UnRegisterComponentWithLayer(Guid id, int layer) + { + if (layerIndexToComponentIDs.ContainsKey(layer)) + { + layerIndexToComponentIDs[layer].Remove(id); + } + } + + public void AdjustComponentLayer(Guid id, int oldLayer, int newLayer) + { + UnRegisterComponentWithLayer(id, oldLayer); + RegisterComponentWithLayer(id, newLayer); + } + + public IEnumerable ComponentIDsByLayer(int layer) + { + return layerIndexToComponentIDs.ContainsKey(layer) ? + layerIndexToComponentIDs[layer] : + Enumerable.Empty(); + } + + public IEnumerable GeneralRenderersByLayer(int layer) + { + return layerIndexToGeneralRenderers.ContainsKey(layer) ? + layerIndexToGeneralRenderers[layer] : + Enumerable.Empty(); + } + } +} diff --git a/encompass-cs/Entity.cs b/encompass-cs/Entity.cs index 20180c1..12055ef 100644 --- a/encompass-cs/Entity.cs +++ b/encompass-cs/Entity.cs @@ -41,6 +41,21 @@ namespace Encompass return componentManager.EntityHasComponentOfType(id, type); } + public void ActivateComponent(Guid componentID) + { + componentManager.MarkForActivation(componentID); + } + + public void DeactivateComponent(Guid componentID) + { + componentManager.MarkForDeactivation(componentID); + } + + public void RemoveComponent(Guid componentID) + { + componentManager.MarkForRemoval(componentID); + } + internal void RemoveAllComponents() { componentManager.RemoveAllComponentsFromEntity(id); diff --git a/encompass-cs/IEntityTracker.cs b/encompass-cs/IEntityTracker.cs index 050090c..b96e54c 100644 --- a/encompass-cs/IEntityTracker.cs +++ b/encompass-cs/IEntityTracker.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace Encompass { - public interface IEntityTracker + internal interface IEntityTracker { IEnumerable ComponentTypes { get; } diff --git a/encompass-cs/RenderManager.cs b/encompass-cs/RenderManager.cs index 4d2ce5c..2c69e0d 100644 --- a/encompass-cs/RenderManager.cs +++ b/encompass-cs/RenderManager.cs @@ -8,17 +8,19 @@ namespace Encompass { private EntityManager entityManager; private ComponentManager componentManager; - - private SortedList layerOrder = new SortedList(); - private Dictionary> layerIndexToComponentIDs = new Dictionary>(); - private Dictionary> layerIndexToGeneralRenderers = new Dictionary>(); + private DrawLayerManager drawLayerManager; private Dictionary drawComponentTypeToEntityRenderer = new Dictionary(); - public RenderManager(EntityManager entityManager, ComponentManager componentManager) + public RenderManager( + EntityManager entityManager, + ComponentManager componentManager, + DrawLayerManager drawLayerManager + ) { this.entityManager = entityManager; this.componentManager = componentManager; + this.drawLayerManager = drawLayerManager; } public void RegisterEntityRenderer(EntityRenderer renderer) @@ -32,79 +34,15 @@ namespace Encompass public void RegisterGeneralRendererWithLayer(GeneralRenderer renderer, int layer) { - if (layerIndexToGeneralRenderers.ContainsKey(layer)) - { - var set = layerIndexToGeneralRenderers[layer]; - set.Add(renderer); - } - else - { - var set = new HashSet(); - layerIndexToGeneralRenderers.Add(layer, set); - set.Add(renderer); - } - - if (!layerOrder.ContainsKey(layer)) - { - layerOrder.Add(layer, layer); - } - } - - public void UnregisterGeneralRendererWithLayer(GeneralRenderer renderer, int layer) - { - if (layerIndexToGeneralRenderers.ContainsKey(layer)) - { - layerIndexToGeneralRenderers[layer].Remove(renderer); - } - } - - public void AdjustRendererLayer(GeneralRenderer renderer, int oldLayer, int newLayer) - { - UnregisterGeneralRendererWithLayer(renderer, oldLayer); - RegisterGeneralRendererWithLayer(renderer, newLayer); - } - - public void RegisterComponentWithLayer(Guid id, int layer) - { - if (layerIndexToComponentIDs.ContainsKey(layer)) - { - var set = layerIndexToComponentIDs[layer]; - set.Add(id); - } - else - { - var set = new HashSet(); - layerIndexToComponentIDs.Add(layer, set); - set.Add(id); - } - - if (!layerOrder.ContainsKey(layer)) - { - layerOrder.Add(layer, layer); - } - } - - public void UnRegisterComponentWithLayer(Guid id, int layer) - { - if (layerIndexToComponentIDs.ContainsKey(layer)) - { - layerIndexToComponentIDs[layer].Remove(id); - } - } - - public void AdjustComponentLayer(Guid id, int oldLayer, int newLayer) - { - UnRegisterComponentWithLayer(id, oldLayer); - RegisterComponentWithLayer(id, newLayer); + drawLayerManager.RegisterGeneralRendererWithLayer(renderer, layer); } public void Draw() { - foreach (var layerKVPair in layerOrder) + foreach (var layer in drawLayerManager.LayerOrder) { - var layer = layerKVPair.Key; - var componentIDSet = layerIndexToComponentIDs[layer]; - var generalRendererSet = layerIndexToGeneralRenderers[layer]; + var componentIDSet = drawLayerManager.ComponentIDsByLayer(layer); + var generalRendererSet = drawLayerManager.GeneralRenderersByLayer(layer); foreach (var componentID in componentIDSet) { diff --git a/encompass-cs/World.cs b/encompass-cs/World.cs index bd53b27..00c9092 100644 --- a/encompass-cs/World.cs +++ b/encompass-cs/World.cs @@ -35,9 +35,9 @@ namespace Encompass messageManager.ClearMessages(); entityManager.DestroyMarkedEntities(); - componentManager.ActivateComponents(); - componentManager.DeactivateComponents(); - componentManager.RemoveComponents(); + componentManager.ActivateMarkedComponents(); + componentManager.DeactivateMarkedComponents(); + componentManager.RemoveMarkedComponents(); entityManager.CheckEntitiesWithAddedComponents(); entityManager.CheckEntitiesWithRemovedComponents(); diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index e47c2fa..f3e6ad3 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -13,6 +13,7 @@ namespace Encompass private ComponentManager componentManager; private EntityManager entityManager; private MessageManager messageManager; + private DrawLayerManager drawLayerManager; private RenderManager renderManager; private Dictionary> messageTypeToEmitters = new Dictionary>(); @@ -22,10 +23,11 @@ namespace Encompass { var entitiesWithAddedComponents = new List(); var entitiesWithRemovedComponents = new List(); - componentManager = new ComponentManager(entitiesWithAddedComponents, entitiesWithRemovedComponents); + drawLayerManager = new DrawLayerManager(); + componentManager = new ComponentManager(drawLayerManager, entitiesWithAddedComponents, entitiesWithRemovedComponents); entityManager = new EntityManager(componentManager, entitiesWithAddedComponents, entitiesWithRemovedComponents); messageManager = new MessageManager(); - renderManager = new RenderManager(entityManager, componentManager); + renderManager = new RenderManager(entityManager, componentManager, drawLayerManager); } public Entity CreateEntity() @@ -190,9 +192,9 @@ namespace Encompass renderManager ); - componentManager.ActivateComponents(); - componentManager.DeactivateComponents(); - componentManager.RemoveComponents(); + componentManager.ActivateMarkedComponents(); + componentManager.DeactivateMarkedComponents(); + componentManager.RemoveMarkedComponents(); entityManager.CheckEntitiesWithAddedComponents(); entityManager.CheckEntitiesWithRemovedComponents(); diff --git a/encompass-cs/renderers/EntityRenderer.cs b/encompass-cs/renderers/EntityRenderer.cs index 9e25be7..1ecac5d 100644 --- a/encompass-cs/renderers/EntityRenderer.cs +++ b/encompass-cs/renderers/EntityRenderer.cs @@ -24,7 +24,7 @@ namespace Encompass } } - public bool CheckAndTrackEntity(Guid entityID) + bool IEntityTracker.CheckAndTrackEntity(Guid entityID) { var entity = GetEntity(entityID); var shouldTrack = CheckEntity(entity); @@ -32,10 +32,10 @@ namespace Encompass return shouldTrack; } - public bool CheckAndUntrackEntity(Guid entityID) + bool IEntityTracker.CheckAndUntrackEntity(Guid entityID) { var entity = GetEntity(entityID); - var shouldUntrack = CheckEntity(entity); + var shouldUntrack = !CheckEntity(entity); if (shouldUntrack) { entityTracker.UntrackEntity(entityID); } return shouldUntrack; } @@ -45,7 +45,7 @@ namespace Encompass return entityTracker.IsTracking(entityID); } - internal bool CheckEntity(Entity entity) + private bool CheckEntity(Entity entity) { return EntityChecker.CheckEntity(entity, componentTypes) && entity.HasComponent(DrawComponentType); diff --git a/test/EntityRendererTest.cs b/test/EntityRendererTest.cs index 69a8251..3b21fa6 100644 --- a/test/EntityRendererTest.cs +++ b/test/EntityRendererTest.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using NUnit.Framework; using Encompass; @@ -57,5 +55,79 @@ namespace Tests Assert.IsFalse(renderer.IsTracking(entityNotToTrack.id)); Assert.IsFalse(renderer.IsTracking(entityWithoutDrawComponent.id)); } + + static bool called = false; + class DeactivatedRenderer : TestRenderer + { + public override void Render(Entity entity) + { + called = true; + } + } + + [Test] + public void InactiveDrawComponent() + { + var worldBuilder = new WorldBuilder(); + var renderer = worldBuilder.AddRenderer(); + + AComponent aComponent; + BComponent bComponent; + TestDrawComponent testDrawComponent = default(TestDrawComponent); + testDrawComponent.Layer = 0; + + var entity = worldBuilder.CreateEntity(); + entity.AddComponent(aComponent); + entity.AddComponent(bComponent); + var testDrawComponentID = entity.AddComponent(testDrawComponent); + + var world = worldBuilder.Build(); + + world.Update(0.01f); + + entity.DeactivateComponent(testDrawComponentID); + + world.Update(0.01f); + + Assert.IsFalse(renderer.IsTracking(entity.id)); + + world.Draw(); + + Assert.IsFalse(called); + } + + static bool calledOnDraw = false; + [Renders(typeof(TestDrawComponent), typeof(AComponent), typeof(CComponent))] + class CalledRenderer : EntityRenderer + { + public override void Render(Entity entity) + { + calledOnDraw = true; + } + } + + [Test] + public void RenderMethodCalledOnWorldDraw() + { + var worldBuilder = new WorldBuilder(); + var renderer = worldBuilder.AddRenderer(); + + AComponent aComponent; + CComponent cComponent; + TestDrawComponent testDrawComponent = default(TestDrawComponent); + + var entity = worldBuilder.CreateEntity(); + entity.AddComponent(aComponent); + entity.AddComponent(cComponent); + entity.AddComponent(testDrawComponent); + + var world = worldBuilder.Build(); + + world.Update(0.01f); + world.Draw(); + + Assert.IsTrue(renderer.IsTracking(entity.id)); + Assert.IsTrue(calledOnDraw); + } } } diff --git a/test/EntityTest.cs b/test/EntityTest.cs index 6fb4a9d..3eb8ffc 100644 --- a/test/EntityTest.cs +++ b/test/EntityTest.cs @@ -93,11 +93,32 @@ namespace Tests mockComponent.myInt = 3; mockComponent.myString = "hello"; - entity.AddComponent(mockComponent); + entity.AddComponent(mockComponent); var world = worldBuilder.Build(); Assert.IsTrue(entity.HasComponent()); } + + [Test] + public void HasComponentWhenInactive() + { + var worldBuilder = new WorldBuilder(); + var entity = worldBuilder.CreateEntity(); + + MockComponent mockComponent; + mockComponent.myInt = 3; + mockComponent.myString = "hello"; + + var componentID = entity.AddComponent(mockComponent); + + var world = worldBuilder.Build(); + + entity.DeactivateComponent(componentID); + + world.Update(0.01f); + + Assert.IsFalse(entity.HasComponent()); + } } }