From 610523e3ea6e27db7f239081b3747034a3766cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 31 Oct 2023 12:14:19 +0100 Subject: [PATCH 1/7] [Viewer3D] Add slider to display cameras based on their resection IDs If any model with cameras is displayed in the 3D Viewer, a slider can be used to filter the cameras that are being currently displayed based on their resection IDs. This allows to visualize the order in which the cameras have been added, and the groups in which they have been added. --- meshroom/ui/qml/Viewer3D/Inspector3D.qml | 84 +++++++++++++++++++ meshroom/ui/qml/Viewer3D/MediaLoader.qml | 7 +- meshroom/ui/qml/Viewer3D/SfmDataLoader.qml | 28 +++++++ meshroom/ui/qml/Viewer3D/Viewer3DSettings.qml | 6 ++ 4 files changed, 123 insertions(+), 2 deletions(-) diff --git a/meshroom/ui/qml/Viewer3D/Inspector3D.qml b/meshroom/ui/qml/Viewer3D/Inspector3D.qml index 64299ba3..cd6f05e4 100644 --- a/meshroom/ui/qml/Viewer3D/Inspector3D.qml +++ b/meshroom/ui/qml/Viewer3D/Inspector3D.qml @@ -109,6 +109,7 @@ FloatingPane { Flow { Layout.fillWidth: true spacing: 2 + // Synchronization MaterialToolButton { id: syncViewpointCamera @@ -118,6 +119,7 @@ FloatingPane { checked: enabled && Viewer3DSettings.syncViewpointCamera onClicked: Viewer3DSettings.syncViewpointCamera = !Viewer3DSettings.syncViewpointCamera } + // Image Overlay controls RowLayout { visible: syncViewpointCamera.enabled && Viewer3DSettings.syncViewpointCamera @@ -152,6 +154,82 @@ FloatingPane { onClicked: Viewer3DSettings.viewpointImageFrame = !Viewer3DSettings.viewpointImageFrame } } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + + RowLayout { + Layout.fillHeight: true + spacing: 2 + + MaterialToolButton { + id: resectionIdButton + text: MaterialIcons.switch_video + ToolTip.text: "Display Cameras Based On Resection IDs" + ToolTip.visible: hovered + enabled: Viewer3DSettings.resectionIdCount + checked: enabled && Viewer3DSettings.displayResectionIds + onClicked: { + Viewer3DSettings.displayResectionIds = !Viewer3DSettings.displayResectionIds + Viewer3DSettings.resectionId = Viewer3DSettings.resectionIdCount + resectionIdSlider.value = Viewer3DSettings.resectionId + } + + onEnabledChanged: { + Viewer3DSettings.resectionId = Viewer3DSettings.resectionIdCount + resectionIdSlider.value = Viewer3DSettings.resectionId + if (!enabled) { + Viewer3DSettings.displayResectionIds = false + } + } + } + + Slider { + id: resectionIdSlider + value: Viewer3DSettings.resectionId + from: 0 + to: Viewer3DSettings.resectionIdCount + stepSize: 1 + onMoved: Viewer3DSettings.resectionId = value + Layout.fillWidth: true + leftPadding: 2 + rightPadding: 2 + ToolTip.text: "Resection ID " + value + "/" + Viewer3DSettings.resectionIdCount + ToolTip.visible: hovered || pressed + ToolTip.delay: 150 + visible: Viewer3DSettings.displayResectionIds + } + } + + Label { + text: "Cameras for ID " + Viewer3DSettings.resectionId + ": " + Viewer3DSettings.resectionGroups[Viewer3DSettings.resectionId] + font.pointSize: 8 + Layout.fillWidth: true + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + visible: Viewer3DSettings.displayResectionIds + } + + Label { + text: { + let currentCameras = 0 + let totalCameras = 0 + for (let i = 0; i <= Viewer3DSettings.resectionIdCount; i++) { + if (i <= Viewer3DSettings.resectionId) + currentCameras += Viewer3DSettings.resectionGroups[i] + totalCameras += Viewer3DSettings.resectionGroups[i] + } + + return "(total cameras: " + currentCameras + "/" + totalCameras + ")" + } + font.pointSize: 8 + Layout.fillWidth: true + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + visible: Viewer3DSettings.displayResectionIds + } + } } } @@ -192,6 +270,12 @@ FloatingPane { ScrollBar.vertical: ScrollBar { id: scrollBar } + onCountChanged: { + if (mediaListView.count === 0) { + Viewer3DSettings.resectionIdCount = 0 + } + } + currentIndex: -1 Connections { diff --git a/meshroom/ui/qml/Viewer3D/MediaLoader.qml b/meshroom/ui/qml/Viewer3D/MediaLoader.qml index a767cf54..c47cc4ef 100644 --- a/meshroom/ui/qml/Viewer3D/MediaLoader.qml +++ b/meshroom/ui/qml/Viewer3D/MediaLoader.qml @@ -99,8 +99,9 @@ import Utils 1.0 'source': source, 'pointSize': Qt.binding(function() { return 0.01 * Viewer3DSettings.pointSize }), 'locatorScale': Qt.binding(function() { return Viewer3DSettings.cameraScale }), - 'cameraPickingEnabled': Qt.binding(function() { return root.enabled }) - }) + 'cameraPickingEnabled': Qt.binding(function() { return root.enabled }), + 'resectionId': Qt.binding(function() { return Viewer3DSettings.resectionId }) + }); obj.statusChanged.connect(function() { if (obj.status === SceneLoader.Ready) { @@ -109,6 +110,8 @@ import Utils 1.0 } cameraCount = obj.spawnCameraSelectors(); } + Viewer3DSettings.resectionIdCount = obj.countResectionIds(); + Viewer3DSettings.resectionGroups = obj.countResectionGroups(Viewer3DSettings.resectionIdCount + 1); root.status = obj.status; }) } diff --git a/meshroom/ui/qml/Viewer3D/SfmDataLoader.qml b/meshroom/ui/qml/Viewer3D/SfmDataLoader.qml index e5637a1b..8dbaf335 100644 --- a/meshroom/ui/qml/Viewer3D/SfmDataLoader.qml +++ b/meshroom/ui/qml/Viewer3D/SfmDataLoader.qml @@ -33,6 +33,34 @@ SfmDataEntity { return validCameras; } + function countResectionIds() { + var maxResectionId = 0 + for (var i = 0; i < root.cameras.length; i++) { + var cam = root.cameras[i] + var resectionId = cam.resectionId + if (resectionId === undefined || resectionId === 4294967295) + continue + if (resectionId > maxResectionId) + maxResectionId = resectionId + } + + return maxResectionId + } + + + function countResectionGroups(resectionIdCount) { + var arr = Array(resectionIdCount).fill(0) + for (var i = 0; i < root.cameras.length; i++) { + var cam = root.cameras[i] + var resectionId = cam.resectionId + if (resectionId === undefined || resectionId === 4294967295) + continue + arr[resectionId] = arr[resectionId] + 1 + } + + return arr + } + SystemPalette { id: activePalette } diff --git a/meshroom/ui/qml/Viewer3D/Viewer3DSettings.qml b/meshroom/ui/qml/Viewer3D/Viewer3DSettings.qml index 39fb2bf3..68f939cf 100644 --- a/meshroom/ui/qml/Viewer3D/Viewer3DSettings.qml +++ b/meshroom/ui/qml/Viewer3D/Viewer3DSettings.qml @@ -56,4 +56,10 @@ Item { readonly property bool showViewpointImageOverlay: syncViewpointCamera && viewpointImageOverlay property bool viewpointImageFrame: false readonly property bool showViewpointImageFrame: syncViewpointCamera && viewpointImageFrame + + // Cameras' resection IDs + property bool displayResectionIds: false + property int resectionIdCount: 0 + property int resectionId: resectionIdCount + property var resectionGroups: [] // Number of cameras for each resection ID } From 4f4e31a24927907ae11cbea03a6935d24da62726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 7 Nov 2023 16:45:01 +0100 Subject: [PATCH 2/7] [Controls] Add a custom `ExpandableGroup` object The `ExpandableGroup` is based on QML's `GroupBox`. It is very similar to the `Group` object, with the difference that it can be hidden/expanded by clicking on the group's title/label. --- meshroom/ui/qml/Controls/ExpandableGroup.qml | 76 ++++++++++++++++++++ meshroom/ui/qml/Controls/qmldir | 1 + 2 files changed, 77 insertions(+) create mode 100644 meshroom/ui/qml/Controls/ExpandableGroup.qml diff --git a/meshroom/ui/qml/Controls/ExpandableGroup.qml b/meshroom/ui/qml/Controls/ExpandableGroup.qml new file mode 100644 index 00000000..afd4459c --- /dev/null +++ b/meshroom/ui/qml/Controls/ExpandableGroup.qml @@ -0,0 +1,76 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.11 +import MaterialIcons 2.2 + +/** + * A custom GroupBox with predefined header that can be hidden and expanded. + */ +GroupBox { + id: root + + title: "" + property int sidePadding: 6 + property alias labelBackground: labelBg + property alias toolBarContent: toolBar.data + property bool expanded: expandButton.checked + + padding: 2 + leftPadding: sidePadding + rightPadding: sidePadding + topPadding: label.height + padding + background: Item {} + + label: Pane { + background: Rectangle { + id: labelBg + color: palette.base + opacity: 0.8 + + MouseArea { + anchors.fill: parent + onClicked: { + expandButton.checked = !expandButton.checked + } + } + } + padding: 2 + width: root.width + + RowLayout { + width: parent.width + Label { + text: root.title + Layout.fillWidth: true + elide: Text.ElideRight + padding: 3 + font.bold: true + font.pointSize: 8 + } + RowLayout { + id: toolBar + height: parent.height + + MaterialToolButton { + id: expandButton + ToolTip.text: "Expand More" + text: MaterialIcons.expand_more + font.pointSize: 10 + implicitHeight: parent.height + checkable: true + checked: false + + onCheckedChanged: { + if (checked) { + ToolTip.text = "Expand Less" + text = MaterialIcons.expand_less + } else { + ToolTip.text = "Expand More" + text = MaterialIcons.expand_more + } + } + } + } + } + } +} diff --git a/meshroom/ui/qml/Controls/qmldir b/meshroom/ui/qml/Controls/qmldir index f4c247b1..7598fadf 100644 --- a/meshroom/ui/qml/Controls/qmldir +++ b/meshroom/ui/qml/Controls/qmldir @@ -1,6 +1,7 @@ module Controls ColorChart 1.0 ColorChart.qml +ExpandableGroup 1.0 ExpandableGroup.qml FloatingPane 1.0 FloatingPane.qml Group 1.0 Group.qml KeyValue 1.0 KeyValue.qml From c8ac11ca05bfde44ac27127614731cb83175f9e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 7 Nov 2023 16:45:31 +0100 Subject: [PATCH 3/7] [Viewer3D] Inspector3D: Replace `Group` by `ExpandableGroup` when relevant The content of the "DISPLAY" and "CAMERA" groups is hidden by default. Instead of customizing the `Group` object's toolbar to hide/expand these groups, the `ExpandableGroup` object, which is specifically made to handle these cases, is used. The groups can be expanded either by clicking the dedicated tool button or anywhere on the toolbar. --- meshroom/ui/qml/Viewer3D/Inspector3D.qml | 46 ++++++++++++++++++------ 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/meshroom/ui/qml/Viewer3D/Inspector3D.qml b/meshroom/ui/qml/Viewer3D/Inspector3D.qml index cd6f05e4..33f34098 100644 --- a/meshroom/ui/qml/Viewer3D/Inspector3D.qml +++ b/meshroom/ui/qml/Viewer3D/Inspector3D.qml @@ -31,7 +31,8 @@ FloatingPane { anchors.fill: parent spacing: 4 - Group { + ExpandableGroup { + id: displayGroup Layout.fillWidth: true title: "DISPLAY" @@ -43,6 +44,7 @@ FloatingPane { Flow { Layout.columnSpan: 2 Layout.fillWidth: true + visible: displayGroup.expanded spacing: 1 MaterialToolButton { text: MaterialIcons.grid_on @@ -63,8 +65,13 @@ FloatingPane { onClicked: Viewer3DSettings.displayOrigin = !Viewer3DSettings.displayOrigin } } - MaterialLabel { text: MaterialIcons.grain; padding: 2 } + MaterialLabel { + text: MaterialIcons.grain + padding: 2 + visible: displayGroup.expanded + } RowLayout { + visible: displayGroup.expanded Slider { Layout.fillWidth: true; from: 0; to: 5; stepSize: 0.001 value: Viewer3DSettings.pointSize @@ -83,8 +90,13 @@ FloatingPane { } } - MaterialLabel { text: MaterialIcons.videocam; padding: 2 } + MaterialLabel { + text: MaterialIcons.videocam + padding: 2 + visible: displayGroup.expanded + } Slider { + visible: displayGroup.expanded value: Viewer3DSettings.cameraScale from: 0 to: 2 @@ -99,15 +111,19 @@ FloatingPane { } } - Group { + ExpandableGroup { + id: cameraGroup Layout.fillWidth: true title: "CAMERA" + + ColumnLayout { width: parent.width // Image/Camera synchronization Flow { Layout.fillWidth: true + visible: cameraGroup.expanded spacing: 2 // Synchronization @@ -115,7 +131,7 @@ FloatingPane { id: syncViewpointCamera enabled: _reconstruction ? _reconstruction.sfmReport : false text: MaterialIcons.linked_camera - ToolTip.text: "Sync with Image Selection" + ToolTip.text: "View Through The Active Camera" checked: enabled && Viewer3DSettings.syncViewpointCamera onClicked: Viewer3DSettings.syncViewpointCamera = !Viewer3DSettings.syncViewpointCamera } @@ -158,6 +174,7 @@ FloatingPane { ColumnLayout { Layout.fillWidth: true spacing: 2 + visible: cameraGroup.expanded RowLayout { Layout.fillHeight: true @@ -166,7 +183,7 @@ FloatingPane { MaterialToolButton { id: resectionIdButton text: MaterialIcons.switch_video - ToolTip.text: "Display Cameras Based On Resection IDs" + ToolTip.text: "Timeline Of Camera Reconstruction Groups" ToolTip.visible: hovered enabled: Viewer3DSettings.resectionIdCount checked: enabled && Viewer3DSettings.displayResectionIds @@ -195,15 +212,22 @@ FloatingPane { Layout.fillWidth: true leftPadding: 2 rightPadding: 2 - ToolTip.text: "Resection ID " + value + "/" + Viewer3DSettings.resectionIdCount - ToolTip.visible: hovered || pressed - ToolTip.delay: 150 + visible: Viewer3DSettings.displayResectionIds + } + + Label { + text: resectionIdSlider.value + "/" + Viewer3DSettings.resectionIdCount visible: Viewer3DSettings.displayResectionIds } } Label { - text: "Cameras for ID " + Viewer3DSettings.resectionId + ": " + Viewer3DSettings.resectionGroups[Viewer3DSettings.resectionId] + text: { + var id = Viewer3DSettings.resectionIdCount + if (Viewer3DSettings.resectionId !== undefined) + id = Math.min(Viewer3DSettings.resectionId, Viewer3DSettings.resectionIdCount) + return "Nb Of Cameras In Group " + id + ": " + Viewer3DSettings.resectionGroups[id] + } font.pointSize: 8 Layout.fillWidth: true wrapMode: Text.WordWrap @@ -221,7 +245,7 @@ FloatingPane { totalCameras += Viewer3DSettings.resectionGroups[i] } - return "(total cameras: " + currentCameras + "/" + totalCameras + ")" + return "Nb Of Cumulated Cameras: " + currentCameras + "/" + totalCameras } font.pointSize: 8 Layout.fillWidth: true From 3d67f830904e08968c5dcfca12794753c504900a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Mon, 6 Nov 2023 16:48:41 +0100 Subject: [PATCH 4/7] [Viewer3D] Display resection IDs of the active 3D model Instead of displaying the resection IDs of the 3D model that was loaded last, update the display whenever the active model selection changes. --- meshroom/ui/qml/Viewer3D/Inspector3D.qml | 13 +++++++++++++ meshroom/ui/qml/Viewer3D/MediaLibrary.qml | 8 +++++--- meshroom/ui/qml/Viewer3D/MediaLoader.qml | 3 +++ meshroom/ui/qml/Viewer3D/MediaLoaderEntity.qml | 6 ++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/meshroom/ui/qml/Viewer3D/Inspector3D.qml b/meshroom/ui/qml/Viewer3D/Inspector3D.qml index 33f34098..b237a3d0 100644 --- a/meshroom/ui/qml/Viewer3D/Inspector3D.qml +++ b/meshroom/ui/qml/Viewer3D/Inspector3D.qml @@ -352,12 +352,25 @@ FloatingPane { if (mouse.button == Qt.RightButton) contextMenu.popup(); mediaListView.currentIndex = index; + + // Update the resection ID-related objects based on the active model + Viewer3DSettings.resectionIdCount = model.resectionIdCount + Viewer3DSettings.resectionGroups = model.resectionGroups + Viewer3DSettings.resectionId = model.resectionId + resectionIdSlider.value = model.resectionId } onDoubleClicked: { model.visible = true; nodeActivated(model.attribute.node); } + Connections { + target: resectionIdSlider + function onValueChanged() { + model.resectionId = resectionIdSlider.value + } + } + RowLayout { width: parent.width spacing: 2 diff --git a/meshroom/ui/qml/Viewer3D/MediaLibrary.qml b/meshroom/ui/qml/Viewer3D/MediaLibrary.qml index e636614f..aa60488d 100644 --- a/meshroom/ui/qml/Viewer3D/MediaLibrary.qml +++ b/meshroom/ui/qml/Viewer3D/MediaLibrary.qml @@ -58,6 +58,9 @@ Entity { "faceCount": 0, "cameraCount": 0, "textureCount": 0, + "resectionIdCount": 0, + "resectionId": 0, + "resectionGroups": [], "status": SceneLoader.None }) } @@ -308,12 +311,11 @@ Entity { if (object) { // bind media info to corresponding model roles // (test for object validity to avoid error messages right after object has been deleted) - var boundProperties = ["vertexCount", "faceCount", "cameraCount", "textureCount"] + var boundProperties = ["vertexCount", "faceCount", "cameraCount", "textureCount", "resectionIdCount", "resectionId", "resectionGroups"] boundProperties.forEach(function(prop) { model[prop] = Qt.binding(function() { return object ? object[prop] : 0 }) }) - } - else if (finalSource && status === Component.Ready) { + } else if (finalSource && status === Component.Ready) { // source was valid but no loader was created, remove element // check if component is ready to avoid removing element from the model before adding instance to the node remove(index) diff --git a/meshroom/ui/qml/Viewer3D/MediaLoader.qml b/meshroom/ui/qml/Viewer3D/MediaLoader.qml index c47cc4ef..ee6ba004 100644 --- a/meshroom/ui/qml/Viewer3D/MediaLoader.qml +++ b/meshroom/ui/qml/Viewer3D/MediaLoader.qml @@ -112,6 +112,9 @@ import Utils 1.0 } Viewer3DSettings.resectionIdCount = obj.countResectionIds(); Viewer3DSettings.resectionGroups = obj.countResectionGroups(Viewer3DSettings.resectionIdCount + 1); + resectionIdCount = Viewer3DSettings.resectionIdCount + resectionGroups = Viewer3DSettings.resectionGroups + resectionId = Viewer3DSettings.resectionIdCount root.status = obj.status; }) } diff --git a/meshroom/ui/qml/Viewer3D/MediaLoaderEntity.qml b/meshroom/ui/qml/Viewer3D/MediaLoaderEntity.qml index cbe56e5b..90170240 100644 --- a/meshroom/ui/qml/Viewer3D/MediaLoaderEntity.qml +++ b/meshroom/ui/qml/Viewer3D/MediaLoaderEntity.qml @@ -17,4 +17,10 @@ Entity { property int cameraCount /// Number of textures property int textureCount + /// Number of resection IDs + property int resectionIdCount + /// Current resection ID + property int resectionId + /// Groups of cameras based on resection IDs + property var resectionGroups } From 45f857c18344d7772e3bba1dff6c893b9a719504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 7 Nov 2023 16:38:33 +0100 Subject: [PATCH 5/7] [MaterialIcons] Add `auto_awesome_motion` icon --- meshroom/ui/qml/MaterialIcons/MaterialIcons.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/meshroom/ui/qml/MaterialIcons/MaterialIcons.qml b/meshroom/ui/qml/MaterialIcons/MaterialIcons.qml index de733b74..bcc39d79 100644 --- a/meshroom/ui/qml/MaterialIcons/MaterialIcons.qml +++ b/meshroom/ui/qml/MaterialIcons/MaterialIcons.qml @@ -92,6 +92,7 @@ QtObject { readonly property string attachment: "\ue2bc" readonly property string audiotrack: "\ue3a1" readonly property string autorenew: "\ue863" + readonly property string auto_awesome_motion: "\ue661" readonly property string av_timer: "\ue01b" readonly property string backspace: "\ue14a" readonly property string backup: "\ue864" From 45b267a49b020f2d6c6b4bc4e5838184357d26bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 7 Nov 2023 17:00:59 +0100 Subject: [PATCH 6/7] [Viewer3D] Inspector3D: Replace resectionID-related labels with ToolLabels --- meshroom/ui/qml/Viewer3D/Inspector3D.qml | 74 +++++++++++++++--------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/meshroom/ui/qml/Viewer3D/Inspector3D.qml b/meshroom/ui/qml/Viewer3D/Inspector3D.qml index b237a3d0..cc338bec 100644 --- a/meshroom/ui/qml/Viewer3D/Inspector3D.qml +++ b/meshroom/ui/qml/Viewer3D/Inspector3D.qml @@ -116,7 +116,6 @@ FloatingPane { Layout.fillWidth: true title: "CAMERA" - ColumnLayout { width: parent.width @@ -221,37 +220,56 @@ FloatingPane { } } - Label { - text: { - var id = Viewer3DSettings.resectionIdCount - if (Viewer3DSettings.resectionId !== undefined) - id = Math.min(Viewer3DSettings.resectionId, Viewer3DSettings.resectionIdCount) - return "Nb Of Cameras In Group " + id + ": " + Viewer3DSettings.resectionGroups[id] - } - font.pointSize: 8 + RowLayout { + spacing: 10 Layout.fillWidth: true - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - visible: Viewer3DSettings.displayResectionIds - } + Layout.margins: 2 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + MaterialToolLabel { + iconText: MaterialIcons.stop + label: { + var id = undefined + // Ensure there are entries in resectionGroups and a valid resectionId before accessing anything + if (Viewer3DSettings.resectionId !== undefined && Viewer3DSettings.resectionGroups.length > 0) + id = Math.min(Viewer3DSettings.resectionId, Viewer3DSettings.resectionIdCount) + if (id !== undefined) + return Viewer3DSettings.resectionGroups[id] + return 0 - Label { - text: { - let currentCameras = 0 - let totalCameras = 0 - for (let i = 0; i <= Viewer3DSettings.resectionIdCount; i++) { - if (i <= Viewer3DSettings.resectionId) - currentCameras += Viewer3DSettings.resectionGroups[i] - totalCameras += Viewer3DSettings.resectionGroups[i] } - - return "Nb Of Cumulated Cameras: " + currentCameras + "/" + totalCameras + ToolTip.text: "Number Of Cameras In Current Resection Group" + visible: Viewer3DSettings.displayResectionIds + } + + MaterialToolLabel { + iconText: MaterialIcons.auto_awesome_motion + label: { + let currentCameras = 0 + for (let i = 0; i <= Viewer3DSettings.resectionIdCount; i++) { + if (i <= Viewer3DSettings.resectionId) + currentCameras += Viewer3DSettings.resectionGroups[i] + } + + return currentCameras + } + ToolTip.text: "Number Of Cumulated Cameras" + visible: Viewer3DSettings.displayResectionIds + } + + MaterialToolLabel { + iconText: MaterialIcons.videocam + label: { + let totalCameras = 0 + for (let i = 0; i <= Viewer3DSettings.resectionIdCount; i++) { + totalCameras += Viewer3DSettings.resectionGroups[i] + } + + return totalCameras + } + ToolTip.text: "Total Number Of Cameras" + visible: Viewer3DSettings.displayResectionIds } - font.pointSize: 8 - Layout.fillWidth: true - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - visible: Viewer3DSettings.displayResectionIds } } } From a579ea349dc8caf42f08b0c800c549d518c25c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Thu, 16 Nov 2023 15:16:22 +0100 Subject: [PATCH 7/7] [Viewer3D] Inspector3D: Update resection ID slider upon any index update --- meshroom/ui/qml/Viewer3D/Inspector3D.qml | 36 ++++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/meshroom/ui/qml/Viewer3D/Inspector3D.qml b/meshroom/ui/qml/Viewer3D/Inspector3D.qml index cc338bec..6674946f 100644 --- a/meshroom/ui/qml/Viewer3D/Inspector3D.qml +++ b/meshroom/ui/qml/Viewer3D/Inspector3D.qml @@ -233,7 +233,7 @@ FloatingPane { // Ensure there are entries in resectionGroups and a valid resectionId before accessing anything if (Viewer3DSettings.resectionId !== undefined && Viewer3DSettings.resectionGroups.length > 0) id = Math.min(Viewer3DSettings.resectionId, Viewer3DSettings.resectionIdCount) - if (id !== undefined) + if (id !== undefined && Viewer3DSettings.resectionGroups[id] !== undefined) return Viewer3DSettings.resectionGroups[id] return 0 @@ -343,13 +343,25 @@ FloatingPane { // add mediaLibrary.count in the binding to ensure 'entity' // is re-evaluated when mediaLibrary delegates are modified property bool loading: model.status === SceneLoader.Loading - property bool hovered: model.attribute ? (uigraph ? uigraph.hoveredNode === model.attribute.node : false) : containsMouse + property bool hovered: model.attribute ? (uigraph ? uigraph.hoveredNode === model.attribute.node : false) : containsMouse property bool isSelectedNode: model.attribute ? (uigraph ? uigraph.selectedNode === model.attribute.node : false) : false onIsSelectedNodeChanged: updateCurrentIndex() function updateCurrentIndex() { - if(isSelectedNode) { mediaListView.currentIndex = index } + if (isSelectedNode) { + mediaListView.currentIndex = index + } + + // If the index is updated, and the resection ID count is available, update every resection-related variable: + // this covers the changes of index that occur when a node whose output is already loaded in the 3D viewer is + // clicked/double-clicked, and when the active entry is removed from the list. + if (model.resectionIdCount) { + Viewer3DSettings.resectionIdCount = model.resectionIdCount + Viewer3DSettings.resectionGroups = model.resectionGroups + Viewer3DSettings.resectionId = model.resectionId + resectionIdSlider.value = model.resectionId + } } height: childrenRect.height @@ -360,16 +372,22 @@ FloatingPane { } hoverEnabled: true - onEntered: { if (model.attribute) uigraph.hoveredNode = model.attribute.node } - onExited: { if (model.attribute) uigraph.hoveredNode = null } + onEntered: { + if (model.attribute) + uigraph.hoveredNode = model.attribute.node + } + onExited: { + if (model.attribute) + uigraph.hoveredNode = null + } onClicked: { if (model.attribute) - uigraph.selectedNode = model.attribute.node; + uigraph.selectedNode = model.attribute.node else - uigraph.selectedNode = null; + uigraph.selectedNode = null if (mouse.button == Qt.RightButton) - contextMenu.popup(); - mediaListView.currentIndex = index; + contextMenu.popup() + mediaListView.currentIndex = index // Update the resection ID-related objects based on the active model Viewer3DSettings.resectionIdCount = model.resectionIdCount