allow only one component per type per entity
parent
314a064b4e
commit
c1e206ef49
|
@ -15,12 +15,12 @@ namespace Encompass
|
|||
private readonly Dictionary<Guid, PooledSet<Guid>> entityIDToComponentIDs = new Dictionary<Guid, PooledSet<Guid>>();
|
||||
private readonly Dictionary<Guid, Guid> componentIDToEntityID = new Dictionary<Guid, Guid>();
|
||||
|
||||
private readonly Dictionary<Guid, PooledDictionary<Type, HashSet<Guid>>> entityIDToComponentTypeToComponentIDs = new Dictionary<Guid, PooledDictionary<Type, HashSet<Guid>>>();
|
||||
private readonly Dictionary<Guid, PooledDictionary<Type, Guid>> entityIDToComponentTypeToComponentID = new Dictionary<Guid, PooledDictionary<Type, Guid>>();
|
||||
|
||||
private readonly Dictionary<Type, HashSet<Guid>> typeToComponentIDs = new Dictionary<Type, HashSet<Guid>>();
|
||||
|
||||
private readonly List<(Entity, Type, Guid, IComponent)> componentAddData = new List<(Entity, Type, Guid, IComponent)>();
|
||||
private readonly HashSet<Guid> componentsMarkedForRemoval = new HashSet<Guid>();
|
||||
|
||||
private readonly Dictionary<Guid, IComponent> pendingUpdates = new Dictionary<Guid, IComponent>();
|
||||
|
||||
public ComponentManager(DrawLayerManager drawLayerManager)
|
||||
|
@ -31,44 +31,62 @@ namespace Encompass
|
|||
internal void RegisterEntity(Guid entityID)
|
||||
{
|
||||
entityIDToComponentIDs.Add(entityID, new PooledSet<Guid>());
|
||||
entityIDToComponentTypeToComponentIDs.Add(entityID, new PooledDictionary<Type, HashSet<Guid>>(ClearMode.Never));
|
||||
entityIDToComponentTypeToComponentID.Add(entityID, new PooledDictionary<Type, Guid>());
|
||||
}
|
||||
|
||||
internal Guid NextID()
|
||||
private Guid NextID()
|
||||
{
|
||||
return Guid.NewGuid();
|
||||
}
|
||||
|
||||
internal Guid AddComponent<TComponent>(Entity entity, Guid componentID, TComponent component) where TComponent : struct, IComponent
|
||||
internal Guid MarkComponentForAdd<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
|
||||
{
|
||||
var id = NextID();
|
||||
componentAddData.Add((entity, typeof(TComponent), id, component));
|
||||
return id;
|
||||
}
|
||||
|
||||
internal Guid MarkDrawComponentForAdd<TComponent>(Entity entity, TComponent component, int layer = 0) where TComponent : struct, IComponent
|
||||
{
|
||||
var id = MarkComponentForAdd(entity, component);
|
||||
drawLayerManager.RegisterComponentWithLayer(id, layer);
|
||||
return id;
|
||||
}
|
||||
|
||||
internal void AddComponent(Entity entity, Type type, Guid componentID, IComponent component)
|
||||
{
|
||||
IDToComponent[componentID] = component;
|
||||
componentIDToType[componentID] = typeof(TComponent);
|
||||
componentIDToType[componentID] = type;
|
||||
|
||||
if (!typeToComponentIDs.ContainsKey(typeof(TComponent)))
|
||||
if (!typeToComponentIDs.ContainsKey(type))
|
||||
{
|
||||
typeToComponentIDs.Add(typeof(TComponent), new HashSet<Guid>());
|
||||
typeToComponentIDs.Add(type, new HashSet<Guid>());
|
||||
}
|
||||
|
||||
typeToComponentIDs[typeof(TComponent)].Add(componentID);
|
||||
typeToComponentIDs[type].Add(componentID);
|
||||
|
||||
entityIDToComponentIDs[entity.ID].Add(componentID);
|
||||
if (!entityIDToComponentTypeToComponentIDs[entity.ID].ContainsKey(typeof(TComponent))) {
|
||||
entityIDToComponentTypeToComponentIDs[entity.ID].Add(typeof(TComponent), new HashSet<Guid>());
|
||||
if (!entityIDToComponentTypeToComponentID[entity.ID].ContainsKey(type))
|
||||
{
|
||||
entityIDToComponentTypeToComponentID[entity.ID][type] = componentID;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MultipleComponentOfSameTypeException("Entity {0} cannot have multiple components of type {1}", entity.ID, type.Name);
|
||||
}
|
||||
entityIDToComponentTypeToComponentIDs[entity.ID][typeof(TComponent)].Add(componentID);
|
||||
|
||||
componentIDToEntityID[componentID] = entity.ID;
|
||||
|
||||
return componentID;
|
||||
}
|
||||
|
||||
internal Guid AddDrawComponent<TComponent>(Entity entity, Guid componentID, TComponent component, int layer = 0) where TComponent : struct, IComponent
|
||||
internal void AddMarkedComponents()
|
||||
{
|
||||
AddComponent(entity, componentID, component);
|
||||
drawLayerManager.RegisterComponentWithLayer(componentID, layer);
|
||||
return componentID;
|
||||
foreach (var (entity, type, componentID, component) in componentAddData)
|
||||
{
|
||||
AddComponent(entity, type, componentID, component);
|
||||
}
|
||||
|
||||
componentAddData.Clear();
|
||||
}
|
||||
|
||||
internal IEnumerable<Guid> GetComponentIDsByEntityID(Guid entityID)
|
||||
{
|
||||
|
@ -88,23 +106,19 @@ namespace Encompass
|
|||
return Enumerable.Empty<(Guid, TComponent)>();
|
||||
}
|
||||
|
||||
internal IEnumerable<ValueTuple<Guid, TComponent>> GetComponentsByEntityAndType<TComponent>(Guid entityID) where TComponent : struct, IComponent
|
||||
internal (Guid, TComponent) GetComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
if (entityIDToComponentTypeToComponentIDs.ContainsKey(entityID) && entityIDToComponentTypeToComponentIDs[entityID].TryGetValue(typeof(TComponent), out HashSet<Guid> idSet))
|
||||
if (entityIDToComponentTypeToComponentID.ContainsKey(entity.ID) && entityIDToComponentTypeToComponentID[entity.ID].TryGetValue(typeof(TComponent), out Guid id))
|
||||
{
|
||||
return idSet.Select(id => (id, (TComponent)IDToComponent[id]));
|
||||
}
|
||||
return Enumerable.Empty<(Guid, TComponent)>();
|
||||
return (id, (TComponent)IDToComponent[id]);
|
||||
}
|
||||
|
||||
internal bool EntityHasComponentOfType<TComponent>(Guid entityID) where TComponent : struct, IComponent
|
||||
{
|
||||
if (entityIDToComponentTypeToComponentIDs.ContainsKey(entityID) && entityIDToComponentTypeToComponentIDs[entityID].TryGetValue(typeof(TComponent), out HashSet<Guid> idSet))
|
||||
{
|
||||
return idSet.Count > 0;
|
||||
throw new NoComponentOfTypeOnEntityException("No Component of type {0} exists on Entity {1}", typeof(TComponent).Name, entity.ID);
|
||||
}
|
||||
|
||||
return false;
|
||||
internal bool EntityHasComponentOfType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
return (entityIDToComponentTypeToComponentID.ContainsKey(entity.ID) && entityIDToComponentTypeToComponentID[entity.ID].ContainsKey(typeof(TComponent)));
|
||||
}
|
||||
|
||||
internal bool ComponentOfTypeExists<TComponent>() where TComponent : struct, IComponent
|
||||
|
@ -185,6 +199,11 @@ namespace Encompass
|
|||
entityIDToComponentIDs[entityID].Remove(componentID);
|
||||
}
|
||||
|
||||
if (entityIDToComponentTypeToComponentID.ContainsKey(entityID))
|
||||
{
|
||||
entityIDToComponentTypeToComponentID[entityID].Remove(type);
|
||||
}
|
||||
|
||||
IDToComponent.Remove(componentID);
|
||||
componentIDToType.Remove(componentID);
|
||||
componentIDToEntityID.Remove(componentID);
|
||||
|
@ -198,12 +217,8 @@ namespace Encompass
|
|||
entityIDToComponentIDs[entityID].Dispose();
|
||||
entityIDToComponentIDs.Remove(entityID);
|
||||
|
||||
foreach (var set in entityIDToComponentTypeToComponentIDs[entityID].Values)
|
||||
{
|
||||
set.Clear();
|
||||
}
|
||||
entityIDToComponentTypeToComponentIDs[entityID].Dispose();
|
||||
entityIDToComponentTypeToComponentIDs.Remove(entityID);
|
||||
entityIDToComponentTypeToComponentID[entityID].Dispose();
|
||||
entityIDToComponentTypeToComponentID.Remove(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Collections.Pooled;
|
||||
using Encompass.Exceptions;
|
||||
|
||||
namespace Encompass
|
||||
{
|
||||
|
@ -13,39 +14,27 @@ namespace Encompass
|
|||
private readonly Dictionary<Type, HashSet<Guid>> componentMessageTypeToPendingComponentIDs = new Dictionary<Type, HashSet<Guid>>();
|
||||
private readonly Dictionary<Type, HashSet<Guid>> componentMessageTypeToComponentIDs = new Dictionary<Type, HashSet<Guid>>();
|
||||
|
||||
private readonly Dictionary<Entity, PooledDictionary<Type, HashSet<Guid>>> entityToTypeToExistingComponentIDs = new Dictionary<Entity, PooledDictionary<Type, HashSet<Guid>>>();
|
||||
private readonly Dictionary<Entity, PooledDictionary<Type, HashSet<Guid>>> entityToTypeToPendingComponentIDs = new Dictionary<Entity, PooledDictionary<Type, HashSet<Guid>>>();
|
||||
private readonly Dictionary<Entity, PooledDictionary<Type, HashSet<Guid>>> entityToTypeToComponentIDs = new Dictionary<Entity, PooledDictionary<Type, HashSet<Guid>>>();
|
||||
private readonly Dictionary<Entity, PooledDictionary<Type, Guid>> entityToTypeToExistingComponentID = new Dictionary<Entity, PooledDictionary<Type, Guid>>();
|
||||
private readonly Dictionary<Entity, PooledDictionary<Type, Guid>> entityToTypeToPendingComponentID = new Dictionary<Entity, PooledDictionary<Type, Guid>>();
|
||||
private readonly Dictionary<Entity, PooledDictionary<Type, Guid>> entityToTypeToComponentID = new Dictionary<Entity, PooledDictionary<Type, Guid>>();
|
||||
|
||||
internal void RegisterEntity(Entity entity)
|
||||
{
|
||||
entityToTypeToComponentIDs[entity] = new PooledDictionary<Type, HashSet<Guid>>(ClearMode.Never);
|
||||
entityToTypeToPendingComponentIDs[entity] = new PooledDictionary<Type, HashSet<Guid>>(ClearMode.Never);
|
||||
entityToTypeToExistingComponentIDs[entity] = new PooledDictionary<Type, HashSet<Guid>>(ClearMode.Never);
|
||||
entityToTypeToComponentID[entity] = new PooledDictionary<Type, Guid>();
|
||||
entityToTypeToPendingComponentID[entity] = new PooledDictionary<Type, Guid>();
|
||||
entityToTypeToExistingComponentID[entity] = new PooledDictionary<Type, Guid>();
|
||||
}
|
||||
|
||||
internal void RegisterDestroyedEntity(Entity entity)
|
||||
{
|
||||
foreach (var set in entityToTypeToComponentIDs[entity].Values)
|
||||
{
|
||||
set.Clear();
|
||||
}
|
||||
entityToTypeToComponentIDs[entity].Dispose();
|
||||
entityToTypeToComponentIDs.Remove(entity);
|
||||
entityToTypeToComponentID[entity].Dispose();
|
||||
entityToTypeToComponentID.Remove(entity);
|
||||
|
||||
foreach (var set in entityToTypeToPendingComponentIDs[entity].Values)
|
||||
{
|
||||
set.Clear();
|
||||
}
|
||||
entityToTypeToPendingComponentIDs[entity].Dispose();
|
||||
entityToTypeToPendingComponentIDs.Remove(entity);
|
||||
entityToTypeToPendingComponentID[entity].Dispose();
|
||||
entityToTypeToPendingComponentID.Remove(entity);
|
||||
|
||||
foreach (var set in entityToTypeToExistingComponentIDs[entity].Values)
|
||||
{
|
||||
set.Clear();
|
||||
}
|
||||
entityToTypeToExistingComponentIDs[entity].Dispose();
|
||||
entityToTypeToExistingComponentIDs.Remove(entity);
|
||||
entityToTypeToExistingComponentID[entity].Dispose();
|
||||
entityToTypeToExistingComponentID.Remove(entity);
|
||||
}
|
||||
|
||||
internal void ClearMessages()
|
||||
|
@ -67,28 +56,19 @@ namespace Encompass
|
|||
set.Clear();
|
||||
}
|
||||
|
||||
foreach (var dictionary in entityToTypeToExistingComponentIDs.Values)
|
||||
foreach (var dictionary in entityToTypeToExistingComponentID.Values)
|
||||
{
|
||||
foreach (var set in dictionary.Values)
|
||||
{
|
||||
set.Clear();
|
||||
}
|
||||
dictionary.Clear();
|
||||
}
|
||||
|
||||
foreach (var dictionary in entityToTypeToPendingComponentIDs.Values)
|
||||
foreach (var dictionary in entityToTypeToPendingComponentID.Values)
|
||||
{
|
||||
foreach (var set in dictionary.Values)
|
||||
{
|
||||
set.Clear();
|
||||
}
|
||||
dictionary.Clear();
|
||||
}
|
||||
|
||||
foreach (var dictionary in entityToTypeToComponentIDs.Values)
|
||||
foreach (var dictionary in entityToTypeToComponentID.Values)
|
||||
{
|
||||
foreach (var set in dictionary.Values)
|
||||
{
|
||||
set.Clear();
|
||||
}
|
||||
dictionary.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,12 +83,14 @@ namespace Encompass
|
|||
|
||||
componentMessageTypeToExistingComponentIDs[typeof(TComponent)].Add(componentMessage.componentID);
|
||||
|
||||
if (!entityToTypeToExistingComponentIDs[componentMessage.entity].ContainsKey(typeof(TComponent)))
|
||||
if (!entityToTypeToExistingComponentID[componentMessage.entity].ContainsKey(typeof(TComponent)))
|
||||
{
|
||||
entityToTypeToExistingComponentIDs[componentMessage.entity].Add(typeof(TComponent), new HashSet<Guid>());
|
||||
entityToTypeToExistingComponentID[componentMessage.entity].Add(typeof(TComponent), componentMessage.componentID);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MultipleComponentOfSameTypeException("Entity {0} cannot have multiple components of type {1}", componentMessage.entity.ID, typeof(TComponent).Name);
|
||||
}
|
||||
|
||||
entityToTypeToExistingComponentIDs[componentMessage.entity][typeof(TComponent)].Add(componentMessage.componentID);
|
||||
}
|
||||
|
||||
internal void AddPendingComponentMessage<TComponent>(PendingComponentMessage<TComponent> pendingComponentMessage) where TComponent : struct, IComponent
|
||||
|
@ -122,12 +104,14 @@ namespace Encompass
|
|||
|
||||
componentMessageTypeToPendingComponentIDs[typeof(TComponent)].Add(pendingComponentMessage.componentID);
|
||||
|
||||
if (!entityToTypeToPendingComponentIDs[pendingComponentMessage.entity].ContainsKey(typeof(TComponent)))
|
||||
if (!entityToTypeToPendingComponentID[pendingComponentMessage.entity].ContainsKey(typeof(TComponent)))
|
||||
{
|
||||
entityToTypeToPendingComponentIDs[pendingComponentMessage.entity].Add(typeof(TComponent), new HashSet<Guid>());
|
||||
entityToTypeToPendingComponentID[pendingComponentMessage.entity].Add(typeof(TComponent), pendingComponentMessage.componentID);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MultipleComponentOfSameTypeException("Entity {0} cannot have multiple components of type {1}", pendingComponentMessage.entity.ID, typeof(TComponent).Name);
|
||||
}
|
||||
|
||||
entityToTypeToPendingComponentIDs[pendingComponentMessage.entity][typeof(TComponent)].Add(pendingComponentMessage.componentID);
|
||||
}
|
||||
|
||||
private void RegisterExistingOrPendingComponentMessage<TComponent>(Entity entity, Guid componentID, TComponent component) where TComponent: struct, IComponent
|
||||
|
@ -140,12 +124,14 @@ namespace Encompass
|
|||
}
|
||||
componentMessageTypeToComponentIDs[typeof(TComponent)].Add(componentID);
|
||||
|
||||
if (!entityToTypeToComponentIDs[entity].ContainsKey(typeof(TComponent)))
|
||||
if (!entityToTypeToComponentID[entity].ContainsKey(typeof(TComponent)))
|
||||
{
|
||||
entityToTypeToComponentIDs[entity].Add(typeof(TComponent), new HashSet<Guid>());
|
||||
entityToTypeToComponentID[entity].Add(typeof(TComponent), componentID);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MultipleComponentOfSameTypeException("Entity {0} cannot have multiple components of type {1}", entity.ID, typeof(TComponent).Name);
|
||||
}
|
||||
|
||||
entityToTypeToComponentIDs[entity][typeof(TComponent)].Add(componentID);
|
||||
}
|
||||
|
||||
// general component reads by type
|
||||
|
@ -231,83 +217,45 @@ namespace Encompass
|
|||
|
||||
// read components by entity and type
|
||||
|
||||
internal IEnumerable<(Guid, TComponent)> ReadExistingAndPendingComponentsByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
internal (Guid, TComponent) ReadExistingComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
if (entityToTypeToComponentIDs.ContainsKey(entity) && entityToTypeToComponentIDs[entity].TryGetValue(typeof(TComponent), out HashSet<Guid> idSet))
|
||||
if (entityToTypeToExistingComponentID.ContainsKey(entity) && entityToTypeToExistingComponentID[entity].TryGetValue(typeof(TComponent), out Guid id))
|
||||
{
|
||||
return idSet.Select(id => (id, (TComponent)componentIDToComponent[id]));
|
||||
return (id, (TComponent)componentIDToComponent[id]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NoComponentOfTypeOnEntityException("No Component of type {0} exists on Entity {1}", typeof(TComponent).Name, entity.ID);
|
||||
}
|
||||
}
|
||||
|
||||
return Enumerable.Empty<(Guid, TComponent)>();
|
||||
}
|
||||
|
||||
internal IEnumerable<(Guid, TComponent)> ReadExistingComponentsByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
internal (Guid, TComponent) ReadPendingComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
if (entityToTypeToExistingComponentIDs.ContainsKey(entity) && entityToTypeToExistingComponentIDs[entity].TryGetValue(typeof(TComponent), out HashSet<Guid> idSet))
|
||||
if (entityToTypeToPendingComponentID.ContainsKey(entity) && entityToTypeToPendingComponentID[entity].TryGetValue(typeof(TComponent), out Guid id))
|
||||
{
|
||||
return idSet.Select(id => (id, (TComponent)componentIDToComponent[id]));
|
||||
return (id, (TComponent)componentIDToComponent[id]);
|
||||
}
|
||||
|
||||
return Enumerable.Empty<(Guid, TComponent)>();
|
||||
}
|
||||
|
||||
internal IEnumerable<(Guid, TComponent)> ReadPendingComponentsByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
else
|
||||
{
|
||||
if (entityToTypeToPendingComponentIDs.ContainsKey(entity) && entityToTypeToPendingComponentIDs[entity].TryGetValue(typeof(TComponent), out HashSet<Guid> idSet))
|
||||
{
|
||||
return idSet.Select(id => (id, (TComponent)componentIDToComponent[id]));
|
||||
throw new NoComponentOfTypeOnEntityException("No Component of type {0} exists on Entity {1}", typeof(TComponent).Name, entity.ID);
|
||||
}
|
||||
|
||||
return Enumerable.Empty<(Guid, TComponent)>();
|
||||
}
|
||||
|
||||
// singular read components by entity and type
|
||||
|
||||
internal (Guid, TComponent) ReadFirstExistingOrPendingComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
return ReadExistingAndPendingComponentsByEntityAndType<TComponent>(entity).First();
|
||||
}
|
||||
|
||||
internal (Guid, TComponent) ReadFirstExistingComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
return ReadExistingComponentsByEntityAndType<TComponent>(entity).First();
|
||||
}
|
||||
|
||||
internal (Guid, TComponent) ReadFirstPendingComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
return ReadPendingComponentsByEntityAndType<TComponent>(entity).First();
|
||||
}
|
||||
|
||||
// check if entity has component of type
|
||||
|
||||
internal bool HasExistingOrPendingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
if (entityToTypeToComponentIDs.TryGetValue(entity, out _) && entityToTypeToComponentIDs[entity].TryGetValue(typeof(TComponent), out HashSet<Guid> idSet))
|
||||
{
|
||||
return idSet.Count > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
return entityToTypeToComponentID.ContainsKey(entity) && entityToTypeToComponentID[entity].ContainsKey(typeof(TComponent));
|
||||
}
|
||||
|
||||
internal bool HasExistingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
if (entityToTypeToExistingComponentIDs.TryGetValue(entity, out _) && entityToTypeToExistingComponentIDs[entity].TryGetValue(typeof(TComponent), out HashSet<Guid> idSet))
|
||||
{
|
||||
return idSet.Count > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
return entityToTypeToExistingComponentID.ContainsKey(entity) && entityToTypeToExistingComponentID[entity].ContainsKey(typeof(TComponent));
|
||||
}
|
||||
|
||||
internal bool HasPendingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
if (entityToTypeToPendingComponentIDs.TryGetValue(entity, out _) && entityToTypeToPendingComponentIDs[entity].TryGetValue(typeof(TComponent), out HashSet<Guid> idSet))
|
||||
{
|
||||
return idSet.Count > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
return entityToTypeToPendingComponentID.ContainsKey(entity) && entityToTypeToPendingComponentID[entity].ContainsKey(typeof(TComponent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,9 +119,7 @@ namespace Encompass
|
|||
|
||||
protected Guid AddComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
|
||||
{
|
||||
var componentID = componentManager.NextID();
|
||||
|
||||
componentManager.AddComponent(entity, componentID, component);
|
||||
var componentID = componentManager.MarkComponentForAdd(entity, component);
|
||||
|
||||
if (sendTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
|
||||
{
|
||||
|
@ -138,9 +136,7 @@ namespace Encompass
|
|||
|
||||
protected Guid AddDrawComponent<TComponent>(Entity entity, TComponent component, int layer = 0) where TComponent : struct, IComponent
|
||||
{
|
||||
var componentID = componentManager.NextID();
|
||||
|
||||
componentManager.AddDrawComponent(entity, componentID, component, layer);
|
||||
var componentID = componentManager.MarkDrawComponentForAdd(entity, component, layer);
|
||||
|
||||
if (sendTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
|
||||
{
|
||||
|
@ -221,43 +217,21 @@ namespace Encompass
|
|||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<ValueTuple<Guid, TComponent>> GetComponents<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>));
|
||||
var existingRead = receiveTypes.Contains(typeof(ComponentMessage<TComponent>));
|
||||
if (existingRead && pendingRead)
|
||||
{
|
||||
return componentMessageManager.ReadExistingAndPendingComponentsByEntityAndType<TComponent>(entity);
|
||||
}
|
||||
else if (existingRead)
|
||||
{
|
||||
return componentMessageManager.ReadExistingComponentsByEntityAndType<TComponent>(entity);
|
||||
}
|
||||
else if (pendingRead)
|
||||
{
|
||||
return componentMessageManager.ReadPendingComponentsByEntityAndType<TComponent>(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalReadException("Engine {0} tried to read undeclared Component {1}", GetType().Name, typeof(TComponent).Name);
|
||||
}
|
||||
}
|
||||
|
||||
protected ValueTuple<Guid, TComponent> GetComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
var pendingRead = receiveTypes.Contains(typeof(PendingComponentMessage<TComponent>));
|
||||
var existingRead = receiveTypes.Contains(typeof(ComponentMessage<TComponent>));
|
||||
if (existingRead && pendingRead)
|
||||
{
|
||||
return componentMessageManager.ReadFirstExistingOrPendingComponentByEntityAndType<TComponent>(entity);
|
||||
return componentMessageManager.ReadPendingComponentByEntityAndType<TComponent>(entity);
|
||||
}
|
||||
else if (existingRead)
|
||||
{
|
||||
return componentMessageManager.ReadFirstExistingComponentByEntityAndType<TComponent>(entity);
|
||||
return componentMessageManager.ReadExistingComponentByEntityAndType<TComponent>(entity);
|
||||
}
|
||||
else if (pendingRead)
|
||||
{
|
||||
return componentMessageManager.ReadFirstPendingComponentByEntityAndType<TComponent>(entity);
|
||||
return componentMessageManager.ReadPendingComponentByEntityAndType<TComponent>(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace Encompass.Exceptions
|
||||
{
|
||||
public class MultipleComponentOfSameTypeException : Exception
|
||||
{
|
||||
public MultipleComponentOfSameTypeException(
|
||||
string format,
|
||||
params object[] args
|
||||
) : base(string.Format(format, args)) { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace Encompass.Exceptions
|
||||
{
|
||||
public class NoComponentOfTypeOnEntityException : Exception
|
||||
{
|
||||
public NoComponentOfTypeOnEntityException(
|
||||
string format,
|
||||
params object[] args
|
||||
) : base(string.Format(format, args)) { }
|
||||
}
|
||||
}
|
|
@ -49,19 +49,14 @@ namespace Encompass
|
|||
return ReadComponents<TComponent>().First();
|
||||
}
|
||||
|
||||
protected IEnumerable<ValueTuple<Guid, TComponent>> GetComponents<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
return componentManager.GetComponentsByEntityAndType<TComponent>(entity.ID);
|
||||
}
|
||||
|
||||
protected ValueTuple<Guid, TComponent> GetComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
return GetComponents<TComponent>(entity).First();
|
||||
return componentManager.GetComponentByEntityAndType<TComponent>(entity);
|
||||
}
|
||||
|
||||
protected bool HasComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
{
|
||||
return componentManager.EntityHasComponentOfType<TComponent>(entity.ID);
|
||||
return componentManager.EntityHasComponentOfType<TComponent>(entity);
|
||||
}
|
||||
|
||||
protected bool SomeComponent<TComponent>() where TComponent : struct, IComponent
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace Encompass
|
|||
|
||||
componentManager.PerformComponentUpdates();
|
||||
componentManager.RemoveMarkedComponents();
|
||||
componentManager.AddMarkedComponents();
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
|
|
|
@ -47,14 +47,12 @@ namespace Encompass
|
|||
|
||||
public Guid AddComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
|
||||
{
|
||||
var componentID = componentManager.NextID();
|
||||
return componentManager.AddComponent(entity, componentID, component);
|
||||
return componentManager.MarkComponentForAdd(entity, component);
|
||||
}
|
||||
|
||||
public Guid AddDrawComponent<TComponent>(Entity entity, TComponent component, int layer = 0) where TComponent : struct, IComponent
|
||||
{
|
||||
var componentID = componentManager.NextID();
|
||||
return componentManager.AddDrawComponent(entity, componentID, component, layer);
|
||||
return componentManager.MarkDrawComponentForAdd(entity, component, layer);
|
||||
}
|
||||
|
||||
internal void RegisterComponent(Type componentType)
|
||||
|
@ -256,6 +254,7 @@ namespace Encompass
|
|||
|
||||
componentManager.PerformComponentUpdates();
|
||||
componentManager.RemoveMarkedComponents();
|
||||
componentManager.AddMarkedComponents();
|
||||
|
||||
return world;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ using Encompass;
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Encompass.Exceptions;
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
|
@ -81,6 +82,78 @@ namespace Tests
|
|||
world.Update(0.01);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddMultipleComponentOfSameTypeToEntity()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
|
||||
MockComponent mockComponent;
|
||||
mockComponent.myInt = 3;
|
||||
mockComponent.myString = "hello";
|
||||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
worldBuilder.AddComponent(entity, mockComponent);
|
||||
worldBuilder.AddComponent(entity, mockComponent);
|
||||
|
||||
Assert.Throws<MultipleComponentOfSameTypeException>(() => worldBuilder.Build());
|
||||
}
|
||||
|
||||
[Reads(typeof(MockComponent))]
|
||||
class MultipleAddEngine : Engine
|
||||
{
|
||||
public override void Update(double dt)
|
||||
{
|
||||
foreach (var (mockComponentID, mockComponent) in ReadComponents<MockComponent>())
|
||||
{
|
||||
var entity = GetEntityByComponentID(mockComponentID);
|
||||
|
||||
AddComponent(entity, new MockComponent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EngineAddMultipleComponentOfSameTypeToEntity()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
worldBuilder.AddEngine(new MultipleAddEngine());
|
||||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
worldBuilder.AddComponent(entity, new MockComponent());
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
Assert.Throws<MultipleComponentOfSameTypeException>(() => world.Update(0.01));
|
||||
}
|
||||
|
||||
[Reads(typeof(MockComponent))]
|
||||
class AddAndRemoveComponentEngine : Engine
|
||||
{
|
||||
public override void Update(double dt)
|
||||
{
|
||||
foreach (var (mockComponentID, mockComponent) in ReadComponents<MockComponent>())
|
||||
{
|
||||
var entity = GetEntityByComponentID(mockComponentID);
|
||||
AddComponent(entity, mockComponent);
|
||||
RemoveComponent(mockComponentID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddMultipleComponentSameFrameAsRemove()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
worldBuilder.AddEngine(new AddAndRemoveComponentEngine());
|
||||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
worldBuilder.AddComponent(entity, new MockComponent());
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
Assert.DoesNotThrow(() => world.Update(0.01));
|
||||
}
|
||||
|
||||
struct AddMockComponentMessage : IMessage
|
||||
{
|
||||
public Entity entity;
|
||||
|
@ -154,89 +227,6 @@ namespace Tests
|
|||
world.Update(0.01);
|
||||
}
|
||||
|
||||
[Receives(typeof(EntityMessage))]
|
||||
[Reads(typeof(MockComponent))]
|
||||
class GetMockComponentsEngine : Engine
|
||||
{
|
||||
private Entity entity;
|
||||
private Guid componentAID;
|
||||
private Guid componentBID;
|
||||
private Guid componentCID;
|
||||
private MockComponent componentA;
|
||||
private MockComponent componentB;
|
||||
private MockComponent componentC;
|
||||
|
||||
public GetMockComponentsEngine(
|
||||
Entity entity,
|
||||
Guid componentAID,
|
||||
MockComponent componentA,
|
||||
Guid componentBID,
|
||||
MockComponent componentB,
|
||||
Guid componentCID,
|
||||
MockComponent componentC
|
||||
) {
|
||||
this.entity = entity;
|
||||
this.componentAID = componentAID;
|
||||
this.componentA = componentA;
|
||||
this.componentBID = componentBID;
|
||||
this.componentB = componentB;
|
||||
this.componentCID = componentCID;
|
||||
this.componentC = componentC;
|
||||
}
|
||||
|
||||
public override void Update(double dt)
|
||||
{
|
||||
foreach (var entityMessage in ReadMessages<EntityMessage>())
|
||||
{
|
||||
var results = GetComponents<MockComponent>(entityMessage.entity);
|
||||
results.Should().Contain((componentAID, componentA));
|
||||
results.Should().Contain((componentBID, componentB));
|
||||
results.Should().Contain((componentCID, componentC));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetComponents()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
|
||||
MockComponent mockComponentA;
|
||||
mockComponentA.myInt = 3;
|
||||
mockComponentA.myString = "hello";
|
||||
|
||||
MockComponent mockComponentB;
|
||||
mockComponentB.myInt = 5;
|
||||
mockComponentB.myString = "wassup";
|
||||
|
||||
MockComponent mockComponentC;
|
||||
mockComponentC.myInt = 1;
|
||||
mockComponentC.myString = "howdy";
|
||||
|
||||
var componentAID = worldBuilder.AddComponent(entity, mockComponentA);
|
||||
var componentBID = worldBuilder.AddComponent(entity, mockComponentB);
|
||||
var componentCID = worldBuilder.AddComponent(entity, mockComponentC);
|
||||
|
||||
worldBuilder.AddEngine(new GetMockComponentsEngine(
|
||||
entity,
|
||||
componentAID,
|
||||
mockComponentA,
|
||||
componentBID,
|
||||
mockComponentB,
|
||||
componentCID,
|
||||
mockComponentC
|
||||
));
|
||||
|
||||
EntityMessage entityMessage;
|
||||
entityMessage.entity = entity;
|
||||
worldBuilder.SendMessage(entityMessage);
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
world.Update(0.01);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetComponent()
|
||||
{
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace Tests
|
|||
worldBuilder.AddEngine(new ReadComponentsTestEngine());
|
||||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
var entityB = worldBuilder.CreateEntity();
|
||||
|
||||
MockComponent mockComponent;
|
||||
mockComponent.myInt = 0;
|
||||
|
@ -59,7 +60,7 @@ namespace Tests
|
|||
mockComponentB.myString = "howdy";
|
||||
|
||||
var componentAID = worldBuilder.AddComponent(entity, mockComponent);
|
||||
var componentBID = worldBuilder.AddComponent(entity, mockComponentB);
|
||||
var componentBID = worldBuilder.AddComponent(entityB, mockComponentB);
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
|
@ -98,6 +99,7 @@ namespace Tests
|
|||
worldBuilder.AddEngine(new ReadComponentTestEngine());
|
||||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
var entityB = worldBuilder.CreateEntity();
|
||||
|
||||
MockComponent mockComponent;
|
||||
mockComponent.myInt = 0;
|
||||
|
@ -108,7 +110,7 @@ namespace Tests
|
|||
mockComponentB.myString = "howdy";
|
||||
|
||||
worldBuilder.AddComponent(entity, mockComponent);
|
||||
worldBuilder.AddComponent(entity, mockComponentB);
|
||||
worldBuilder.AddComponent(entityB, mockComponentB);
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
|
@ -390,7 +392,9 @@ namespace Tests
|
|||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
worldBuilder.AddComponent(entity, componentA);
|
||||
worldBuilder.AddComponent(entity, componentB);
|
||||
|
||||
var entityB = worldBuilder.CreateEntity();
|
||||
worldBuilder.AddComponent(entityB, componentB);
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
world.Update(0.01f);
|
||||
|
|
|
@ -53,7 +53,9 @@ namespace Tests
|
|||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
var componentID = worldBuilder.AddComponent(entity, aComponent);
|
||||
var componentTwoID = worldBuilder.AddComponent(entity, aComponentTwo);
|
||||
|
||||
var entityB = worldBuilder.CreateEntity();
|
||||
var componentTwoID = worldBuilder.AddComponent(entityB, aComponentTwo);
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
world.Update(0.01f);
|
||||
|
|
Loading…
Reference in New Issue