Meshroom/meshroom/ui/qml/Viewer3D/Viewer3D.qml
Candice Bentéjac 091346cbb8 [qml] Optimize QML files and fix syntax warnings
This commit addresses warnings that were raised by QtCreator's linter:
- IDs declared more than once
- variables declared more than once in the same scope
- type coercions
- variables declared as "var" when their type is known
- unclosed "case" in switch-case
2023-07-04 12:04:14 +02:00

366 lines
13 KiB
QML

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls 1.4 as Controls1
import QtQuick.Layouts 1.11
import QtQml.Models 2.15
import QtQuick.Scene3D 2.15
import Qt3D.Core 2.15
import Qt3D.Render 2.15
import Qt3D.Extras 2.15
import Qt3D.Input 2.15 as Qt3DInput // to avoid clash with Controls2 Action
import MaterialIcons 2.2
import Controls 1.0
import Utils 1.0
FocusScope {
id: root
property int renderMode: 2
readonly property alias library: mediaLibrary
readonly property alias mainCamera: mainCamera
readonly property vector3d defaultCamPosition: Qt.vector3d(12.0, 10.0, -12.0)
readonly property vector3d defaultCamUpVector: Qt.vector3d(0.0, 1.0, 0.0)
readonly property vector3d defaultCamViewCenter: Qt.vector3d(0.0, 0.0, 0.0)
readonly property var viewpoint: _reconstruction ? _reconstruction.selectedViewpoint : null
readonly property bool doSyncViewpointCamera: Viewer3DSettings.syncViewpointCamera && (viewpoint && viewpoint.isReconstructed)
// functions
function resetCameraPosition() {
mainCamera.position = defaultCamPosition;
mainCamera.upVector = defaultCamUpVector;
mainCamera.viewCenter = defaultCamViewCenter;
}
function load(filepath, label = undefined) {
mediaLibrary.load(filepath, label);
}
/// 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) {
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() {
mediaLibrary.clear()
}
SystemPalette { id: activePalette }
Scene3D {
id: scene3D
anchors.fill: parent
cameraAspectRatioMode: Scene3D.AutomaticAspectRatio // vs. UserAspectRatio
hoverEnabled: true // if true, will trigger positionChanged events in attached MouseHandler
aspects: ["logic", "input"]
focus: true
// We cannot use directly an ExifOrientedViewer since this component is not a Loader
// so we redefine the transform using the ExifOrientation utility functions
property var orientationTag: (doSyncViewpointCamera && root.viewpoint) ? root.viewpoint.orientation.toString() : "1"
transform: [
Rotation {
angle: ExifOrientation.rotation(scene3D.orientationTag)
origin.x: scene3D.width * 0.5
origin.y: scene3D.height * 0.5
},
Scale {
xScale: ExifOrientation.xscale(scene3D.orientationTag)
origin.x: scene3D.width * 0.5
origin.y: scene3D.height * 0.5
}
]
Keys.onPressed: {
if (event.key === Qt.Key_F) {
resetCameraPosition();
}
else if(Qt.Key_1 <= event.key && event.key < Qt.Key_1 + Viewer3DSettings.renderModes.length)
{
Viewer3DSettings.renderMode = event.key - Qt.Key_1;
}
else {
event.accepted = false
}
}
Entity {
id: rootEntity
Camera {
id: mainCamera
projectionType: CameraLens.PerspectiveProjection
enabled: cameraSelector.camera == mainCamera
fieldOfView: 45
nearPlane : 0.01
farPlane : 10000.0
position: defaultCamPosition
upVector: defaultCamUpVector
viewCenter: defaultCamViewCenter
aspectRatio: width/height
Behavior on viewCenter {
Vector3dAnimation { duration: 250 }
}
Behavior on position {
Vector3dAnimation { duration: 250 }
}
// Scene light, attached to the camera
Entity {
components: [
PointLight {
color: "white"
}
]
}
}
ViewpointCamera {
id: viewpointCamera
enabled: cameraSelector.camera === camera
viewpoint: root.viewpoint
camera.aspectRatio: width/height
}
TrackballGizmo {
beamRadius: 4.0/root.height
alpha: cameraController.moving ? 1.0 : 0.7
enabled: Viewer3DSettings.displayGizmo && cameraSelector.camera == mainCamera
xColor: Colors.red
yColor: Colors.green
zColor: Colors.blue
centerColor: Colors.sysPalette.highlight
transform: Transform {
translation: mainCamera.viewCenter
scale: 0.15 * mainCamera.viewCenter.minus(mainCamera.position).length()
}
}
DefaultCameraController {
id: cameraController
enabled: cameraSelector.camera == mainCamera
windowSize {
width: root.width
height: root.height
}
rotationSpeed: 16
trackballSize: 0.9
camera: mainCamera
focus: scene3D.activeFocus
onMousePressed: {
scene3D.forceActiveFocus()
if(mouse.button === Qt.LeftButton)
{
if(!doubleClickTimer.running)
doubleClickTimer.restart()
}
else
doubleClickTimer.stop()
}
onMouseReleased: {
if(moving)
return
if(!moved && mouse.button === Qt.RightButton)
{
contextMenu.popup()
}
}
// Manually handle double click to activate object picking
// for camera re-centering only during a short amount of time
Timer {
id: doubleClickTimer
running: false
interval: 300
}
}
components: [
RenderSettings {
pickingSettings.pickMethod: PickingSettings.PrimitivePicking // enables point/edge/triangle picking
pickingSettings.pickResultMode: PickingSettings.NearestPick
renderPolicy: RenderSettings.Always
activeFrameGraph: RenderSurfaceSelector {
// Use the whole viewport
Viewport {
normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
CameraSelector {
id: cameraSelector
camera: doSyncViewpointCamera ? viewpointCamera.camera : mainCamera
FrustumCulling {
ClearBuffers {
clearColor: "transparent"
buffers : ClearBuffers.ColorDepthBuffer
RenderStateSet {
renderStates: [
PointSize {
sizeMode: Viewer3DSettings.fixedPointSize ? PointSize.Fixed : PointSize.Programmable
value: Viewer3DSettings.pointSize
},
DepthTest { depthFunction: DepthTest.Less }
]
}
}
LayerFilter {
filterMode: LayerFilter.DiscardAnyMatchingLayers
layers: Layer {id: drawOnFront}
}
LayerFilter {
filterMode: LayerFilter.AcceptAnyMatchingLayers
layers: [drawOnFront]
RenderStateSet {
renderStates: DepthTest { depthFunction: DepthTest.GreaterOrEqual }
}
}
}
}
}
}
},
Qt3DInput.InputSettings { }
]
MediaLibrary {
id: mediaLibrary
renderMode: Viewer3DSettings.renderMode
// Picking to set focus point (camera view center)
// Only activate it when a double click may happen or when the 'Control' key is pressed
pickingEnabled: cameraController.pickingActive || doubleClickTimer.running
camera: cameraSelector.camera
// Used for TransformGizmo in BoundingBox
sceneCameraController: cameraController
frontLayerComponent: drawOnFront
window: root
components: [
Transform {
id: transform
}
]
onPressed: {
if(pick.button === Qt.LeftButton)
{
mainCamera.viewCenter = pick.worldIntersection;
}
doubleClickTimer.stop();
}
}
Locator3D { enabled: Viewer3DSettings.displayOrigin }
Grid3D { enabled: Viewer3DSettings.displayGrid }
}
}
// Image overlay when navigating reconstructed cameras
Loader {
id: imageOverlayLoader
anchors.fill: parent
active: doSyncViewpointCamera
visible: Viewer3DSettings.showViewpointImageOverlay
sourceComponent: ImageOverlay {
id: imageOverlay
source: root.viewpoint.undistortedImageSource
imageRatio: root.viewpoint.orientedImageSize.width / root.viewpoint.orientedImageSize.height
uvCenterOffset: root.viewpoint.uvCenterOffset
showFrame: Viewer3DSettings.showViewpointImageFrame
imageOpacity: Viewer3DSettings.viewpointImageOverlayOpacity
}
}
// Media loading overlay
// (Scene3D is frozen while a media is being loaded)
Rectangle {
anchors.fill: parent
visible: mediaLibrary.loading
color: Qt.darker(Colors.sysPalette.mid, 1.2)
opacity: 0.6
BusyIndicator {
anchors.centerIn: parent
running: parent.visible
}
}
FloatingPane {
visible: Viewer3DSettings.renderMode == 3
anchors.bottom: renderModesPanel.top
GridLayout {
columns: 2
rowSpacing: 0
RadioButton { text: "SHL File"; autoExclusive: true; checked: true }
TextField {
text: Viewer3DSettings.shlFile
selectByMouse: true
Layout.minimumWidth: 300
onEditingFinished: Viewer3DSettings.shlFile = text
}
RadioButton {
Layout.columnSpan: 2
autoExclusive: true
text: "Normals"
onCheckedChanged: Viewer3DSettings.displayNormals = checked
}
}
}
// Rendering modes
FloatingPane {
id: renderModesPanel
anchors.bottom: parent.bottom
padding: 4
Row {
Repeater {
model: Viewer3DSettings.renderModes
delegate: MaterialToolButton {
text: modelData["icon"]
ToolTip.text: modelData["name"] + " (" + (index+1) + ")"
font.pointSize: 11
onClicked: Viewer3DSettings.renderMode = index
checked: Viewer3DSettings.renderMode === index
checkable: !checked // hack to disabled check on toggle
}
}
}
}
// Menu
Menu {
id: contextMenu
MenuItem {
text: "Fit All"
onTriggered: mainCamera.viewAll()
}
MenuItem {
text: "Reset View"
onTriggered: resetCameraPosition()
}
}
}