src/glRenderer.cpp

changeset 1057
3c7782ec3753
parent 1056
27b7991b3bea
child 1061
273333700685
--- a/src/glRenderer.cpp	Thu Nov 17 13:56:13 2016 +0200
+++ b/src/glRenderer.cpp	Thu Nov 17 14:12:59 2016 +0200
@@ -926,16 +926,13 @@
 void GLRenderer::pick(const QRect& range, bool additive)
 {
 	makeCurrent();
+	QSet<LDObject*> priorSelection = selectedObjects().toSet();
+	QSet<LDObject*> newSelection;
 
-	// Clear the selection if we do not wish to add to it.
-	if (not additive)
-	{
-		LDObjectList oldSelection = selectedObjects();
-		currentDocument()->clearSelection();
-
-		for (LDObject* object : oldSelection)
-			compileObject(object);
-	}
+	// If we're doing an additive selection, we start off with the existing selection.
+	// Otherwise we start selecting from scratch.
+	if (additive)
+		newSelection = priorSelection;
 
 	// Paint the picking scene
 	setPicking(true);
@@ -962,10 +959,10 @@
 	// Read pixels from the color buffer.
 	glReadPixels(x0, m_height - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data());
 
-	LDObject* unselectedObject = nullptr;
 	QSet<int32_t> indices;
 
 	// Go through each pixel read and add them to the selection.
+	// Each pixel maps to an LDObject index injectively.
 	// Note: black is background, those indices are skipped.
 	for (unsigned char *pixelCursor = pixelData.begin(); pixelCursor < pixelData.end(); pixelCursor += 4)
 	{
@@ -976,38 +973,37 @@
 			indices.insert(index);
 	}
 
+	// For each index read, resolve the LDObject behind it and add it to the selection.
 	for (int32_t index : indices)
 	{
-		LDObject* object = LDObject::fromID (index);
+		LDObject* object = LDObject::fromID(index);
 
-		if (object == nullptr)
-			continue;
-
-		// If this is an additive single pick and the object is currently selected,
-		// we remove it from selection instead.
-		if (additive)
+		if (object != nullptr)
 		{
-			if (object->isSelected())
-			{
-				object->deselect();
-				unselectedObject = object;
-				break;
-			}
+			// If this is an additive single pick and the object is currently selected,
+			// we remove it from selection instead.
+			if (additive and newSelection.contains(object))
+				newSelection.remove(object);
+			else
+				newSelection.insert(object);
 		}
-
-		object->select();
 	}
 
-	// Update everything now.
-	m_window->updateSelection();
+	// Select all objects that we now have selected that were not selected before.
+	for (LDObject* object : newSelection - priorSelection)
+	{
+		object->select();
+		compileObject(object);
+	}
 
-	// Recompile the objects now to update their color
-	for (LDObject* obj : selectedObjects())
-		compileObject (obj);
+	// Likewise, deselect whatever was selected that isn't anymore.
+	for (LDObject* object : priorSelection - newSelection)
+	{
+		object->deselect();
+		compileObject(object);
+	}
 
-	if (unselectedObject)
-		compileObject(unselectedObject);
-
+	m_window->updateSelection();
 	setPicking(false);
 	repaint();
 }

mercurial