using System; using System.Collections.Generic; namespace Encompass { internal class ComponentManager { private readonly ComponentStore _existingComponentStore; private readonly ComponentStore _immediateComponentStore; private readonly ComponentDeltaStore _replayStore; private readonly ComponentStore _upToDateComponentStore; public Dictionary TypeToIndex { get; } private Dictionary IndexToType { get; } private readonly HashSet _entitiesMarkedForRemoval = new HashSet(); internal ComponentBitSet ImmediateBits { get { return _immediateComponentStore.ComponentBitSet; } } internal ComponentBitSet ExistingBits { get { return _existingComponentStore.ComponentBitSet; } } public ComponentManager(Dictionary typeToIndex, Dictionary indexToType) { _existingComponentStore = new ComponentStore(typeToIndex); _immediateComponentStore = new ComponentStore(typeToIndex); _replayStore = new ComponentDeltaStore(typeToIndex); _upToDateComponentStore = new ComponentStore(typeToIndex); TypeToIndex = typeToIndex; IndexToType = indexToType; } public void RegisterComponentType() where TComponent : struct { _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 WriteComponents() { _existingComponentStore.UpdateUsing(_replayStore); _existingComponentStore.ClearAllPriorities(); _upToDateComponentStore.ClearAllPriorities(); _immediateComponentStore.ClearAll(); _replayStore.ClearAll(); } internal bool AddImmediateComponent(int entityID, in TComponent component, int priority) where TComponent : struct { if (_immediateComponentStore.Set(entityID, component, priority)) { _replayStore.Set(entityID, component); _upToDateComponentStore.Set(entityID, component); return true; } return false; } internal void AddImmediateComponent(int entityID, in TComponent component) where TComponent : struct { _immediateComponentStore.Set(entityID, component); _replayStore.Set(entityID, component); _upToDateComponentStore.Set(entityID, component); } internal bool UpdateComponent(int entityID, in TComponent component, int priority) where TComponent : struct { var result = _upToDateComponentStore.Set(entityID, component, priority); if (result) { _replayStore.Set(entityID, component); } return result; } #if DEBUG internal void Debug_UpdateComponent(int entityID, in TComponent component) where TComponent : struct { _existingComponentStore.Set(entityID, component); } #endif internal void AddComponent(int entityID, in TComponent component) where TComponent : struct { _upToDateComponentStore.Set(entityID, component); _replayStore.Set(entityID, component); } // existing or immediate reads internal ReadOnlySpan ReadExistingAndImmediateComponentsByType() where TComponent : struct { return _upToDateComponentStore.All(); } internal ref readonly TComponent ExistingOrImmediateSingular() where TComponent : struct { return ref _upToDateComponentStore.Singular(); } internal ReadOnlySpan GetExistingAndImmediateEntities() where TComponent : struct { return _upToDateComponentStore.AllEntities(); } internal ref readonly Entity ExistingOrImmediateSingularEntity() where TComponent : struct { return ref _upToDateComponentStore.SingularEntity(); } internal bool SomeExistingOrImmediateComponent() where TComponent : struct { return _upToDateComponentStore.Any(); } // existing reads internal ReadOnlySpan GetExistingComponents() where TComponent : struct { return _existingComponentStore.All(); } internal ref readonly TComponent ExistingSingular() where TComponent : struct { return ref _existingComponentStore.Singular(); } internal ReadOnlySpan GetExistingEntities() where TComponent : struct { return _existingComponentStore.AllEntities(); } internal IEnumerable GetExistingEntitiesAsEnumerable() where TComponent : struct { return _existingComponentStore.AllEntitiesAsEnumerable(); } internal ref readonly Entity ExistingSingularEntity() where TComponent : struct { return ref _existingComponentStore.SingularEntity(); } internal bool SomeExistingComponent() where TComponent : struct { return _existingComponentStore.Any(); } // immediate reads internal ReadOnlySpan ReadImmediateComponentsByType() where TComponent : struct { return _immediateComponentStore.All(); } internal ref readonly TComponent ImmediateSingular() where TComponent : struct { return ref _immediateComponentStore.Singular(); } internal ReadOnlySpan GetImmediateEntities() where TComponent : struct { return _immediateComponentStore.AllEntities(); } internal ref readonly Entity ImmediateSingularEntity() where TComponent : struct { return ref _immediateComponentStore.SingularEntity(); } internal bool SomeImmediateComponent() where TComponent : struct { return _immediateComponentStore.Any(); } // component getters internal ref TComponent ReadImmediateOrExistingComponentByEntityAndType(int entityID) where TComponent : struct { return ref _upToDateComponentStore.Get(entityID); } internal ref TComponent ReadExistingComponentByEntityAndType(int entityID) where TComponent : struct { return ref _existingComponentStore.Get(entityID); } #if DEBUG internal TComponent Debug_ReadExistingComponentByEntityAndType(int entityID) where TComponent : struct { return _existingComponentStore.Get(entityID); } #endif internal ref TComponent ReadImmediateComponentByEntityAndType(int entityID) where TComponent : struct { return ref _immediateComponentStore.Get(entityID); } // has checkers internal bool HasExistingOrImmediateComponent(int entityID) where TComponent : struct { return _upToDateComponentStore.Has(entityID); } internal bool HasExistingOrImmediateComponent(int entityID, Type type) { return _upToDateComponentStore.Has(type, entityID); } internal bool HasExistingComponent(int entityID) where TComponent : struct { return _existingComponentStore.Has(entityID); } internal bool HasExistingComponent(int entityID, Type type) { return _existingComponentStore.Has(type, entityID); } internal bool HasImmediateComponent(int entityID) where TComponent : struct { return _immediateComponentStore.Has(entityID); } internal bool HasImmediateComponent(int entityID, Type type) { return _immediateComponentStore.Has(type, entityID); } internal ReadOnlySpan GetComponentsByType() where TComponent : struct { return _existingComponentStore.All(); } internal IEnumerable GetComponentsByTypeEnumerable() where TComponent : struct { return _existingComponentStore.AllAsEnumerable(); } internal ref readonly TComponent GetComponentByEntityAndType(int entityID) where TComponent : struct { return ref _existingComponentStore.Get(entityID); } internal bool EntityHasComponentOfType(int entityID) where TComponent : struct { 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); } _entitiesMarkedForRemoval.Clear(); } public bool RemoveImmediate(int entityID, int priority) where TComponent : struct { if (_immediateComponentStore.Remove(entityID, priority)) { _replayStore.Remove(entityID, priority); _upToDateComponentStore.Remove(entityID, priority); return true; } return false; } public void Remove(int entityID, int priority) where TComponent : struct { if (_upToDateComponentStore.Remove(entityID, priority)) { _replayStore.Remove(entityID, priority); } } public bool UpToDateEntityIsEmpty(int entityID) { return _upToDateComponentStore.EntityBitArray(entityID).AllFalse(); } // should be used for debugging only! #if DEBUG internal IEnumerable Debug_Components(int entityID) { foreach (var typeIndex in ExistingBits.EntityBitArray(entityID).TrueIndices()) { var method = typeof(ComponentManager).GetMethod(nameof(ComponentManager.Debug_ReadExistingComponentByEntityAndType), System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var generic = method.MakeGenericMethod(IndexToType[typeIndex]); yield return generic.Invoke(this, new object[] { entityID }); } } internal IEnumerable Debug_SearchComponentType(string typeString) { foreach (var type in TypeToIndex.Keys) { if (type.ToString().ToLower().Contains(typeString.ToLower())) { yield return type; } } } #endif } }