component updates at end of frame

pull/5/head
thatcosmonaut 2019-07-17 18:53:31 -07:00
parent ca82fa82cf
commit a62153730f
6 changed files with 85 additions and 7 deletions

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Encompass.Exceptions;
namespace Encompass
{
@ -22,6 +23,8 @@ namespace Encompass
private readonly HashSet<Guid> componentsMarkedForDeactivation = new HashSet<Guid>();
private readonly HashSet<Guid> componentsMarkedForRemoval = new HashSet<Guid>();
private readonly Dictionary<Guid, IComponent> pendingUpdates = new Dictionary<Guid, IComponent>();
//shared references with EntityManager
private readonly HashSet<Guid> entitiesWithAddedComponents;
private readonly HashSet<Guid> entitiesWithRemovedComponents;
@ -149,9 +152,24 @@ namespace Encompass
return componentIDToEntityID[componentID];
}
internal void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent
internal void AddUpdateComponentOperation<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent
{
IDToComponent[componentID] = newComponentValue;
if (pendingUpdates.ContainsKey(componentID))
{
throw new RepeatUpdateComponentException("Component with ID {0} was updated multiple times this frame", componentID);
}
pendingUpdates.Add(componentID, newComponentValue);
}
internal void PerformComponentUpdates()
{
foreach (var idPair in pendingUpdates)
{
IDToComponent[idPair.Key] = idPair.Value;
}
pendingUpdates.Clear();
}
internal void MarkAllComponentsOnEntityForRemoval(Guid entityID)

View File

@ -134,7 +134,7 @@ namespace Encompass
throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name);
}
componentManager.UpdateComponent(componentID, newComponent);
componentManager.AddUpdateComponentOperation(componentID, newComponent);
}
protected void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent

View File

@ -0,0 +1,12 @@
using System;
namespace Encompass.Exceptions
{
public class RepeatUpdateComponentException : Exception
{
public RepeatUpdateComponentException(
string format,
params object[] args
) : base(string.Format(format, args)) { }
}
}

View File

@ -35,6 +35,7 @@ namespace Encompass
messageManager.ClearMessages();
entityManager.DestroyMarkedEntities();
componentManager.PerformComponentUpdates();
componentManager.ActivateMarkedComponents();
componentManager.DeactivateMarkedComponents();
componentManager.RemoveMarkedComponents();

View File

@ -224,10 +224,11 @@ namespace Encompass
renderManager
);
componentManager.PerformComponentUpdates();
componentManager.ActivateMarkedComponents();
componentManager.DeactivateMarkedComponents();
componentManager.RemoveMarkedComponents();
entityManager.CheckEntitiesWithAddedComponents();
entityManager.CheckEntitiesWithRemovedComponents();

View File

@ -31,6 +31,7 @@ namespace Tests
}
}
public class ReadComponentTestEngine : Engine
{
public override void Update(double dt)
@ -126,16 +127,17 @@ namespace Tests
component.myInt = 420;
component.myString = "blaze it";
UpdateComponent(componentID, component);
resultComponent = ReadComponent<MockComponent>().Item2;
}
}
// this test needs to be improved...
[Test]
public void UpdateComponent()
{
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new UpdateComponentTestEngine());
worldBuilder.AddEngine(new ReadComponentTestEngine());
var entity = worldBuilder.CreateEntity();
@ -147,7 +149,8 @@ namespace Tests
var world = worldBuilder.Build();
world.Update(0.01f);
world.Update(0.01);
world.Update(0.01);
Assert.AreEqual(420, resultComponent.myInt);
Assert.AreEqual("blaze it", resultComponent.myString);
@ -642,5 +645,48 @@ namespace Tests
Assert.Throws<ComponentAndMessageWriteException>(() => worldBuilder.AddEngine(new EngineThatWritesComponentAndMessage()));
}
struct MockComponentUpdateMessage : IMessage
{
public Guid componentID;
public MockComponent mockComponent;
}
[Reads(typeof(MockComponentUpdateMessage))]
[Writes(typeof(MockComponent))]
class RepeatUpdateEngine : Engine
{
public override void Update(double dt)
{
foreach (var mockComponentUpdateMessage in ReadMessages<MockComponentUpdateMessage>())
{
UpdateComponent(mockComponentUpdateMessage.componentID, mockComponentUpdateMessage.mockComponent);
UpdateComponent(mockComponentUpdateMessage.componentID, mockComponentUpdateMessage.mockComponent);
}
}
}
[Test]
public void EngineUpdatesComponentMultipleTimes()
{
var worldBuilder = new WorldBuilder();
worldBuilder.AddEngine(new RepeatUpdateEngine());
var entity = worldBuilder.CreateEntity();
MockComponent mockComponent;
mockComponent.myInt = 1;
mockComponent.myString = "5";
var mockComponentID = worldBuilder.AddComponent(entity, mockComponent);
MockComponentUpdateMessage mockComponentUpdateMessage;
mockComponentUpdateMessage.componentID = mockComponentID;
mockComponentUpdateMessage.mockComponent = mockComponent;
worldBuilder.EmitMessage(mockComponentUpdateMessage);
var world = worldBuilder.Build();
Assert.Throws<RepeatUpdateComponentException>(() => world.Update(0.01));
}
}
}