encompass-cs/src/ComponentManager.cs

162 lines
5.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace Encompass
{
internal class ComponentManager
{
private Dictionary<uint, List<IComponent>> entityIDToComponents = new Dictionary<uint, List<IComponent>>();
private Dictionary<IComponent, uint> componentToEntityID = new Dictionary<IComponent, uint>();
private Dictionary<Type, List<IComponent>> activeComponents = new Dictionary<Type, List<IComponent>>();
private Dictionary<Type, List<IComponent>> inactiveComponents = new Dictionary<Type, List<IComponent>>();
private List<IComponent> componentsToActivate = new List<IComponent>();
private List<IComponent> componentsToDeactivate = new List<IComponent>();
private List<IComponent> componentsToRemove = new List<IComponent>();
internal void AddComponent<TComponent>(uint entityID, TComponent component) where TComponent : struct, IComponent
{
if (!entityIDToComponents.ContainsKey(entityID))
{
entityIDToComponents.Add(entityID, new List<IComponent>());
}
entityIDToComponents[entityID].Add(component);
componentToEntityID[component] = entityID;
if (!activeComponents.ContainsKey(typeof(TComponent)))
{
activeComponents.Add(typeof(TComponent), new List<IComponent>());
inactiveComponents.Add(typeof(TComponent), new List<IComponent>());
}
MarkForActivation(component);
}
internal IEnumerable<IComponent> GetComponentsByEntity(uint entityID)
{
return entityIDToComponents[entityID];
}
internal IEnumerable<TComponent> GetActiveComponentsByType<TComponent>() where TComponent : struct, IComponent
{
return activeComponents[typeof(TComponent)].Cast<TComponent>();
}
internal TComponent GetActiveComponentByType<TComponent>() where TComponent : struct, IComponent
{
return GetActiveComponentsByType<TComponent>().Single();
}
internal IEnumerable<TComponent> GetComponentsByEntityAndType<TComponent>(uint entityID) where TComponent : struct, IComponent
{
var entity_components = GetComponentsByEntity(entityID).Cast<TComponent>();
var active_components_by_type = GetActiveComponentsByType<TComponent>();
return entity_components.Intersect(active_components_by_type).Cast<TComponent>();
}
internal bool EntityHasComponentOfType<TComponent>(uint entityID) where TComponent : struct, IComponent
{
return GetComponentsByEntityAndType<TComponent>(entityID).Any();
}
/** Replaces the component with another. */
internal void UpdateComponent<TComponent>(TComponent originalComponent, TComponent newComponent) where TComponent : struct, IComponent
{
var entityID = componentToEntityID[originalComponent];
entityIDToComponents[entityID].Remove(originalComponent);
entityIDToComponents[entityID].Add(newComponent);
componentToEntityID.Remove(originalComponent);
componentToEntityID.Add(newComponent, entityID);
if (activeComponents[originalComponent.GetType()].Remove(originalComponent))
{
activeComponents[originalComponent.GetType()].Add(newComponent);
}
if (inactiveComponents[originalComponent.GetType()].Remove(originalComponent))
{
inactiveComponents[originalComponent.GetType()].Add(newComponent);
}
if (componentsToActivate.Remove(originalComponent))
{
componentsToActivate.Add(newComponent);
}
if (componentsToDeactivate.Remove(originalComponent))
{
componentsToDeactivate.Add(newComponent);
}
if (componentsToRemove.Remove(originalComponent))
{
componentsToRemove.Add(newComponent);
}
}
internal void RemoveAllComponentsFromEntity(uint entityID)
{
var components = GetComponentsByEntity(entityID);
foreach (var component in components)
{
activeComponents[component.GetType()].Remove(component);
inactiveComponents[component.GetType()].Remove(component);
}
entityIDToComponents.Remove(entityID);
}
internal void MarkForActivation(IComponent component)
{
componentsToActivate.Add(component);
}
internal void MarkForDeactivation(IComponent component)
{
componentsToDeactivate.Add(component);
}
internal void MarkForRemoval(IComponent component)
{
componentsToRemove.Add(component);
}
internal void ActivateComponents()
{
foreach (var component in componentsToActivate)
{
activeComponents[component.GetType()].Add(component);
inactiveComponents[component.GetType()].Remove(component);
}
componentsToActivate.Clear();
}
internal void DeactivateComponents()
{
foreach (var component in componentsToDeactivate)
{
activeComponents[component.GetType()].Remove(component);
inactiveComponents[component.GetType()].Add(component);
}
}
internal void RemoveComponents()
{
foreach (var component in componentsToRemove)
{
activeComponents[component.GetType()].Remove(component);
inactiveComponents[component.GetType()].Remove(component);
}
componentsToRemove.Clear();
}
}
}