using System; using System.Collections.Generic; using System.Linq; using Encompass.Exceptions; namespace Encompass { internal class DrawLayerManager { private readonly SortedList _layerOrder = new SortedList(); private readonly Dictionary>> _layerIndexToTypeToID = new Dictionary>>(); private readonly Dictionary> _layerIndexToGeneralRenderers = new Dictionary>(512); private readonly Dictionary> _typeToEntityToLayer = new Dictionary>(512); public IEnumerable LayerOrder { get { return _layerOrder.Values; } } public DrawLayerManager() { RegisterDrawLayer(0); } public void RegisterDrawLayer(int layer) { if (!_layerIndexToTypeToID.ContainsKey(layer)) { _layerOrder.Add(layer, layer); _layerIndexToGeneralRenderers.Add(layer, new HashSet()); _layerIndexToTypeToID.Add(layer, new Dictionary>()); } } public void RegisterOrderedDrawable() where TComponent : struct { if (!_typeToEntityToLayer.ContainsKey(typeof(TComponent))) { _typeToEntityToLayer.Add(typeof(TComponent), new Dictionary(128)); } foreach (var pair in _layerIndexToTypeToID) { if (!pair.Value.ContainsKey(typeof(TComponent))) { pair.Value.Add(typeof(TComponent), new HashSet()); } } } public void RegisterGeneralRendererWithLayer(GeneralRenderer renderer, int layer) { RegisterDrawLayer(layer); var set = _layerIndexToGeneralRenderers[layer]; set.Add(renderer); } public void RegisterComponentWithLayer(int entityID, int layer) where TComponent : struct { if (!_layerIndexToTypeToID.ContainsKey(layer)) { throw new UndefinedLayerException("Layer {0} is not defined. Use WorldBuilder.RegisterDrawLayer to register the layer.", layer); } if (_typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) { if (_typeToEntityToLayer[typeof(TComponent)][entityID] != layer) { UnRegisterComponentWithLayer(entityID); var set = _layerIndexToTypeToID[layer][typeof(TComponent)]; set.Add(entityID); _typeToEntityToLayer[typeof(TComponent)].Add(entityID, layer); } } else { var set = _layerIndexToTypeToID[layer][typeof(TComponent)]; set.Add(entityID); _typeToEntityToLayer[typeof(TComponent)].Add(entityID, layer); } } public void UnRegisterComponentWithLayer(int entityID) where TComponent : struct { if (!_typeToEntityToLayer.ContainsKey(typeof(TComponent))) { return; } if (_typeToEntityToLayer[typeof(TComponent)].ContainsKey(entityID)) { var layer = _typeToEntityToLayer[typeof(TComponent)][entityID]; _layerIndexToTypeToID[layer][typeof(TComponent)].Remove(entityID); } _typeToEntityToLayer[typeof(TComponent)].Remove(entityID); } public void UnRegisterEntityWithLayer(int entityID) { foreach (var store in _layerIndexToTypeToID.Values) { foreach (var typeToSet in store) { var type = typeToSet.Key; var set = typeToSet.Value; if (set.Contains(entityID)) { _typeToEntityToLayer[type].Remove(entityID); set.Remove(entityID); } } } } public IEnumerable GeneralRenderersByLayer(int layer) { return _layerIndexToGeneralRenderers.ContainsKey(layer) ? _layerIndexToGeneralRenderers[layer] : Enumerable.Empty(); } public IEnumerable<(int, Type)> AllInLayer(int layer) { foreach (var kvp in _layerIndexToTypeToID[layer]) { foreach (var id in kvp.Value) { yield return (id, kvp.Key); } } } } }