using System; using System.Collections.Generic; using System.Linq; namespace Encompass { internal class ComponentManager { private Dictionary> entityIDToComponents = new Dictionary>(); private Dictionary componentToEntityID = new Dictionary(); private Dictionary> activeComponents = new Dictionary>(); private Dictionary> inactiveComponents = new Dictionary>(); private List componentsToActivate = new List(); private List componentsToDeactivate = new List(); private List componentsToRemove = new List(); internal void AddComponent(uint entityID, TComponent component) where TComponent : struct, IComponent { if (!entityIDToComponents.ContainsKey(entityID)) { entityIDToComponents.Add(entityID, new List()); } entityIDToComponents[entityID].Add(component); componentToEntityID[component] = entityID; if (!activeComponents.ContainsKey(typeof(TComponent))) { activeComponents.Add(typeof(TComponent), new List()); inactiveComponents.Add(typeof(TComponent), new List()); } MarkForActivation(component); } internal IEnumerable GetComponentsByEntity(uint entityID) { return entityIDToComponents[entityID]; } internal IEnumerable GetActiveComponentsByType() where TComponent : struct, IComponent { return activeComponents[typeof(TComponent)].Cast(); } internal TComponent GetActiveComponentByType() where TComponent : struct, IComponent { return GetActiveComponentsByType().Single(); } internal IEnumerable GetComponentsByEntityAndType(uint entityID) where TComponent : struct, IComponent { var entity_components = GetComponentsByEntity(entityID).Cast(); var active_components_by_type = GetActiveComponentsByType(); return entity_components.Intersect(active_components_by_type).Cast(); } internal bool EntityHasComponentOfType(uint entityID) where TComponent : struct, IComponent { return GetComponentsByEntityAndType(entityID).Any(); } /** Replaces the component with another. */ internal void UpdateComponent(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(); } } }