using System; using System.Collections.Generic; namespace Encompass { internal class ComponentManager { private readonly DrawLayerManager _drawLayerManager; private readonly ComponentStore _existingComponentStore; private readonly ComponentStore _immediateComponentStore; private readonly ComponentDeltaStore _replayStore; private readonly ComponentStore _upToDateComponentStore; public Dictionary TypeToIndex { get; } private readonly HashSet _entitiesMarkedForRemoval = new HashSet(); internal ComponentBitSet ImmediateBits { get { return _immediateComponentStore.ComponentBitSet; } } internal ComponentBitSet ExistingBits { get { return _existingComponentStore.ComponentBitSet; } } public ComponentManager(DrawLayerManager drawLayerManager, Dictionary typeToIndex) { this._drawLayerManager = drawLayerManager; _existingComponentStore = new ComponentStore(typeToIndex); _immediateComponentStore = new ComponentStore(typeToIndex); _replayStore = new ComponentDeltaStore(typeToIndex); _upToDateComponentStore = new ComponentStore(typeToIndex); TypeToIndex = typeToIndex; } public void RegisterComponentType() where TComponent : unmanaged { _existingComponentStore.RegisterComponentType(); _immediateComponentStore.RegisterComponentType(); _replayStore.RegisterComponentType(); _upToDateComponentStore.RegisterComponentType(); } internal void SetExistingComponentStore(ComponentStore componentStore) { _existingComponentStore.SwapWith(componentStore); } internal void SetUpToDateComponentStore(ComponentStore componentStore) { _upToDateComponentStore.SwapWith(componentStore); } internal void RegisterDrawableComponent(int entityID, int layer) where TComponent : unmanaged { _drawLayerManager.RegisterComponentWithLayer(entityID, layer); } internal void WriteComponents() { _existingComponentStore.UpdateUsing(_replayStore); _existingComponentStore.ClearAllPriorities(); _upToDateComponentStore.ClearAllPriorities(); _immediateComponentStore.ClearAll(); _replayStore.ClearAll(); } internal bool AddImmediateComponent(int entityID, TComponent component, int priority) where TComponent : unmanaged { if (_immediateComponentStore.Set(entityID, component, priority)) { _replayStore.Set(entityID, component); _upToDateComponentStore.Set(entityID, component); return true; } return false; } internal void AddImmediateComponent(int entityID, TComponent component) where TComponent : unmanaged { _immediateComponentStore.Set(entityID, component); _replayStore.Set(entityID, component); _upToDateComponentStore.Set(entityID, component); } internal bool UpdateComponent(int entityID, TComponent component, int priority) where TComponent : unmanaged { var result = _upToDateComponentStore.Set(entityID, component, priority); if (result) { _replayStore.Set(entityID, component); } return result; } internal void AddComponent(int entityID, TComponent component) where TComponent : unmanaged { _upToDateComponentStore.Set(entityID, component); _replayStore.Set(entityID, component); } // existing or immediate reads internal IEnumerable<(TComponent, int)> ReadExistingAndImmediateComponentsByType() where TComponent : unmanaged { return _upToDateComponentStore.All(); } internal (TComponent, int) ReadFirstExistingOrImmediateComponentByType() where TComponent : unmanaged { if (!SomeExistingOrImmediateComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadExistingAndImmediateComponentsByType().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } internal bool SomeExistingOrImmediateComponent() where TComponent : unmanaged { return _upToDateComponentStore.Any(); } // existing reads internal (TComponent, int) ReadFirstExistingComponentByType() where TComponent : unmanaged { if (!SomeExistingComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = GetComponentsIncludingEntity().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } internal bool SomeExistingComponent() where TComponent : unmanaged { return _existingComponentStore.Any(); } // immediate reads internal IEnumerable<(TComponent, int)> ReadImmediateComponentsByType() where TComponent : unmanaged { return _immediateComponentStore.All(); } internal (TComponent, int) ReadFirstImmediateComponentByType() where TComponent : unmanaged { if (!SomeImmediateComponent()) { throw new Exceptions.NoComponentOfTypeException($"No Component with type {typeof(TComponent)} exists"); } var enumerator = ReadImmediateComponentsByType().GetEnumerator(); enumerator.MoveNext(); return enumerator.Current; } internal bool SomeImmediateComponent() where TComponent : unmanaged { return _immediateComponentStore.Any(); } // component getters internal ref readonly TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : unmanaged { return ref _upToDateComponentStore.Get(entityID); } internal ref readonly TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : unmanaged { return ref _existingComponentStore.Get(entityID); } internal ref readonly TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : unmanaged { return ref _immediateComponentStore.Get(entityID); } // has checkers internal bool HasExistingOrImmediateComponent(int entityID) where TComponent : unmanaged { return _upToDateComponentStore.Has(entityID); } internal bool HasExistingOrImmediateComponent(int entityID, Type type) { return _upToDateComponentStore.Has(type, entityID); } internal bool HasExistingComponent(int entityID) where TComponent : unmanaged { return _existingComponentStore.Has(entityID); } internal bool HasExistingComponent(int entityID, Type type) { return _existingComponentStore.Has(type, entityID); } internal bool HasImmediateComponent(int entityID) where TComponent : unmanaged { return _immediateComponentStore.Has(entityID); } internal bool HasImmediateComponent(int entityID, Type type) { return _immediateComponentStore.Has(type, entityID); } internal IEnumerable<(TComponent, int)> GetComponentsIncludingEntity() where TComponent : unmanaged { return _existingComponentStore.All(); } internal IEnumerable GetComponentsByType() where TComponent : unmanaged { foreach (var pair in _existingComponentStore.All()) { yield return pair.Item1; } } internal ref readonly TComponent GetComponentByEntityAndType(int entityID) where TComponent : unmanaged { return ref _existingComponentStore.Get(entityID); } internal bool EntityHasComponentOfType(int entityID) where TComponent : unmanaged { return _existingComponentStore.Has(entityID); } internal void MarkAllComponentsOnEntityForRemoval(int entityID) { _entitiesMarkedForRemoval.Add(entityID); } internal void RemoveMarkedComponents() { foreach (var entityID in _entitiesMarkedForRemoval) { _existingComponentStore.Remove(entityID); _immediateComponentStore.Remove(entityID); _replayStore.Remove(entityID); _upToDateComponentStore.Remove(entityID); _drawLayerManager.UnRegisterEntityWithLayer(entityID); } _entitiesMarkedForRemoval.Clear(); } public bool RemoveImmediate(int entityID, int priority) where TComponent : unmanaged { if (_immediateComponentStore.Remove(entityID, priority)) { _replayStore.Remove(entityID, priority); _upToDateComponentStore.Remove(entityID, priority); _drawLayerManager.UnRegisterComponentWithLayer(entityID); return true; } return false; } public void Remove(int entityID, int priority) where TComponent : unmanaged { if (_upToDateComponentStore.Remove(entityID, priority)) { _replayStore.Remove(entityID, priority); _drawLayerManager.UnRegisterComponentWithLayer(entityID); } } public bool UpToDateEntityIsEmpty(int entityID) { return _upToDateComponentStore.EntityBitArray(entityID).AllFalse(); } } }