encompass-cs/src/ComponentManager.cs

135 lines
5.6 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();
}
}
}