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