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