component updates at end of frame
parent
ca82fa82cf
commit
a62153730f
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Encompass.Exceptions;
|
||||||
|
|
||||||
namespace Encompass
|
namespace Encompass
|
||||||
{
|
{
|
||||||
|
@ -22,6 +23,8 @@ namespace Encompass
|
||||||
private readonly HashSet<Guid> componentsMarkedForDeactivation = 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>();
|
||||||
|
|
||||||
//shared references with EntityManager
|
//shared references with EntityManager
|
||||||
private readonly HashSet<Guid> entitiesWithAddedComponents;
|
private readonly HashSet<Guid> entitiesWithAddedComponents;
|
||||||
private readonly HashSet<Guid> entitiesWithRemovedComponents;
|
private readonly HashSet<Guid> entitiesWithRemovedComponents;
|
||||||
|
@ -149,9 +152,24 @@ namespace Encompass
|
||||||
return componentIDToEntityID[componentID];
|
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)
|
internal void MarkAllComponentsOnEntityForRemoval(Guid entityID)
|
||||||
|
|
|
@ -134,7 +134,7 @@ namespace Encompass
|
||||||
throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name);
|
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
|
protected void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent
|
||||||
|
|
|
@ -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)) { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,7 @@ namespace Encompass
|
||||||
messageManager.ClearMessages();
|
messageManager.ClearMessages();
|
||||||
entityManager.DestroyMarkedEntities();
|
entityManager.DestroyMarkedEntities();
|
||||||
|
|
||||||
|
componentManager.PerformComponentUpdates();
|
||||||
componentManager.ActivateMarkedComponents();
|
componentManager.ActivateMarkedComponents();
|
||||||
componentManager.DeactivateMarkedComponents();
|
componentManager.DeactivateMarkedComponents();
|
||||||
componentManager.RemoveMarkedComponents();
|
componentManager.RemoveMarkedComponents();
|
||||||
|
|
|
@ -224,6 +224,7 @@ namespace Encompass
|
||||||
renderManager
|
renderManager
|
||||||
);
|
);
|
||||||
|
|
||||||
|
componentManager.PerformComponentUpdates();
|
||||||
componentManager.ActivateMarkedComponents();
|
componentManager.ActivateMarkedComponents();
|
||||||
componentManager.DeactivateMarkedComponents();
|
componentManager.DeactivateMarkedComponents();
|
||||||
componentManager.RemoveMarkedComponents();
|
componentManager.RemoveMarkedComponents();
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class ReadComponentTestEngine : Engine
|
public class ReadComponentTestEngine : Engine
|
||||||
{
|
{
|
||||||
public override void Update(double dt)
|
public override void Update(double dt)
|
||||||
|
@ -126,16 +127,17 @@ namespace Tests
|
||||||
component.myInt = 420;
|
component.myInt = 420;
|
||||||
component.myString = "blaze it";
|
component.myString = "blaze it";
|
||||||
UpdateComponent(componentID, component);
|
UpdateComponent(componentID, component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resultComponent = ReadComponent<MockComponent>().Item2;
|
// this test needs to be improved...
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void UpdateComponent()
|
public void UpdateComponent()
|
||||||
{
|
{
|
||||||
var worldBuilder = new WorldBuilder();
|
var worldBuilder = new WorldBuilder();
|
||||||
worldBuilder.AddEngine(new UpdateComponentTestEngine());
|
worldBuilder.AddEngine(new UpdateComponentTestEngine());
|
||||||
|
worldBuilder.AddEngine(new ReadComponentTestEngine());
|
||||||
|
|
||||||
var entity = worldBuilder.CreateEntity();
|
var entity = worldBuilder.CreateEntity();
|
||||||
|
|
||||||
|
@ -147,7 +149,8 @@ namespace Tests
|
||||||
|
|
||||||
var world = worldBuilder.Build();
|
var world = worldBuilder.Build();
|
||||||
|
|
||||||
world.Update(0.01f);
|
world.Update(0.01);
|
||||||
|
world.Update(0.01);
|
||||||
|
|
||||||
Assert.AreEqual(420, resultComponent.myInt);
|
Assert.AreEqual(420, resultComponent.myInt);
|
||||||
Assert.AreEqual("blaze it", resultComponent.myString);
|
Assert.AreEqual("blaze it", resultComponent.myString);
|
||||||
|
@ -642,5 +645,48 @@ namespace Tests
|
||||||
|
|
||||||
Assert.Throws<ComponentAndMessageWriteException>(() => worldBuilder.AddEngine(new EngineThatWritesComponentAndMessage()));
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue