diff --git a/meshroom/ui/qml/Viewer/FloatImage.qml b/meshroom/ui/qml/Viewer/FloatImage.qml index 3ae092aa..e34f5b3d 100644 --- a/meshroom/ui/qml/Viewer/FloatImage.qml +++ b/meshroom/ui/qml/Viewer/FloatImage.qml @@ -62,7 +62,9 @@ AliceVision.FloatImageViewer { property string sfmPath: "" function updateSfmPath() { - var activeNode = _reconstruction.activeNodes.get('sfm').node; + console.warn("SFM UPDATE - Float IV") + + var activeNode = _reconstruction.activeNodes.get('SfMTransform').node; if(!activeNode) { @@ -70,7 +72,7 @@ AliceVision.FloatImageViewer { } else { - root.sfmPath = activeNode.attribute("outputViewsAndPoses").value; + root.sfmPath = activeNode.attribute("input").value; } root.setSfmPath(sfmPath); } @@ -81,8 +83,12 @@ AliceVision.FloatImageViewer { ppRect.y = pp.y; } - function rotatePanorama(dx, dy) { - root.setRotationPano(dx, dy); + function rotatePanoDegrees(yaw, pitch) { + root.rotatePanoramaDegrees(yaw, pitch); + } + + function rotatePanoRadians(yaw, pitch) { + root.rotatePanoramaRadians(yaw, pitch); } function updateMouseAreaPano() { diff --git a/meshroom/ui/qml/Viewer/PanoramaViewer.qml b/meshroom/ui/qml/Viewer/PanoramaViewer.qml index 7e46428a..e2779da5 100644 --- a/meshroom/ui/qml/Viewer/PanoramaViewer.qml +++ b/meshroom/ui/qml/Viewer/PanoramaViewer.qml @@ -60,6 +60,28 @@ AliceVision.PanoramaViewer { property int yaw: 0; property int pitch: 0; + // Yaw and Pitch in Degrees from SfMTransform sliders + property int yawNode: _reconstruction.activeNodes.get('SfMTransform').node.attribute("manualTransform.manualRotation.y").value; + property int pitchNode: _reconstruction.activeNodes.get('SfMTransform').node.attribute("manualTransform.manualRotation.x").value; + + + onYawNodeChanged: { + if (!isRotating) { + for (var i = 0; i < repeater.model; i++) { + repeater.itemAt(i).item.rotatePanoramaDegrees(yawNode, pitchNode); + } + } + } + + onPitchNodeChanged: { + if (!isRotating) { + for (var i = 0; i < repeater.model; i++) { + repeater.itemAt(i).item.rotatePanoDegrees(yawNode, pitchNode); + } + } + } + + Item { id: containerPanorama z: 10 @@ -90,8 +112,7 @@ AliceVision.PanoramaViewer { lastX = mouse.x; lastY = mouse.y; for (var i = 0; i < repeater.model; i++) { - //repeater.itemAt(i).item.rotatePanorama((xoffset / width) * mouseMultiplier, -(yoffset / height) * mouseMultiplier) - repeater.itemAt(i).item.rotatePanorama(0, -(yoffset / height) * mouseMultiplier) + repeater.itemAt(i).item.rotatePanoRadians((xoffset / width) * mouseMultiplier, -(yoffset / height) * mouseMultiplier); } } } @@ -106,7 +127,7 @@ AliceVision.PanoramaViewer { if (isRotating) { // Update Euler angles - var activeNode = _reconstruction.activeNodes.get('sfm').node; + var activeNode = _reconstruction.activeNodes.get('SfMTransform').node; root.yaw = repeater.itemAt(0).item.getYaw(); root.pitch = repeater.itemAt(0).item.getPitch(); @@ -152,12 +173,11 @@ AliceVision.PanoramaViewer { } - - property string sfmPath: "" function updateSfmPath() { - var activeNode = _reconstruction.activeNodes.get('sfm').node; + console.warn("SFM UPDATE - PANO") + var activeNode = _reconstruction.activeNodes.get('SfMTransform').node; if(!activeNode) { @@ -165,7 +185,7 @@ AliceVision.PanoramaViewer { } else { - root.sfmPath = activeNode.attribute("outputViewsAndPoses").value; + root.sfmPath = activeNode.attribute("input").value; } root.setSfmPath(sfmPath); } @@ -196,7 +216,6 @@ AliceVision.PanoramaViewer { 'index' : index, 'idView': Qt.binding(function() { return cId; }), }) - //repeater.itemAt(index).item.rotatePanorama(yaw * (3.14 / 180), pitch * (3.14 / 180)) } else { // Force the unload (instead of using Component.onCompleted to load it once and for all) is necessary since Qt 5.14 diff --git a/meshroom/ui/qml/Viewer/PanoramaViewer.qml.autosave b/meshroom/ui/qml/Viewer/PanoramaViewer.qml.autosave new file mode 100644 index 00000000..bec2c6d3 --- /dev/null +++ b/meshroom/ui/qml/Viewer/PanoramaViewer.qml.autosave @@ -0,0 +1,266 @@ +import QtQuick 2.11 +import Utils 1.0 + +import AliceVision 1.0 as AliceVision + +/** + * FloatImage displays an Image with gamma / offset / channel controls + * Requires QtAliceVision plugin. + */ + +AliceVision.PanoramaViewer { + id: root + + width: 3000 + height: 1500 + visible: (status === Image.Ready) + + // paintedWidth / paintedHeight / status for compatibility with standard Image + property int paintedWidth: textureSize.width + property int paintedHeight: textureSize.height + property var status: Image.Null + + property int downscaleValue: 2 + + property int subdivisionsPano: 12 + + property bool isEditable: true + property bool isHighlightable: true + + property bool displayGridPano: true + + property int mouseMultiplier: 1 + + onIsHighlightableChanged:{ + for (var i = 0; i < repeater.model; i++) { + repeater.itemAt(i).item.onChangedHighlightState(isHighlightable); + } + } + + onSubdivisionsPanoChanged:{ + for (var i = 0; i < repeater.model; i++) { + repeater.itemAt(i).item.updateSubdivisions(subdivisionsPano); + } + } + + onDownscaleValueChanged: { + for (var i = 0; i < repeater.model; i++) { + repeater.itemAt(i).item.setDownscale(downscaleValue); + } + } + + clearBeforeLoad: true + + property alias containsMouse: mouseAreaPano.containsMouse + + property bool isRotating: false + property var lastX : 0 + property var lastY: 0 + + property int yaw: 0; + property int pitch: 0; + + // Yaw and Pitch in Degrees from SfMTransform sliders + property int yawNode: _reconstruction.activeNodes.get('SfMTransform').node.attribute("manualTransform.manualRotation.y").value; + property int pitchNode: _reconstruction.activeNodes.get('SfMTransform').node.attribute("manualTransform.manualRotation.x").value; + + + onYawNodeChanged: { + if (!isRotating) { + for (var i = 0; i < repeater.model; i++) { + repeater.itemAt(i).item.rotatePanoramaDegrees(yawNode, pitchNod); + } + } + } + + onPitchNodeChanged: { + if (!isRotating) { + for (var i = 0; i < repeater.model; i++) { + repeater.itemAt(i).item.rotatePanoDegrees(yawNode, pitchNode); + } + } + } + + + Item { + id: containerPanorama + z: 10 + Rectangle { + width: 3000 + height: 1500 + //color: mouseAreaPano.containsMouse? "red" : "green" + color: "transparent" + MouseArea { + id: mouseAreaPano + anchors.fill: parent + hoverEnabled: true + cursorShape: { + if (isEditable) + isRotating ? Qt.ClosedHandCursor : Qt.OpenHandCursor + } + onPositionChanged: { + // Send Mouse Coordinates to Float Images Viewers + for (var i = 0; i < repeater.model && isHighlightable; i++) { + var highlight = repeater.itemAt(i).item.getMouseCoordinates(mouse.x, mouse.y); + repeater.itemAt(i).z = highlight ? 2 : 0 + } + + // Rotate Panorama + if (isRotating && isEditable) { + var xoffset = mouse.x - lastX; + var yoffset = mouse.y - lastY; + lastX = mouse.x; + lastY = mouse.y; + for (var i = 0; i < repeater.model; i++) { + repeater.itemAt(i).item.rotatePanoRadians((xoffset / width) * mouseMultiplier, -(yoffset / height) * mouseMultiplier); + } + } + } + + onPressed:{ + isRotating = true; + lastX = mouse.x; + lastY = mouse.y; + } + + onReleased: { + if (isRotating) + { + // Update Euler angles + var activeNode = _reconstruction.activeNodes.get('SfMTransform').node; + + root.yaw = repeater.itemAt(0).item.getYaw(); + root.pitch = repeater.itemAt(0).item.getPitch(); + + activeNode.attribute("manualTransform.manualRotation.y").value = root.yaw; + activeNode.attribute("manualTransform.manualRotation.x").value = root.pitch; + } + + isRotating = false; + lastX = 0 + lastY = 0 + } + } + + // Grid Panorama Viewer + Canvas { + id: gridPano + visible: displayGridPano + anchors.fill : parent + property int wgrid: 40 + onPaint: { + var ctx = getContext("2d") + ctx.lineWidth = 1.0 + ctx.shadowBlur = 0 + ctx.strokeStyle = "grey" + var nrows = height/wgrid; + for(var i=0; i < nrows+1; i++){ + ctx.moveTo(0, wgrid*i); + ctx.lineTo(width, wgrid*i); + } + + var ncols = width/wgrid + for(var j=0; j < ncols+1; j++){ + ctx.moveTo(wgrid*j, 0); + ctx.lineTo(wgrid*j, height); + } + + ctx.closePath() + ctx.stroke() + } + } + } + } + + + property string sfmPath: "" + + function updateSfmPath() { + console.warn("SFM UPDATE - PANO") + var activeNode = _reconstruction.activeNodes.get('SfMTransform').node; + + if(!activeNode) + { + root.sfmPath = ""; + } + else + { + root.sfmPath = activeNode.attribute("input").value; + } + root.setSfmPath(sfmPath); + } + + property var pathList : [] + property var idList : [] + + Item { + id: panoImages + width: root.width + height: root.height + + Component { + id: imgPano + Loader { + id: floatOneLoader + active: root.status + visible: (floatOneLoader.status === Loader.Ready) + z:0 + //anchors.centerIn: parent + property string cSource: Filepath.stringToUrl(root.pathList[index].toString()) + property int cId: root.idList[index] + onActiveChanged: { + if(active) { + setSource("FloatImage.qml", { + 'isPanoViewer' : true, + 'source': Qt.binding(function() { return cSource; }), + 'index' : index, + 'idView': Qt.binding(function() { return cId; }), + }) + + } else { + // Force the unload (instead of using Component.onCompleted to load it once and for all) is necessary since Qt 5.14 + setSource("", {}) + } + } + } + } + Repeater { + id: repeater + model: 0 + delegate: imgPano + + } + Connections { + target: root + onImagesDataChanged: { + //We receive the map from C++ + //Resetting arrays to avoid problem with push + pathList = [] + idList = [] + + //Iterating through the map + for (var path in imagesData) { + console.warn("Object item:", path, "=", imagesData[path]) + root.pathList.push(path) + root.idList.push(imagesData[path]) + } + console.warn(root.pathList.length) + + //Changing the repeater model (number of elements) + panoImages.updateRepeater() + + root.status = Image.Ready; + } + } + + function updateRepeater() { + if(repeater.model !== root.pathList.length){ + repeater.model = 0; + } + repeater.model = root.pathList.length; + } + } + + + +}