misc backend fixes + more tests
parent
116f424262
commit
dd75a94d18
|
@ -161,8 +161,6 @@ namespace Encompass
|
|||
{
|
||||
MarkForRemoval(componentID);
|
||||
}
|
||||
|
||||
entityIDToComponentIDs.Remove(entityID);
|
||||
}
|
||||
|
||||
internal void MarkForActivation(Guid componentID)
|
||||
|
@ -217,7 +215,7 @@ namespace Encompass
|
|||
componentsToDeactivate.Clear();
|
||||
}
|
||||
|
||||
internal void RemoveMarkedComponents()
|
||||
public void RemoveMarkedComponents()
|
||||
{
|
||||
foreach (var componentID in componentsToRemove)
|
||||
{
|
||||
|
@ -228,7 +226,10 @@ namespace Encompass
|
|||
inactiveComponents.Remove(componentID);
|
||||
|
||||
var entityID = componentIDToEntityID[componentID];
|
||||
entityIDToComponentIDs[entityID].Remove(componentID);
|
||||
if (entityIDToComponentIDs.ContainsKey(entityID))
|
||||
{
|
||||
entityIDToComponentIDs[entityID].Remove(componentID);
|
||||
}
|
||||
|
||||
IDToComponent.Remove(componentID);
|
||||
componentIDToType.Remove(componentID);
|
||||
|
@ -243,5 +244,10 @@ namespace Encompass
|
|||
|
||||
componentsToRemove.Clear();
|
||||
}
|
||||
|
||||
public void RegisterDestroyedEntity(Guid entityID)
|
||||
{
|
||||
entityIDToComponentIDs.Remove(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,19 +17,19 @@ namespace Encompass
|
|||
|
||||
public Engine()
|
||||
{
|
||||
var mutatesAttribute = this.GetType().GetCustomAttribute<Mutates>(false);
|
||||
var mutatesAttribute = GetType().GetCustomAttribute<Mutates>(false);
|
||||
if (mutatesAttribute != null)
|
||||
{
|
||||
mutateComponentTypes = mutatesAttribute.mutateComponentTypes;
|
||||
}
|
||||
|
||||
var emitsAttribute = this.GetType().GetCustomAttribute<Emits>(false);
|
||||
var emitsAttribute = GetType().GetCustomAttribute<Emits>(false);
|
||||
if (emitsAttribute != null)
|
||||
{
|
||||
emitMessageTypes = emitsAttribute.emitMessageTypes;
|
||||
}
|
||||
|
||||
var readsAttribute = this.GetType().GetCustomAttribute<Reads>(false);
|
||||
var readsAttribute = GetType().GetCustomAttribute<Reads>(false);
|
||||
if (readsAttribute != null)
|
||||
{
|
||||
readMessageTypes = readsAttribute.readMessageTypes;
|
||||
|
@ -55,24 +55,34 @@ namespace Encompass
|
|||
|
||||
protected Entity CreateEntity()
|
||||
{
|
||||
return this.entityManager.CreateEntity();
|
||||
return entityManager.CreateEntity();
|
||||
}
|
||||
|
||||
protected Entity GetEntity(Guid entityID)
|
||||
{
|
||||
return entityManager.GetEntity(entityID);
|
||||
}
|
||||
|
||||
protected Guid GetEntityIDFromComponentID(Guid componentID)
|
||||
{
|
||||
return componentManager.GetEntityIDFromComponentID(componentID);
|
||||
}
|
||||
|
||||
protected IEnumerable<KeyValuePair<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
|
||||
{
|
||||
return this.componentManager.GetActiveComponentsByType<TComponent>();
|
||||
return componentManager.GetActiveComponentsByType<TComponent>();
|
||||
}
|
||||
|
||||
protected KeyValuePair<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
|
||||
{
|
||||
return this.componentManager.GetActiveComponentByType<TComponent>();
|
||||
return componentManager.GetActiveComponentByType<TComponent>();
|
||||
}
|
||||
|
||||
internal void UpdateComponentInWorld<TComponent>(Guid componentID, TComponent newComponent) where TComponent : struct, IComponent
|
||||
{
|
||||
if (mutateComponentTypes.Contains(typeof(TComponent)))
|
||||
{
|
||||
this.componentManager.UpdateComponent(componentID, newComponent);
|
||||
componentManager.UpdateComponent(componentID, newComponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -82,14 +92,14 @@ namespace Encompass
|
|||
|
||||
protected void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent
|
||||
{
|
||||
this.UpdateComponentInWorld(componentID, newComponentValue);
|
||||
UpdateComponentInWorld(componentID, newComponentValue);
|
||||
}
|
||||
|
||||
protected void EmitMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
|
||||
{
|
||||
if (emitMessageTypes.Contains(typeof(TMessage)))
|
||||
{
|
||||
this.messageManager.AddMessage(message);
|
||||
messageManager.AddMessage(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -101,7 +111,7 @@ namespace Encompass
|
|||
{
|
||||
if (readMessageTypes.Contains(typeof(TMessage)))
|
||||
{
|
||||
return this.messageManager.GetMessagesByType<TMessage>();
|
||||
return messageManager.GetMessagesByType<TMessage>();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -120,5 +130,10 @@ namespace Encompass
|
|||
throw new IllegalMessageReadException("Engine {0} tried to read undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
|
||||
}
|
||||
}
|
||||
|
||||
protected void Destroy(Guid entityID)
|
||||
{
|
||||
entityManager.MarkForDestroy(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace Encompass
|
|||
entity.RemoveAllComponents();
|
||||
IDToEntity.Remove(entityID);
|
||||
entityToEntityTrackers.Remove(entityID);
|
||||
componentManager.RegisterDestroyedEntity(entityID);
|
||||
}
|
||||
|
||||
entitiesMarkedForDestroy.Clear();
|
||||
|
|
|
@ -357,5 +357,60 @@ namespace Tests
|
|||
|
||||
Assert.That(emptyComponentReadResult, Is.Empty);
|
||||
}
|
||||
|
||||
struct DestroyerComponent : IComponent { }
|
||||
|
||||
class DestroyerEngine : Engine
|
||||
{
|
||||
public override void Update(float dt)
|
||||
{
|
||||
var componentPairs = ReadComponents<DestroyerComponent>();
|
||||
|
||||
foreach (var componentPair in componentPairs)
|
||||
{
|
||||
var componentID = componentPair.Key;
|
||||
var entityID = GetEntityIDFromComponentID(componentID);
|
||||
Destroy(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerable<KeyValuePair<Guid, MockComponent>> results;
|
||||
class ReaderEngine : Engine
|
||||
{
|
||||
public override void Update(float dt)
|
||||
{
|
||||
results = ReadComponents<MockComponent>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DestroyEntity()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
worldBuilder.AddEngine<DestroyerEngine>();
|
||||
worldBuilder.AddEngine<ReaderEngine>();
|
||||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
var entityB = worldBuilder.CreateEntity();
|
||||
|
||||
DestroyerComponent destroyerComponent;
|
||||
MockComponent mockComponent;
|
||||
mockComponent.myInt = 2;
|
||||
mockComponent.myString = "blah";
|
||||
|
||||
entity.AddComponent(destroyerComponent);
|
||||
var componentID = entity.AddComponent(mockComponent);
|
||||
|
||||
entityB.AddComponent(destroyerComponent);
|
||||
var componentBID = entityB.AddComponent(mockComponent);
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
world.Update(0.01f);
|
||||
|
||||
Assert.That(results, Does.Not.Contain(new KeyValuePair<Guid, MockComponent>(componentID, mockComponent)));
|
||||
Assert.That(results, Does.Not.Contain(new KeyValuePair<Guid, MockComponent>(componentBID, mockComponent)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
using NUnit.Framework;
|
||||
using FluentAssertions;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using Encompass;
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
public class WorldTest
|
||||
{
|
||||
struct TestComponent : IComponent { }
|
||||
struct TestDrawComponent : IDrawComponent
|
||||
{
|
||||
public int Layer { get ; set; }
|
||||
}
|
||||
|
||||
static List<object> drawOrder = new List<object>();
|
||||
|
||||
[Renders(typeof(TestDrawComponent), typeof(TestComponent))]
|
||||
class TestEntityRenderer : EntityRenderer
|
||||
{
|
||||
public override void Render(Entity entity)
|
||||
{
|
||||
drawOrder.Add(entity);
|
||||
}
|
||||
}
|
||||
|
||||
class TestGeneralRenderer : GeneralRenderer
|
||||
{
|
||||
public new int Layer { get { return 9; } }
|
||||
|
||||
public override void Render()
|
||||
{
|
||||
drawOrder.Add(this);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DrawOrder()
|
||||
{
|
||||
var worldBuilder = new WorldBuilder();
|
||||
worldBuilder.AddRenderer<TestEntityRenderer>();
|
||||
var testGeneralRenderer = worldBuilder.AddRenderer<TestGeneralRenderer>();
|
||||
|
||||
TestComponent testComponent;
|
||||
TestDrawComponent testDrawComponent = default(TestDrawComponent);
|
||||
testDrawComponent.Layer = 3;
|
||||
|
||||
var entity = worldBuilder.CreateEntity();
|
||||
entity.AddComponent(testComponent);
|
||||
entity.AddComponent(testDrawComponent);
|
||||
|
||||
TestDrawComponent testDrawComponentTwo = default(TestDrawComponent);
|
||||
testDrawComponentTwo.Layer = 1;
|
||||
|
||||
var entityTwo = worldBuilder.CreateEntity();
|
||||
entityTwo.AddComponent(testComponent);
|
||||
entityTwo.AddComponent(testDrawComponentTwo);
|
||||
|
||||
TestDrawComponent testDrawComponentThree = default(TestDrawComponent);
|
||||
testDrawComponentThree.Layer = 5;
|
||||
|
||||
var entityThree = worldBuilder.CreateEntity();
|
||||
entityThree.AddComponent(testComponent);
|
||||
entityThree.AddComponent(testDrawComponentThree);
|
||||
|
||||
TestDrawComponent testDrawComponentFour = default(TestDrawComponent);
|
||||
testDrawComponentFour.Layer = -5;
|
||||
|
||||
var entityFour = worldBuilder.CreateEntity();
|
||||
entityFour.AddComponent(testComponent);
|
||||
entityFour.AddComponent(testDrawComponentFour);
|
||||
|
||||
var world = worldBuilder.Build();
|
||||
|
||||
world.Update(0.01f);
|
||||
world.Draw();
|
||||
|
||||
drawOrder.Should().BeEquivalentTo(entityFour, entityTwo, entity, entityThree, testGeneralRenderer);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue