encompass-cs/encompass-cs/ComponentManager.cs

215 lines
8.2 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
2019-06-16 01:05:56 +00:00
namespace Encompass
{
internal class ComponentManager
{
2019-06-20 17:46:15 +00:00
private readonly DrawLayerManager drawLayerManager;
2019-06-20 17:46:15 +00:00
private readonly Dictionary<Guid, Type> componentIDToType = new Dictionary<Guid, Type>();
private readonly Dictionary<Guid, IComponent> IDToComponent = new Dictionary<Guid, IComponent>();
private readonly Dictionary<Guid, List<Guid>> entityIDToComponentIDs = new Dictionary<Guid, List<Guid>>();
private readonly Dictionary<Guid, Guid> componentIDToEntityID = new Dictionary<Guid, Guid>();
2019-06-20 17:46:15 +00:00
private readonly Dictionary<Type, List<Guid>> typeToComponentIDs = new Dictionary<Type, List<Guid>>();
2019-06-20 17:46:15 +00:00
private readonly List<Guid> activeComponents = new List<Guid>();
private readonly List<Guid> inactiveComponents = new List<Guid>();
2019-06-19 23:13:02 +00:00
//shared references with EntityManager
private readonly HashSet<Guid> entitiesWithAddedComponents;
private readonly HashSet<Guid> entitiesWithRemovedComponents;
2019-06-19 23:13:02 +00:00
public ComponentManager(
DrawLayerManager drawLayerManager,
HashSet<Guid> entitiesWithAddedComponents,
HashSet<Guid> entitiesWithRemovedComponents
2019-06-19 23:13:02 +00:00
)
{
this.drawLayerManager = drawLayerManager;
2019-06-19 23:13:02 +00:00
this.entitiesWithAddedComponents = entitiesWithAddedComponents;
this.entitiesWithRemovedComponents = entitiesWithRemovedComponents;
}
internal void RegisterEntity(Guid entityID)
{
entityIDToComponentIDs.Add(entityID, new List<Guid>());
}
internal Guid AddComponent<TComponent>(Guid entityID, TComponent component) where TComponent : struct, IComponent
2019-06-16 01:05:56 +00:00
{
var componentID = Guid.NewGuid();
IDToComponent[componentID] = component;
2019-06-19 21:14:44 +00:00
componentIDToType[componentID] = typeof(TComponent);
2019-06-20 17:46:15 +00:00
2019-06-19 23:13:02 +00:00
if (!typeToComponentIDs.ContainsKey(typeof(TComponent)))
{
typeToComponentIDs.Add(typeof(TComponent), new List<Guid>());
}
typeToComponentIDs[typeof(TComponent)].Add(componentID);
entityIDToComponentIDs[entityID].Add(componentID);
componentIDToEntityID[componentID] = entityID;
2019-06-19 23:13:02 +00:00
inactiveComponents.Add(componentID);
2019-07-17 18:24:21 +00:00
Activate(componentID);
2019-06-19 23:13:02 +00:00
entitiesWithAddedComponents.Add(entityID);
return componentID;
}
internal Guid AddDrawComponent<TComponent>(Guid entityID, TComponent component, int layer = 0) where TComponent : struct, IComponent
{
var componentID = AddComponent(entityID, component);
drawLayerManager.RegisterComponentWithLayer(componentID, layer);
return componentID;
}
internal IEnumerable<Guid> GetComponentIDsByEntityID(Guid entityID)
{
return entityIDToComponentIDs.ContainsKey(entityID) ?
entityIDToComponentIDs[entityID] :
Enumerable.Empty<Guid>();
}
internal IEnumerable<ValueTuple<Guid, IComponent>> GetComponentsByEntity(Guid entityID)
2019-06-16 01:05:56 +00:00
{
return GetComponentIDsByEntityID(entityID).Intersect(activeComponents).Select((id) => new ValueTuple<Guid, IComponent>(id, IDToComponent[id]));
}
internal IEnumerable<ValueTuple<Guid, TComponent>> GetActiveComponentsByType<TComponent>() where TComponent : struct, IComponent
2019-06-16 01:05:56 +00:00
{
2019-06-19 23:13:02 +00:00
return typeToComponentIDs.ContainsKey(typeof(TComponent)) ?
typeToComponentIDs[typeof(TComponent)].Intersect(activeComponents).Select((id) => new ValueTuple<Guid, TComponent>(id, (TComponent)IDToComponent[id])) :
Enumerable.Empty<ValueTuple<Guid, TComponent>>();
}
internal IEnumerable<ValueTuple<Guid, IComponent>> GetActiveComponentsByType(Type type)
2019-06-19 21:14:44 +00:00
{
2019-06-19 23:13:02 +00:00
return typeToComponentIDs.ContainsKey(type) ?
typeToComponentIDs[type].Intersect(activeComponents).Select((id) => new ValueTuple<Guid, IComponent>(id, IDToComponent[id])) :
Enumerable.Empty<ValueTuple<Guid, IComponent>>();
2019-06-19 21:14:44 +00:00
}
internal ValueTuple<Guid, TComponent> GetActiveComponentByType<TComponent>() where TComponent : struct, IComponent
2019-06-16 01:05:56 +00:00
{
2019-06-15 00:51:06 +00:00
return GetActiveComponentsByType<TComponent>().Single();
}
internal IEnumerable<ValueTuple<Guid, TComponent>> GetComponentsByEntityAndType<TComponent>(Guid entityID) where TComponent : struct, IComponent
2019-06-16 01:05:56 +00:00
{
var entityComponentsByType = GetComponentsByEntity(entityID).Where((pair) => componentIDToType[pair.Item1] == typeof(TComponent)).Select((pair) => new ValueTuple<Guid, TComponent>(pair.Item1, (TComponent)pair.Item2));
2019-06-20 19:38:19 +00:00
var activeComponentsByType = GetActiveComponentsByType<TComponent>();
return activeComponentsByType.Intersect(entityComponentsByType);
}
internal IEnumerable<ValueTuple<Guid, IComponent>> GetComponentsByEntityAndType(Guid entityID, Type type)
2019-06-19 21:14:44 +00:00
{
var entityComponents = GetComponentsByEntity(entityID);
var activeComponentsByType = GetActiveComponentsByType(type);
return entityComponents.Intersect(activeComponentsByType);
}
2019-06-19 23:13:02 +00:00
internal IEnumerable<Type> GetAllComponentTypesOfEntity(Guid entityID)
{
return GetComponentIDsByEntityID(entityID).Select((id) => componentIDToType[id]);
2019-06-19 23:13:02 +00:00
}
internal bool EntityHasComponentOfType<TComponent>(Guid entityID) where TComponent : struct, IComponent
2019-06-16 01:05:56 +00:00
{
return GetComponentsByEntityAndType<TComponent>(entityID).Any();
}
2019-06-19 21:14:44 +00:00
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 GetEntityIDByComponentID(Guid componentID)
2019-06-19 21:14:44 +00:00
{
return componentIDToEntityID[componentID];
}
internal void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent
2019-06-16 01:05:56 +00:00
{
IDToComponent[componentID] = newComponentValue;
2019-06-15 07:39:08 +00:00
}
internal void RemoveAllComponentsFromEntity(Guid entityID)
2019-06-16 01:05:56 +00:00
{
var componentIDs = entityIDToComponentIDs[entityID];
2019-07-17 18:24:21 +00:00
for (int i = componentIDs.Count - 1; i >= 0; i--)
2019-06-16 01:05:56 +00:00
{
2019-07-17 18:24:21 +00:00
Remove(componentIDs[i]);
}
}
2019-07-17 18:24:21 +00:00
internal void Activate(Guid componentID)
2019-06-16 01:05:56 +00:00
{
2019-07-17 18:24:21 +00:00
if (inactiveComponents.Remove(componentID))
{
activeComponents.Add(componentID);
}
var entityID = GetEntityIDByComponentID(componentID);
entitiesWithAddedComponents.Add(entityID);
}
2019-07-17 18:24:21 +00:00
internal void Deactivate(Guid componentID)
2019-06-16 01:05:56 +00:00
{
2019-07-17 18:24:21 +00:00
if (activeComponents.Remove(componentID))
{
inactiveComponents.Add(componentID);
}
var entityID = GetEntityIDByComponentID(componentID);
entitiesWithRemovedComponents.Add(entityID);
}
2019-07-17 18:24:21 +00:00
internal void Remove(Guid componentID)
2019-06-16 01:05:56 +00:00
{
2019-07-17 18:24:21 +00:00
var component = IDToComponent[componentID];
var type = componentIDToType[componentID];
2019-07-17 18:24:21 +00:00
activeComponents.Remove(componentID);
inactiveComponents.Remove(componentID);
2019-07-17 18:24:21 +00:00
var entityID = componentIDToEntityID[componentID];
if (entityIDToComponentIDs.ContainsKey(entityID))
2019-06-16 01:05:56 +00:00
{
2019-07-17 18:24:21 +00:00
entityIDToComponentIDs[entityID].Remove(componentID);
2019-06-15 07:39:08 +00:00
}
2019-07-17 18:24:21 +00:00
IDToComponent.Remove(componentID);
componentIDToType.Remove(componentID);
componentIDToEntityID.Remove(componentID);
typeToComponentIDs[type].Remove(componentID);
2019-07-17 18:24:21 +00:00
drawLayerManager.UnRegisterComponentWithLayer(componentID);
2019-07-17 18:24:21 +00:00
entitiesWithRemovedComponents.Add(entityID);
}
2019-06-20 03:37:46 +00:00
public void RegisterDestroyedEntity(Guid entityID)
{
entityIDToComponentIDs.Remove(entityID);
}
}
}