diff --git a/Blarg.GameFramework/Blarg.GameFramework.csproj b/Blarg.GameFramework/Blarg.GameFramework.csproj
index 415242e..fbe2608 100644
--- a/Blarg.GameFramework/Blarg.GameFramework.csproj
+++ b/Blarg.GameFramework/Blarg.GameFramework.csproj
@@ -144,7 +144,13 @@
+
+
+
+
+
+
@@ -160,6 +166,8 @@
+
+
diff --git a/Blarg.GameFramework/Entities/Component.cs b/Blarg.GameFramework/Entities/Component.cs
new file mode 100644
index 0000000..22a0a83
--- /dev/null
+++ b/Blarg.GameFramework/Entities/Component.cs
@@ -0,0 +1,11 @@
+using System;
+using Blarg.GameFramework.Support;
+
+namespace Blarg.GameFramework.Entities
+{
+ public abstract class Component : IPoolable
+ {
+ public abstract void Reset();
+ }
+}
+
diff --git a/Blarg.GameFramework/Entities/ComponentSystem.cs b/Blarg.GameFramework/Entities/ComponentSystem.cs
new file mode 100644
index 0000000..4e83f36
--- /dev/null
+++ b/Blarg.GameFramework/Entities/ComponentSystem.cs
@@ -0,0 +1,49 @@
+using System;
+using Blarg.GameFramework.Events;
+
+namespace Blarg.GameFramework.Entities
+{
+ public class ComponentSystem : EventListener, IDisposable
+ {
+ public readonly EntityManager EntityManager;
+
+ public ComponentSystem(EntityManager entityManager, EventManager eventManager)
+ : base(eventManager)
+ {
+ if (entityManager == null)
+ throw new ArgumentNullException("entityManager");
+
+ EntityManager = entityManager;
+ }
+
+ public virtual void OnAppPause()
+ {
+ }
+
+ public virtual void OnAppResume()
+ {
+ }
+
+ public virtual void OnResize()
+ {
+ }
+
+ public virtual void OnRender(float delta)
+ {
+ }
+
+ public virtual void OnUpdate(float delta)
+ {
+ }
+
+ public override bool Handle(Event e)
+ {
+ return false;
+ }
+
+ public virtual void Dispose()
+ {
+ }
+ }
+}
+
diff --git a/Blarg.GameFramework/Entities/Entity.cs b/Blarg.GameFramework/Entities/Entity.cs
new file mode 100644
index 0000000..dc09e14
--- /dev/null
+++ b/Blarg.GameFramework/Entities/Entity.cs
@@ -0,0 +1,38 @@
+using System;
+
+namespace Blarg.GameFramework.Entities
+{
+ public class Entity
+ {
+ EntityManager _entityManager;
+
+ internal Entity(EntityManager entityManager)
+ {
+ if (entityManager == null)
+ throw new ArgumentNullException("entityManager");
+
+ _entityManager = entityManager;
+ }
+
+ public T Get() where T : Component
+ {
+ return null;
+ }
+
+ public T Add() where T : Component
+ {
+ return null;
+ }
+
+ public void Remove() where T : Component
+ {
+ return;
+ }
+
+ public bool Has() where T : Component
+ {
+ return false;
+ }
+ }
+}
+
diff --git a/Blarg.GameFramework/Entities/EntityManager.cs b/Blarg.GameFramework/Entities/EntityManager.cs
new file mode 100644
index 0000000..56a567b
--- /dev/null
+++ b/Blarg.GameFramework/Entities/EntityManager.cs
@@ -0,0 +1,356 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Blarg.GameFramework.Entities.SystemComponents;
+using Blarg.GameFramework.Events;
+using Blarg.GameFramework.Support;
+
+namespace Blarg.GameFramework.Entities
+{
+ using EntityList = List;
+ using ComponentList = List;
+ using EntityToComponentMap = Dictionary;
+ using ComponentStore = Dictionary>;
+ using GlobalComponentStore = Dictionary;
+ using ComponentSystemList = List;
+
+ public class EntityManager : IDisposable
+ {
+ public readonly EventManager EventManager;
+
+ EntityList _entities;
+ ComponentStore _components;
+ GlobalComponentStore _globalComponents;
+ ComponentSystemList _componentSystems;
+
+ EntityPool _entityPool;
+
+ EntityList _tempEntityList;
+
+ public EntityManager(EventManager eventManager)
+ {
+ if (eventManager == null)
+ throw new ArgumentNullException("eventManager");
+
+ EventManager = eventManager;
+ _entities = new EntityList();
+ _components = new ComponentStore();
+ _globalComponents = new GlobalComponentStore();
+ _componentSystems = new ComponentSystemList();
+
+ _entityPool = new EntityPool(this);
+
+ _tempEntityList = new EntityList(100);
+ }
+
+ #region ComponentSystem management
+
+ public T AddSubsystem() where T : ComponentSystem
+ {
+ if (GetSubsystem() != null)
+ throw new InvalidOperationException("ComponentSystem of that type is already registered.");
+
+ T subsystem = (T)Activator.CreateInstance(typeof(T), this, EventManager);
+ _componentSystems.Add(subsystem);
+ return subsystem;
+ }
+
+ public T GetSubsystem() where T : ComponentSystem
+ {
+ int i = GetSubsystemIndex(typeof(T));
+ if (i == -1)
+ return null;
+ else
+ return (T)_componentSystems[i];
+ }
+
+ public void RemoveSubsystem() where T : ComponentSystem
+ {
+ int i = GetSubsystemIndex(typeof(T));
+ if (i == -1)
+ return;
+ else
+ _componentSystems.RemoveAt(i);
+ }
+
+ public void RemoveAllSubsystems()
+ {
+ for (int i = 0; i < _componentSystems.Count; ++i)
+ _componentSystems[i].Dispose();
+ _componentSystems.Clear();
+ }
+
+ #endregion
+
+ #region Entity management
+
+ public Entity Add()
+ {
+ var entity = _entityPool.Take();
+ _entities.Add(entity);
+ return entity;
+ }
+
+ public Entity GetFirstWith() where T : Component
+ {
+ EntityToComponentMap componentEntities;
+ _components.TryGetValue(typeof(T), out componentEntities);
+ if (componentEntities == null)
+ return null;
+
+ if (componentEntities.Count > 0)
+ return componentEntities.Keys.GetEnumerator().Current;
+ else
+ return null;
+ }
+
+
+ public void GetAllWith(EntityList list) where T : Component
+ {
+ if (list == null)
+ throw new ArgumentNullException("list", "Must provide a list to store matching Entity's in.");
+ EntityToComponentMap componentEntities;
+ _components.TryGetValue(typeof(T), out componentEntities);
+ if (componentEntities == null)
+ return;
+ else
+ {
+ foreach (var i in componentEntities)
+ list.Add(i.Key);
+ }
+ }
+
+ public void Remove(Entity entity)
+ {
+ if (entity == null)
+ throw new ArgumentNullException("entity");
+
+ RemoveAllComponentsFrom(entity);
+ _entities.Remove(entity);
+ _entityPool.Free(entity);
+ }
+
+ public void RemoveAll()
+ {
+ foreach (var entity in _entities)
+ {
+ RemoveAllComponentsFrom(entity);
+ _entityPool.Free(entity);
+ }
+ _entities.Clear();
+ }
+
+ #endregion
+
+ #region Component management
+
+ public T AddComponent(Entity entity) where T : Component
+ {
+ if (GetComponent(entity) != null)
+ throw new InvalidOperationException("Component of that type has been added to this entity already.");
+
+ EntityToComponentMap componentEntities;
+ _components.TryGetValue(typeof(T), out componentEntities);
+ if (componentEntities == null)
+ {
+ // need to create the component-to-entity list
+ componentEntities = new EntityToComponentMap();
+ _components.Add(typeof(T), componentEntities);
+ }
+
+ T component = ObjectPools.Take();
+
+ componentEntities.Add(entity, component);
+ return component;
+ }
+
+ public T GetComponent(Entity entity) where T : Component
+ {
+ EntityToComponentMap componentEntities;
+ _components.TryGetValue(typeof(T), out componentEntities);
+ if (componentEntities == null)
+ return null;
+
+ Component existing;
+ componentEntities.TryGetValue(entity, out existing);
+ if (existing == null)
+ return null;
+ else
+ return (T)existing;
+ }
+
+ public void RemoveComponent(Entity entity) where T : Component
+ {
+ EntityToComponentMap componentEntities;
+ _components.TryGetValue(typeof(T), out componentEntities);
+ if (componentEntities == null)
+ return;
+
+ Component existing;
+ componentEntities.TryGetValue(entity, out existing);
+ if (existing == null)
+ throw new InvalidOperationException("Entity does not have this component.");
+ componentEntities.Remove(entity);
+ ObjectPools.Free((T)existing);
+ }
+
+ public bool HasComponent(Entity entity) where T : Component
+ {
+ EntityToComponentMap componentEntities;
+ _components.TryGetValue(typeof(T), out componentEntities);
+ if (componentEntities == null)
+ return false;
+
+ return componentEntities.ContainsKey(entity);
+ }
+
+ public void GetAllComponentsFor(Entity entity, ComponentList list)
+ {
+ if (list == null)
+ throw new ArgumentNullException("Must provide a list to store the Components for this Entity.");
+
+ foreach (var i in _components)
+ {
+ EntityToComponentMap entitiesWithComponent = i.Value;
+ Component component;
+ entitiesWithComponent.TryGetValue(entity, out component);
+ if (component != null)
+ list.Add(component);
+ }
+ }
+
+ #endregion
+
+ #region Global Component management
+
+ public T AddGlobalComponent() where T : Component
+ {
+ if (GetGlobalComponent() != null)
+ throw new InvalidOperationException("Global component of that type has been added already.");
+
+ T component = ObjectPools.Take();
+
+ _globalComponents.Add(typeof(T), component);
+ return component;
+ }
+
+ public T GetGlobalComponent() where T : Component
+ {
+ Component existing;
+ _globalComponents.TryGetValue(typeof(T), out existing);
+ if (existing == null)
+ return null;
+ else
+ return (T)existing;
+ }
+
+ public void RemoveGlobalComponent() where T : Component
+ {
+ Component existing;
+ _globalComponents.TryGetValue(typeof(T), out existing);
+ if (existing == null)
+ throw new InvalidOperationException("No global component of that type exists.");
+ else
+ {
+ _globalComponents.Remove(typeof(T));
+ ObjectPools.Free((T)existing);
+ }
+ }
+
+ public bool HasGlobalComponent() where T : Component
+ {
+ return _globalComponents.ContainsKey(typeof(T));
+ }
+
+ public void RemoveAllGlobalComponents()
+ {
+ foreach (var i in _globalComponents)
+ ObjectPools.Free(i.Key, i.Value);
+ }
+
+ #endregion
+
+ #region Events
+
+ public void OnAppResume()
+ {
+ for (int i = 0; i < _componentSystems.Count; ++i)
+ _componentSystems[i].OnAppResume();
+ }
+
+ public void OnAppPause()
+ {
+ for (int i = 0; i < _componentSystems.Count; ++i)
+ _componentSystems[i].OnAppPause();
+ }
+
+ public void OnResize()
+ {
+ for (int i = 0; i < _componentSystems.Count; ++i)
+ _componentSystems[i].OnResize();
+ }
+
+ public void OnRender(float delta)
+ {
+ for (int i = 0; i < _componentSystems.Count; ++i)
+ _componentSystems[i].OnRender(delta);
+ }
+
+ public void OnUpdate(float delta)
+ {
+ _tempEntityList.Clear();
+ GetAllWith(_tempEntityList);
+ foreach (var entity in _tempEntityList)
+ Remove(entity);
+
+ for (int i = 0; i < _componentSystems.Count; ++i)
+ _componentSystems[i].OnUpdate(delta);
+ }
+
+ #endregion
+
+ #region Misc support methods
+
+ private void RemoveAllComponentsFrom(Entity entity)
+ {
+ if (entity == null)
+ throw new ArgumentNullException("entity");
+
+ foreach (var i in _components)
+ {
+ var entitiesWithComponent = i.Value;
+ Component component;
+ entitiesWithComponent.TryGetValue(entity, out component);
+ if (component != null)
+ {
+ ObjectPools.Free(i.Key, component);
+ entitiesWithComponent.Remove(entity);
+ }
+ }
+ }
+
+ private int GetSubsystemIndex(Type type)
+ {
+ for (int i = 0; i < _componentSystems.Count; ++i)
+ {
+ if (_componentSystems[i].GetType() == type)
+ return i;
+ }
+ return -1;
+ }
+
+ #endregion
+
+ #region Disposable
+
+ public void Dispose()
+ {
+ RemoveAll();
+ RemoveAllGlobalComponents();
+ RemoveAllSubsystems();
+ }
+
+ #endregion
+ }
+}
+
diff --git a/Blarg.GameFramework/Entities/EntityPool.cs b/Blarg.GameFramework/Entities/EntityPool.cs
new file mode 100644
index 0000000..06d4283
--- /dev/null
+++ b/Blarg.GameFramework/Entities/EntityPool.cs
@@ -0,0 +1,24 @@
+using System;
+using Blarg.GameFramework.Support;
+
+namespace Blarg.GameFramework.Entities
+{
+ internal class EntityPool : ObjectPool
+ {
+ EntityManager _entityManager;
+
+ public EntityPool(EntityManager entityManager)
+ {
+ if (entityManager == null)
+ throw new ArgumentNullException("entityManager");
+
+ _entityManager = entityManager;
+ }
+
+ protected override Entity Allocate()
+ {
+ return new Entity(_entityManager);
+ }
+ }
+}
+
diff --git a/Blarg.GameFramework/Entities/SystemComponents/InactiveComponent.cs b/Blarg.GameFramework/Entities/SystemComponents/InactiveComponent.cs
new file mode 100644
index 0000000..7a1013a
--- /dev/null
+++ b/Blarg.GameFramework/Entities/SystemComponents/InactiveComponent.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Blarg.GameFramework.Entities.SystemComponents
+{
+ public class InactiveComponent : Component
+ {
+ public override void Reset()
+ {
+ }
+ }
+}
+