encompass-cs/encompass-cs/ComponentUpdateManager.cs

276 lines
11 KiB
C#
Raw Normal View History

using System;
2019-12-22 09:15:58 +00:00
using System.Collections;
using System.Collections.Generic;
2019-12-22 09:15:58 +00:00
using System.Linq;
2019-08-02 00:34:54 +00:00
namespace Encompass
{
internal class ComponentUpdateManager
{
2019-12-22 09:15:58 +00:00
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);
2019-12-22 09:15:58 +00:00
private Dictionary<Type, int> typeToIndex;
public ComponentStore UpToDateComponentStore { get; private set; }
2019-12-22 19:54:37 +00:00
// bitarray references to avoid garbage collection
BitArray pendingMask;
BitArray readMask;
BitArray withMask;
BitArray withoutMask;
BitArray notWithMask;
BitArray solverArrayA;
BitArray solverArrayB;
BitArray solverArrayC;
2019-12-22 09:15:58 +00:00
public ComponentUpdateManager(Dictionary<Type, int> typeToIndex)
{
existingAndPendingComponentStore = new ComponentStore(typeToIndex);
existingComponentStore = new ComponentStore(typeToIndex);
pendingComponentStore = new ComponentStore(typeToIndex);
UpToDateComponentStore = new ComponentStore(typeToIndex);
this.typeToIndex = typeToIndex;
}
2019-12-05 22:59:55 +00:00
2019-12-16 07:28:02 +00:00
public void RegisterComponentType<TComponent>() where TComponent : struct, IComponent
{
existingAndPendingComponentStore.RegisterComponentType<TComponent>();
existingComponentStore.RegisterComponentType<TComponent>();
pendingComponentStore.RegisterComponentType<TComponent>();
2019-12-17 02:51:45 +00:00
UpToDateComponentStore.RegisterComponentType<TComponent>();
2019-12-16 07:28:02 +00:00
}
public void FinishRegistering()
{
existingAndPendingComponentStore.FinishRegistering();
existingComponentStore.FinishRegistering();
pendingComponentStore.FinishRegistering();
UpToDateComponentStore.FinishRegistering();
2019-12-22 19:54:37 +00:00
pendingMask = new BitArray(typeToIndex.Count);
readMask = new BitArray(typeToIndex.Count);
withMask = new BitArray(typeToIndex.Count);
withoutMask = new BitArray(typeToIndex.Count);
notWithMask = new BitArray(typeToIndex.Count);
solverArrayA = new BitArray(typeToIndex.Count);
solverArrayB = new BitArray(typeToIndex.Count);
solverArrayC = new BitArray(typeToIndex.Count);
}
internal void Clear()
2019-08-01 23:24:57 +00:00
{
existingAndPendingComponentStore.ClearAll();
2019-12-05 20:10:33 +00:00
existingComponentStore.ClearAll();
pendingComponentStore.ClearAll();
2019-12-06 03:55:17 +00:00
UpToDateComponentStore.ClearAll();
foreach (var dictionary in typeToEntityToPendingComponentPriority.Values)
{
dictionary.Clear();
}
2019-08-01 23:24:57 +00:00
}
internal void SetStartingComponentStore(ComponentStore componentStore)
{
UpToDateComponentStore = componentStore;
}
2019-12-06 03:55:17 +00:00
internal void AddExistingComponent<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
2019-12-06 03:55:17 +00:00
RegisterExistingOrPendingComponentMessage(entity, component);
2019-08-01 23:24:57 +00:00
2019-12-06 03:55:17 +00:00
existingComponentStore.Set(entity, component);
2019-08-01 23:24:57 +00:00
}
internal bool AddPendingComponent<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
2019-12-06 03:55:17 +00:00
if (pendingComponentStore.Set(entity, component, priority))
2019-12-05 22:59:55 +00:00
{
2019-12-06 03:55:17 +00:00
RegisterExistingOrPendingComponentMessage(entity, component);
return true;
2019-12-05 22:59:55 +00:00
}
return false;
2019-08-01 23:24:57 +00:00
}
2019-12-05 20:10:33 +00:00
private void RegisterExistingOrPendingComponentMessage<TComponent>(Entity entity, TComponent component) where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
existingAndPendingComponentStore.Set(entity, component);
UpToDateComponentStore.Set(entity, component);
2019-12-05 23:14:28 +00:00
}
public bool UpdateComponent<TComponent>(Entity entity, TComponent component, int priority) where TComponent : struct, IComponent
2019-12-05 23:14:28 +00:00
{
return UpToDateComponentStore.Set<TComponent>(entity, component, priority);
2019-08-01 23:24:57 +00:00
}
// general component reads by type
2019-12-17 04:40:15 +00:00
internal IEnumerable<(TComponent, Entity)> ReadExistingAndPendingComponentsByType<TComponent>() where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
return existingAndPendingComponentStore.All<TComponent>();
2019-08-01 23:24:57 +00:00
}
2019-12-17 04:40:15 +00:00
internal IEnumerable<(TComponent, Entity)> ReadExistingComponentsByType<TComponent>() where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
2019-12-05 20:10:33 +00:00
return existingComponentStore.All<TComponent>();
2019-08-01 23:24:57 +00:00
}
2019-12-17 04:40:15 +00:00
internal IEnumerable<(TComponent, Entity)> ReadPendingComponentsByType<TComponent>() where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
2019-12-05 20:10:33 +00:00
return pendingComponentStore.All<TComponent>();
2019-08-01 23:24:57 +00:00
}
// singular component reads by type
2019-12-17 04:40:15 +00:00
internal (TComponent, Entity) ReadFirstExistingOrPendingComponentByType<TComponent>() where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
if (!SomeExistingOrPendingComponent<TComponent>()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); }
2019-12-17 04:40:15 +00:00
var enumerator = ReadExistingAndPendingComponentsByType<TComponent>().GetEnumerator();
enumerator.MoveNext();
return enumerator.Current;
2019-08-01 23:24:57 +00:00
}
2019-12-17 04:40:15 +00:00
internal (TComponent, Entity) ReadFirstExistingComponentByType<TComponent>() where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
if (!SomeExistingComponent<TComponent>()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); }
2019-12-17 04:40:15 +00:00
var enumerator = ReadExistingComponentsByType<TComponent>().GetEnumerator();
enumerator.MoveNext();
return enumerator.Current;
2019-08-01 23:24:57 +00:00
}
2019-12-17 04:40:15 +00:00
internal (TComponent, Entity) ReadFirstPendingComponentByType<TComponent>() where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
if (!SomePendingComponent<TComponent>()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); }
2019-12-17 04:40:15 +00:00
var enumerator = ReadPendingComponentsByType<TComponent>().GetEnumerator();
enumerator.MoveNext();
return enumerator.Current;
2019-08-01 23:24:57 +00:00
}
// check if some component of type exists in the world
internal bool SomeExistingOrPendingComponent<TComponent>() where TComponent : struct, IComponent
{
return existingAndPendingComponentStore.Any<TComponent>();
2019-08-01 23:24:57 +00:00
}
internal bool SomeExistingComponent<TComponent>() where TComponent : struct, IComponent
{
2019-12-05 20:10:33 +00:00
return existingComponentStore.Any<TComponent>();
2019-08-01 23:24:57 +00:00
}
internal bool SomePendingComponent<TComponent>() where TComponent : struct, IComponent
{
2019-12-05 20:10:33 +00:00
return pendingComponentStore.Any<TComponent>();
2019-08-01 23:24:57 +00:00
}
// read components by entity and type
2019-12-05 20:10:33 +00:00
internal TComponent ReadExistingComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
2019-12-05 20:10:33 +00:00
return existingComponentStore.Get<TComponent>(entity);
2019-08-01 23:24:57 +00:00
}
2019-12-05 20:10:33 +00:00
internal TComponent ReadPendingComponentByEntityAndType<TComponent>(Entity entity) where TComponent : struct, IComponent
2019-08-01 23:24:57 +00:00
{
2019-12-05 20:10:33 +00:00
return pendingComponentStore.Get<TComponent>(entity);
2019-08-01 23:24:57 +00:00
}
// check if entity has component of type
internal bool HasExistingOrPendingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
{
return existingAndPendingComponentStore.Has<TComponent>(entity);
2019-08-01 23:24:57 +00:00
}
2019-11-13 21:15:43 +00:00
internal bool HasExistingOrPendingComponent(Entity entity, Type type)
{
return existingAndPendingComponentStore.Has(type, entity);
2019-11-13 21:15:43 +00:00
}
2019-08-01 23:24:57 +00:00
internal bool HasExistingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
{
2019-12-05 20:10:33 +00:00
return existingComponentStore.Has<TComponent>(entity);
2019-08-01 23:24:57 +00:00
}
2019-11-13 21:15:43 +00:00
internal bool HasExistingComponent(Entity entity, Type type)
{
2019-12-05 20:10:33 +00:00
return existingComponentStore.Has(type, entity);
2019-11-13 21:15:43 +00:00
}
2019-08-01 23:24:57 +00:00
internal bool HasPendingComponent<TComponent>(Entity entity) where TComponent : struct, IComponent
{
2019-12-05 20:10:33 +00:00
return pendingComponentStore.Has<TComponent>(entity);
2019-08-01 23:24:57 +00:00
}
2019-11-13 21:15:43 +00:00
internal bool HasPendingComponent(Entity entity, Type type)
{
2019-12-05 20:10:33 +00:00
return pendingComponentStore.Has(type, entity);
}
2019-12-05 23:14:28 +00:00
internal void Remove<TComponent>(Entity entity) where TComponent : struct, IComponent
{
UpToDateComponentStore.Remove<TComponent>(entity);
2019-12-05 23:14:28 +00:00
}
2019-12-22 09:15:58 +00:00
internal IEnumerable<Entity> QueryEntities(IEnumerable<Entity> entities, HashSet<Type> readTypes, HashSet<Type> readPendingTypes, IEnumerable<Type> withTypes, IEnumerable<Type> withoutTypes)
{
2019-12-22 19:54:37 +00:00
pendingMask.SetAll(false);
2019-12-22 09:15:58 +00:00
foreach (var type in readPendingTypes)
{
pendingMask.Set(typeToIndex[type], true);
}
2019-12-22 19:54:37 +00:00
readMask.SetAll(false);
2019-12-22 09:15:58 +00:00
foreach (var type in readTypes)
{
readMask.Set(typeToIndex[type], true);
}
2019-12-22 19:54:37 +00:00
withMask.SetAll(false);
2019-12-22 09:15:58 +00:00
foreach (var type in withTypes)
{
withMask.Set(typeToIndex[type], true);
}
2019-12-22 19:54:37 +00:00
withoutMask.SetAll(false);
2019-12-22 09:15:58 +00:00
foreach (var type in withoutTypes)
{
withoutMask.Set(typeToIndex[type], true);
}
2019-12-22 19:54:37 +00:00
notWithMask.SetAll(false);
notWithMask.Or(withMask).Not();
2019-12-22 09:15:58 +00:00
foreach (var entity in entities)
{
var pendingEntity = pendingComponentStore.EntityBitArray(entity);
var existingEntity = existingComponentStore.EntityBitArray(entity);
2019-12-22 19:54:37 +00:00
if (VerifyTypes(pendingEntity, existingEntity, readMask, pendingMask, withMask, withoutMask, notWithMask)) { yield return entity; }
2019-12-22 09:15:58 +00:00
}
}
2019-12-22 19:54:37 +00:00
internal bool VerifyTypes(BitArray pendingEntity, BitArray existingEntity, BitArray readMask, BitArray pendingMask, BitArray withMask, BitArray withoutMask, BitArray notWithMask)
2019-12-22 09:15:58 +00:00
{
2019-12-22 19:54:37 +00:00
solverArrayA.SetAll(false);
solverArrayB.SetAll(false);
solverArrayC.SetAll(false);
2019-12-22 09:15:58 +00:00
2019-12-22 19:54:37 +00:00
solverArrayA.Or(pendingMask).And(withMask).And(pendingEntity);
solverArrayB.Or(readMask).And(withMask).And(existingEntity);
solverArrayA.Or(solverArrayB).Or(notWithMask);
2019-12-22 09:15:58 +00:00
2019-12-22 19:54:37 +00:00
solverArrayB.SetAll(false);
solverArrayB.Or(pendingMask).And(withoutMask).And(pendingEntity).Not();
solverArrayC.Or(readMask).And(withoutMask).And(existingEntity).Not();
solverArrayB.And(solverArrayC);
2019-12-22 09:15:58 +00:00
2019-12-22 19:54:37 +00:00
solverArrayA.And(solverArrayB);
2019-12-22 09:15:58 +00:00
2019-12-22 19:54:37 +00:00
return !solverArrayA.Cast<bool>().Contains(false);
2019-12-22 09:15:58 +00:00
}
}
}