remove activation concept from components and entities

pull/5/head
Evan Hemsley 2019-07-31 10:35:17 -07:00
parent 2304cabe97
commit d6c84b950a
9 changed files with 14 additions and 333 deletions

View File

@ -16,11 +16,6 @@ namespace Encompass
private readonly Dictionary<Type, HashSet<Guid>> typeToComponentIDs = new Dictionary<Type, HashSet<Guid>>(); private readonly Dictionary<Type, HashSet<Guid>> typeToComponentIDs = new Dictionary<Type, HashSet<Guid>>();
private readonly List<Guid> activeComponents = new List<Guid>();
private readonly List<Guid> inactiveComponents = new List<Guid>();
private readonly HashSet<Guid> componentsMarkedForActivation = new HashSet<Guid>();
private readonly HashSet<Guid> componentsMarkedForDeactivation = new HashSet<Guid>();
private readonly HashSet<Guid> componentsMarkedForRemoval = new HashSet<Guid>(); private readonly HashSet<Guid> componentsMarkedForRemoval = new HashSet<Guid>();
private readonly Dictionary<Guid, IComponent> pendingUpdates = new Dictionary<Guid, IComponent>(); private readonly Dictionary<Guid, IComponent> pendingUpdates = new Dictionary<Guid, IComponent>();
@ -65,8 +60,6 @@ namespace Encompass
entityIDToComponentIDs[entity.ID].Add(componentID); entityIDToComponentIDs[entity.ID].Add(componentID);
componentIDToEntityID[componentID] = entity.ID; componentIDToEntityID[componentID] = entity.ID;
activeComponents.Add(componentID);
entitiesWithAddedComponents.Add(entity.ID); entitiesWithAddedComponents.Add(entity.ID);
return componentID; return componentID;
@ -88,34 +81,34 @@ namespace Encompass
internal IEnumerable<ValueTuple<Guid, IComponent>> GetComponentsByEntity(Guid entityID) internal IEnumerable<ValueTuple<Guid, IComponent>> GetComponentsByEntity(Guid entityID)
{ {
return GetComponentIDsByEntityID(entityID).Intersect(activeComponents).Select((id) => new ValueTuple<Guid, IComponent>(id, IDToComponent[id])); return GetComponentIDsByEntityID(entityID).Select((id) => new ValueTuple<Guid, IComponent>(id, IDToComponent[id]));
} }
internal IEnumerable<ValueTuple<Guid, Guid, TComponent>> GetActiveComponentsByType<TComponent>() where TComponent : struct, IComponent internal IEnumerable<ValueTuple<Guid, Guid, TComponent>> GetComponentsByType<TComponent>() where TComponent : struct, IComponent
{ {
return typeToComponentIDs.ContainsKey(typeof(TComponent)) ? return typeToComponentIDs.ContainsKey(typeof(TComponent)) ?
typeToComponentIDs[typeof(TComponent)].Intersect(activeComponents).Select((id) => new ValueTuple<Guid, Guid, TComponent>(GetEntityIDByComponentID(id), id, (TComponent)IDToComponent[id])) : typeToComponentIDs[typeof(TComponent)].Select((id) => new ValueTuple<Guid, Guid, TComponent>(GetEntityIDByComponentID(id), id, (TComponent)IDToComponent[id])) :
Enumerable.Empty<ValueTuple<Guid, Guid, TComponent>>(); Enumerable.Empty<ValueTuple<Guid, Guid, TComponent>>();
} }
internal IEnumerable<ValueTuple<Guid, IComponent>> GetActiveComponentsByType(Type type) internal IEnumerable<ValueTuple<Guid, IComponent>> GetComponentsByType(Type type)
{ {
return typeToComponentIDs.ContainsKey(type) ? return typeToComponentIDs.ContainsKey(type) ?
typeToComponentIDs[type].Intersect(activeComponents).Select((id) => new ValueTuple<Guid, IComponent>(id, IDToComponent[id])) : typeToComponentIDs[type].Select((id) => new ValueTuple<Guid, IComponent>(id, IDToComponent[id])) :
Enumerable.Empty<ValueTuple<Guid, IComponent>>(); Enumerable.Empty<ValueTuple<Guid, IComponent>>();
} }
internal IEnumerable<ValueTuple<Guid, TComponent>> GetComponentsByEntityAndType<TComponent>(Guid entityID) where TComponent : struct, IComponent internal IEnumerable<ValueTuple<Guid, TComponent>> GetComponentsByEntityAndType<TComponent>(Guid entityID) where TComponent : struct, IComponent
{ {
var entityComponentsByType = GetComponentsByEntity(entityID).Where((pair) => componentIDToType[pair.Item1] == typeof(TComponent)).Select((pair) => new ValueTuple<Guid, TComponent>(pair.Item1, (TComponent)pair.Item2)); var entityComponentsByType = GetComponentsByEntity(entityID).Where((pair) => componentIDToType[pair.Item1] == typeof(TComponent)).Select((pair) => new ValueTuple<Guid, TComponent>(pair.Item1, (TComponent)pair.Item2));
var activeComponentsByType = GetActiveComponentsByType<TComponent>(); var activeComponentsByType = GetComponentsByType<TComponent>();
return activeComponentsByType.Select((triple) => (triple.Item2, triple.Item3)).Intersect(entityComponentsByType); return activeComponentsByType.Select((triple) => (triple.Item2, triple.Item3)).Intersect(entityComponentsByType);
} }
internal IEnumerable<ValueTuple<Guid, IComponent>> GetComponentsByEntityAndType(Guid entityID, Type type) internal IEnumerable<ValueTuple<Guid, IComponent>> GetComponentsByEntityAndType(Guid entityID, Type type)
{ {
var entityComponents = GetComponentsByEntity(entityID); var entityComponents = GetComponentsByEntity(entityID);
var activeComponentsByType = GetActiveComponentsByType(type); var activeComponentsByType = GetComponentsByType(type);
return entityComponents.Intersect(activeComponentsByType); return entityComponents.Intersect(activeComponentsByType);
} }
@ -177,43 +170,6 @@ namespace Encompass
} }
} }
internal void Activate(Guid componentID)
{
if (inactiveComponents.Remove(componentID))
{
activeComponents.Add(componentID);
}
var entityID = GetEntityIDByComponentID(componentID);
entitiesWithAddedComponents.Add(entityID);
}
internal void MarkForDeactivation(Guid componentID)
{
componentsMarkedForDeactivation.Add(componentID);
}
internal void DeactivateMarkedComponents()
{
foreach (var componentID in componentsMarkedForDeactivation)
{
Deactivate(componentID);
}
componentsMarkedForDeactivation.Clear();
}
private void Deactivate(Guid componentID)
{
if (activeComponents.Remove(componentID))
{
inactiveComponents.Add(componentID);
}
var entityID = GetEntityIDByComponentID(componentID);
entitiesWithRemovedComponents.Add(entityID);
}
internal void MarkForRemoval(Guid componentID) internal void MarkForRemoval(Guid componentID)
{ {
componentsMarkedForRemoval.Add(componentID); componentsMarkedForRemoval.Add(componentID);
@ -234,9 +190,6 @@ namespace Encompass
var component = IDToComponent[componentID]; var component = IDToComponent[componentID];
var type = componentIDToType[componentID]; var type = componentIDToType[componentID];
activeComponents.Remove(componentID);
inactiveComponents.Remove(componentID);
var entityID = componentIDToEntityID[componentID]; var entityID = componentIDToEntityID[componentID];
if (entityIDToComponentIDs.ContainsKey(entityID)) if (entityIDToComponentIDs.ContainsKey(entityID))
{ {

View File

@ -108,7 +108,7 @@ namespace Encompass
internal IEnumerable<ValueTuple<Entity, Guid, TComponent>> ReadComponentsFromWorld<TComponent>() where TComponent : struct, IComponent internal IEnumerable<ValueTuple<Entity, Guid, TComponent>> ReadComponentsFromWorld<TComponent>() where TComponent : struct, IComponent
{ {
return componentManager.GetActiveComponentsByType<TComponent>().Select((triple) => (GetEntity(triple.Item1), triple.Item2, triple.Item3)); return componentManager.GetComponentsByType<TComponent>().Select((triple) => (GetEntity(triple.Item1), triple.Item2, triple.Item3));
} }
protected Guid AddComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent protected Guid AddComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
@ -147,28 +147,6 @@ namespace Encompass
return componentID; return componentID;
} }
protected void ActivateComponent<TComponent>(Guid componentID) where TComponent : struct, IComponent
{
var entity = GetEntity(componentManager.GetEntityIDByComponentID(componentID));
var component = GetComponentByID<TComponent>(componentID);
if (sendTypes.Contains(typeof(PendingComponentMessage<TComponent>)))
{
PendingComponentMessage<TComponent> newComponentMessage;
newComponentMessage.entity = entity;
newComponentMessage.componentID = componentID;
newComponentMessage.component = component;
SendMessage(newComponentMessage);
componentManager.Activate(componentID);
}
}
protected void DeactivateComponent(Guid componentID)
{
componentManager.MarkForDeactivation(componentID);
}
private IEnumerable<ValueTuple<Entity, Guid, TComponent>> ExistingComponents<TComponent>() where TComponent : struct, IComponent private IEnumerable<ValueTuple<Entity, Guid, TComponent>> ExistingComponents<TComponent>() where TComponent : struct, IComponent
{ {
return ReadMessages<ComponentMessage<TComponent>>().Select((message) => (message.entity, message.componentID, message.component)); return ReadMessages<ComponentMessage<TComponent>>().Select((message) => (message.entity, message.componentID, message.component));

View File

@ -41,7 +41,7 @@ namespace Encompass
protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
{ {
return componentManager.GetActiveComponentsByType<TComponent>().Select((triple) => (triple.Item2, triple.Item3)); return componentManager.GetComponentsByType<TComponent>().Select((triple) => (triple.Item2, triple.Item3));
} }
protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
@ -66,7 +66,7 @@ namespace Encompass
protected bool SomeComponent<TComponent>() where TComponent : struct, IComponent protected bool SomeComponent<TComponent>() where TComponent : struct, IComponent
{ {
return componentManager.GetActiveComponentsByType<TComponent>().Any(); return componentManager.GetComponentsByType<TComponent>().Any();
} }
} }
} }

View File

@ -7,18 +7,12 @@ namespace Encompass
internal class EntityTracker internal class EntityTracker
{ {
private readonly HashSet<Guid> trackedEntityIDs = new HashSet<Guid>(); private readonly HashSet<Guid> trackedEntityIDs = new HashSet<Guid>();
private readonly HashSet<Guid> deactivatedEntityIDs = new HashSet<Guid>();
public IEnumerable<Guid> TrackedEntityIDs public IEnumerable<Guid> TrackedEntityIDs
{ {
get { return trackedEntityIDs; } get { return trackedEntityIDs; }
} }
public IEnumerable<Guid> DeactivatedEntityIds
{
get { return deactivatedEntityIDs; }
}
public void TrackEntity(Guid entityID) public void TrackEntity(Guid entityID)
{ {
trackedEntityIDs.Add(entityID); trackedEntityIDs.Add(entityID);
@ -26,26 +20,7 @@ namespace Encompass
public void UntrackEntity(Guid entityID) public void UntrackEntity(Guid entityID)
{ {
if (trackedEntityIDs.Remove(entityID)) trackedEntityIDs.Remove(entityID);
{
deactivatedEntityIDs.Remove(entityID);
}
}
public void ActivateEntity(Guid entityID)
{
if (deactivatedEntityIDs.Remove(entityID))
{
trackedEntityIDs.Add(entityID);
}
}
public void DeactivateEntity(Guid entityID)
{
if (trackedEntityIDs.Remove(entityID))
{
deactivatedEntityIDs.Add(entityID);
}
} }
public bool IsTracking(Guid entityID) public bool IsTracking(Guid entityID)

View File

@ -36,7 +36,6 @@ namespace Encompass
entityManager.DestroyMarkedEntities(); entityManager.DestroyMarkedEntities();
componentManager.PerformComponentUpdates(); componentManager.PerformComponentUpdates();
componentManager.DeactivateMarkedComponents();
componentManager.RemoveMarkedComponents(); componentManager.RemoveMarkedComponents();
entityManager.CheckEntitiesWithAddedComponents(); entityManager.CheckEntitiesWithAddedComponents();

View File

@ -58,11 +58,6 @@ namespace Encompass
return componentManager.AddDrawComponent(entity, componentID, component, layer); return componentManager.AddDrawComponent(entity, componentID, component, layer);
} }
public void DeactivateComponent(Guid componentID)
{
componentManager.MarkForDeactivation(componentID);
}
internal void RegisterComponent(Type componentType) internal void RegisterComponent(Type componentType)
{ {
registeredComponentTypes.Add(componentType); registeredComponentTypes.Add(componentType);
@ -265,7 +260,6 @@ namespace Encompass
); );
componentManager.PerformComponentUpdates(); componentManager.PerformComponentUpdates();
componentManager.DeactivateMarkedComponents();
componentManager.RemoveMarkedComponents(); componentManager.RemoveMarkedComponents();
entityManager.CheckEntitiesWithAddedComponents(); entityManager.CheckEntitiesWithAddedComponents();

View File

@ -303,48 +303,6 @@ namespace Tests
world.Update(0.01); world.Update(0.01);
} }
struct HasComponentWhenInactiveTestMessage : IMessage
{
public Entity entity;
}
[Receives(typeof(HasComponentWhenInactiveTestMessage))]
[Reads(typeof(MockComponent))]
class HasComponentWhenInactiveTestEngine : Engine
{
public override void Update(double dt)
{
foreach (var hasComponentTestEngine in ReadMessages<HasComponentWhenInactiveTestMessage>())
{
Assert.IsFalse(HasComponent<MockComponent>(hasComponentTestEngine.entity));
}
}
}
[Test]
public void HasComponentWhenInactive()
{
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new HasComponentWhenInactiveTestEngine());
var entity = worldBuilder.CreateEntity();
MockComponent mockComponent;
mockComponent.myInt = 3;
mockComponent.myString = "hello";
var componentID = worldBuilder.AddComponent(entity, mockComponent);
HasComponentWhenInactiveTestMessage testMessage;
testMessage.entity = entity;
worldBuilder.SendMessage(testMessage);
worldBuilder.DeactivateComponent(componentID);
var world = worldBuilder.Build();
world.Update(0.01f);
}
struct RemoveComponentTestMessage : IMessage struct RemoveComponentTestMessage : IMessage
{ {
public Entity entity; public Entity entity;
@ -432,54 +390,12 @@ namespace Tests
world.Update(0.01f); world.Update(0.01f);
} }
struct ActivateComponentMessage : IMessage
{
public Entity entity;
public Guid componentID;
}
[Activates(typeof(MockComponent))]
[Receives(typeof(ActivateComponentMessage))]
class ActivateComponentEngine : Engine
{
public override void Update(double dt)
{
foreach (var activateComponentMessage in ReadMessages<ActivateComponentMessage>())
{
ActivateComponent<MockComponent>(activateComponentMessage.componentID);
}
}
}
struct CheckHasMockComponentMessage : IMessage struct CheckHasMockComponentMessage : IMessage
{ {
public Entity entity; public Entity entity;
public bool shouldHaveComponent; public bool shouldHaveComponent;
} }
[Receives(typeof(ActivateComponentMessage))]
[Sends(typeof(CheckHasMockComponentMessage))]
class DoActivateCheckEngine : Engine
{
private Entity entity;
public DoActivateCheckEngine(Entity entity)
{
this.entity = entity;
}
public override void Update(double dt)
{
if (SomeMessage<ActivateComponentMessage>())
{
CheckHasMockComponentMessage checkHasMockComponentMessage;
checkHasMockComponentMessage.entity = entity;
checkHasMockComponentMessage.shouldHaveComponent = true;
SendMessage(checkHasMockComponentMessage);
}
}
}
[Receives(typeof(CheckHasMockComponentMessage))] [Receives(typeof(CheckHasMockComponentMessage))]
[ReadsPending(typeof(MockComponent))] [ReadsPending(typeof(MockComponent))]
class CheckHasPendingMockComponentEngine : Engine class CheckHasPendingMockComponentEngine : Engine
@ -492,107 +408,5 @@ namespace Tests
} }
} }
} }
[Test]
public void ActivateComponent()
{
var worldBuilder = new WorldBuilder();
var entity = worldBuilder.CreateEntity();
worldBuilder.AddEngine(new ActivateComponentEngine());
worldBuilder.AddEngine(new CheckHasPendingMockComponentEngine());
worldBuilder.AddEngine(new DoActivateCheckEngine(entity));
MockComponent mockComponent;
mockComponent.myInt = 3;
mockComponent.myString = "hello";
var componentID = worldBuilder.AddComponent(entity, mockComponent);
worldBuilder.DeactivateComponent(componentID);
ActivateComponentMessage activateMessage;
activateMessage.entity = entity;
activateMessage.componentID = componentID;
worldBuilder.SendMessage(activateMessage);
var world = worldBuilder.Build();
world.Update(0.01);
}
struct DeactivateComponentMessage : IMessage
{
public Entity entity;
public Guid componentID;
}
[Receives(typeof(DeactivateComponentMessage))]
class DeactivateComponentEngine : Engine
{
public override void Update(double dt)
{
foreach (var deactivateComponentMessage in ReadMessages<DeactivateComponentMessage>())
{
DeactivateComponent(deactivateComponentMessage.componentID);
}
}
}
[Receives(typeof(DeactivateComponentMessage))]
[Sends(typeof(CheckHasMockComponentMessage))]
class DoDeactivateCheckEngine : Engine
{
private Entity entity;
public DoDeactivateCheckEngine(Entity entity)
{
this.entity = entity;
}
public override void Update(double dt)
{
if (SomeMessage<DeactivateComponentMessage>())
{
CheckHasMockComponentMessage checkHasMockComponentMessage;
checkHasMockComponentMessage.entity = entity;
checkHasMockComponentMessage.shouldHaveComponent = true;
SendMessage(checkHasMockComponentMessage);
}
else
{
CheckHasMockComponentMessage checkHasMockComponentMessage;
checkHasMockComponentMessage.entity = entity;
checkHasMockComponentMessage.shouldHaveComponent = false;
SendMessage(checkHasMockComponentMessage);
}
}
}
[Test]
public void DeactivateComponent()
{
var worldBuilder = new WorldBuilder();
var entity = worldBuilder.CreateEntity();
worldBuilder.AddEngine(new DeactivateComponentEngine());
worldBuilder.AddEngine(new CheckHasMockComponentEngine());
worldBuilder.AddEngine(new DoDeactivateCheckEngine(entity));
MockComponent mockComponent;
mockComponent.myInt = 3;
mockComponent.myString = "hello";
var componentID = worldBuilder.AddComponent(entity, mockComponent);
DeactivateComponentMessage deactivateComponentMessage;
deactivateComponentMessage.entity = entity;
deactivateComponentMessage.componentID = componentID;
worldBuilder.SendMessage(deactivateComponentMessage);
var world = worldBuilder.Build();
world.Update(0.01);
}
} }
} }

View File

@ -60,9 +60,6 @@ namespace Tests
var componentAID = worldBuilder.AddComponent(entity, mockComponent); var componentAID = worldBuilder.AddComponent(entity, mockComponent);
var componentBID = worldBuilder.AddComponent(entity, mockComponentB); var componentBID = worldBuilder.AddComponent(entity, mockComponentB);
var inactiveComponentAID = worldBuilder.AddComponent(entity, mockComponent);
worldBuilder.DeactivateComponent(inactiveComponentAID);
var world = worldBuilder.Build(); var world = worldBuilder.Build();
@ -71,7 +68,6 @@ namespace Tests
var resultComponentValues = resultComponents.Select((kv) => kv.Item2); var resultComponentValues = resultComponents.Select((kv) => kv.Item2);
resultComponentValues.Should().Contain(mockComponent); resultComponentValues.Should().Contain(mockComponent);
resultComponentValues.Should().Contain(mockComponentB); resultComponentValues.Should().Contain(mockComponentB);
resultComponents.Should().NotContain((inactiveComponentAID, mockComponent));
} }
[Test] [Test]

View File

@ -62,34 +62,6 @@ namespace Tests
} }
} }
[Test]
public void InactiveDrawComponent()
{
var worldBuilder = new WorldBuilder();
var renderer = worldBuilder.AddEntityRenderer(new TestRenderer());
AComponent aComponent;
BComponent bComponent;
TestDrawComponent testDrawComponent = default(TestDrawComponent);
var entity = worldBuilder.CreateEntity();
worldBuilder.AddComponent(entity, aComponent);
worldBuilder.AddComponent(entity, bComponent);
var testDrawComponentID = worldBuilder.AddDrawComponent(entity, testDrawComponent, 1);
worldBuilder.DeactivateComponent(testDrawComponentID);
var world = worldBuilder.Build();
world.Update(0.01f);
Assert.IsFalse(renderer.IsTracking(entity.ID));
world.Draw();
Assert.IsFalse(called);
}
static bool calledOnDraw = false; static bool calledOnDraw = false;
static IEnumerable<ValueTuple<Guid, TestDrawComponent>> resultComponents; static IEnumerable<ValueTuple<Guid, TestDrawComponent>> resultComponents;
[Renders(typeof(TestDrawComponent), typeof(AComponent), typeof(CComponent))] [Renders(typeof(TestDrawComponent), typeof(AComponent), typeof(CComponent))]