component updates at end of frame
							parent
							
								
									ca82fa82cf
								
							
						
					
					
						commit
						a62153730f
					
				|  | @ -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) | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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(); | ||||
|             entityManager.DestroyMarkedEntities(); | ||||
| 
 | ||||
|             componentManager.PerformComponentUpdates(); | ||||
|             componentManager.ActivateMarkedComponents(); | ||||
|             componentManager.DeactivateMarkedComponents(); | ||||
|             componentManager.RemoveMarkedComponents(); | ||||
|  |  | |||
|  | @ -224,6 +224,7 @@ namespace Encompass | |||
|                 renderManager | ||||
|             ); | ||||
| 
 | ||||
|             componentManager.PerformComponentUpdates(); | ||||
|             componentManager.ActivateMarkedComponents(); | ||||
|             componentManager.DeactivateMarkedComponents(); | ||||
|             componentManager.RemoveMarkedComponents(); | ||||
|  |  | |||
|  | @ -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)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue