encompass-cs/encompass-cs/ComponentManager.cs

208 lines
7.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace Encompass
{
internal class ComponentManager
{
private Dictionary<Guid, Type> componentIDToType = new Dictionary<Guid, Type>();
private Dictionary<Guid, IComponent> IDToComponent = new Dictionary<Guid, IComponent>();
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>> 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))
{
entityIDToComponentIDs.Add(entityID, new List<Guid>());
}
entityIDToComponentIDs[entityID].Add(componentID);
componentIDToEntityID[componentID] = entityID;
inactiveComponents.Add(componentID);
MarkForActivation(componentID);
entitiesWithAddedComponents.Add(entityID);
return componentID;
}
internal IEnumerable<KeyValuePair<Guid, IComponent>> GetComponentsByEntity(Guid entityID)
{
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 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 typeToComponentIDs.ContainsKey(type) ?
typeToComponentIDs[type].Select((id) => new KeyValuePair<Guid, IComponent>(id, IDToComponent[id])) :
Enumerable.Empty<KeyValuePair<Guid, IComponent>>();
}
internal KeyValuePair<Guid, TComponent> GetActiveComponentByType<TComponent>() where TComponent : struct, IComponent
{
return GetActiveComponentsByType<TComponent>().Single();
}
internal IEnumerable<KeyValuePair<Guid, TComponent>> GetComponentsByEntityAndType<TComponent>(Guid entityID) where TComponent : struct, IComponent
{
var entity_components = GetComponentsByEntity(entityID).Select((kv) => new KeyValuePair<Guid, TComponent>(kv.Key, (TComponent)kv.Value));
var active_components_by_type = GetActiveComponentsByType<TComponent>();
return entity_components.Intersect(active_components_by_type);
}
internal IEnumerable<KeyValuePair<Guid, IComponent>> GetComponentsByEntityAndType(Guid entityID, Type type)
{
var entityComponents = GetComponentsByEntity(entityID);
var activeComponentsByType = GetActiveComponentsByType(type);
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();
}
internal bool EntityHasComponentOfType(Guid entityID, Type type)
{
return GetComponentsByEntityAndType(entityID, type).Any();
}
internal IComponent GetComponentByID(Guid componentID)
{
return IDToComponent[componentID];
}
internal Type GetComponentTypeByID(Guid componentID)
{
return componentIDToType[componentID];
}
internal Guid GetEntityIDFromComponentID(Guid componentID)
{
return componentIDToEntityID[componentID];
}
internal void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent
{
var entityID = GetEntityIDFromComponentID(componentID);
IDToComponent[componentID] = newComponentValue;
}
internal void RemoveAllComponentsFromEntity(Guid entityID)
{
var componentIDs = entityIDToComponentIDs[entityID];
foreach (var componentID in componentIDs)
{
MarkForRemoval(componentID);
}
entityIDToComponentIDs.Remove(entityID);
}
internal void MarkForActivation(Guid componentID)
{
componentsToActivate.Add(componentID);
}
internal void MarkForDeactivation(Guid componentID)
{
componentsToDeactivate.Add(componentID);
}
internal void MarkForRemoval(Guid componentID)
{
componentsToRemove.Add(componentID);
}
internal void ActivateComponents()
{
foreach (var componentID in componentsToActivate)
{
var component = IDToComponent[componentID];
if (inactiveComponents.Remove(componentID))
{
activeComponents.Add(componentID);
}
}
componentsToActivate.Clear();
}
internal void DeactivateComponents()
{
foreach (var componentID in componentsToDeactivate)
{
var component = IDToComponent[componentID];
if (activeComponents.Remove(componentID))
{
inactiveComponents.Add(componentID);
}
}
componentsToDeactivate.Clear();
}
internal void RemoveComponents()
{
foreach (var componentID in componentsToRemove)
{
var component = IDToComponent[componentID];
activeComponents.Remove(componentID);
inactiveComponents.Remove(componentID);
}
componentsToRemove.Clear();
}
}
}