entity tracker system
parent
5941029927
commit
f010b39c3c
|
@ -11,19 +11,41 @@ namespace Encompass
|
|||
private Dictionary<Guid, List<Guid>> entityIDToComponentIDs = new Dictionary<Guid, List<Guid>>();
|
||||
private Dictionary<Guid, Guid> componentIDToEntityID = new Dictionary<Guid, Guid>();
|
||||
|
||||
private Dictionary<Type, List<Guid>> activeComponents = new Dictionary<Type, List<Guid>>();
|
||||
private Dictionary<Type, List<Guid>> inactiveComponents = new Dictionary<Type, List<Guid>>();
|
||||
private Dictionary<Type, List<Guid>> typeToComponentIDs = new Dictionary<Type, List<Guid>>();
|
||||
|
||||
private List<Guid> activeComponents = new List<Guid>();
|
||||
private List<Guid> inactiveComponents = new List<Guid>();
|
||||
|
||||
private List<Guid> componentsToActivate = new List<Guid>();
|
||||
private List<Guid> componentsToDeactivate = new List<Guid>();
|
||||
private List<Guid> componentsToRemove = new List<Guid>();
|
||||
|
||||
//shared references with EntityManager
|
||||
private List<Guid> entitiesWithAddedComponents;
|
||||
private List<Guid> entitiesWithRemovedComponents;
|
||||
|
||||
public ComponentManager(
|
||||
List<Guid> entitiesWithAddedComponents,
|
||||
List<Guid> entitiesWithRemovedComponents
|
||||
)
|
||||
{
|
||||
this.entitiesWithAddedComponents = entitiesWithAddedComponents;
|
||||
this.entitiesWithRemovedComponents = entitiesWithRemovedComponents;
|
||||
}
|
||||
|
||||
internal Guid AddComponent<TComponent>(Guid entityID, TComponent component) where TComponent : struct, IComponent
|
||||
{
|
||||
var componentID = Guid.NewGuid();
|
||||
|
||||
IDToComponent[componentID] = component;
|
||||
componentIDToType[componentID] = typeof(TComponent);
|
||||
|
||||
if (!typeToComponentIDs.ContainsKey(typeof(TComponent)))
|
||||
{
|
||||
typeToComponentIDs.Add(typeof(TComponent), new List<Guid>());
|
||||
}
|
||||
|
||||
typeToComponentIDs[typeof(TComponent)].Add(componentID);
|
||||
|
||||
if (!entityIDToComponentIDs.ContainsKey(entityID))
|
||||
{
|
||||
|
@ -33,33 +55,30 @@ namespace Encompass
|
|||
entityIDToComponentIDs[entityID].Add(componentID);
|
||||
componentIDToEntityID[componentID] = entityID;
|
||||
|
||||
if (!activeComponents.ContainsKey(typeof(TComponent)))
|
||||
{
|
||||
activeComponents.Add(typeof(TComponent), new List<Guid>());
|
||||
inactiveComponents.Add(typeof(TComponent), new List<Guid>());
|
||||
}
|
||||
|
||||
inactiveComponents.Add(componentID);
|
||||
MarkForActivation(componentID);
|
||||
|
||||
entitiesWithAddedComponents.Add(entityID);
|
||||
|
||||
return componentID;
|
||||
}
|
||||
|
||||
internal IEnumerable<KeyValuePair<Guid, IComponent>> GetComponentsByEntity(Guid entityID)
|
||||
{
|
||||
return entityIDToComponentIDs[entityID].Select((id) => new KeyValuePair<Guid, IComponent>(id, IDToComponent[id]));
|
||||
return entityIDToComponentIDs[entityID].Intersect(activeComponents).Select((id) => new KeyValuePair<Guid, IComponent>(id, IDToComponent[id]));
|
||||
}
|
||||
|
||||
internal IEnumerable<KeyValuePair<Guid, TComponent>> GetActiveComponentsByType<TComponent>() where TComponent : struct, IComponent
|
||||
{
|
||||
return activeComponents.ContainsKey(typeof(TComponent)) ?
|
||||
activeComponents[typeof(TComponent)].Select((id) => new KeyValuePair<Guid, TComponent>(id, (TComponent)IDToComponent[id])) :
|
||||
return typeToComponentIDs.ContainsKey(typeof(TComponent)) ?
|
||||
typeToComponentIDs[typeof(TComponent)].Select((id) => new KeyValuePair<Guid, TComponent>(id, (TComponent)IDToComponent[id])) :
|
||||
Enumerable.Empty<KeyValuePair<Guid, TComponent>>();
|
||||
}
|
||||
|
||||
internal IEnumerable<KeyValuePair<Guid, IComponent>> GetActiveComponentsByType(Type type)
|
||||
{
|
||||
return activeComponents.ContainsKey(type) ?
|
||||
activeComponents[type].Select((id) => new KeyValuePair<Guid, IComponent>(id, IDToComponent[id])) :
|
||||
return typeToComponentIDs.ContainsKey(type) ?
|
||||
typeToComponentIDs[type].Select((id) => new KeyValuePair<Guid, IComponent>(id, IDToComponent[id])) :
|
||||
Enumerable.Empty<KeyValuePair<Guid, IComponent>>();
|
||||
}
|
||||
|
||||
|
@ -82,6 +101,11 @@ namespace Encompass
|
|||
return entityComponents.Intersect(activeComponentsByType);
|
||||
}
|
||||
|
||||
internal IEnumerable<Type> GetAllComponentTypesOfEntity(Guid entityID)
|
||||
{
|
||||
return entityIDToComponentIDs[entityID].Select((id) => componentIDToType[id]);
|
||||
}
|
||||
|
||||
internal bool EntityHasComponentOfType<TComponent>(Guid entityID) where TComponent : struct, IComponent
|
||||
{
|
||||
return GetComponentsByEntityAndType<TComponent>(entityID).Any();
|
||||
|
@ -119,9 +143,7 @@ namespace Encompass
|
|||
|
||||
foreach (var componentID in componentIDs)
|
||||
{
|
||||
var component = IDToComponent[componentID];
|
||||
activeComponents[component.GetType()].Remove(componentID);
|
||||
inactiveComponents[component.GetType()].Remove(componentID);
|
||||
MarkForRemoval(componentID);
|
||||
}
|
||||
|
||||
entityIDToComponentIDs.Remove(entityID);
|
||||
|
@ -147,8 +169,10 @@ namespace Encompass
|
|||
foreach (var componentID in componentsToActivate)
|
||||
{
|
||||
var component = IDToComponent[componentID];
|
||||
activeComponents[component.GetType()].Add(componentID);
|
||||
inactiveComponents[component.GetType()].Remove(componentID);
|
||||
if (inactiveComponents.Remove(componentID))
|
||||
{
|
||||
activeComponents.Add(componentID);
|
||||
}
|
||||
}
|
||||
|
||||
componentsToActivate.Clear();
|
||||
|
@ -159,8 +183,10 @@ namespace Encompass
|
|||
foreach (var componentID in componentsToDeactivate)
|
||||
{
|
||||
var component = IDToComponent[componentID];
|
||||
activeComponents[component.GetType()].Remove(componentID);
|
||||
inactiveComponents[component.GetType()].Add(componentID);
|
||||
if (activeComponents.Remove(componentID))
|
||||
{
|
||||
inactiveComponents.Add(componentID);
|
||||
}
|
||||
}
|
||||
|
||||
componentsToDeactivate.Clear();
|
||||
|
@ -171,8 +197,8 @@ namespace Encompass
|
|||
foreach (var componentID in componentsToRemove)
|
||||
{
|
||||
var component = IDToComponent[componentID];
|
||||
activeComponents[component.GetType()].Remove(componentID);
|
||||
inactiveComponents[component.GetType()].Remove(componentID);
|
||||
activeComponents.Remove(componentID);
|
||||
inactiveComponents.Remove(componentID);
|
||||
}
|
||||
|
||||
componentsToRemove.Clear();
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Encompass
|
|||
|
||||
public Guid AddComponent<TComponent>(TComponent component) where TComponent : struct, IComponent
|
||||
{
|
||||
return componentManager.AddComponent<TComponent>(id, component);
|
||||
return componentManager.AddComponent(id, component);
|
||||
}
|
||||
|
||||
public IEnumerable<KeyValuePair<Guid, TComponent>> GetComponents<TComponent>() where TComponent : struct, IComponent
|
||||
|
|
|
@ -5,23 +5,35 @@ namespace Encompass
|
|||
{
|
||||
internal class EntityManager
|
||||
{
|
||||
private List<Entity> entities = new List<Entity>();
|
||||
private Dictionary<Guid, Entity> IDToEntity = new Dictionary<Guid, Entity>();
|
||||
|
||||
private List<Entity> entitiesMarkedForDestroy = new List<Entity>();
|
||||
private List<Guid> entitiesMarkedForDestroy = new List<Guid>();
|
||||
|
||||
private Dictionary<Type, HashSet<IEntityTracker>> componentTypeToEntityTrackers = new Dictionary<Type, HashSet<IEntityTracker>>();
|
||||
private Dictionary<Guid, HashSet<IEntityTracker>> entityToEntityTrackers = new Dictionary<Guid, HashSet<IEntityTracker>>();
|
||||
|
||||
private List<Guid> entitiesWithAddedComponents;
|
||||
private List<Guid> entitiesWithRemovedComponents;
|
||||
|
||||
private ComponentManager componentManager;
|
||||
|
||||
public EntityManager(
|
||||
ComponentManager componentManager
|
||||
ComponentManager componentManager,
|
||||
List<Guid> entitiesWithAddedComponents,
|
||||
List<Guid> entitiesWithRemovedComponents
|
||||
)
|
||||
{
|
||||
this.componentManager = componentManager;
|
||||
this.entitiesWithAddedComponents = entitiesWithAddedComponents;
|
||||
this.entitiesWithRemovedComponents = entitiesWithRemovedComponents;
|
||||
}
|
||||
|
||||
public Entity CreateEntity()
|
||||
{
|
||||
return new Entity(NextID(), componentManager);
|
||||
var id = NextID();
|
||||
var entity = new Entity(id, componentManager);
|
||||
IDToEntity[id] = entity;
|
||||
return entity;
|
||||
}
|
||||
|
||||
public Entity GetEntity(Guid id)
|
||||
|
@ -29,22 +41,109 @@ namespace Encompass
|
|||
return IDToEntity[id];
|
||||
}
|
||||
|
||||
public void MarkForDestroy(Entity entity)
|
||||
public void MarkForDestroy(Guid entityID)
|
||||
{
|
||||
entitiesMarkedForDestroy.Add(entity);
|
||||
entitiesMarkedForDestroy.Add(entityID);
|
||||
}
|
||||
|
||||
internal void DestroyMarkedEntities()
|
||||
public void DestroyMarkedEntities()
|
||||
{
|
||||
foreach (var entity in entitiesMarkedForDestroy)
|
||||
foreach (var entityID in entitiesMarkedForDestroy)
|
||||
{
|
||||
var entity = IDToEntity[entityID];
|
||||
entity.RemoveAllComponents();
|
||||
IDToEntity.Remove(entityID);
|
||||
entityToEntityTrackers.Remove(entityID);
|
||||
}
|
||||
|
||||
entitiesMarkedForDestroy.Clear();
|
||||
}
|
||||
|
||||
private Guid NextID()
|
||||
{
|
||||
return Guid.NewGuid();
|
||||
}
|
||||
|
||||
public void RegisterEntityTracker(IEntityTracker entityTracker)
|
||||
{
|
||||
foreach (var componentType in entityTracker.ComponentTypes)
|
||||
{
|
||||
if (!componentTypeToEntityTrackers.ContainsKey(componentType))
|
||||
{
|
||||
componentTypeToEntityTrackers.Add(componentType, new HashSet<IEntityTracker>());
|
||||
}
|
||||
|
||||
componentTypeToEntityTrackers[componentType].Add(entityTracker);
|
||||
}
|
||||
|
||||
if (entityTracker is EntityRenderer)
|
||||
{
|
||||
var entityRenderer = entityTracker as EntityRenderer;
|
||||
if (!componentTypeToEntityTrackers.ContainsKey(entityRenderer.DrawComponentType))
|
||||
{
|
||||
componentTypeToEntityTrackers.Add(entityRenderer.DrawComponentType, new HashSet<IEntityTracker>());
|
||||
}
|
||||
|
||||
componentTypeToEntityTrackers[entityRenderer.DrawComponentType].Add(entityRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterDirtyEntityWithAddedComponents(Guid entityID)
|
||||
{
|
||||
entitiesWithAddedComponents.Add(entityID);
|
||||
}
|
||||
|
||||
public void RegisterDirtyEntityWithRemovedComponents(Guid entityID)
|
||||
{
|
||||
entitiesWithRemovedComponents.Add(entityID);
|
||||
}
|
||||
|
||||
public void CheckEntitiesWithAddedComponents()
|
||||
{
|
||||
foreach (var entityID in entitiesWithAddedComponents)
|
||||
{
|
||||
CheckAndRegisterEntity(entityID);
|
||||
}
|
||||
|
||||
entitiesWithAddedComponents.Clear();
|
||||
}
|
||||
|
||||
public void CheckEntitiesWithRemovedComponents()
|
||||
{
|
||||
foreach (var entityID in entitiesWithRemovedComponents)
|
||||
{
|
||||
if (entityToEntityTrackers.ContainsKey(entityID))
|
||||
{
|
||||
foreach (var engine in entityToEntityTrackers[entityID])
|
||||
{
|
||||
engine.CheckAndUntrackEntity(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entitiesWithRemovedComponents.Clear();
|
||||
}
|
||||
|
||||
private void CheckAndRegisterEntity(Guid entityID)
|
||||
{
|
||||
var componentTypes = componentManager.GetAllComponentTypesOfEntity(entityID);
|
||||
foreach (var componentType in componentTypes)
|
||||
{
|
||||
if (componentTypeToEntityTrackers.ContainsKey(componentType))
|
||||
{
|
||||
foreach (var entityTracker in componentTypeToEntityTrackers[componentType])
|
||||
{
|
||||
if (entityTracker.CheckAndTrackEntity(entityID))
|
||||
{
|
||||
if (!entityToEntityTrackers.ContainsKey(entityID))
|
||||
{
|
||||
entityToEntityTrackers.Add(entityID, new HashSet<IEntityTracker>());
|
||||
}
|
||||
entityToEntityTrackers[entityID].Add(entityTracker);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
public interface IEntityTracker
|
||||
{
|
||||
IEnumerable<Type> ComponentTypes { get; }
|
||||
|
||||
bool CheckAndTrackEntity(Guid entityID);
|
||||
bool CheckAndUntrackEntity(Guid entityID);
|
||||
}
|
||||
}
|
|
@ -34,9 +34,13 @@ namespace Encompass
|
|||
|
||||
messageManager.ClearMessages();
|
||||
entityManager.DestroyMarkedEntities();
|
||||
|
||||
componentManager.ActivateComponents();
|
||||
componentManager.DeactivateComponents();
|
||||
componentManager.RemoveComponents();
|
||||
|
||||
entityManager.CheckEntitiesWithAddedComponents();
|
||||
entityManager.CheckEntitiesWithRemovedComponents();
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
|
|
|
@ -20,8 +20,10 @@ namespace Encompass
|
|||
|
||||
public WorldBuilder()
|
||||
{
|
||||
componentManager = new ComponentManager();
|
||||
entityManager = new EntityManager(componentManager);
|
||||
var entitiesWithAddedComponents = new List<Guid>();
|
||||
var entitiesWithRemovedComponents = new List<Guid>();
|
||||
componentManager = new ComponentManager(entitiesWithAddedComponents, entitiesWithRemovedComponents);
|
||||
entityManager = new EntityManager(componentManager, entitiesWithAddedComponents, entitiesWithRemovedComponents);
|
||||
messageManager = new MessageManager();
|
||||
renderManager = new RenderManager(entityManager, componentManager);
|
||||
}
|
||||
|
@ -43,6 +45,11 @@ namespace Encompass
|
|||
|
||||
engineGraph.AddVertex(engine);
|
||||
|
||||
if (engine is IEntityTracker)
|
||||
{
|
||||
entityManager.RegisterEntityTracker(engine as IEntityTracker);
|
||||
}
|
||||
|
||||
var emitMessageAttribute = engine.GetType().GetCustomAttribute<Emits>(false);
|
||||
if (emitMessageAttribute != null)
|
||||
{
|
||||
|
@ -98,6 +105,7 @@ namespace Encompass
|
|||
|
||||
if (renderer is EntityRenderer)
|
||||
{
|
||||
entityManager.RegisterEntityTracker(renderer as IEntityTracker);
|
||||
renderManager.RegisterEntityRenderer(renderer as EntityRenderer);
|
||||
}
|
||||
else if (renderer is GeneralRenderer)
|
||||
|
@ -182,8 +190,12 @@ namespace Encompass
|
|||
renderManager
|
||||
);
|
||||
|
||||
this.componentManager.ActivateComponents();
|
||||
this.componentManager.RemoveComponents();
|
||||
componentManager.ActivateComponents();
|
||||
componentManager.DeactivateComponents();
|
||||
componentManager.RemoveComponents();
|
||||
|
||||
entityManager.CheckEntitiesWithAddedComponents();
|
||||
entityManager.CheckEntitiesWithRemovedComponents();
|
||||
|
||||
return world;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,29 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
public abstract class EntityRenderer : Renderer
|
||||
public abstract class EntityRenderer : Renderer, IEntityTracker
|
||||
{
|
||||
private readonly List<Type> componentTypes = new List<Type>();
|
||||
private readonly Type drawComponentType;
|
||||
|
||||
private EntityTracker entityTracker = new EntityTracker();
|
||||
|
||||
public IEnumerable<Type> ComponentTypes { get { return componentTypes; } }
|
||||
public Type DrawComponentType { get; }
|
||||
|
||||
public abstract void Render(Entity entity);
|
||||
|
||||
public EntityRenderer()
|
||||
{
|
||||
var rendersAttribute = GetType().GetCustomAttribute<Renders>(false);
|
||||
if (rendersAttribute != null)
|
||||
{
|
||||
componentTypes = rendersAttribute.componentTypes;
|
||||
DrawComponentType = rendersAttribute.drawComponentType;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CheckAndTrackEntity(Guid entityID)
|
||||
{
|
||||
var entity = GetEntity(entityID);
|
||||
|
@ -37,7 +48,7 @@ namespace Encompass
|
|||
internal bool CheckEntity(Entity entity)
|
||||
{
|
||||
return EntityChecker.CheckEntity(entity, componentTypes) &&
|
||||
entity.HasComponent(drawComponentType);
|
||||
entity.HasComponent(DrawComponentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue