924 // ============================================================================= |
924 // ============================================================================= |
925 // |
925 // |
926 void GLRenderer::pick(const QRect& range, bool additive) |
926 void GLRenderer::pick(const QRect& range, bool additive) |
927 { |
927 { |
928 makeCurrent(); |
928 makeCurrent(); |
929 |
929 QSet<LDObject*> priorSelection = selectedObjects().toSet(); |
930 // Clear the selection if we do not wish to add to it. |
930 QSet<LDObject*> newSelection; |
931 if (not additive) |
931 |
932 { |
932 // If we're doing an additive selection, we start off with the existing selection. |
933 LDObjectList oldSelection = selectedObjects(); |
933 // Otherwise we start selecting from scratch. |
934 currentDocument()->clearSelection(); |
934 if (additive) |
935 |
935 newSelection = priorSelection; |
936 for (LDObject* object : oldSelection) |
|
937 compileObject(object); |
|
938 } |
|
939 |
936 |
940 // Paint the picking scene |
937 // Paint the picking scene |
941 setPicking(true); |
938 setPicking(true); |
942 drawGLScene(); |
939 drawGLScene(); |
943 |
940 |
960 pixelData.resize(4 * numpixels); |
957 pixelData.resize(4 * numpixels); |
961 |
958 |
962 // Read pixels from the color buffer. |
959 // Read pixels from the color buffer. |
963 glReadPixels(x0, m_height - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data()); |
960 glReadPixels(x0, m_height - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data()); |
964 |
961 |
965 LDObject* unselectedObject = nullptr; |
|
966 QSet<int32_t> indices; |
962 QSet<int32_t> indices; |
967 |
963 |
968 // Go through each pixel read and add them to the selection. |
964 // Go through each pixel read and add them to the selection. |
|
965 // Each pixel maps to an LDObject index injectively. |
969 // Note: black is background, those indices are skipped. |
966 // Note: black is background, those indices are skipped. |
970 for (unsigned char *pixelCursor = pixelData.begin(); pixelCursor < pixelData.end(); pixelCursor += 4) |
967 for (unsigned char *pixelCursor = pixelData.begin(); pixelCursor < pixelData.end(); pixelCursor += 4) |
971 { |
968 { |
972 int32_t index = pixelCursor[0] * 0x10000 + |
969 int32_t index = pixelCursor[0] * 0x10000 + |
973 pixelCursor[1] * 0x100 + |
970 pixelCursor[1] * 0x100 + |
974 pixelCursor[2] * 0x1; |
971 pixelCursor[2] * 0x1; |
975 if (index != 0) |
972 if (index != 0) |
976 indices.insert(index); |
973 indices.insert(index); |
977 } |
974 } |
978 |
975 |
|
976 // For each index read, resolve the LDObject behind it and add it to the selection. |
979 for (int32_t index : indices) |
977 for (int32_t index : indices) |
980 { |
978 { |
981 LDObject* object = LDObject::fromID (index); |
979 LDObject* object = LDObject::fromID(index); |
982 |
980 |
983 if (object == nullptr) |
981 if (object != nullptr) |
984 continue; |
982 { |
985 |
983 // If this is an additive single pick and the object is currently selected, |
986 // If this is an additive single pick and the object is currently selected, |
984 // we remove it from selection instead. |
987 // we remove it from selection instead. |
985 if (additive and newSelection.contains(object)) |
988 if (additive) |
986 newSelection.remove(object); |
989 { |
987 else |
990 if (object->isSelected()) |
988 newSelection.insert(object); |
991 { |
989 } |
992 object->deselect(); |
990 } |
993 unselectedObject = object; |
991 |
994 break; |
992 // Select all objects that we now have selected that were not selected before. |
995 } |
993 for (LDObject* object : newSelection - priorSelection) |
996 } |
994 { |
997 |
|
998 object->select(); |
995 object->select(); |
999 } |
996 compileObject(object); |
1000 |
997 } |
1001 // Update everything now. |
998 |
|
999 // Likewise, deselect whatever was selected that isn't anymore. |
|
1000 for (LDObject* object : priorSelection - newSelection) |
|
1001 { |
|
1002 object->deselect(); |
|
1003 compileObject(object); |
|
1004 } |
|
1005 |
1002 m_window->updateSelection(); |
1006 m_window->updateSelection(); |
1003 |
|
1004 // Recompile the objects now to update their color |
|
1005 for (LDObject* obj : selectedObjects()) |
|
1006 compileObject (obj); |
|
1007 |
|
1008 if (unselectedObject) |
|
1009 compileObject(unselectedObject); |
|
1010 |
|
1011 setPicking(false); |
1007 setPicking(false); |
1012 repaint(); |
1008 repaint(); |
1013 } |
1009 } |
1014 |
1010 |
1015 // |
1011 // |