diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs
index 6428abc..2557b9f 100644
--- a/encompass-cs/Engine.cs
+++ b/encompass-cs/Engine.cs
@@ -213,7 +213,7 @@ namespace Encompass
///
/// Returns all Entities containing the specified Component type.
///
- protected Span ReadEntities() where TComponent : struct
+ protected Span ReadEntities() where TComponent : struct, IComponent
{
var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent));
var existingRead = ReadTypes.Contains(typeof(TComponent));
@@ -238,7 +238,7 @@ namespace Encompass
///
/// Returns an Entity containing the specified Component type.
///
- protected ref readonly Entity ReadEntity() where TComponent : struct
+ protected ref readonly Entity ReadEntity() where TComponent : struct, IComponent
{
var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent));
var existingRead = ReadTypes.Contains(typeof(TComponent));
@@ -263,7 +263,7 @@ namespace Encompass
///
/// Returns all of the Components with the specified Component Type.
///
- protected Span ReadComponents() where TComponent : struct
+ protected Span ReadComponents() where TComponent : struct, IComponent
{
var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent));
var existingRead = ReadTypes.Contains(typeof(TComponent));
@@ -288,7 +288,7 @@ namespace Encompass
///
/// Returns a Component with the specified Component Type. If multiples exist, an arbitrary Component is returned.
///
- protected ref readonly TComponent ReadComponent() where TComponent : struct
+ protected ref readonly TComponent ReadComponent() where TComponent : struct, IComponent
{
var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent));
var existingRead = ReadTypes.Contains(typeof(TComponent));
@@ -313,7 +313,7 @@ namespace Encompass
///
/// Returns true if any Component with the specified Component Type exists.
///
- protected bool SomeComponent() where TComponent : struct
+ protected bool SomeComponent() where TComponent : struct, IComponent
{
var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent));
var existingRead = ReadTypes.Contains(typeof(TComponent));
@@ -335,7 +335,7 @@ namespace Encompass
}
}
- private ref TComponent GetComponentHelper(int entityID) where TComponent : struct
+ private ref TComponent GetComponentHelper(int entityID) where TComponent : struct, IComponent
{
var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent));
var existingRead = ReadTypes.Contains(typeof(TComponent));
@@ -366,7 +366,7 @@ namespace Encompass
///
/// Thrown when the Engine does not declare that it reads the given Component Type.
///
- protected ref readonly TComponent GetComponent(in Entity entity) where TComponent : struct
+ protected ref readonly TComponent GetComponent(in Entity entity) where TComponent : struct, IComponent
{
return ref GetComponentHelper(entity.ID);
}
@@ -380,7 +380,7 @@ namespace Encompass
///
/// Thrown when the Engine does not declare that it reads the given Component Type.
///
- protected ref TComponent GetComponentMutable(in Entity entity) where TComponent : struct
+ protected ref TComponent GetComponentMutable(in Entity entity) where TComponent : struct, IComponent
{
return ref GetComponentHelper(entity.ID);
}
@@ -391,7 +391,7 @@ namespace Encompass
///
/// Thrown when the Engine does not declare that is Reads the given Component Type.
///
- protected bool HasComponent(in Entity entity) where TComponent : struct
+ protected bool HasComponent(in Entity entity) where TComponent : struct, IComponent
{
var immediateRead = ReadImmediateTypes.Contains(typeof(TComponent));
var existingRead = ReadTypes.Contains(typeof(TComponent));
@@ -449,7 +449,7 @@ namespace Encompass
///
/// Thrown when the Engine does not declare that it Writes the given Component Type.
///
- protected void SetComponent(in Entity entity, in TComponent component) where TComponent : struct
+ protected void SetComponent(in Entity entity, in TComponent component) where TComponent : struct, IComponent
{
var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority;
@@ -489,7 +489,7 @@ namespace Encompass
///
/// Thrown when the Engine does not declare that it Writes the given Component Type.
///
- protected void AddComponent(in Entity entity, in TComponent component) where TComponent : struct
+ protected void AddComponent(in Entity entity, in TComponent component) where TComponent : struct, IComponent
{
if (!EntityCreatedThisFrame(entity.ID))
{
@@ -597,7 +597,7 @@ namespace Encompass
/// Destroys an arbitrary Entity containing a Component of the specified Type.
/// Entity destruction takes place after all the Engines have been processed by World Update.
///
- protected void DestroyWith() where TComponent : struct
+ protected void DestroyWith() where TComponent : struct, IComponent
{
Destroy(ReadEntity());
}
@@ -606,7 +606,7 @@ namespace Encompass
/// Destroys all Entities containing a Component of the specified Type.
/// Entity destruction takes place after all the Engines have been processed by World Update.
///
- protected void DestroyAllWith() where TComponent : struct
+ protected void DestroyAllWith() where TComponent : struct, IComponent
{
foreach (var entity in ReadEntities())
{
@@ -619,7 +619,7 @@ namespace Encompass
/// Note that the Engine must Read the Component type that is being removed.
/// If a Component with the specified type does not exist on the Entity, returns false and does not mutate the Entity.
///
- protected void RemoveComponent(in Entity entity) where TComponent : struct
+ protected void RemoveComponent(in Entity entity) where TComponent : struct, IComponent
{
var priority = WritePriorities.ContainsKey(typeof(TComponent)) ? WritePriorities[typeof(TComponent)] : DefaultWritePriority;
diff --git a/encompass-cs/Interfaces/IComponent.cs b/encompass-cs/Interfaces/IComponent.cs
new file mode 100644
index 0000000..d51b93c
--- /dev/null
+++ b/encompass-cs/Interfaces/IComponent.cs
@@ -0,0 +1,4 @@
+namespace Encompass
+{
+ public interface IComponent { }
+}
diff --git a/encompass-cs/Renderer.cs b/encompass-cs/Renderer.cs
index ccc8e59..85b5489 100644
--- a/encompass-cs/Renderer.cs
+++ b/encompass-cs/Renderer.cs
@@ -18,37 +18,37 @@ namespace Encompass
_componentManager = componentManager;
}
- protected Span ReadEntities() where TComponent : struct
+ protected Span ReadEntities() where TComponent : struct, IComponent
{
return _componentManager.GetExistingEntities();
}
- protected ref readonly Entity ReadEntity() where TComponent : struct
+ protected ref readonly Entity ReadEntity() where TComponent : struct, IComponent
{
return ref _componentManager.ExistingSingularEntity();
}
- protected Span ReadComponents() where TComponent : struct
+ protected Span ReadComponents() where TComponent : struct, IComponent
{
return _componentManager.GetComponentsByType();
}
- protected ref readonly TComponent ReadComponent() where TComponent : struct
+ protected ref readonly TComponent ReadComponent() where TComponent : struct, IComponent
{
return ref _componentManager.ExistingSingular();
}
- protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct
+ protected ref readonly TComponent GetComponent(Entity entity) where TComponent : struct, IComponent
{
return ref _componentManager.GetComponentByEntityAndType(entity.ID);
}
- protected bool HasComponent(Entity entity) where TComponent : struct
+ protected bool HasComponent(Entity entity) where TComponent : struct, IComponent
{
return _componentManager.EntityHasComponentOfType(entity.ID);
}
- protected bool SomeComponent() where TComponent : struct
+ protected bool SomeComponent() where TComponent : struct, IComponent
{
return _componentManager.SomeExistingComponent();
}
diff --git a/encompass-cs/Renderers/OrderedRenderer.cs b/encompass-cs/Renderers/OrderedRenderer.cs
index 56935f2..5b462b3 100644
--- a/encompass-cs/Renderers/OrderedRenderer.cs
+++ b/encompass-cs/Renderers/OrderedRenderer.cs
@@ -5,7 +5,7 @@ namespace Encompass
///
/// OrdereredRenderer provides a structure for the common pattern of wishing to draw a specific DrawComponent at a specific layer.
///
- public abstract class OrderedRenderer : Renderer where TComponent : struct, IDrawableComponent
+ public abstract class OrderedRenderer : Renderer where TComponent : struct, IComponent, IDrawableComponent
{
public abstract void Render(Entity entity, in TComponent drawComponent);
diff --git a/encompass-cs/UberEngine.cs b/encompass-cs/UberEngine.cs
index d0957bf..5d5378e 100644
--- a/encompass-cs/UberEngine.cs
+++ b/encompass-cs/UberEngine.cs
@@ -35,15 +35,14 @@ namespace Encompass
}
}
- // we can't reflect invoke on Span returns right now... tragic
public override void Update(double dt)
{
foreach (var type in _componentTypes)
{
CallGenericMethod(type, "ReadComponent", null);
- //CallGenericMethod(type, "ReadComponents", null);
+ CallGenericWrappedMethod(type, "ReadComponentsWrapper", null);
CallGenericMethod(type, "ReadEntity", null);
- //CallGenericMethod(type, "ReadEntities", null);
+ CallGenericWrappedMethod(type, "ReadEntitiesWrapper", null);
CallGenericMethod(type, "GetComponent", new object[] { Entity });
CallGenericMethod(type, "HasComponent", 1, new object[] { Entity });
CallGenericMethod(type, "SomeComponent", null);
@@ -59,7 +58,7 @@ namespace Encompass
CallGenericMethod(type, "SendMessage", 2, new object[] { Activator.CreateInstance(type), 1 });
CallGenericMethod(type, "ReadMessage", null);
- //CallGenericMethod(type, "ReadMessages", null);
+ CallGenericWrappedMethod(type, "ReadMessagesWrapper", null);
CallGenericMethod(type, "SomeMessage", null);
if (typeof(IHasEntity).IsAssignableFrom(type))
{
@@ -70,6 +69,23 @@ namespace Encompass
}
}
+ // we can't reflect invoke on Span returns right now... so we have non-return wrapper methods
+
+ protected void ReadComponentsWrapper() where TComponent : struct, IComponent
+ {
+ ReadComponents();
+ }
+
+ protected void ReadMessagesWrapper() where TMessage : struct, IMessage
+ {
+ ReadMessages();
+ }
+
+ protected void ReadEntitiesWrapper() where TComponent : struct, IComponent
+ {
+ ReadEntities();
+ }
+
// trying to use PrepareMethod because we can't reflect invoke methods that return a span...
private void CallGenericMethod(Type type, string methodName, object[] parameters)
{
@@ -79,6 +95,13 @@ namespace Encompass
// RuntimeHelpers.PrepareMethod(genericReadComponentMethod.MethodHandle);
}
+ private void CallGenericWrappedMethod(Type type, string methodName, object[] parameters)
+ {
+ var readComponentMethod = typeof(UberEngine).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);
diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs
index 5da3d3a..9295844 100644
--- a/encompass-cs/WorldBuilder.cs
+++ b/encompass-cs/WorldBuilder.cs
@@ -183,7 +183,7 @@ namespace Encompass
///
/// Adds the specified OrderedRenderer to the World.
///
- public OrderedRenderer AddOrderedRenderer(OrderedRenderer renderer) where TComponent : struct, IDrawableComponent
+ public OrderedRenderer AddOrderedRenderer(OrderedRenderer renderer) where TComponent : struct, IComponent, IDrawableComponent
{
RegisterComponentType();
renderer.AssignEntityManager(_entityManager);
@@ -354,7 +354,7 @@ namespace Encompass
throw new EngineWriteConflictException(errorString);
}
- PreloadJIT(_componentTypesToPreload, _messageTypes);
+ PreloadJIT(_messageTypes);
var engineOrder = new List();
@@ -388,7 +388,7 @@ namespace Encompass
/// It does so by grabbing all component and message types known to the WorldBuilder and
/// executing every possible generic method that could be executed with those types.
///
- private void PreloadJIT(IEnumerable componentTypes, IEnumerable messageTypes)
+ private void PreloadJIT(IEnumerable messageTypes)
{
var dummyTimeManager = new TimeManager();
var dummyMessageManager = new MessageManager(dummyTimeManager);
@@ -398,9 +398,30 @@ namespace Encompass
var dummyEntityManager = new EntityManager(dummyComponentManager, _entityCapacity);
var dummyRenderManager = new RenderManager(dummyEntityManager, dummyDrawLayerManager);
+ // doing reflection to grab all component types, because not all writes need to be declared
+ foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
+ {
+ foreach (var componentType in assembly.GetTypes())
+ {
+ if (typeof(IComponent).IsAssignableFrom(componentType) && componentType.IsValueType && !componentType.IsEnum && !componentType.IsPrimitive)
+ {
+ var method = typeof(WorldBuilder).GetMethod("RegisterComponentType", BindingFlags.NonPublic | BindingFlags.Instance);
+ var generic = method.MakeGenericMethod(componentType);
+ generic.Invoke(this, null);
+ }
+
+ if (componentType.GetInterface("IDrawableComponent") != null)
+ {
+ var drawLayerManagerRegisterMethod = typeof(DrawLayerManager).GetMethod("RegisterOrderedDrawable");
+ var drawLayerManagerRegisterGenericMethod = drawLayerManagerRegisterMethod.MakeGenericMethod(componentType);
+ drawLayerManagerRegisterGenericMethod.Invoke(dummyDrawLayerManager, null);
+ }
+ }
+ }
+
var prepEngineOrder = new List();
- var uberEngine = new UberEngine(componentTypes, messageTypes);
+ var uberEngine = new UberEngine(_componentTypesToPreload, messageTypes);
uberEngine.AssignEntityManager(dummyEntityManager);
uberEngine.AssignComponentManager(dummyComponentManager);
@@ -408,24 +429,10 @@ namespace Encompass
uberEngine.AssignTimeManager(dummyTimeManager);
uberEngine.AssignTrackingManager(dummyTrackingManager);
- var uberRenderer = new UberRenderer(componentTypes);
+ var uberRenderer = new UberRenderer(_componentTypesToPreload);
uberRenderer.AssignComponentManager(dummyComponentManager);
uberRenderer.AssignEntityManager(dummyEntityManager);
- foreach (var type in componentTypes)
- {
- var componentManagerRegisterMethod = typeof(ComponentManager).GetMethod("RegisterComponentType");
- var componentManagerRegisterGenericMethod = componentManagerRegisterMethod.MakeGenericMethod(type);
- componentManagerRegisterGenericMethod.Invoke(dummyComponentManager, null);
-
- if (type.GetInterface("IDrawableComponent") != null)
- {
- var drawLayerManagerRegisterMethod = typeof(DrawLayerManager).GetMethod("RegisterOrderedDrawable");
- var drawLayerManagerRegisterGenericMethod = drawLayerManagerRegisterMethod.MakeGenericMethod(type);
- drawLayerManagerRegisterGenericMethod.Invoke(dummyDrawLayerManager, null);
- }
- }
-
prepEngineOrder.Add(uberEngine);
var dummyWorld = new World(
diff --git a/test/ComponentTest.cs b/test/ComponentTest.cs
index 62050f6..9c6e2e7 100644
--- a/test/ComponentTest.cs
+++ b/test/ComponentTest.cs
@@ -8,7 +8,7 @@ namespace Tests
{
public class ComponentTests
{
- struct MockComponent
+ struct MockComponent : IComponent
{
public int myInt;
}
diff --git a/test/EngineTest.cs b/test/EngineTest.cs
index ebc5f29..c5621fe 100644
--- a/test/EngineTest.cs
+++ b/test/EngineTest.cs
@@ -10,7 +10,7 @@ using Encompass.Exceptions;
namespace Tests
{
- struct MockComponent
+ struct MockComponent : IComponent
{
public int myInt;
}
@@ -618,7 +618,7 @@ namespace Tests
world.Update(0.01f);
}
- struct DestroyerComponent { }
+ struct DestroyerComponent : IComponent { }
[Reads(typeof(DestroyerComponent))]
class DestroyerEngine : Engine
@@ -964,7 +964,7 @@ namespace Tests
entity.Should().BeEquivalentTo(readEntity);
}
- struct MockComponentB
+ struct MockComponentB : IComponent
{
private int value;
@@ -1407,9 +1407,9 @@ namespace Tests
public class QueryTests
{
- struct MockComponentB { }
- struct MockComponentC { }
- struct MockComponentD { }
+ struct MockComponentB : IComponent { }
+ struct MockComponentC : IComponent { }
+ struct MockComponentD : IComponent { }
[Reads(typeof(MockComponent), typeof(MockComponentB))]
[Writes(typeof(MockComponentB))]
@@ -1863,7 +1863,7 @@ namespace Tests
_components.Should().NotBeEmpty();
}
- struct MockTimerComponent
+ struct MockTimerComponent : IComponent
{
public double Timer { get; }
diff --git a/test/GeneralRendererTest.cs b/test/GeneralRendererTest.cs
index 7ccc3ea..32659c0 100644
--- a/test/GeneralRendererTest.cs
+++ b/test/GeneralRendererTest.cs
@@ -5,7 +5,7 @@ namespace Tests
{
public static class GeneralRendererTest
{
- struct AComponent { }
+ struct AComponent : IComponent { }
public class SingletonRead
{
diff --git a/test/OrderedRendererTest.cs b/test/OrderedRendererTest.cs
index 2ee2af7..92cb3b8 100644
--- a/test/OrderedRendererTest.cs
+++ b/test/OrderedRendererTest.cs
@@ -9,11 +9,11 @@ namespace Tests
{
public class OrderedRendererTest
{
- struct AComponent { }
- struct BComponent { }
- struct CComponent { }
+ struct AComponent : IComponent { }
+ struct BComponent : IComponent { }
+ struct CComponent : IComponent { }
- struct TestDrawComponent : IDrawableComponent
+ struct TestDrawComponent : IComponent, IDrawableComponent
{
public int Layer { get; set; }
}
diff --git a/test/SpawnerTest.cs b/test/SpawnerTest.cs
index e31ed37..c0c5f0c 100644
--- a/test/SpawnerTest.cs
+++ b/test/SpawnerTest.cs
@@ -5,7 +5,7 @@ namespace Tests
{
public class SpawnerTest
{
- struct TestComponent { }
+ struct TestComponent : IComponent { }
struct SpawnMessageA : IMessage { }
static Entity resultEntity;
diff --git a/test/WorldBuilderTest.cs b/test/WorldBuilderTest.cs
index 871dce4..2f3e7d2 100644
--- a/test/WorldBuilderTest.cs
+++ b/test/WorldBuilderTest.cs
@@ -147,7 +147,7 @@ namespace Tests
public Entity entity;
}
- struct AComponent
+ struct AComponent : IComponent
{
public int myInt;
}
@@ -216,7 +216,7 @@ namespace Tests
public Entity entity;
}
- struct AComponent
+ struct AComponent : IComponent
{
public int myInt;
}
@@ -407,8 +407,8 @@ namespace Tests
{
static List order = new List();
- struct AComponent { }
- struct BComponent { }
+ struct AComponent : IComponent { }
+ struct BComponent : IComponent { }
struct AMessage : IMessage { }
struct BMessage : IMessage { }
diff --git a/test/WorldTest.cs b/test/WorldTest.cs
index f985dc1..6ce089b 100644
--- a/test/WorldTest.cs
+++ b/test/WorldTest.cs
@@ -11,8 +11,8 @@ namespace Tests
{
public class WorldTest
{
- struct TestComponent { }
- struct TestDrawComponent : IDrawableComponent
+ struct TestComponent : IComponent { }
+ struct TestDrawComponent : IComponent, IDrawableComponent
{
public int Layer { get; set; }
}