mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-06-02 02:42:05 +02:00
[ui] GraphEditor: solo 3D media with Double Click + Control modifier
* allow to solo a 3D media from the GraphEditor by double clicking on a node or an attribute with the Control modifier pressed * consistent with Viewer3D.MediaLibrary behavior (solo on Ctrl+Click on visibility button) * handle supported file extensions in Viewer3DSettings
This commit is contained in:
parent
4541d825ad
commit
b5c985b3fb
8 changed files with 46 additions and 30 deletions
|
@ -15,7 +15,7 @@ ListView {
|
||||||
property int labelWidth: 180
|
property int labelWidth: 180
|
||||||
|
|
||||||
signal upgradeRequest()
|
signal upgradeRequest()
|
||||||
signal attributeDoubleClicked(var attribute)
|
signal attributeDoubleClicked(var mouse, var attribute)
|
||||||
|
|
||||||
implicitHeight: contentHeight
|
implicitHeight: contentHeight
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ ListView {
|
||||||
readOnly: root.readOnly
|
readOnly: root.readOnly
|
||||||
labelWidth: root.labelWidth
|
labelWidth: root.labelWidth
|
||||||
attribute: object
|
attribute: object
|
||||||
onDoubleClicked: root.attributeDoubleClicked(attr)
|
onDoubleClicked: root.attributeDoubleClicked(mouse, attr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ RowLayout {
|
||||||
|
|
||||||
readonly property bool editable: !attribute.isOutput && !attribute.isLink && !readOnly
|
readonly property bool editable: !attribute.isOutput && !attribute.isLink && !readOnly
|
||||||
|
|
||||||
signal doubleClicked(var attr)
|
signal doubleClicked(var mouse, var attr)
|
||||||
|
|
||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ RowLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
acceptedButtons: Qt.AllButtons
|
acceptedButtons: Qt.AllButtons
|
||||||
onDoubleClicked: root.doubleClicked(root.attribute)
|
onDoubleClicked: root.doubleClicked(mouse, root.attribute)
|
||||||
|
|
||||||
property Component menuComp: Menu {
|
property Component menuComp: Menu {
|
||||||
id: paramMenu
|
id: paramMenu
|
||||||
|
|
|
@ -21,7 +21,7 @@ Item {
|
||||||
// signals
|
// signals
|
||||||
signal workspaceMoved()
|
signal workspaceMoved()
|
||||||
signal workspaceClicked()
|
signal workspaceClicked()
|
||||||
signal nodeDoubleClicked(var node)
|
signal nodeDoubleClicked(var mouse, var node)
|
||||||
|
|
||||||
// trigger initial fit() after initialization
|
// trigger initial fit() after initialization
|
||||||
// (ensure GraphEditor has its final size)
|
// (ensure GraphEditor has its final size)
|
||||||
|
@ -409,7 +409,7 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDoubleClicked: root.nodeDoubleClicked(node)
|
onDoubleClicked: root.nodeDoubleClicked(mouse, node)
|
||||||
|
|
||||||
onMoved: uigraph.moveNode(node, position)
|
onMoved: uigraph.moveNode(node, position)
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ Panel {
|
||||||
property bool readOnly: false
|
property bool readOnly: false
|
||||||
property bool isCompatibilityNode: node && node.compatibilityIssue !== undefined
|
property bool isCompatibilityNode: node && node.compatibilityIssue !== undefined
|
||||||
|
|
||||||
signal attributeDoubleClicked(var attribute)
|
signal attributeDoubleClicked(var mouse, var attribute)
|
||||||
signal upgradeRequest()
|
signal upgradeRequest()
|
||||||
|
|
||||||
title: "Node" + (node !== null ? " - <b>" + node.label + "</b>" : "")
|
title: "Node" + (node !== null ? " - <b>" + node.label + "</b>" : "")
|
||||||
|
@ -116,7 +116,7 @@ Panel {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
attributes: root.node.attributes
|
attributes: root.node.attributes
|
||||||
readOnly: root.readOnly || root.isCompatibilityNode
|
readOnly: root.readOnly || root.isCompatibilityNode
|
||||||
onAttributeDoubleClicked: root.attributeDoubleClicked(attribute)
|
onAttributeDoubleClicked: root.attributeDoubleClicked(mouse, attribute)
|
||||||
onUpgradeRequest: root.upgradeRequest()
|
onUpgradeRequest: root.upgradeRequest()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,21 @@ FocusScope {
|
||||||
mediaLibrary.load(filepath);
|
mediaLibrary.load(filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// View 'attribute' in the 3D Viewer. Media will be loaded if needed.
|
||||||
|
/// Returns whether the attribute can be visualized (matching type and extension).
|
||||||
function view(attribute) {
|
function view(attribute) {
|
||||||
mediaLibrary.view(attribute)
|
if( attribute.desc.type === "File"
|
||||||
|
&& Viewer3DSettings.supportedExtensions.indexOf(Filepath.extension(attribute.value)) > - 1 )
|
||||||
|
{
|
||||||
|
mediaLibrary.view(attribute);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Solo (i.e display only) the given attribute.
|
||||||
|
function solo(attribute) {
|
||||||
|
mediaLibrary.solo(mediaLibrary.find(attribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
function clear() {
|
function clear() {
|
||||||
|
|
|
@ -11,6 +11,16 @@ Item {
|
||||||
readonly property Component depthMapLoaderComp: Qt.createComponent("DepthMapLoader.qml")
|
readonly property Component depthMapLoaderComp: Qt.createComponent("DepthMapLoader.qml")
|
||||||
readonly property bool supportDepthMap: depthMapLoaderComp.status == Component.Ready
|
readonly property bool supportDepthMap: depthMapLoaderComp.status == Component.Ready
|
||||||
|
|
||||||
|
// supported 3D files extensions
|
||||||
|
readonly property var supportedExtensions: {
|
||||||
|
var exts = ['.obj'];
|
||||||
|
if(supportAlembic)
|
||||||
|
exts.push('.abc');
|
||||||
|
if(supportDepthMap)
|
||||||
|
exts.push('.exr');
|
||||||
|
return exts;
|
||||||
|
}
|
||||||
|
|
||||||
// Available render modes
|
// Available render modes
|
||||||
readonly property var renderModes: [ // Can't use ListModel because of MaterialIcons expressions
|
readonly property var renderModes: [ // Can't use ListModel because of MaterialIcons expressions
|
||||||
{"name": "Solid", "icon": MaterialIcons.crop_din },
|
{"name": "Solid", "icon": MaterialIcons.crop_din },
|
||||||
|
|
|
@ -21,6 +21,7 @@ Item {
|
||||||
property variant reconstruction: _reconstruction
|
property variant reconstruction: _reconstruction
|
||||||
readonly property variant cameraInits: _reconstruction.cameraInits
|
readonly property variant cameraInits: _reconstruction.cameraInits
|
||||||
property bool readOnly: false
|
property bool readOnly: false
|
||||||
|
readonly property Viewer3D viewer3D: viewer3D
|
||||||
|
|
||||||
|
|
||||||
implicitWidth: 300
|
implicitWidth: 300
|
||||||
|
@ -32,10 +33,6 @@ Item {
|
||||||
viewer3D.load(filepath);
|
viewer3D.load(filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
function viewAttribute(attr) {
|
|
||||||
viewer3D.view(attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: reconstruction
|
target: reconstruction
|
||||||
onGraphChanged: viewer3D.clear()
|
onGraphChanged: viewer3D.clear()
|
||||||
|
@ -48,7 +45,7 @@ Item {
|
||||||
function viewSfM() {
|
function viewSfM() {
|
||||||
if(!reconstruction.sfm)
|
if(!reconstruction.sfm)
|
||||||
return;
|
return;
|
||||||
viewAttribute(reconstruction.sfm.attribute('output'));
|
viewer3D.view(reconstruction.sfm.attribute('output'));
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemPalette { id: activePalette }
|
SystemPalette { id: activePalette }
|
||||||
|
@ -144,7 +141,7 @@ Item {
|
||||||
anchors.bottomMargin: 10
|
anchors.bottomMargin: 10
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
visible: outputReady && outputMediaIndex == -1
|
visible: outputReady && outputMediaIndex == -1
|
||||||
onClicked: viewAttribute(_reconstruction.endNode.attribute("outputMesh"))
|
onClicked: viewer3D.view(_reconstruction.endNode.attribute("outputMesh"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,6 @@ ApplicationWindow {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
// supported 3D files extensions
|
|
||||||
readonly property var _3dFileExtensions: ['.obj', '.abc']
|
|
||||||
onClosing: {
|
onClosing: {
|
||||||
// make sure document is saved before exiting application
|
// make sure document is saved before exiting application
|
||||||
close.accepted = false
|
close.accepted = false
|
||||||
|
@ -505,6 +503,14 @@ ApplicationWindow {
|
||||||
Layout.minimumHeight: 50
|
Layout.minimumHeight: 50
|
||||||
reconstruction: _reconstruction
|
reconstruction: _reconstruction
|
||||||
readOnly: _reconstruction.computing
|
readOnly: _reconstruction.computing
|
||||||
|
|
||||||
|
function viewIn3D(attribute, mouse) {
|
||||||
|
var loaded = viewer3D.view(attribute);
|
||||||
|
// solo media if Control modifier was held
|
||||||
|
if(loaded && mouse && mouse.modifiers & Qt.ControlModifier)
|
||||||
|
viewer3D.solo(attribute);
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,15 +556,6 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayAttribute(attr) {
|
|
||||||
if( attr.desc.type === "File"
|
|
||||||
&& _3dFileExtensions.indexOf(Filepath.extension(attr.value)) > - 1 )
|
|
||||||
{
|
|
||||||
workspaceView.viewAttribute(attr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphEditor {
|
GraphEditor {
|
||||||
id: graphEditor
|
id: graphEditor
|
||||||
|
@ -571,14 +568,13 @@ ApplicationWindow {
|
||||||
onNodeDoubleClicked: {
|
onNodeDoubleClicked: {
|
||||||
if(node.nodeType === "StructureFromMotion")
|
if(node.nodeType === "StructureFromMotion")
|
||||||
{
|
{
|
||||||
_reconstruction.sfm = node
|
_reconstruction.sfm = node;
|
||||||
return
|
|
||||||
}
|
}
|
||||||
for(var i=0; i < node.attributes.count; ++i)
|
for(var i=0; i < node.attributes.count; ++i)
|
||||||
{
|
{
|
||||||
var attr = node.attributes.at(i)
|
var attr = node.attributes.at(i)
|
||||||
if(attr.isOutput
|
if(attr.isOutput
|
||||||
&& graphEditorPanel.displayAttribute(attr))
|
&& workspaceView.viewIn3D(attr, mouse))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -592,7 +588,7 @@ ApplicationWindow {
|
||||||
node: _reconstruction.selectedNode
|
node: _reconstruction.selectedNode
|
||||||
// Make NodeEditor readOnly when computing
|
// Make NodeEditor readOnly when computing
|
||||||
readOnly: graphLocked
|
readOnly: graphLocked
|
||||||
onAttributeDoubleClicked: graphEditorPanel.displayAttribute(attribute)
|
onAttributeDoubleClicked: workspaceView.viewIn3D(attribute, mouse)
|
||||||
onUpgradeRequest: {
|
onUpgradeRequest: {
|
||||||
var n = _reconstruction.upgradeNode(node);
|
var n = _reconstruction.upgradeNode(node);
|
||||||
_reconstruction.selectedNode = n;
|
_reconstruction.selectedNode = n;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue