Fix logic bugs in reordering of RenderObjects within a layer. patched
authorachurch
Tue, 16 Aug 2011 18:43:52 +0900
branchpatched
changeset 679 2fc57365a294
parent 674 813441490f18
child 680 8e56fbb5eac0
Fix logic bugs in reordering of RenderObjects within a layer. This patch fixes logic bugs with state management for the array-based RenderObjectLayer implementation which could cause crashes when an object was moved to the back of the layer.
BBGE/RenderObjectLayer.cpp
--- a/BBGE/RenderObjectLayer.cpp	Sat Apr 23 02:00:18 2011 +0900
+++ b/BBGE/RenderObjectLayer.cpp	Tue Aug 16 18:43:52 2011 +0900
@@ -229,8 +229,8 @@
 		renderObjects[curIdx] = 0;
 		renderObjects[newIdx] = r;
 		r->setIdx(newIdx);
-		if (firstFreeIdx == newIdx)
-			firstFreeIdx++;
+		if (firstFreeIdx > curIdx)
+			firstFreeIdx = curIdx;
 	}
 	else if (objectCount == size)
 	{
@@ -242,7 +242,7 @@
 		r->setIdx(size);
 		for (int i = size+1; i < newSize; i++)
 			renderObjects[i] = 0;
-		firstFreeIdx = size+1;
+		firstFreeIdx = curIdx;
 	}
 	else
 	{
@@ -254,17 +254,16 @@
 			if (!renderObjects[lastFree])
 				break;
 		}
-
 		for (int i = lastFree + 1; i <= lastUsed; i++)
 		{
 			renderObjects[i-1] = renderObjects[i];
-			renderObjects[i-1]->setIdx(i-1);
+			renderObjects[i-1]->setIdx(i-1);  // Known to be non-NULL.
 		}
-
 		renderObjects[lastUsed] = r;
 		r->setIdx(lastUsed);
-		if (firstFreeIdx == lastFree)
-			firstFreeIdx = lastUsed + 1;
+		firstFreeIdx = curIdx;
+		while (renderObjects[firstFreeIdx])
+			firstFreeIdx++;
 	}
 #endif  // RLT_FIXED
 #ifdef RLT_DYNAMIC
@@ -297,7 +296,9 @@
 		renderObjects[curIdx] = 0;
 		renderObjects[newIdx] = r;
 		r->setIdx(newIdx);
-		if (firstFreeIdx == newIdx)
+		// firstFreeIdx must be 0 here; if we filled slot 0, then
+		// scan forward for the next empty element.
+		while (!renderObjects[firstFreeIdx])
 			firstFreeIdx++;
 	}
 	else if (objectCount == size)
@@ -311,7 +312,7 @@
 		for (int i = newSize - 1; i >= sizeDiff; i--)
 		{
 			renderObjects[i] = renderObjects[i - sizeDiff];
-			renderObjects[i]->setIdx(i);
+			renderObjects[i]->setIdx(i);  // Known to be non-NULL.
 		}
 		for (int i = 0; i < newIdx; i++)
 			renderObjects[i] = 0;
@@ -327,7 +328,7 @@
 		for (int i = firstFreeIdx; i > 0; i--)
 		{
 			renderObjects[i] = renderObjects[i-1];
-			renderObjects[i]->setIdx(i);
+			renderObjects[i]->setIdx(i);  // Known to be non-NULL.
 		}
 		renderObjects[0] = r;
 		r->setIdx(0);