component removes are treated as priority writes
							parent
							
								
									51a248156e
								
							
						
					
					
						commit
						7885c2e0f4
					
				|  | @ -70,21 +70,34 @@ namespace Encompass | |||
| 
 | ||||
|         public bool Set<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent | ||||
|         { | ||||
|             ComponentBitSet.Set<TComponent>(entity); | ||||
|             return Lookup<TComponent>().Set(entity, component, priority); | ||||
|             if (Lookup<TComponent>().Set(entity, component, priority)) | ||||
|             { | ||||
|                 ComponentBitSet.Set<TComponent>(entity); | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         public void Remove<TComponent>(Entity entity) where TComponent : struct, IComponent | ||||
|         public bool Remove<TComponent>(Entity entity, int priority) where TComponent : struct, IComponent | ||||
|         { | ||||
|             ComponentBitSet.RemoveComponent<TComponent>(entity); | ||||
|             Lookup<TComponent>().Remove(entity); | ||||
|             if (Lookup<TComponent>().Remove(entity, priority)) | ||||
|             { | ||||
|                 ComponentBitSet.RemoveComponent<TComponent>(entity); | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         public void ForceRemove<TComponent>(Entity entity) where TComponent : struct, IComponent | ||||
|         { | ||||
|             Lookup<TComponent>().ForceRemove(entity); | ||||
|         } | ||||
| 
 | ||||
|         public void Remove(Entity entity) | ||||
|         { | ||||
|             foreach (var entry in Stores.Values) | ||||
|             { | ||||
|                 entry.Remove(entity); | ||||
|                 entry.ForceRemove(entity); | ||||
|             } | ||||
|             ComponentBitSet.RemoveEntity(entity); | ||||
|         } | ||||
|  |  | |||
|  | @ -8,7 +8,8 @@ namespace Encompass | |||
|         public abstract int Count { get; } | ||||
|         public abstract IEnumerable<(Entity, Type, IComponent)> AllInterfaceTyped(); | ||||
|         public abstract bool Has(Entity entity); | ||||
|         public abstract void Remove(Entity entity); | ||||
|         public abstract bool Remove(Entity entity, int priority); | ||||
|         public abstract void ForceRemove(Entity entity); | ||||
|         public abstract void Clear(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -40,6 +41,25 @@ namespace Encompass | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         public override bool Remove(Entity entity, int priority) | ||||
|         { | ||||
|             if (!priorities.ContainsKey(entity) || priority < priorities[entity]) | ||||
|             { | ||||
|                 priorities[entity] = priority; | ||||
|                 store.Remove(entity); | ||||
|                 priorities.Remove(entity); | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         public override void ForceRemove(Entity entity) | ||||
|         { | ||||
|             store.Remove(entity); | ||||
|             priorities.Remove(entity); | ||||
|         } | ||||
| 
 | ||||
|         public override bool Has(Entity entity) | ||||
|         { | ||||
|             return store.ContainsKey(entity); | ||||
|  | @ -66,11 +86,5 @@ namespace Encompass | |||
|                 yield return (kvp.Key, typeof(TComponent), (IComponent)kvp.Value); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public override void Remove(Entity entity) | ||||
|         { | ||||
|             store.Remove(entity); | ||||
|             priorities.Remove(entity); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -92,10 +92,24 @@ namespace Encompass | |||
|             entitiesMarkedForRemoval.Clear(); | ||||
|         } | ||||
| 
 | ||||
|         public void Remove<TComponent>(Entity entity) where TComponent : struct, IComponent | ||||
|         public bool RemovePending<TComponent>(Entity entity, int priority) where TComponent : struct, IComponent | ||||
|         { | ||||
|             componentUpdateManager.Remove<TComponent>(entity); | ||||
|             drawLayerManager.UnRegisterComponentWithLayer<TComponent>(entity); | ||||
|             if (componentUpdateManager.RemovePending<TComponent>(entity, priority)) | ||||
|             { | ||||
|                 drawLayerManager.UnRegisterComponentWithLayer<TComponent>(entity); | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         public bool Remove<TComponent>(Entity entity, int priority) where TComponent : struct, IComponent | ||||
|         { | ||||
|             if (componentUpdateManager.Remove<TComponent>(entity, priority)) | ||||
|             { | ||||
|                 drawLayerManager.UnRegisterComponentWithLayer<TComponent>(entity); | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,4 @@ | |||
| using Encompass.Collections; | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| 
 | ||||
|  | @ -8,7 +6,6 @@ namespace Encompass | |||
| { | ||||
|     internal class ComponentUpdateManager | ||||
|     { | ||||
|         private readonly ComponentStore existingAndPendingComponentStore; | ||||
|         private readonly ComponentStore existingComponentStore; | ||||
|         private readonly ComponentStore pendingComponentStore; | ||||
|         private readonly Dictionary<Type, Dictionary<Entity, int>> typeToEntityToPendingComponentPriority = new Dictionary<Type, Dictionary<Entity, int>>(128); | ||||
|  | @ -18,7 +15,6 @@ namespace Encompass | |||
| 
 | ||||
|         public ComponentUpdateManager(Dictionary<Type, int> typeToIndex) | ||||
|         { | ||||
|             existingAndPendingComponentStore = new ComponentStore(typeToIndex); | ||||
|             existingComponentStore = new ComponentStore(typeToIndex); | ||||
|             pendingComponentStore = new ComponentStore(typeToIndex); | ||||
|             UpToDateComponentStore = new ComponentStore(typeToIndex); | ||||
|  | @ -27,7 +23,6 @@ namespace Encompass | |||
| 
 | ||||
|         public void RegisterComponentType<TComponent>() where TComponent : struct, IComponent | ||||
|         { | ||||
|             existingAndPendingComponentStore.RegisterComponentType<TComponent>(); | ||||
|             existingComponentStore.RegisterComponentType<TComponent>(); | ||||
|             pendingComponentStore.RegisterComponentType<TComponent>(); | ||||
|             UpToDateComponentStore.RegisterComponentType<TComponent>(); | ||||
|  | @ -35,7 +30,6 @@ namespace Encompass | |||
| 
 | ||||
|         public void FinishRegistering() | ||||
|         { | ||||
|             existingAndPendingComponentStore.FinishRegistering(); | ||||
|             existingComponentStore.FinishRegistering(); | ||||
|             pendingComponentStore.FinishRegistering(); | ||||
|             UpToDateComponentStore.FinishRegistering(); | ||||
|  | @ -43,7 +37,6 @@ namespace Encompass | |||
| 
 | ||||
|         internal void Clear() | ||||
|         { | ||||
|             existingAndPendingComponentStore.ClearAll(); | ||||
|             existingComponentStore.ClearAll(); | ||||
|             pendingComponentStore.ClearAll(); | ||||
|             UpToDateComponentStore.ClearAll(); | ||||
|  | @ -77,9 +70,19 @@ namespace Encompass | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         internal bool RemovePending<TComponent>(Entity entity, int priority) where TComponent : struct, IComponent | ||||
|         { | ||||
|             UpToDateComponentStore.Remove<TComponent>(entity, priority); | ||||
|             return pendingComponentStore.Remove<TComponent>(entity, priority); | ||||
|         } | ||||
| 
 | ||||
|         internal bool Remove<TComponent>(Entity entity, int priority) where TComponent : struct, IComponent | ||||
|         { | ||||
|             return UpToDateComponentStore.Remove<TComponent>(entity, priority); | ||||
|         } | ||||
| 
 | ||||
|         private void RegisterExistingOrPendingComponentMessage<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent | ||||
|         { | ||||
|             existingAndPendingComponentStore.Set(entity, component); | ||||
|             UpToDateComponentStore.Set(entity, component); | ||||
|         } | ||||
| 
 | ||||
|  | @ -92,7 +95,7 @@ namespace Encompass | |||
| 
 | ||||
|         internal IEnumerable<(TComponent, Entity)> ReadExistingAndPendingComponentsByType<TComponent>() where TComponent : struct, IComponent | ||||
|         { | ||||
|             return existingAndPendingComponentStore.All<TComponent>(); | ||||
|             return UpToDateComponentStore.All<TComponent>(); | ||||
|         } | ||||
| 
 | ||||
|         internal IEnumerable<(TComponent, Entity)> ReadExistingComponentsByType<TComponent>() where TComponent : struct, IComponent | ||||
|  | @ -135,7 +138,7 @@ namespace Encompass | |||
| 
 | ||||
|         internal bool SomeExistingOrPendingComponent<TComponent>() where TComponent : struct, IComponent | ||||
|         { | ||||
|             return existingAndPendingComponentStore.Any<TComponent>(); | ||||
|             return UpToDateComponentStore.Any<TComponent>(); | ||||
|         } | ||||
| 
 | ||||
|         internal bool SomeExistingComponent<TComponent>() where TComponent : struct, IComponent | ||||
|  | @ -164,12 +167,12 @@ namespace Encompass | |||
| 
 | ||||
|         internal bool HasExistingOrPendingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent | ||||
|         { | ||||
|             return existingAndPendingComponentStore.Has<TComponent>(entity); | ||||
|             return UpToDateComponentStore.Has<TComponent>(entity); | ||||
|         } | ||||
| 
 | ||||
|         internal bool HasExistingOrPendingComponent(Entity entity, Type type) | ||||
|         { | ||||
|             return existingAndPendingComponentStore.Has(type, entity); | ||||
|             return UpToDateComponentStore.Has(type, entity); | ||||
|         } | ||||
| 
 | ||||
|         internal bool HasExistingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent | ||||
|  | @ -192,11 +195,6 @@ namespace Encompass | |||
|             return pendingComponentStore.Has(type, entity); | ||||
|         } | ||||
| 
 | ||||
|         internal void Remove<TComponent>(Entity entity) where TComponent : struct, IComponent | ||||
|         { | ||||
|             UpToDateComponentStore.Remove<TComponent>(entity); | ||||
|         } | ||||
| 
 | ||||
|         internal ComponentBitSet PendingBits { get { return pendingComponentStore.ComponentBitSet; } } | ||||
|         internal ComponentBitSet ExistingBits {  get { return existingComponentStore.ComponentBitSet; } } | ||||
|     } | ||||
|  |  | |||
|  | @ -96,7 +96,7 @@ namespace Encompass | |||
|             if (typeToEntityToLayer[typeof(TComponent)].ContainsKey(entity)) | ||||
|             { | ||||
|                 var layer = typeToEntityToLayer[typeof(TComponent)][entity]; | ||||
|                 layerIndexToComponentStore[layer].Remove<TComponent>(entity); | ||||
|                 layerIndexToComponentStore[layer].ForceRemove<TComponent>(entity); | ||||
|             } | ||||
|             typeToEntityToLayer[typeof(TComponent)].Remove(entity); | ||||
|         } | ||||
|  |  | |||
|  | @ -561,12 +561,23 @@ namespace Encompass | |||
|         /// Note that the Engine must Read the Component type that is being removed. | ||||
|         /// If a Component with the specified type does not exist on the Entity, returns false and does not mutate the Entity. | ||||
|         /// </summary> | ||||
|         protected bool RemoveComponent<TComponent>(Entity entity) where TComponent : struct, IComponent | ||||
|         protected void RemoveComponent<TComponent>(Entity entity) where TComponent : struct, IComponent | ||||
|         { | ||||
|             if (!HasComponent<TComponent>(entity)) { return false; } | ||||
|             var priority = writePriorities.ContainsKey(typeof(TComponent)) ? writePriorities[typeof(TComponent)] : defaultWritePriority; | ||||
| 
 | ||||
|             componentManager.Remove<TComponent>(entity); | ||||
|             return true; | ||||
|             if (!writeTypes.Contains(typeof(TComponent))) | ||||
|             { | ||||
|                 throw new IllegalWriteException("Engine {0} tried to remove undeclared Component {1}. Declare with Writes attribute.", GetType().Name, typeof(TComponent).Name); | ||||
|             } | ||||
| 
 | ||||
|             if (writePendingTypes.Contains(typeof(TComponent))) | ||||
|             { | ||||
|                 componentManager.RemovePending<TComponent>(entity, priority); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 componentManager.Remove<TComponent>(entity, priority); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  |  | |||
|  | @ -369,6 +369,7 @@ namespace Tests | |||
| 
 | ||||
|         [Reads(typeof(MockComponent))] | ||||
|         [Receives(typeof(RemoveComponentTestMessage))] | ||||
|         [Writes(typeof(MockComponent))] | ||||
|         class RemoveComponentTestEngine : Engine | ||||
|         { | ||||
|             public override void Update(double dt) | ||||
|  |  | |||
|  | @ -593,7 +593,8 @@ namespace Tests | |||
|             Assert.That(results, Does.Not.Contain((mockComponent, entity))); | ||||
|         } | ||||
| 
 | ||||
|         [Reads(typeof(DestroyerComponent), typeof(MockComponent))] | ||||
|         [Reads(typeof(DestroyerComponent))] | ||||
|         [Writes(typeof(MockComponent))] | ||||
|         class DestroyAndAddComponentEngine : Engine | ||||
|         { | ||||
|             public override void Update(double dt) | ||||
|  | @ -665,6 +666,7 @@ namespace Tests | |||
|         } | ||||
| 
 | ||||
|         [Reads(typeof(MockComponent))] | ||||
|         [Writes(typeof(MockComponent))] | ||||
|         class DelayedMessageEngine : Engine | ||||
|         { | ||||
|             public override void Update(double dt) | ||||
|  | @ -711,6 +713,7 @@ namespace Tests | |||
|         } | ||||
| 
 | ||||
|         [Reads(typeof(MockComponent))] | ||||
|         [Writes(typeof(MockComponent))] | ||||
|         class DelayedMessageIgnoringTimeDilationEngine : Engine | ||||
|         { | ||||
|             public override void Update(double dt) | ||||
|  | @ -754,7 +757,7 @@ namespace Tests | |||
| 
 | ||||
|         [Receives(typeof(MockMessage))] | ||||
|         [WritesPending(typeof(MockComponent))] | ||||
|         [Writes(typeof(MockComponent))] | ||||
|         [Writes(typeof(MockComponent), 1)] | ||||
|         class ActivateComponentEngine : Engine | ||||
|         { | ||||
|             public override void Update(double dt) | ||||
|  | @ -768,6 +771,7 @@ namespace Tests | |||
|         } | ||||
| 
 | ||||
|         [ReadsPending(typeof(MockComponent))] | ||||
|         [Writes(typeof(MockComponent), 0)] | ||||
|         class RemoveComponentEngine : Engine | ||||
|         { | ||||
|             public override void Update(double dt) | ||||
|  | @ -780,17 +784,20 @@ namespace Tests | |||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void EngineAddAndRemoveComponentSameFrame() | ||||
|         public void EngineAddAndRemoveComponentSameFrameWithRemovePriority() | ||||
|         { | ||||
|             var worldBuilder = new WorldBuilder(); | ||||
|             worldBuilder.AddEngine(new ActivateComponentEngine()); | ||||
|             worldBuilder.AddEngine(new RemoveComponentEngine()); | ||||
|             worldBuilder.AddEngine(new ReadComponentsTestEngine()); | ||||
| 
 | ||||
|             worldBuilder.SendMessage(new MockMessage { }); | ||||
| 
 | ||||
|             var world = worldBuilder.Build(); | ||||
| 
 | ||||
|             Assert.DoesNotThrow(() => world.Update(0.01)); | ||||
|             world.Update(0.01); // update again for the read | ||||
|             resultComponents.Should().BeEmpty(); | ||||
|         } | ||||
| 
 | ||||
|         struct DestroyComponentMessage : IMessage { public Entity entity; } | ||||
|  | @ -926,6 +933,7 @@ namespace Tests | |||
|         } | ||||
| 
 | ||||
|         [Reads(typeof(MockComponent))] | ||||
|         [Writes(typeof(MockComponent))] | ||||
|         class RemoveComponentByTypeEngine : Engine | ||||
|         { | ||||
|             public override void Update(double dt) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue