diff --git a/meshroom/ui/qml/Viewer/FeaturesInfoOverlay.qml b/meshroom/ui/qml/Viewer/FeaturesInfoOverlay.qml index 52c1321072..dbc9854241 100644 --- a/meshroom/ui/qml/Viewer/FeaturesInfoOverlay.qml +++ b/meshroom/ui/qml/Viewer/FeaturesInfoOverlay.qml @@ -16,6 +16,7 @@ FloatingPane { property int pluginStatus: Loader.Null property Item featuresViewer: null property var featureExtractionNode: null + property var mfeatures: null ColumnLayout { // Header @@ -73,7 +74,7 @@ FloatingPane { id: featureType property var viewer: root.featuresViewer.itemAt(index) - + property var mfeatures: root.mfeatures spacing: 4 // Features visibility toogle @@ -127,18 +128,19 @@ FloatingPane { } // Feature type name Label { + property var mdescfeatures : featureType.viewer.mdescFeatures text: { - if(featureType.viewer.loadingFeatures) + if(featureType.mfeatures.loadingFeatures || mdescfeatures === null) return featureType.viewer.describerType; return featureType.viewer.describerType + ": " + - featureType.viewer.features.length + " / " + - (featureType.viewer.haveValidTracks ? featureType.viewer.nbTracks : " - ") + " / " + - (featureType.viewer.haveValidLandmarks ? featureType.viewer.nbLandmarks : " - "); + mdescfeatures.features.length + " / " + + (featureType.mfeatures.haveValidTracks ? mdescfeatures.nbTracks : " - ") + " / " + + (featureType.mfeatures.haveValidLandmarks ? mdescfeatures.nbLandmarks : " - "); } } // Feature loading status Loader { - active: featureType.viewer.loadingFeatures + active: featureType.mfeatures.loadingFeatures sourceComponent: BusyIndicator { padding: 0 implicitWidth: 12 diff --git a/meshroom/ui/qml/Viewer/FeaturesViewer.qml b/meshroom/ui/qml/Viewer/FeaturesViewers.qml similarity index 64% rename from meshroom/ui/qml/Viewer/FeaturesViewer.qml rename to meshroom/ui/qml/Viewer/FeaturesViewers.qml index 83b796cc52..2f9f05b5d3 100644 --- a/meshroom/ui/qml/Viewer/FeaturesViewer.qml +++ b/meshroom/ui/qml/Viewer/FeaturesViewers.qml @@ -7,19 +7,12 @@ import Utils 1.0 * FeaturesViewer displays the extracted feature points of a View. * Requires QtAliceVision plugin. */ + Repeater { id: root - /// ViewID to display the features of - property int viewId - /// SfMData to display the data of SfM - property var sfmData - /// Folder containing the features files - property string featureFolder - /// Folder containing the matches files - property var tracks - /// The list of describer types to load - property alias describerTypes: root.model + /// MFeatures instance + property var mfeatures /// List of available display modes readonly property var displayModes: ['Points', 'Squares', 'Oriented Squares'] /// Current display mode index @@ -27,20 +20,16 @@ Repeater { /// The list of colors used for displaying several describers property var colors: [Colors.blue, Colors.green, Colors.yellow, Colors.orange, Colors.cyan, Colors.pink, Colors.lime] //, Colors.red - model: root.describerTypes + model: mfeatures.describerTypes // instantiate one FeaturesViewer by describer type delegate: AliceVision.FeaturesViewer { readonly property int colorIndex: (index + colorOffset) % root.colors.length property int colorOffset: 0 describerType: modelData - featureFolder: root.featureFolder - mtracks: root.tracks - viewId: root.viewId color: root.colors[colorIndex] landmarkColor: Colors.red displayMode: root.displayMode - msfmData: root.sfmData + mdescFeatures: root.mfeatures.allFeatures.hasOwnProperty(modelData) ? root.mfeatures.allFeatures[modelData] : null } - -} +} \ No newline at end of file diff --git a/meshroom/ui/qml/Viewer/MFeatures.qml b/meshroom/ui/qml/Viewer/MFeatures.qml new file mode 100644 index 0000000000..39dafc9b47 --- /dev/null +++ b/meshroom/ui/qml/Viewer/MFeatures.qml @@ -0,0 +1,7 @@ +import QtQuick 2.11 +import AliceVision 1.0 as AliceVision + +// Features Data +AliceVision.MFeatures { + id: root +} \ No newline at end of file diff --git a/meshroom/ui/qml/Viewer/Viewer2D.qml b/meshroom/ui/qml/Viewer/Viewer2D.qml index 919c732bc6..40b18ff6c0 100644 --- a/meshroom/ui/qml/Viewer/Viewer2D.qml +++ b/meshroom/ui/qml/Viewer/Viewer2D.qml @@ -19,12 +19,12 @@ FocusScope { property string loadingModules: { var res = "" - if(imgContainer.image.status === Image.Loading) + if(imgContainer.image && imgContainer.image.status === Image.Loading) res += " Image"; - if(featuresViewerLoader.status === Loader.Ready) + if(featuresViewerLoader.item && featuresViewerLoader.status === Loader.Ready) { for (var i = 0; i < featuresViewerLoader.item.count; ++i) { - if(featuresViewerLoader.item.itemAt(i).loadingFeatures) + if(featuresViewerLoader.item.itemAt(i).mdescFeatures.loadingFeatures) { res += " Features"; break; @@ -33,14 +33,14 @@ FocusScope { } if(msfmDataLoader.status === Loader.Ready) { - if(msfmDataLoader.item.status === MSfMData.Loading) + if(msfmDataLoader.item && msfmDataLoader.item.status === MSfMData.Loading) { res += " SfMData"; } } if(mtracksLoader.status === Loader.Ready) { - if(mtracksLoader.item.status === MTracks.Loading) + if(mtracksLoader.item && mtracksLoader.item.status === MTracks.Loading) res += " Tracks"; } return res; @@ -253,16 +253,12 @@ FocusScope { } x: (imgContainer.image && rotation === 90) ? imgContainer.image.paintedWidth : 0 y: (imgContainer.image && rotation === -90) ? imgContainer.image.paintedHeight : 0 - + onActiveChanged: { if(active) { - // instantiate and initialize a FeaturesViewer component dynamically using Loader.setSource - setSource("FeaturesViewer.qml", { - 'viewId': Qt.binding(function() { return _reconstruction.selectedViewId; }), - 'model': Qt.binding(function() { return _reconstruction.featureExtraction ? _reconstruction.featureExtraction.attribute("describerTypes").value : ""; }), - 'featureFolder': Qt.binding(function() { return _reconstruction.featureExtraction ? Filepath.stringToUrl(_reconstruction.featureExtraction.attribute("output").value) : ""; }), - 'tracks': Qt.binding(function() { return mtracksLoader.status === Loader.Ready ? mtracksLoader.item : null; }), - 'sfmData': Qt.binding(function() { return msfmDataLoader.status === Loader.Ready ? msfmDataLoader.item : null; }), + // instantiate and initialize FeaturesViewer(s) component(s) dynamically using Loader.setSource + setSource("FeaturesViewers.qml", { + 'mfeatures': Qt.binding(function() { return mfeaturesLoader.status === Loader.Ready ? mfeaturesLoader.item : null; }) }) } else { // Force the unload (instead of using Component.onCompleted to load it once and for all) is necessary since Qt 5.14 @@ -332,11 +328,26 @@ FocusScope { metadata: visible ? root.metadata : {} } + Loader { + id: mfeaturesLoader + // active: mfeaturesLoader.status === Loader.Ready + + Component.onCompleted: { + setSource("MFeatures.qml", { + 'viewId': Qt.binding(function() { return _reconstruction.selectedViewId; }), + 'describerTypes': Qt.binding(function() { return _reconstruction.featureExtraction ? _reconstruction.featureExtraction.attribute("describerTypes").value : ""; }), + 'featureFolder': Qt.binding(function() { return _reconstruction.featureExtraction ? Filepath.stringToUrl(_reconstruction.featureExtraction.attribute("output").value) : ""; }), + 'mtracks': Qt.binding(function() { return mtracksLoader.status === Loader.Ready ? mtracksLoader.item : null; }), + 'msfmData': Qt.binding(function() { return msfmDataLoader.status === Loader.Ready ? msfmDataLoader.item : null; }), + }) + } + } + Loader { id: msfmDataLoader // active: _reconstruction.sfm && _reconstruction.sfm.isComputed() - property bool isUsed: displayFeatures.checked || displaySfmStatsView.checked || displaySfmDataGlobalStats.checked + property bool isUsed: displayFeatures.checked || displaySfmStatsView.checked || displaySfmDataGlobalStats.checked || mfeaturesLoader property var activeNode: _reconstruction.sfm property bool isComputed: activeNode && activeNode.isComputed() @@ -366,7 +377,7 @@ FocusScope { // instantiate and initialize a SfmStatsView component dynamically using Loader.setSource // so it can fail safely if the c++ plugin is not available setSource("MSfMData.qml", { - 'sfmDataPath': Qt.binding(function() { return Filepath.stringToUrl(isComputed ? activeNode.attribute("output").value : ""); }), + 'sfmDataPath': Qt.binding(function() { return Filepath.stringToUrl(isComputed ? activeNode.attribute("output").value : ""); }) }) } } @@ -374,7 +385,7 @@ FocusScope { id: mtracksLoader // active: _reconstruction.featureMatching - property bool isUsed: displayFeatures.checked || displaySfmStatsView.checked || displaySfmDataGlobalStats.checked + property bool isUsed: displayFeatures.checked || displaySfmStatsView.checked || displaySfmDataGlobalStats.checked || mfeaturesLoader property var activeNode: _reconstruction.featureMatching property bool isComputed: activeNode && activeNode.isComputed() @@ -434,7 +445,6 @@ FocusScope { setSource("SfmGlobalStats.qml", { 'msfmData': Qt.binding(function() { return msfmDataLoader.item; }), 'mTracks': Qt.binding(function() { return mtracksLoader.item; }), - }) } } @@ -452,6 +462,7 @@ FocusScope { featureExtractionNode: _reconstruction.featureExtraction pluginStatus: featuresViewerLoader.status featuresViewer: featuresViewerLoader.item + mfeatures: mfeaturesLoader.item } } }