diff --git a/encompass-cs/ComponentUpdateManager.cs b/encompass-cs/ComponentUpdateManager.cs index 26b3ea8..654ed99 100644 --- a/encompass-cs/ComponentUpdateManager.cs +++ b/encompass-cs/ComponentUpdateManager.cs @@ -18,6 +18,7 @@ namespace Encompass existingAndPendingComponentStore.RegisterComponentType(); existingComponentStore.RegisterComponentType(); pendingComponentStore.RegisterComponentType(); + UpToDateComponentStore.RegisterComponentType(); } internal void Clear() diff --git a/encompass-cs/DrawLayerManager.cs b/encompass-cs/DrawLayerManager.cs index 1680df2..7c9a68f 100644 --- a/encompass-cs/DrawLayerManager.cs +++ b/encompass-cs/DrawLayerManager.cs @@ -16,6 +16,11 @@ namespace Encompass public IEnumerable LayerOrder { get { return layerOrder.Values; } } + public DrawLayerManager() + { + RegisterDrawLayer(0); + } + public void RegisterDrawLayer(int layer) { if (!layerIndexToComponentStore.ContainsKey(layer)) @@ -28,7 +33,11 @@ namespace Encompass public void RegisterOrderedDrawable() where TComponent : struct, IComponent { - typeToEntityToLayer.Add(typeof(TComponent), new Dictionary(128)); + if (!typeToEntityToLayer.ContainsKey(typeof(TComponent))) + { + typeToEntityToLayer.Add(typeof(TComponent), new Dictionary(128)); + } + foreach (var pair in layerIndexToComponentStore) { pair.Value.RegisterComponentType(); diff --git a/encompass-cs/UberEngine.cs b/encompass-cs/UberEngine.cs index f27b596..035d2ef 100644 --- a/encompass-cs/UberEngine.cs +++ b/encompass-cs/UberEngine.cs @@ -1,33 +1,60 @@ using System; +using System.Collections.Generic; using System.Reflection; namespace Encompass { internal class UberEngine : Engine { - public override void Update(double dt) - { - foreach (var type in readTypes) - { - var instanceParam = new object[] { Activator.CreateInstance(type) }; + private IEnumerable _componentTypes; + private Entity _entity; - CallMethodByName(type, "ReadComponent", null); - CallMethodByName(type, "ReadComponentIncludingEntity", null); - CallMethodByName(type, "ReadComponents", null); - CallMethodByName(type, "ReadComponentsIncludingEntity", null); - CallMethodByName(type, "GetComponent", null); - CallMethodByName(type, "SetComponent", instanceParam); - CallMethodByName(type, "HasComponent", null); - CallMethodByName(type, "SomeComponent", null); - CallMethodByName(type, "RemoveComponent", null); - CallMethodByName(type, "DestroyWith", null); - CallMethodByName(type, "DestroyAllWith", null); + public UberEngine(Entity entity, IEnumerable componentTypes) + { + _componentTypes = componentTypes; + readTypes.UnionWith(componentTypes); + writeTypes.UnionWith(componentTypes); + _entity = entity; + } + + public void Write() + { + foreach (var type in _componentTypes) + { + var instanceParam = new object[] { _entity, Activator.CreateInstance(type) }; + var setComponentMethod = typeof(Engine).GetMethod("SetComponent", BindingFlags.NonPublic | BindingFlags.Instance); + var genericSetComponentMethod = setComponentMethod.MakeGenericMethod(type); + genericSetComponentMethod.Invoke(this, instanceParam); } } - private void CallMethodByName(Type type, string methodName, object[] parameters) + public override void Update(double dt) { - var readComponentMethod = typeof(WorldBuilder).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); + foreach (var type in _componentTypes) + { + CallGenericMethod(type, "ReadComponent", null); + CallGenericMethod(type, "ReadComponentIncludingEntity", null); + CallGenericMethod(type, "ReadComponents", null); + CallGenericMethod(type, "ReadComponentsIncludingEntity", null); + CallGenericMethod(type, "GetComponent", new Type[] { typeof(Entity) }, new object[] { _entity }); + CallGenericMethod(type, "HasComponent", new Type[] { typeof(Entity) }, new object[] { _entity }); + CallGenericMethod(type, "SomeComponent", null); + CallGenericMethod(type, "RemoveComponent", new Type[] { typeof(Entity) }, new object[] { _entity }); + CallGenericMethod(type, "DestroyWith", null); + CallGenericMethod(type, "DestroyAllWith", null); + } + } + + private void CallGenericMethod(Type type, string methodName, object[] parameters) + { + var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); + var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); + genericReadComponentMethod.Invoke(this, parameters); + } + + private void CallGenericMethod(Type type, string methodName, Type[] types, object[] parameters) + { + var readComponentMethod = typeof(Engine).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance, null, types, null); var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); genericReadComponentMethod.Invoke(this, parameters); } diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index ac84f26..0eb7a08 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -78,6 +78,7 @@ namespace Encompass public void SetComponent(Entity entity, TComponent component) where TComponent : struct, IComponent { RegisterComponentType(); + componentTypesToRegister.Add(typeof(TComponent)); startingComponentStoreForComponentManager.Set(entity, component); startingComponentStoreForComponentUpdateManager.Set(entity, component); @@ -85,6 +86,7 @@ namespace Encompass if (component is IDrawableComponent drawableComponent) { componentManager.RegisterDrawableComponent(entity, component, drawableComponent.Layer); + drawLayerManager.RegisterOrderedDrawable(); } } @@ -350,6 +352,8 @@ namespace Encompass engineOrder.Add(emitterEngine); } + PreloadJIT(componentTypesToRegister); + foreach (var engine in engineGraph.TopologicalSort()) { engineOrder.Add(engine); @@ -377,14 +381,67 @@ namespace Encompass /// private void PreloadJIT(IEnumerable componentTypes) { - var dummyWorldBuilder = new WorldBuilder(); + var dummyTimeManager = new TimeManager(); + var dummyMessageManager = new MessageManager(dummyTimeManager); + var dummyDrawLayerManager = new DrawLayerManager(); + var dummyComponentUpdateManager = new ComponentUpdateManager(); + var dummyComponentManager = new ComponentManager(dummyDrawLayerManager, dummyComponentUpdateManager); + var dummyEntityManager = new EntityManager(dummyComponentManager); + var dummyRenderManager = new RenderManager(dummyDrawLayerManager); - dummyWorldBuilder.AddEngine(new UberEngine()); + var prepEngineOrder = new List(); + var uberEngine = new UberEngine(dummyEntityManager.CreateEntity(), componentTypes); - var dummyWorld = dummyWorldBuilder.Build(); + uberEngine.AssignEntityManager(dummyEntityManager); + uberEngine.AssignComponentManager(dummyComponentManager); + uberEngine.AssignMessageManager(dummyMessageManager); + uberEngine.AssignComponentUpdateManager(dummyComponentUpdateManager); + uberEngine.AssignTimeManager(dummyTimeManager); + + foreach (var type in componentTypes) + { + var componentManagerRegisterMethod = typeof(ComponentManager).GetMethod("RegisterComponentType"); + var componentManagerRegisterGenericMethod = componentManagerRegisterMethod.MakeGenericMethod(type); + componentManagerRegisterGenericMethod.Invoke(dummyComponentManager, null); + + var componentUpdateManagerRegisterMethod = typeof(ComponentUpdateManager).GetMethod("RegisterComponentType"); + var componentUpdateManagerRegisterGenericMethod = componentUpdateManagerRegisterMethod.MakeGenericMethod(type); + componentUpdateManagerRegisterGenericMethod.Invoke(dummyComponentUpdateManager, null); + + if (type.GetInterface("IDrawableComponent") != null) + { + var drawLayerManagerRegisterMethod = typeof(DrawLayerManager).GetMethod("RegisterOrderedDrawable"); + var drawLayerManagerRegisterGenericMethod = drawLayerManagerRegisterMethod.MakeGenericMethod(type); + drawLayerManagerRegisterGenericMethod.Invoke(dummyDrawLayerManager, null); + } + + var emitterEngine = (Engine)Activator.CreateInstance(typeof(ComponentEmitter<>).MakeGenericType(type)); + emitterEngine.AssignEntityManager(dummyEntityManager); + emitterEngine.AssignComponentManager(dummyComponentManager); + emitterEngine.AssignMessageManager(dummyMessageManager); + emitterEngine.AssignComponentUpdateManager(dummyComponentUpdateManager); + emitterEngine.AssignTimeManager(dummyTimeManager); + + prepEngineOrder.Add(emitterEngine); + } + + prepEngineOrder.Add(uberEngine); + + var dummyWorld = new World( + prepEngineOrder, + dummyEntityManager, + dummyComponentManager, + dummyMessageManager, + dummyComponentUpdateManager, + dummyTimeManager, + dummyRenderManager + ); + + uberEngine.Write(); + dummyComponentManager.WriteComponents(); + dummyComponentUpdateManager.Clear(); dummyWorld.Update(1); - dummyWorld.Draw(); } } } diff --git a/test/OrderedRendererTest.cs b/test/OrderedRendererTest.cs index 4dfa315..6f7dc8a 100644 --- a/test/OrderedRendererTest.cs +++ b/test/OrderedRendererTest.cs @@ -48,6 +48,8 @@ namespace Tests public void RenderMethodCalledOnWorldDraw() { var worldBuilder = new WorldBuilder(); + worldBuilder.RegisterDrawLayer(2); + var renderer = worldBuilder.AddOrderedRenderer(new CalledRenderer()); AComponent aComponent; @@ -86,6 +88,8 @@ namespace Tests calledOnDraw = false; var worldBuilder = new WorldBuilder(); + worldBuilder.RegisterDrawLayer(1); + worldBuilder.AddEngine(new DestroyerEngine()); var renderer = worldBuilder.AddOrderedRenderer(new CalledRenderer()); diff --git a/test/WorldTest.cs b/test/WorldTest.cs index c02a38f..def4165 100644 --- a/test/WorldTest.cs +++ b/test/WorldTest.cs @@ -39,6 +39,12 @@ namespace Tests public void DrawOrder() { var worldBuilder = new WorldBuilder(); + worldBuilder.RegisterDrawLayer(1); + worldBuilder.RegisterDrawLayer(2); + worldBuilder.RegisterDrawLayer(3); + worldBuilder.RegisterDrawLayer(4); + worldBuilder.RegisterDrawLayer(7); + worldBuilder.AddOrderedRenderer(new TestEntityRenderer()); var testGeneralRenderer = worldBuilder.AddGeneralRenderer(new TestGeneralRenderer(), 7);