Browse Source

Fix AreaAllocator end iterator bug when going through a grow cycle. If growing the allocator before first allocation, simply expand the existing free area.

Lasse Öörni 11 năm trước cách đây
mục cha
commit
b0598282d9
1 tập tin đã thay đổi với 22 bổ sung6 xóa
  1. 22 6
      Source/Engine/Math/AreaAllocator.cpp

+ 22 - 6
Source/Engine/Math/AreaAllocator.cpp

@@ -65,11 +65,13 @@ bool AreaAllocator::Allocate(int width, int height, int& x, int& y)
     if (height < 0)
     if (height < 0)
         height = 0;
         height = 0;
     
     
-    PODVector<IntRect>::Iterator best = freeAreas_.End();
-    int bestFreeArea = M_MAX_INT;
+    PODVector<IntRect>::Iterator best;
+    int bestFreeArea;
     
     
     for(;;)
     for(;;)
     {
     {
+        best = freeAreas_.End();
+        bestFreeArea = M_MAX_INT;
         for (PODVector<IntRect>::Iterator i = freeAreas_.Begin(); i != freeAreas_.End(); ++i)
         for (PODVector<IntRect>::Iterator i = freeAreas_.Begin(); i != freeAreas_.End(); ++i)
         {
         {
             int freeWidth = i->Width();
             int freeWidth = i->Width();
@@ -94,15 +96,29 @@ bool AreaAllocator::Allocate(int width, int height, int& x, int& y)
             {
             {
                 int oldWidth = size_.x_;
                 int oldWidth = size_.x_;
                 size_.x_ <<= 1;
                 size_.x_ <<= 1;
-                IntRect newArea(oldWidth, 0, size_.x_, size_.y_);
-                freeAreas_.Push(newArea);
+                // If no allocations yet, simply expand the single free area
+                IntRect& first = freeAreas_.Front();
+                if (freeAreas_.Size() == 1 && first.left_ == 0 && first.top_ == 0 && first.right_ == oldWidth && first.bottom_ == size_.y_)
+                    first.right_ = size_.x_;
+                else
+                {
+                    IntRect newArea(oldWidth, 0, size_.x_, size_.y_);
+                    freeAreas_.Push(newArea);
+                }
             }
             }
             else if (!doubleWidth_ && size_.y_ < maxSize_.y_)
             else if (!doubleWidth_ && size_.y_ < maxSize_.y_)
             {
             {
                 int oldHeight = size_.y_;
                 int oldHeight = size_.y_;
                 size_.y_ <<= 1;
                 size_.y_ <<= 1;
-                IntRect newArea(0, oldHeight, size_.x_, size_.y_);
-                freeAreas_.Push(newArea);
+                // If no allocations yet, simply expand the single free area
+                IntRect& first = freeAreas_.Front();
+                if (freeAreas_.Size() == 1 && first.left_ == 0 && first.top_ == 0 && first.right_ == size_.x_ && first.bottom_ == oldHeight)
+                    first.bottom_ = size_.y_;
+                else
+                {
+                    IntRect newArea(0, oldHeight, size_.x_, size_.y_);
+                    freeAreas_.Push(newArea);
+                }
             }
             }
             else
             else
                 return false;
                 return false;