public virtual void Draw() { using (DisposableArray <IDraw> sortedEntities = GetSortedEntities <IDraw>(true)) { int currentIndex = 0; float totalEntities = sortedEntities.Length; for (int i = 0; i < sortedEntities.Length; i++) { var entity = sortedEntities[i]; if (entity == null) { break; } float depth = (currentIndex++) / totalEntities; GameService.GetService <IRenderService>().SetDepth(depth); entity.Draw(); } } }
public DisposableArray <T> GetSortedEntities <T>(bool ShouldReverse = false) where T : class, IDraw { DisposableList <T> visibleSortableEntities = GetEntitiesOfType <T>( e => e.IsVisible() && e.GetBackingBox() != BackingBox.Dummy && Camera.ContainsBox(e.GetBackingBox().B) ); DisposableList <T> visibleDummyEntities = GetEntitiesOfType <T>( e => e.IsVisible() && e.GetBackingBox() == BackingBox.Dummy ); for (int i = 0; i < visibleSortableEntities.Count; i++) { T entity = visibleSortableEntities[i]; outboundEdges[entity].Clear(); inboundEdges[entity].Clear(); } for (int i = 0; i < visibleSortableEntities.Count; i++) { var ie = visibleSortableEntities[i]; var ib = ie.GetBackingBox(); for (int j = i + 1; j < visibleSortableEntities.Count; j++) { var je = visibleSortableEntities[j]; var jb = je.GetBackingBox(); if (ib.DoesProjectionOverlapOther(jb)) { int comparison = ib.Compare(jb); T inboundNode = null; T outboundNode = null; if (comparison >= 0) { outboundNode = ie; inboundNode = je; } else if (comparison < 0) { outboundNode = je; inboundNode = ie; } else { continue; } outboundEdges[outboundNode].Add(inboundNode); inboundEdges[inboundNode].Add(outboundNode); } } } int totalEntityCount = visibleDummyEntities.Count + visibleSortableEntities.Count; int insertIndex = 0; DisposableArray <T> sortedEntities = DisposableArray <T> .Shared.Rent().Initialize(totalEntityCount); HashSet <IDraw> sortedLookup = hashSetPool.Rent(); int visibleLower = 0; int visibleUpper = visibleSortableEntities.Count; while (insertIndex < visibleSortableEntities.Count) { bool didLoopInfinitely = true; for (int i = visibleLower; i < visibleUpper; i++) { var entity = visibleSortableEntities[i]; if (sortedLookup.Contains(entity)) { continue; } HashSet <IDraw> entityOutbound = outboundEdges[entity]; if (entityOutbound.Count == 0) { didLoopInfinitely = false; foreach (T inboundEntity in inboundEdges[entity]) { outboundEdges[inboundEntity].Remove(entity); } sortedLookup.Add(entity); sortedEntities[insertIndex++] = entity; visibleLower = Math.Min(visibleLower, i); if (i == visibleUpper - 1) { visibleUpper = i; } continue; } } if (didLoopInfinitely) { T minTop = null; for (int i = 0; i < visibleSortableEntities.Count; i++) { T outerEntity = visibleSortableEntities[i]; if (sortedLookup.Contains(outerEntity)) { continue; } if ( minTop == null || outerEntity.GetBackingBox().Top < minTop.GetBackingBox().Top || (outerEntity.GetBackingBox().Top == minTop.GetBackingBox().Top&& outerEntity.GetBackingBox().Front < minTop.GetBackingBox().Front) ) { minTop = outerEntity; } } outboundEdges[minTop].Clear(); } } if (ShouldReverse) { for (int i = 0; i < Math.Ceiling(totalEntityCount / 2f); i++) { var swap = sortedEntities[totalEntityCount - 1 - i]; sortedEntities[totalEntityCount - 1 - i] = sortedEntities[i]; sortedEntities[i] = swap; } for (int i = 0; i < visibleDummyEntities.Count; i++) { sortedEntities[i] = visibleDummyEntities[i]; } } else { for (int i = 0; i < visibleDummyEntities.Count; i++) { sortedEntities[visibleSortableEntities.Count + i] = visibleDummyEntities[i]; } } hashSetPool.Return(sortedLookup); visibleSortableEntities.Dispose(); visibleDummyEntities.Dispose(); return(sortedEntities); }