예제 #1
0
 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();
         }
     }
 }
예제 #2
0
        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);
        }