Merge remote-tracking branch 'origin/4.11'

Conflicts:
	src/plugins/designer/codemodelhelpers.cpp

Change-Id: I78906f2fbbfd27d254589a272ebca423b0b80699
This commit is contained in:
Eike Ziller
2019-11-28 08:24:10 +01:00
125 changed files with 2380 additions and 881 deletions

View File

@@ -31,7 +31,6 @@ Prerequisites:
* ActiveState Active Perl * ActiveState Active Perl
* MinGW with g++ 5.3 or Visual Studio 2017 or later * MinGW with g++ 5.3 or Visual Studio 2017 or later
* jom * jom
* Ninja (optional, needed for CMake)
* Python 3.5 or later (optional, needed for the python enabled debug helper) * Python 3.5 or later (optional, needed for the python enabled debug helper)
* On Mac OS X: latest Xcode * On Mac OS X: latest Xcode
* On Linux: g++ 5.3 or later * On Linux: g++ 5.3 or later
@@ -40,6 +39,7 @@ Prerequisites:
"Get LLVM/Clang for the Clang Code Model". The LLVM C++ API provides no compatibility garantee, "Get LLVM/Clang for the Clang Code Model". The LLVM C++ API provides no compatibility garantee,
so if later versions don't compile we don't support that version.) so if later versions don't compile we don't support that version.)
* CMake (for manual builds of LLVM/Clang, and Qt Creator itself) * CMake (for manual builds of LLVM/Clang, and Qt Creator itself)
* Ninja (optional, recommended for building with CMake)
* Qbs 1.7.x (optional, sources also contain Qbs itself) * Qbs 1.7.x (optional, sources also contain Qbs itself)
The installed toolchains have to match the one Qt was compiled with. The installed toolchains have to match the one Qt was compiled with.

View File

@@ -112,6 +112,10 @@ you can check out from the public Git repository. For example:
* Added option to remove directories directly from project tree (QTCREATORBUG-16575) * Added option to remove directories directly from project tree (QTCREATORBUG-16575)
* Added support for Framework paths (QTCREATORBUG-20099) * Added support for Framework paths (QTCREATORBUG-20099)
### Compilation Database
* Fixed issue with `/imsvc` compiler option (QTCREATORBUG-23146)
## Debugging ## Debugging
### CDB ### CDB
@@ -131,6 +135,7 @@ you can check out from the public Git repository. For example:
* Changed to use separate `clang-tidy` executable * Changed to use separate `clang-tidy` executable
* Separated diagnostic configuration settings for code model * Separated diagnostic configuration settings for code model
(`C++` > `Code Model`) and analyzer (`Analyzer` > `Clang Tools`) (`C++` > `Code Model`) and analyzer (`Analyzer` > `Clang Tools`)
* Fixed invocation of `clazy` with latest `clazy` versions
## Qt Widget Designer ## Qt Widget Designer
@@ -174,6 +179,8 @@ you can check out from the public Git repository. For example:
* Removed auto-detection of GCC toolchains * Removed auto-detection of GCC toolchains
* Fixed closing of terminal window after application finishes (QTCREATORBUG-15138) * Fixed closing of terminal window after application finishes (QTCREATORBUG-15138)
* Fixed execution of `qtc-askpass` (QTCREATORBUG-23120)
* Fixed environment when opening terminal with `zsh` (QTCREATORBUG-21712)
### Android ### Android

View File

@@ -23,7 +23,8 @@ imagedirs = ../images \
../../src/plugins/qmldesigner/qmlpreviewplugin/images \ ../../src/plugins/qmldesigner/qmlpreviewplugin/images \
../../src/plugins/scxmleditor/common/images \ ../../src/plugins/scxmleditor/common/images \
../../src/plugins/texteditor/images \ ../../src/plugins/texteditor/images \
../../src/plugins/valgrind/images ../../src/plugins/valgrind/images \
../../src/plugins/welcome/images
exampledirs = ../examples exampledirs = ../examples
examples.fileextensions += *.qml *.svg examples.fileextensions += *.qml *.svg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -60,6 +60,11 @@
Clang tools are delivered and installed with \QC, and therefore you do not Clang tools are delivered and installed with \QC, and therefore you do not
need to set them up separately. need to set them up separately.
In addition to running the tools to collect diagnostics, you can select
\inlineimage open.png
to load diagnostics from \l{https://yaml.org/}{YAML} files that you exported
using the \c {-export fixes} option.
\section1 Running Clang Tools \section1 Running Clang Tools
To run the Clang tools to analyze an open project: To run the Clang tools to analyze an open project:
@@ -68,41 +73,25 @@
\li Select \uicontrol Analyze > \uicontrol {Clang-Tidy and Clazy}. \li Select \uicontrol Analyze > \uicontrol {Clang-Tidy and Clazy}.
\image qtcreator-files-to-analyze.png "Analyzer Configuration dialog" \image qtcreator-files-to-analyze.png "Files to Analyze dialog"
\li In the \uicontrol General group, select \uicontrol {Custom Settings} \li Select the files to apply the checks to.
to modify the analyzer configuration.
\li To build the project before running the Clang tools, select the
\uicontrol {Build the project before analysis} check box. The Clang
tools do not require the project to be built before analysis, but
they might display misleading warnings about files missing that are
generated during the build. For big projects, not building the
project might save some time.
\li In the \uicontrol {Diagnostic configuration} field, select a Clang
configuration in the list of pre-defined configurations (1). For
more information about creating a custom configuration, see
\l {Configuring Clang Tools}.
\li In the \uicontrol {Files to Analyze} group, select the files to
apply the checks to.
\li Select \uicontrol Analyze to start the checks. \li Select \uicontrol Analyze to start the checks.
\endlist \endlist
If you select \uicontrol Debug in the mode selector to open the
\uicontrol Debug mode and then select \uicontrol {Clang-Tidy and Clazy},
you must select the \inlineimage qtcreator-analyze-start-button.png
(\uicontrol Start) button to open the \uicontrol {Analyzer Configuration}
dialog.
The found issues are displayed in the \uicontrol {Clang-Tidy and Clazy} The found issues are displayed in the \uicontrol {Clang-Tidy and Clazy}
view: view:
\image qtcreator-clang-tools.png "Clang-Tidy and Clazy view" \image qtcreator-clang-tools.png "Clang-Tidy and Clazy view"
\note If you select \uicontrol Debug in the mode selector to open the
\uicontrol Debug mode and then select \uicontrol {Clang-Tidy and Clazy},
you must select the \inlineimage qtcreator-analyze-start-button.png
(\uicontrol Start) button to open the \uicontrol {Files to Analyze}
dialog.
Double-click an issue to move to the location where the issue appears in Double-click an issue to move to the location where the issue appears in
the code editor. the code editor.

View File

@@ -57,6 +57,10 @@
To reset the changes that you made, select \uicontrol Reset. To reset the changes that you made, select \uicontrol Reset.
To reconfigure CMake, select \uicontrol Build >
\uicontrol {Clear CMake Configuration}, and then
select \uicontrol Build > \uicontrol {Rescan Project}.
//! [cmake build configuration] //! [cmake build configuration]
@@ -65,7 +69,7 @@
\section2 CMake Build Steps \section2 CMake Build Steps
\QC builds CMake projects by running \c {cmake . --build}, which then runs \QC builds CMake projects by running \c {cmake . --build}, which then runs
run whatever is needed based on how the project was configured: \c make, whatever is needed based on how the project was configured: \c make,
\c mingw32-make, \c nmake, or \c ninja, for example. \c mingw32-make, \c nmake, or \c ninja, for example.
You can add arguments and targets for the build command in You can add arguments and targets for the build command in

View File

@@ -61,6 +61,10 @@
provide less information to the code model, which will then fail to resolve provide less information to the code model, which will then fail to resolve
includes and defines. includes and defines.
For CMake version 3.14, or later, \QC supports the
\l {https://cmake.org/cmake/help/latest/manual/cmake-file-api.7.html}
{file-based API}.
To specify paths to CMake executables: To specify paths to CMake executables:
\list 1 \list 1
@@ -99,9 +103,14 @@
\section1 Editing CMake Configuration Files \section1 Editing CMake Configuration Files
To open a CMakeLists.txt file for editing, right-click it in the To open a CMakeLists.txt file for editing, right-click it in the
\uicontrol Projects view and select \uicontrol {Open with} > \uicontrol Projects view and select \uicontrol {Open With} >
\uicontrol {CMake Editor}. \uicontrol {CMake Editor}.
You can also use the \c cmo filter in the \l {Searching with the Locator}
{locator} to open the CMakeLists.txt file for the current run configuration
in the editor. This is the same build target as when you select
\uicontrol Build > \uicontrol {Build for Run Configuration}.
The following features are supported: The following features are supported:
\list \list

View File

@@ -150,6 +150,11 @@
\if defined(qtcreator) \if defined(qtcreator)
\li Running external tools (\c x) \li Running external tools (\c x)
\li Using CMake to build the project for the current run configuration
(\c {cm}). For more information, see \l {Setting up CMake}.
\li Opening the CMakeLists.txt file for the current run configuration in
the editor (\c {cmo}). This is the same build target as when you
select \uicontrol Build > \uicontrol {Build for Run Configuration}.
\endif \endif
\endlist \endlist

View File

@@ -84,16 +84,18 @@
To quickly check the compile output for changes that you made in one file or To quickly check the compile output for changes that you made in one file or
subproject, you can use the \uicontrol Build menu commands to build a file or subproject, you can use the \uicontrol Build menu commands to build a file or
subproject. subproject. The available build menu commands depend on the build system
you selected for the project: CMake, qmake, or Qbs.
To build the executable that corresponds to the selected run configuration, Select \uicontrol Build > \uicontrol {Build for Run Configuration} to
select \uicontrol Build > \uicontrol {Build for Run Configuration}. build the executable that corresponds to the selected run configuration.
You can also use the \c cm filter in the \l {Searching with the Locator}
{locator}.
To remove all build artifacts, select \uicontrol Build > \uicontrol {Clean All} or To remove all build artifacts, select \uicontrol Build > \uicontrol {Clean All} or
\uicontrol {Clean Project}. To clean the build directory and then build \uicontrol {Clean Project}. To clean the build directory and then build
the project, select \uicontrol Build > \uicontrol {Rebuild All} or the project, select \uicontrol Build > \uicontrol {Rebuild All} or
\uicontrol {Rebuild Project}. If you use qmake, rebuilding also runs qmake \uicontrol {Rebuild Project}.
to generate new Makefiles between cleaning and building.
To build and clean projects without dependencies, select the To build and clean projects without dependencies, select the
\uicontrol {Build Without Dependencies}, \uicontrol {Build Without Dependencies},
@@ -101,11 +103,22 @@
\uicontrol {Clean Without Dependencies} options in the context menu in the \uicontrol {Clean Without Dependencies} options in the context menu in the
\uicontrol Projects view. \uicontrol Projects view.
\section1 Additional qmake Commands To run qmake or CMake to regenerate build system files, select
\uicontrol Build > \uicontrol {Run qmake} or \uicontrol {Run CMake}.
To run qmake to generate new Makefiles, select \uicontrol Build > \section2 Building with CMake
\uicontrol qmake. To prevent failures on incremental builds, it might make
sense to always run qmake before building, even though it means that \QC automatically runs CMake when you make changes to \c {CMakeLists.txt}
files. To disable this feature, select \uicontrol Tools >
\uicontrol Options > \uicontrol Kits > \uicontrol CMake >
\uicontrol {Autorun CMake}.
For more information, see \l {Setting Up CMake}.
\section2 Building with qmake
To prevent failures on incremental builds, it might make sense
to always run qmake before building, even though it means that
building will take more time. To enable this option, select \uicontrol Tools building will take more time. To enable this option, select \uicontrol Tools
> \uicontrol Options > \uicontrol {Build & Run} > \uicontrol qmake > > \uicontrol Options > \uicontrol {Build & Run} > \uicontrol qmake >
\uicontrol {Run qmake on every build}. \uicontrol {Run qmake on every build}.

View File

@@ -46,7 +46,7 @@ Node {
} }
Connections { Connections {
target: designStudioNativeCameraControlHelper target: _generalHelper
onOverlayUpdateNeeded: updateScale() onOverlayUpdateNeeded: updateScale()
} }
@@ -81,6 +81,7 @@ Node {
MouseArea3D { MouseArea3D {
id: helper id: helper
active: false
view3D: overlayNode.view3D view3D: overlayNode.view3D
} }
} }

View File

@@ -0,0 +1,133 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.0
import QtQuick3D 1.0
View3D {
id: axisHelperView
property var editCameraCtrl
property Node selectedNode
camera: axisHelperCamera
Node {
OrthographicCamera {
id: axisHelperCamera
rotation: editCameraCtrl.camera.rotation
position: editCameraCtrl.camera.position.minus(editCameraCtrl._lookAtPoint)
.normalized().times(600)
}
AutoScaleHelper {
id: autoScale
view3D: axisHelperView
position: axisHelperGizmo.scenePosition
}
Node {
id: axisHelperGizmo
scale: autoScale.getScale(Qt.vector3d(4, 4, 4))
AxisHelperArm {
id: armX
rotation: Qt.vector3d(0, 0, -90)
color: Qt.rgba(1, 0, 0, 1)
hoverColor: Qt.lighter(Qt.rgba(1, 0, 0, 1))
view3D: axisHelperView
camRotPos: Qt.vector3d(0, 90, 0)
camRotNeg: Qt.vector3d(0, -90, 0)
}
AxisHelperArm {
id: armY
rotation: Qt.vector3d(0, 0, 0)
color: Qt.rgba(0, 0.6, 0, 1)
hoverColor: Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
view3D: axisHelperView
camRotPos: Qt.vector3d(-90, 0, 0)
camRotNeg: Qt.vector3d(90, 0, 0)
}
AxisHelperArm {
id: armZ
rotation: Qt.vector3d(90, 0, 0)
color: Qt.rgba(0, 0, 1, 1)
hoverColor: Qt.lighter(Qt.rgba(0, 0, 1, 1))
view3D: axisHelperView
camRotPos: Qt.vector3d(0, 0, 0)
camRotNeg: Qt.vector3d(0, 180, 0)
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton
property var pickObj: null
function cancelHover()
{
if (pickObj) {
pickObj.hovering = false;
pickObj = null;
}
}
function pick(mouse)
{
var result = axisHelperView.pick(mouse.x, mouse.y);
if (result.objectHit) {
if (result.objectHit !== pickObj) {
cancelHover();
pickObj = result.objectHit;
pickObj.hovering = true;
}
} else {
cancelHover();
}
}
onPositionChanged: {
pick(mouse);
}
onPressed: {
pick(mouse);
if (pickObj) {
axisHelperView.editCameraCtrl.fitObject(axisHelperView.selectedNode,
pickObj.cameraRotation);
} else {
mouse.accepted = false;
}
}
onExited: cancelHover()
onCanceled: cancelHover()
}
}

View File

@@ -23,40 +23,48 @@
** **
****************************************************************************/ ****************************************************************************/
#pragma once import QtQuick 2.0
import QtQuick3D 1.0
#include <QtCore/QObject> Node {
#include <QtCore/QTimer> id: armRoot
property alias posModel: posModel
property alias negModel: negModel
property View3D view3D
property color hoverColor
property color color
property vector3d camRotPos
property vector3d camRotNeg
namespace QmlDesigner { Model {
namespace Internal { id: posModel
class CameraControlHelper : public QObject
{
Q_OBJECT
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
public: property bool hovering: false
CameraControlHelper(); property vector3d cameraRotation: armRoot.camRotPos
bool enabled(); source: "meshes/axishelper.mesh"
void setEnabled(bool enabled); materials: DefaultMaterial {
id: posMat
emissiveColor: posModel.hovering ? armRoot.hoverColor : armRoot.color
lighting: DefaultMaterial.NoLighting
}
pickable: true
}
Q_INVOKABLE void requestOverlayUpdate(); Model {
Q_INVOKABLE QString generateUniqueName(const QString &nameRoot); id: negModel
public slots: property bool hovering: false
void handleUpdateTimer(); property vector3d cameraRotation: armRoot.camRotNeg
signals:
void updateInputs();
void enabledChanged(bool enabled);
void overlayUpdateNeeded();
private:
bool m_enabled = false;
QTimer m_inputUpdateTimer;
QTimer m_overlayUpdateTimer;
};
source: "#Sphere"
y: -6
scale: Qt.vector3d(0.025, 0.025, 0.025)
materials: DefaultMaterial {
id: negMat
emissiveColor: negModel.hovering ? armRoot.hoverColor : armRoot.color
lighting: DefaultMaterial.NoLighting
}
pickable: true
} }
} }

View File

@@ -31,21 +31,26 @@ IconGizmo {
id: cameraGizmo id: cameraGizmo
iconSource: "qrc:///qtquickplugin/mockfiles/images/editor_camera.png" iconSource: "qrc:///qtquickplugin/mockfiles/images/editor_camera.png"
gizmoModel.geometry: cameraGeometry
property alias geometryName: cameraGeometry.name // Name must be unique for each geometry property alias geometryName: cameraGeometry.name // Name must be unique for each geometry
property alias viewPortRect: cameraGeometry.viewPortRect property alias viewPortRect: cameraGeometry.viewPortRect
CameraGeometry { Model {
id: cameraGeometry id: gizmoModel
camera: cameraGizmo.targetNode geometry: cameraGeometry
} visible: cameraGizmo.visible
materials: [
gizmoModel.materials: [
DefaultMaterial { DefaultMaterial {
id: defaultMaterial id: defaultMaterial
emissiveColor: cameraGizmo.targetNode === cameraGizmo.selectedNode ? "#FF0000" : "#555555" emissiveColor: cameraGizmo.targetNode === cameraGizmo.selectedNode ? "#FF0000"
: "#555555"
lighting: DefaultMaterial.NoLighting lighting: DefaultMaterial.NoLighting
cullingMode: Material.DisableCulling cullingMode: Material.DisableCulling
} }
] ]
} }
CameraGeometry {
id: cameraGeometry
camera: cameraGizmo.targetNode
}
}

View File

@@ -34,7 +34,7 @@ Model {
property View3D view3D property View3D view3D
property alias color: material.emissiveColor property alias color: material.emissiveColor
property Node targetNode: null property Node targetNode: null
property bool dragging: false property bool dragging: mouseAreaYZ.dragging || mouseAreaXZ.dragging
property bool active: false property bool active: false
readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering
@@ -61,7 +61,6 @@ Model {
_pointerPosPressed = mouseArea.mapPositionToScene(maskedPosition); _pointerPosPressed = mouseArea.mapPositionToScene(maskedPosition);
var sp = targetNode.scenePosition; var sp = targetNode.scenePosition;
_targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z); _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z);
dragging = true;
pressed(mouseArea); pressed(mouseArea);
} }
@@ -88,7 +87,6 @@ Model {
return; return;
released(mouseArea, calcRelativeDistance(mouseArea, scenePos)); released(mouseArea, calcRelativeDistance(mouseArea, scenePos));
dragging = false;
} }
MouseArea3D { MouseArea3D {

View File

@@ -0,0 +1,128 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.12
import QtQuick3D 1.0
Item {
id: cameraCtrl
property Camera camera: null
property View3D view3d: null
property vector3d _lookAtPoint
property vector3d _pressPoint
property vector3d _prevPoint
property vector3d _startRotation
property vector3d _startPosition
property vector3d _startLookAtPoint
property matrix4x4 _startTransform
property bool _dragging
property int _button
property real _zoomFactor: 1
property real _defaultCameraLookAtDistance: 0
property Camera _prevCamera: null
function fitObject(targetObject, rotation)
{
camera.rotation = rotation;
var newLookAtAndZoom = _generalHelper.fitObjectToCamera(
camera, _defaultCameraLookAtDistance, targetObject, view3d);
_lookAtPoint = newLookAtAndZoom.toVector3d();
_zoomFactor = newLookAtAndZoom.w;
}
function zoomRelative(distance)
{
_zoomFactor = _generalHelper.zoomCamera(camera, distance, _defaultCameraLookAtDistance,
_lookAtPoint, _zoomFactor, true);
}
Component.onCompleted: {
cameraCtrl._defaultCameraLookAtDistance = cameraCtrl.camera.position.length();
}
onCameraChanged: {
if (_prevCamera) {
// Reset zoom on previous camera to ensure it's properties are good to copy to new cam
_generalHelper.zoomCamera(_prevCamera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
1, false);
camera.position = _prevCamera.position;
camera.rotation = _prevCamera.rotation;
// Apply correct zoom to new camera
_generalHelper.zoomCamera(camera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
_zoomFactor, false);
}
_prevCamera = camera;
}
MouseArea {
id: mouseHandler
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
hoverEnabled: false
anchors.fill: parent
onPositionChanged: {
if (mouse.modifiers === Qt.AltModifier && cameraCtrl._dragging) {
var currentPoint = Qt.vector3d(mouse.x, mouse.y, 0);
if (cameraCtrl._button == Qt.LeftButton) {
_generalHelper.orbitCamera(cameraCtrl.camera, cameraCtrl._startRotation,
cameraCtrl._lookAtPoint, cameraCtrl._pressPoint,
currentPoint);
} else if (cameraCtrl._button == Qt.MiddleButton) {
cameraCtrl._lookAtPoint = _generalHelper.panCamera(
cameraCtrl.camera, cameraCtrl._startTransform,
cameraCtrl._startPosition, cameraCtrl._startLookAtPoint,
cameraCtrl._pressPoint, currentPoint, _zoomFactor);
} else if (cameraCtrl._button == Qt.RightButton) {
cameraCtrl.zoomRelative(currentPoint.y - cameraCtrl._prevPoint.y)
cameraCtrl._prevPoint = currentPoint;
}
}
}
onPressed: {
if (mouse.modifiers === Qt.AltModifier) {
cameraCtrl._dragging = true;
cameraCtrl._startRotation = cameraCtrl.camera.rotation;
cameraCtrl._startPosition = cameraCtrl.camera.position;
cameraCtrl._startLookAtPoint = _lookAtPoint;
cameraCtrl._pressPoint = Qt.vector3d(mouse.x, mouse.y, 0);
cameraCtrl._prevPoint = cameraCtrl._pressPoint;
cameraCtrl._button = mouse.button;
cameraCtrl._startTransform = cameraCtrl.camera.sceneTransform;
} else {
mouse.accepted = false;
}
}
onReleased: cameraCtrl._dragging = false;
onCanceled: cameraCtrl._dragging = false;
onWheel: {
// Emprically determined divisor for nice zoom
cameraCtrl.zoomRelative(wheel.angleDelta.y / -40);
}
}
}

View File

@@ -26,7 +26,6 @@
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Window 2.0 import QtQuick.Window 2.0
import QtQuick3D 1.0 import QtQuick3D 1.0
import QtQuick3D.Helpers 1.0
import QtQuick.Controls 2.0 import QtQuick.Controls 2.0
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
@@ -39,8 +38,8 @@ Window {
flags: Qt.WindowStaysOnTopHint | Qt.Window | Qt.WindowTitleHint | Qt.WindowCloseButtonHint flags: Qt.WindowStaysOnTopHint | Qt.Window | Qt.WindowTitleHint | Qt.WindowCloseButtonHint
property alias scene: editView.importScene property alias scene: editView.importScene
property alias showEditLight: editLightCheckbox.checked property alias showEditLight: btnEditViewLight.toggled
property alias usePerspective: usePerspectiveCheckbox.checked property alias usePerspective: btnPerspective.toggled
property Node selectedNode: null property Node selectedNode: null
@@ -56,9 +55,14 @@ Window {
selectedNode = object; selectedNode = object;
} }
function emitObjectClicked(object) { function handleObjectClicked(object) {
selectObject(object); var theObject = object;
objectClicked(object); if (btnSelectGroup.selected) {
while (theObject && theObject.parent !== scene)
theObject = theObject.parent;
}
selectObject(theObject);
objectClicked(theObject);
} }
function addLightGizmo(obj) function addLightGizmo(obj)
@@ -69,7 +73,7 @@ Window {
{"view3D": overlayView, "targetNode": obj, {"view3D": overlayView, "targetNode": obj,
"selectedNode": selectedNode}); "selectedNode": selectedNode});
lightGizmos[lightGizmos.length] = gizmo; lightGizmos[lightGizmos.length] = gizmo;
gizmo.clicked.connect(emitObjectClicked); gizmo.clicked.connect(handleObjectClicked);
gizmo.selectedNode = Qt.binding(function() {return selectedNode;}); gizmo.selectedNode = Qt.binding(function() {return selectedNode;});
} }
} }
@@ -78,13 +82,13 @@ Window {
{ {
var component = Qt.createComponent("CameraGizmo.qml"); var component = Qt.createComponent("CameraGizmo.qml");
if (component.status === Component.Ready) { if (component.status === Component.Ready) {
var geometryName = designStudioNativeCameraControlHelper.generateUniqueName("CameraGeometry"); var geometryName = _generalHelper.generateUniqueName("CameraGeometry");
var gizmo = component.createObject( var gizmo = component.createObject(
overlayScene, overlayScene,
{"view3D": overlayView, "targetNode": obj, "geometryName": geometryName, {"view3D": overlayView, "targetNode": obj, "geometryName": geometryName,
"viewPortRect": viewPortRect, "selectedNode": selectedNode}); "viewPortRect": viewPortRect, "selectedNode": selectedNode});
cameraGizmos[cameraGizmos.length] = gizmo; cameraGizmos[cameraGizmos.length] = gizmo;
gizmo.clicked.connect(emitObjectClicked); gizmo.clicked.connect(handleObjectClicked);
gizmo.viewPortRect = Qt.binding(function() {return viewPortRect;}); gizmo.viewPortRect = Qt.binding(function() {return viewPortRect;});
gizmo.selectedNode = Qt.binding(function() {return selectedNode;}); gizmo.selectedNode = Qt.binding(function() {return selectedNode;});
} }
@@ -92,10 +96,10 @@ Window {
// Work-around the fact that the projection matrix for the camera is not calculated until // Work-around the fact that the projection matrix for the camera is not calculated until
// the first frame is rendered, so any initial calls to mapFrom3DScene() will fail. // the first frame is rendered, so any initial calls to mapFrom3DScene() will fail.
Component.onCompleted: designStudioNativeCameraControlHelper.requestOverlayUpdate(); Component.onCompleted: _generalHelper.requestOverlayUpdate();
onWidthChanged: designStudioNativeCameraControlHelper.requestOverlayUpdate(); onWidthChanged: _generalHelper.requestOverlayUpdate();
onHeightChanged: designStudioNativeCameraControlHelper.requestOverlayUpdate(); onHeightChanged: _generalHelper.requestOverlayUpdate();
Node { Node {
id: overlayScene id: overlayScene
@@ -114,6 +118,7 @@ Window {
clipNear: editOrthoCamera.clipNear clipNear: editOrthoCamera.clipNear
position: editOrthoCamera.position position: editOrthoCamera.position
rotation: editOrthoCamera.rotation rotation: editOrthoCamera.rotation
scale: editOrthoCamera.scale
} }
MoveGizmo { MoveGizmo {
@@ -123,7 +128,7 @@ Window {
targetNode: viewWindow.selectedNode targetNode: viewWindow.selectedNode
position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition
: Qt.vector3d(0, 0, 0) : Qt.vector3d(0, 0, 0)
globalOrientation: globalControl.checked globalOrientation: btnLocalGlobal.toggled
visible: selectedNode && btnMove.selected visible: selectedNode && btnMove.selected
view3D: overlayView view3D: overlayView
@@ -138,7 +143,7 @@ Window {
targetNode: viewWindow.selectedNode targetNode: viewWindow.selectedNode
position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition
: Qt.vector3d(0, 0, 0) : Qt.vector3d(0, 0, 0)
globalOrientation: globalControl.checked globalOrientation: false
visible: selectedNode && btnScale.selected visible: selectedNode && btnScale.selected
view3D: overlayView view3D: overlayView
@@ -153,7 +158,7 @@ Window {
targetNode: viewWindow.selectedNode targetNode: viewWindow.selectedNode
position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition
: Qt.vector3d(0, 0, 0) : Qt.vector3d(0, 0, 0)
globalOrientation: globalControl.checked globalOrientation: btnLocalGlobal.toggled
visible: selectedNode && btnRotate.selected visible: selectedNode && btnRotate.selected
view3D: overlayView view3D: overlayView
@@ -169,16 +174,19 @@ Window {
} }
Rectangle { Rectangle {
id: sceneBg
color: "#FFFFFF"
anchors.fill: parent anchors.fill: parent
focus: true focus: true
gradient: Gradient {
GradientStop { position: 1.0; color: "#222222" }
GradientStop { position: 0.0; color: "#999999" }
}
TapHandler { // check tapping/clicking an object in the scene TapHandler { // check tapping/clicking an object in the scene
onTapped: { onTapped: {
var pickResult = editView.pick(eventPoint.scenePosition.x, var pickResult = editView.pick(eventPoint.scenePosition.x,
eventPoint.scenePosition.y); eventPoint.scenePosition.y);
emitObjectClicked(pickResult.objectHit); handleObjectClicked(pickResult.objectHit);
} }
} }
@@ -200,6 +208,12 @@ Window {
step: 50 step: 50
} }
SelectionBox {
id: selectionBox
view3D: editView
targetNode: viewWindow.selectedNode
}
PointLight { PointLight {
id: editLight id: editLight
visible: showEditLight visible: showEditLight
@@ -209,11 +223,14 @@ Window {
linearFade: 0 linearFade: 0
} }
// Initial camera position and rotation should be such that they look at origin.
// Otherwise EditCameraController._lookAtPoint needs to be initialized to correct
// point.
PerspectiveCamera { PerspectiveCamera {
id: editPerspectiveCamera id: editPerspectiveCamera
z: -600 z: -600
y: 200 y: 600
rotation.x: 30 rotation.x: 45
clipFar: 100000 clipFar: 100000
clipNear: 1 clipNear: 1
} }
@@ -221,10 +238,10 @@ Window {
OrthographicCamera { OrthographicCamera {
id: editOrthoCamera id: editOrthoCamera
z: -600 z: -600
y: 200 y: 600
rotation.x: 30 rotation.x: 45
clipFar: 100000 clipFar: 100000
clipNear: 1 clipNear: -10000
} }
} }
} }
@@ -240,14 +257,12 @@ Window {
id: gizmoLabel id: gizmoLabel
targetNode: moveGizmo.visible ? moveGizmo : scaleGizmo targetNode: moveGizmo.visible ? moveGizmo : scaleGizmo
targetView: overlayView targetView: overlayView
offsetX: 0
offsetY: 45
visible: targetNode.dragging visible: targetNode.dragging
Rectangle { Rectangle {
color: "white" color: "white"
x: -width / 2 x: -width / 2
y: -height y: -height - 8
width: gizmoLabelText.width + 4 width: gizmoLabelText.width + 4
height: gizmoLabelText.height + 4 height: gizmoLabelText.height + 4
border.width: 1 border.width: 1
@@ -273,19 +288,11 @@ Window {
} }
} }
WasdController { EditCameraController {
id: cameraControl id: cameraControl
controlledObject: editView.camera camera: editView.camera
acceptedButtons: Qt.RightButton anchors.fill: parent
view3d: editView
onInputsNeedProcessingChanged: designStudioNativeCameraControlHelper.enabled
= cameraControl.inputsNeedProcessing
// Use separate native timer as QML timers don't work inside Qt Design Studio
Connections {
target: designStudioNativeCameraControlHelper
onUpdateInputs: cameraControl.processInputs()
}
} }
} }
@@ -301,7 +308,8 @@ Window {
spacing: 5 spacing: 5
padding: 5 padding: 5
property var group: [btnSelectItem, btnSelectGroup, btnMove, btnRotate, btnScale] property var groupSelect: [btnSelectGroup, btnSelectItem]
property var groupTransform: [btnMove, btnRotate, btnScale]
ToolBarButton { ToolBarButton {
id: btnSelectItem id: btnSelectItem
@@ -310,7 +318,7 @@ Window {
shortcut: "Q" shortcut: "Q"
currentShortcut: selected ? "" : shortcut currentShortcut: selected ? "" : shortcut
tool: "item_selection" tool: "item_selection"
buttonsGroup: col.group buttonsGroup: col.groupSelect
} }
ToolBarButton { ToolBarButton {
@@ -319,7 +327,7 @@ Window {
shortcut: "Q" shortcut: "Q"
currentShortcut: btnSelectItem.currentShortcut === shortcut ? "" : shortcut currentShortcut: btnSelectItem.currentShortcut === shortcut ? "" : shortcut
tool: "group_selection" tool: "group_selection"
buttonsGroup: col.group buttonsGroup: col.groupSelect
} }
Rectangle { // separator Rectangle { // separator
@@ -331,11 +339,12 @@ Window {
ToolBarButton { ToolBarButton {
id: btnMove id: btnMove
selected: true
tooltip: qsTr("Move current selection") tooltip: qsTr("Move current selection")
shortcut: "M" shortcut: "W"
currentShortcut: shortcut currentShortcut: shortcut
tool: "move" tool: "move"
buttonsGroup: col.group buttonsGroup: col.groupTransform
} }
ToolBarButton { ToolBarButton {
@@ -344,60 +353,96 @@ Window {
shortcut: "E" shortcut: "E"
currentShortcut: shortcut currentShortcut: shortcut
tool: "rotate" tool: "rotate"
buttonsGroup: col.group buttonsGroup: col.groupTransform
} }
ToolBarButton { ToolBarButton {
id: btnScale id: btnScale
tooltip: qsTr("Scale current selection") tooltip: qsTr("Scale current selection")
shortcut: "T" shortcut: "R"
currentShortcut: shortcut currentShortcut: shortcut
tool: "scale" tool: "scale"
buttonsGroup: col.group buttonsGroup: col.groupTransform
}
Rectangle { // separator
width: 25
height: 1
color: "#f1f1f1"
anchors.horizontalCenter: parent.horizontalCenter
}
ToolBarButton {
id: btnFit
tooltip: qsTr("Fit camera to current selection")
shortcut: "F"
currentShortcut: shortcut
tool: "fit"
togglable: false
onSelectedChanged: {
if (selected) {
var targetNode = viewWindow.selectedNode ? selectionBox.model : null;
cameraControl.fitObject(targetNode, editView.camera.rotation);
}
}
} }
} }
} }
Column { AxisHelper {
y: 8
anchors.right: parent.right anchors.right: parent.right
CheckBox { anchors.top: parent.top
id: editLightCheckbox width: 100
checked: false height: width
text: qsTr("Use Edit View Light") editCameraCtrl: cameraControl
onCheckedChanged: cameraControl.forceActiveFocus() selectedNode : viewWindow.selectedNode ? selectionBox.model : null
} }
CheckBox { Rectangle { // top controls bar
id: usePerspectiveCheckbox color: "#aa000000"
checked: true width: 265
text: qsTr("Use Perspective Projection") height: btnPerspective.height + 10
onCheckedChanged: { anchors.top: parent.top
// Since WasdController always acts on active camera, we need to update pos/rot anchors.right: parent.right
// to the other camera when we change anchors.rightMargin: 100
if (checked) {
editPerspectiveCamera.position = editOrthoCamera.position; ToggleButton {
editPerspectiveCamera.rotation = editOrthoCamera.rotation; id: btnPerspective
} else { anchors.top: parent.top
editOrthoCamera.position = editPerspectiveCamera.position; anchors.topMargin: 5
editOrthoCamera.rotation = editPerspectiveCamera.rotation; anchors.left: parent.left
} anchors.leftMargin: 5
designStudioNativeCameraControlHelper.requestOverlayUpdate(); tooltip: qsTr("Toggle Perspective / Orthographic Projection")
cameraControl.forceActiveFocus(); states: [{iconId: "ortho", text: qsTr("Orthographic")}, {iconId: "persp", text: qsTr("Perspective")}]
}
} }
CheckBox { ToggleButton {
id: globalControl id: btnLocalGlobal
checked: true anchors.top: parent.top
text: qsTr("Use Global Orientation") anchors.topMargin: 5
onCheckedChanged: cameraControl.forceActiveFocus() anchors.left: parent.left
anchors.leftMargin: 100
tooltip: qsTr("Toggle Global / Local Orientation")
states: [{iconId: "local", text: qsTr("Local")}, {iconId: "global", text: qsTr("Global")}]
}
ToggleButton {
id: btnEditViewLight
anchors.top: parent.top
anchors.topMargin: 5
anchors.left: parent.left
anchors.leftMargin: 165
toggleBackground: true
tooltip: qsTr("Toggle Edit Light")
states: [{iconId: "edit_light_off", text: qsTr("Edit Light Off")}, {iconId: "edit_light_on", text: qsTr("Edit Light On")}]
} }
} }
Text { Text {
id: helpText id: helpText
text: qsTr("Camera: W,A,S,D,R,F,right mouse drag") color: "white"
text: qsTr("Camera controls: ALT + mouse press and drag. Left: Rotate, Middle: Pan, Right/Wheel: Zoom.")
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
} }
} }

View File

@@ -45,7 +45,7 @@ Node {
materials: [ materials: [
DefaultMaterial { DefaultMaterial {
id: mainGridMaterial id: mainGridMaterial
emissiveColor: "#e6e6e6" emissiveColor: "#cccccc"
lighting: DefaultMaterial.NoLighting lighting: DefaultMaterial.NoLighting
cullingMode: Material.DisableCulling cullingMode: Material.DisableCulling
} }

View File

@@ -25,6 +25,7 @@
import QtQuick 2.0 import QtQuick 2.0
import QtQuick3D 1.0 import QtQuick3D 1.0
import QtGraphicalEffects 1.12
Node { Node {
id: iconGizmo id: iconGizmo
@@ -34,8 +35,8 @@ Node {
property Node targetNode: null property Node targetNode: null
property Node selectedNode: null property Node selectedNode: null
property alias gizmoModel: gizmoModel
property alias iconSource: iconImage.source property alias iconSource: iconImage.source
property alias overlayColor: colorOverlay.color
signal positionCommit() signal positionCommit()
signal clicked(Node node) signal clicked(Node node)
@@ -44,30 +45,25 @@ Node {
rotation: targetNode ? targetNode.sceneRotation : Qt.vector3d(0, 0, 0) rotation: targetNode ? targetNode.sceneRotation : Qt.vector3d(0, 0, 0)
visible: targetNode ? targetNode.visible : false visible: targetNode ? targetNode.visible : false
Model {
id: gizmoModel
visible: iconGizmo.visible
}
Overlay2D { Overlay2D {
id: gizmoLabel id: iconOverlay
targetNode: gizmoModel targetNode: iconGizmo
targetView: view3D targetView: view3D
offsetX: 0
offsetY: 0
visible: iconGizmo.visible && !isBehindCamera visible: iconGizmo.visible && !isBehindCamera
parent: view3D parent: view3D
Rectangle { Rectangle {
id: iconRect
width: iconImage.width width: iconImage.width
height: iconImage.height height: iconImage.height
x: -width / 2 x: -width / 2
y: -height y: -height / 2
color: "transparent" color: "transparent"
border.color: "#7777ff" border.color: "#7777ff"
border.width: iconGizmo.selectedNode === iconGizmo.targetNode border.width: iconGizmo.selectedNode !== iconGizmo.targetNode
|| (iconGizmo.highlightOnHover && iconMouseArea.containsMouse) ? 2 : 0 && iconGizmo.highlightOnHover && iconMouseArea.containsMouse ? 2 : 0
radius: 5 radius: 5
opacity: iconGizmo.selectedNode === iconGizmo.targetNode ? 0.3 : 1 opacity: iconGizmo.selectedNode === iconGizmo.targetNode ? 0.2 : 1
Image { Image {
id: iconImage id: iconImage
fillMode: Image.Pad fillMode: Image.Pad
@@ -81,6 +77,15 @@ Node {
? Qt.LeftButton : Qt.NoButton ? Qt.LeftButton : Qt.NoButton
} }
} }
ColorOverlay {
id: colorOverlay
anchors.fill: parent
cached: true
source: iconImage
color: "transparent"
opacity: 0.6
}
} }
} }
} }

View File

@@ -29,14 +29,13 @@ import QtQuick3D 1.0
IconGizmo { IconGizmo {
id: lightGizmo id: lightGizmo
iconSource: "qrc:///qtquickplugin/mockfiles/images/light-pick-icon.png" iconSource: targetNode
gizmoModel.source: "#Sphere" ? targetNode instanceof DirectionalLight
gizmoModel.scale: Qt.vector3d(0.10, 0.10, 0.10) ? "qrc:///qtquickplugin/mockfiles/images/directional_light_gradient.png"
gizmoModel.materials: [ : targetNode instanceof AreaLight
DefaultMaterial { ? "qrc:///qtquickplugin/mockfiles/images/area_light_gradient.png"
id: defaultMaterial : "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png"
emissiveColor: "yellow" : "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png"
lighting: DefaultMaterial.NoLighting
} overlayColor: targetNode ? targetNode.color : "transparent"
]
} }

View File

@@ -31,8 +31,7 @@ Item {
property Node targetNode property Node targetNode
property View3D targetView property View3D targetView
property real offsetX: 0 property vector3d offset: Qt.vector3d(0, 0, 0)
property real offsetY: 0
property bool isBehindCamera property bool isBehindCamera
@@ -49,14 +48,16 @@ Item {
} }
Connections { Connections {
target: designStudioNativeCameraControlHelper target: _generalHelper
onOverlayUpdateNeeded: updateOverlay() onOverlayUpdateNeeded: updateOverlay()
} }
function updateOverlay() function updateOverlay()
{ {
var scenePos = targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0); var scenePos = targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0);
var scenePosWithOffset = Qt.vector3d(scenePos.x + offsetX, scenePos.y + offsetY, scenePos.z); var scenePosWithOffset = Qt.vector3d(scenePos.x + offset.x,
scenePos.y + offset.y,
scenePos.z + offset.z);
var viewPos = targetView ? targetView.mapFrom3DScene(scenePosWithOffset) var viewPos = targetView ? targetView.mapFrom3DScene(scenePosWithOffset)
: Qt.vector3d(0, 0, 0); : Qt.vector3d(0, 0, 0);
root.x = viewPos.x; root.x = viewPos.x;

View File

@@ -34,7 +34,7 @@ Model {
property alias color: gizmoMaterial.emissiveColor property alias color: gizmoMaterial.emissiveColor
property alias priority: mouseArea.priority property alias priority: mouseArea.priority
property Node targetNode: null property Node targetNode: null
property bool dragging: false property bool dragging: mouseArea.dragging
property bool active: false property bool active: false
readonly property bool hovering: mouseArea.hovering readonly property bool hovering: mouseArea.hovering
@@ -65,7 +65,6 @@ Model {
_pointerPosPressed = mouseArea.mapPositionToScene(scenePos); _pointerPosPressed = mouseArea.mapPositionToScene(scenePos);
var sp = targetNode.scenePosition; var sp = targetNode.scenePosition;
_targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z); _targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z);
dragging = true;
pressed(mouseArea); pressed(mouseArea);
} }
@@ -91,7 +90,6 @@ Model {
return; return;
released(mouseArea, calcRelativeDistance(mouseArea, scenePos)); released(mouseArea, calcRelativeDistance(mouseArea, scenePos));
dragging = false;
} }
MouseArea3D { MouseArea3D {

View File

@@ -134,8 +134,7 @@ Node {
targetNode: rotateGizmo.targetNode targetNode: rotateGizmo.targetNode
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1)) color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1))
: Qt.rgba(0.5, 0.5, 0.5, 1) : Qt.rgba(0.5, 0.5, 0.5, 1)
// Just a smidge smaller than higher priority rings so that it doesn't obscure them scale: Qt.vector3d(1.1, 1.1, 1.1)
scale: Qt.vector3d(0.994, 0.994, 0.994)
priority: 10 priority: 10
view3D: rotateGizmo.view3D view3D: rotateGizmo.view3D
active: rotateGizmo.visible active: rotateGizmo.visible

View File

@@ -33,7 +33,7 @@ Model {
property View3D view3D property View3D view3D
property alias color: material.emissiveColor property alias color: material.emissiveColor
property Node targetNode: null property Node targetNode: null
property bool dragging: false property bool dragging: mouseAreaMain.dragging
property bool active: false property bool active: false
property alias hovering: mouseAreaMain.hovering property alias hovering: mouseAreaMain.hovering
property alias priority: mouseAreaMain.priority property alias priority: mouseAreaMain.priority
@@ -80,7 +80,6 @@ Model {
_targetPosOnScreen = view3D.mapFrom3DScene(targetNode.scenePosition); _targetPosOnScreen = view3D.mapFrom3DScene(targetNode.scenePosition);
_targetPosOnScreen.z = 0; _targetPosOnScreen.z = 0;
_pointerPosPressed = Qt.vector3d(screenPos.x, screenPos.y, 0); _pointerPosPressed = Qt.vector3d(screenPos.x, screenPos.y, 0);
dragging = true;
_trackBall = angle < 0.1; _trackBall = angle < 0.1;
// Recreate vector so we don't follow the changes in targetNode.rotation // Recreate vector so we don't follow the changes in targetNode.rotation
@@ -108,7 +107,6 @@ Model {
applyLocalRotation(screenPos); applyLocalRotation(screenPos);
rotateCommit(); rotateCommit();
dragging = false;
currentAngle = 0; currentAngle = 0;
currentMousePos = screenPos; currentMousePos = screenPos;
} }

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.0
import QtQuick3D 1.0
import SelectionBoxGeometry 1.0
Node {
id: selectionBox
property View3D view3D
property Node targetNode: null
property alias model: selectionBoxModel
SelectionBoxGeometry {
id: selectionBoxGeometry
name: "Selection Box of 3D Edit View"
view3D: selectionBox.view3D
targetNode: selectionBox.targetNode
rootNode: selectionBox
}
Model {
id: selectionBoxModel
geometry: selectionBoxGeometry
scale: selectionBox.targetNode ? selectionBox.targetNode.scale : Qt.vector3d(1, 1, 1)
rotation: selectionBox.targetNode ? selectionBox.targetNode.rotation : Qt.vector3d(0, 0, 0)
position: selectionBox.targetNode ? selectionBox.targetNode.position : Qt.vector3d(0, 0, 0)
pivot: selectionBox.targetNode ? selectionBox.targetNode.pivot : Qt.vector3d(0, 0, 0)
orientation: selectionBox.targetNode ? selectionBox.targetNode.orientation : Node.LeftHanded
rotationOrder: selectionBox.targetNode ? selectionBox.targetNode.rotationOrder : Node.YXZ
visible: selectionBox.targetNode && !selectionBoxGeometry.isEmpty
materials: [
DefaultMaterial {
emissiveColor: "#fff600"
lighting: DefaultMaterial.NoLighting
cullingMode: Material.DisableCulling
}
]
}
}

View File

@@ -0,0 +1,70 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.12
import QtQuick 2.0
import QtQuick.Controls 2.0
Rectangle {
property bool toggled: false
property string tooltip
property bool toggleBackground: false // show a black background for the toggled state
property var states: [] // array of 2 state-objects, idx 0: untoggled, idx 1: toggled
id: root
color: toggleBackground && toggled ? "#aa000000" : mouseArea.containsMouse ? "#44000000" : "#00000000"
width: img.width + txt.width + 5
height: img.height
Image {
id: img
anchors.verticalCenter: parent.verticalCenter
source: "qrc:///qtquickplugin/mockfiles/images/" + root.states[toggled ? 1 : 0].iconId + ".png"
}
Text {
id: txt
color: "#b5b5b5"
anchors.verticalCenter: parent.verticalCenter
anchors.left: img.right
text: root.states[toggled ? 1 : 0].text
}
ToolTip {
text: tooltip
visible: mouseArea.containsMouse
delay: 1000
}
MouseArea {
id: mouseArea
cursorShape: "PointingHandCursor"
hoverEnabled: true
anchors.fill: parent
onClicked: root.toggled = !root.toggled
}
}

View File

@@ -34,6 +34,7 @@ Rectangle {
property string currentShortcut property string currentShortcut
property string tool property string tool
property variant buttonsGroup: [] property variant buttonsGroup: []
property bool togglable: true
id: root id: root
width: img.width + 5 width: img.width + 5
@@ -71,6 +72,11 @@ Rectangle {
root.buttonsGroup[i].selected = false; root.buttonsGroup[i].selected = false;
root.selected = true; root.selected = true;
if (!root.togglable) {
// Deselect button after a short while (selection acts as simple click indicator)
_generalHelper.delayedPropertySet(root, 200, "selected", false);
}
} }
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1,78 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "cameracontrolhelper.h"
#include <QHash>
namespace QmlDesigner {
namespace Internal {
CameraControlHelper::CameraControlHelper()
: QObject()
{
m_inputUpdateTimer.setInterval(16);
QObject::connect(&m_inputUpdateTimer, &QTimer::timeout,
this, &CameraControlHelper::handleUpdateTimer);
m_overlayUpdateTimer.setInterval(16);
m_overlayUpdateTimer.setSingleShot(true);
QObject::connect(&m_overlayUpdateTimer, &QTimer::timeout,
this, &CameraControlHelper::overlayUpdateNeeded);
}
bool CameraControlHelper::enabled()
{
return m_enabled;
}
void CameraControlHelper::handleUpdateTimer()
{
emit updateInputs();
}
void CameraControlHelper::setEnabled(bool enabled)
{
if (enabled)
m_inputUpdateTimer.start();
else
m_inputUpdateTimer.stop();
m_enabled = enabled;
}
void CameraControlHelper::requestOverlayUpdate()
{
if (!m_overlayUpdateTimer.isActive())
m_overlayUpdateTimer.start();
}
QString CameraControlHelper::generateUniqueName(const QString &nameRoot)
{
static QHash<QString, int> counters;
int count = counters[nameRoot]++;
return QStringLiteral("%1_%2").arg(nameRoot).arg(count);
}
}
}

View File

@@ -1,9 +1,11 @@
HEADERS += $$PWD/cameracontrolhelper.h \ HEADERS += $$PWD/generalhelper.h \
$$PWD/mousearea3d.h \ $$PWD/mousearea3d.h \
$$PWD/camerageometry.h \ $$PWD/camerageometry.h \
$$PWD/gridgeometry.h $$PWD/gridgeometry.h \
$$PWD/selectionboxgeometry.h
SOURCES += $$PWD/cameracontrolhelper.cpp \ SOURCES += $$PWD/generalhelper.cpp \
$$PWD/mousearea3d.cpp \ $$PWD/mousearea3d.cpp \
$$PWD/camerageometry.cpp \ $$PWD/camerageometry.cpp \
$$PWD/gridgeometry.cpp $$PWD/gridgeometry.cpp \
$$PWD/selectionboxgeometry.cpp

View File

@@ -0,0 +1,210 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "generalhelper.h"
#ifdef QUICK3D_MODULE
#include "selectionboxgeometry.h"
#include <QtQuick3D/private/qquick3dorthographiccamera_p.h>
#include <QtQuick3D/private/qquick3dperspectivecamera_p.h>
#include <QtQuick3D/private/qquick3dobject_p_p.h>
#include <QtQuick3D/private/qquick3dcamera_p.h>
#include <QtQuick3D/private/qquick3dnode_p.h>
#include <QtQuick3D/private/qquick3dmodel_p.h>
#include <QtQuick3D/private/qquick3dviewport_p.h>
#include <QtQuick3D/private/qquick3ddefaultmaterial_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h>
#include <QtQuick3DUtils/private/qssgbounds3_p.h>
#include <QtQuick/qquickwindow.h>
#include <QtCore/qmath.h>
namespace QmlDesigner {
namespace Internal {
GeneralHelper::GeneralHelper()
: QObject()
{
m_overlayUpdateTimer.setInterval(16);
m_overlayUpdateTimer.setSingleShot(true);
QObject::connect(&m_overlayUpdateTimer, &QTimer::timeout,
this, &GeneralHelper::overlayUpdateNeeded);
}
void GeneralHelper::requestOverlayUpdate()
{
if (!m_overlayUpdateTimer.isActive())
m_overlayUpdateTimer.start();
}
QString GeneralHelper::generateUniqueName(const QString &nameRoot)
{
static QHash<QString, int> counters;
int count = counters[nameRoot]++;
return QStringLiteral("%1_%2").arg(nameRoot).arg(count);
}
void GeneralHelper::orbitCamera(QQuick3DCamera *camera, const QVector3D &startRotation,
const QVector3D &lookAtPoint, const QVector3D &pressPos,
const QVector3D &currentPos)
{
QVector3D dragVector = currentPos - pressPos;
if (dragVector.length() < 0.001f)
return;
camera->setRotation(startRotation);
QVector3D newRotation(dragVector.y(), dragVector.x(), 0.f);
newRotation *= 0.5f; // Emprically determined multiplier for nice drag
newRotation += startRotation;
camera->setRotation(newRotation);
const QVector3D oldLookVector = camera->position() - lookAtPoint;
QMatrix4x4 m = camera->sceneTransform();
const float *dataPtr(m.data());
QVector3D newLookVector(-dataPtr[8], -dataPtr[9], -dataPtr[10]);
newLookVector.normalize();
newLookVector *= oldLookVector.length();
camera->setPosition(lookAtPoint + newLookVector);
}
// Pans camera and returns the new look-at point
QVector3D GeneralHelper::panCamera(QQuick3DCamera *camera, const QMatrix4x4 startTransform,
const QVector3D &startPosition, const QVector3D &startLookAt,
const QVector3D &pressPos, const QVector3D &currentPos,
float zoomFactor)
{
QVector3D dragVector = currentPos - pressPos;
if (dragVector.length() < 0.001f)
return startLookAt;
const float *dataPtr(startTransform.data());
const QVector3D xAxis = QVector3D(dataPtr[0], dataPtr[1], dataPtr[2]).normalized();
const QVector3D yAxis = QVector3D(dataPtr[4], dataPtr[5], dataPtr[6]).normalized();
const QVector3D xDelta = -1.f * xAxis * dragVector.x();
const QVector3D yDelta = yAxis * dragVector.y();
const QVector3D delta = (xDelta + yDelta) * zoomFactor;
camera->setPosition(startPosition + delta);
return startLookAt + delta;
}
float GeneralHelper::zoomCamera(QQuick3DCamera *camera, float distance, float defaultLookAtDistance,
const QVector3D &lookAt, float zoomFactor, bool relative)
{
// Emprically determined divisor for nice zoom
float multiplier = 1.f + (distance / 40.f);
float newZoomFactor = relative ? qBound(.0001f, zoomFactor * multiplier, 10000.f)
: zoomFactor;
if (qobject_cast<QQuick3DOrthographicCamera *>(camera)) {
// Ortho camera we can simply scale
camera->setScale(QVector3D(newZoomFactor, newZoomFactor, newZoomFactor));
} else if (qobject_cast<QQuick3DPerspectiveCamera *>(camera)) {
// Perspective camera is zoomed by moving camera forward or backward while keeping the
// look-at point the same
const QVector3D lookAtVec = (camera->position() - lookAt).normalized();
const float newDistance = defaultLookAtDistance * newZoomFactor;
camera->setPosition(lookAt + (lookAtVec * newDistance));
}
return newZoomFactor;
}
// Return value contains new lookAt point (xyz) and zoom factor (w)
QVector4D GeneralHelper::fitObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance,
QQuick3DNode *targetObject, QQuick3DViewport *viewPort)
{
if (!camera)
return QVector4D(0.f, 0.f, 0.f, 1.f);
QVector3D lookAt = targetObject ? targetObject->scenePosition() : QVector3D();
// Get object bounds
qreal maxExtent = 200.;
if (auto modelNode = qobject_cast<QQuick3DModel *>(targetObject)) {
auto targetPriv = QQuick3DObjectPrivate::get(targetObject);
if (auto renderModel = static_cast<QSSGRenderModel *>(targetPriv->spatialNode)) {
QWindow *window = static_cast<QWindow *>(viewPort->window());
if (window) {
auto context = QSSGRenderContextInterface::getRenderContextInterface(quintptr(window));
if (!context.isNull()) {
QSSGBounds3 bounds;
auto geometry = qobject_cast<SelectionBoxGeometry *>(modelNode->geometry());
if (geometry) {
bounds = geometry->bounds();
} else {
auto bufferManager = context->bufferManager();
bounds = renderModel->getModelBounds(bufferManager);
}
QVector3D center = bounds.center();
const QVector3D e = bounds.extents();
const QVector3D s = targetObject->sceneScale();
qreal maxScale = qSqrt(qreal(s.x() * s.x() + s.y() * s.y() + s.z() * s.z()));
maxExtent = qSqrt(qreal(e.x() * e.x() + e.y() * e.y() + e.z() * e.z()));
maxExtent *= maxScale;
// Adjust lookAt to look directly at the center of the object bounds
lookAt = renderModel->globalTransform.map(center);
lookAt.setZ(-lookAt.z()); // Render node transforms have inverted z
}
}
}
}
// Reset camera position to default zoom
QMatrix4x4 m = camera->sceneTransform();
const float *dataPtr(m.data());
QVector3D newLookVector(-dataPtr[8], -dataPtr[9], -dataPtr[10]);
newLookVector.normalize();
newLookVector *= defaultLookAtDistance;
camera->setPosition(lookAt + newLookVector);
// Emprically determined algorithm for nice zoom
float newZoomFactor = qBound(.0001f, float(maxExtent / 700.), 10000.f);
return QVector4D(lookAt,
zoomCamera(camera, 0, defaultLookAtDistance, lookAt, newZoomFactor, false));
}
void GeneralHelper::delayedPropertySet(QObject *obj, int delay, const QString &property,
const QVariant &value)
{
QTimer::singleShot(delay, [obj, property, value]() {
obj->setProperty(property.toLatin1().constData(), value);
});
}
}
}
#endif // QUICK3D_MODULE

View File

@@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#ifdef QUICK3D_MODULE
#include <QtCore/qobject.h>
#include <QtCore/qtimer.h>
#include <QtCore/qhash.h>
#include <QtGui/qvector3d.h>
#include <QtGui/qmatrix4x4.h>
QT_BEGIN_NAMESPACE
class QQuick3DCamera;
class QQuick3DNode;
class QQuick3DViewport;
QT_END_NAMESPACE
namespace QmlDesigner {
namespace Internal {
class GeneralHelper : public QObject
{
Q_OBJECT
public:
GeneralHelper();
Q_INVOKABLE void requestOverlayUpdate();
Q_INVOKABLE QString generateUniqueName(const QString &nameRoot);
Q_INVOKABLE void orbitCamera(QQuick3DCamera *camera, const QVector3D &startRotation,
const QVector3D &lookAtPoint, const QVector3D &pressPos,
const QVector3D &currentPos);
Q_INVOKABLE QVector3D panCamera(QQuick3DCamera *camera, const QMatrix4x4 startTransform,
const QVector3D &startPosition, const QVector3D &startLookAt,
const QVector3D &pressPos, const QVector3D &currentPos,
float zoomFactor);
Q_INVOKABLE float zoomCamera(QQuick3DCamera *camera, float distance,
float defaultLookAtDistance, const QVector3D &lookAt,
float zoomFactor, bool relative);
Q_INVOKABLE QVector4D fitObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance,
QQuick3DNode *targetObject, QQuick3DViewport *viewPort);
Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property,
const QVariant& value);
signals:
void overlayUpdateNeeded();
private:
QTimer m_overlayUpdateTimer;
};
}
}
#endif // QUICK3D_MODULE

View File

@@ -37,7 +37,6 @@ namespace QmlDesigner {
namespace Internal { namespace Internal {
MouseArea3D *MouseArea3D::s_mouseGrab = nullptr; MouseArea3D *MouseArea3D::s_mouseGrab = nullptr;
static const qreal s_mouseDragMultiplier = .02;
MouseArea3D::MouseArea3D(QQuick3DNode *parent) MouseArea3D::MouseArea3D(QQuick3DNode *parent)
: QQuick3DNode(parent) : QQuick3DNode(parent)
@@ -124,6 +123,13 @@ void MouseArea3D::setGrabsMouse(bool grabsMouse)
return; return;
m_grabsMouse = grabsMouse; m_grabsMouse = grabsMouse;
if (!m_grabsMouse && s_mouseGrab == this) {
setDragging(false);
setHovering(false);
s_mouseGrab = nullptr;
}
emit grabsMouseChanged(); emit grabsMouseChanged();
} }
@@ -133,6 +139,13 @@ void MouseArea3D::setActive(bool active)
return; return;
m_active = active; m_active = active;
if (!m_active && s_mouseGrab == this) {
setDragging(false);
setHovering(false);
s_mouseGrab = nullptr;
}
emit activeChanged(); emit activeChanged();
} }
@@ -340,7 +353,7 @@ qreal QmlDesigner::Internal::MouseArea3D::getNewRotationAngle(
dragDir = (screenDragDir - nodePos).normalized(); dragDir = (screenDragDir - nodePos).normalized();
const QVector3D pressToCurrent = (currentPos - pressPos); const QVector3D pressToCurrent = (currentPos - pressPos);
float magnitude = QVector3D::dotProduct(pressToCurrent, dragDir); float magnitude = QVector3D::dotProduct(pressToCurrent, dragDir);
qreal angle = -s_mouseDragMultiplier * qreal(magnitude); qreal angle = -mouseDragMultiplier() * qreal(magnitude);
return angle; return angle;
} else { } else {
const QVector3D nodeToPress = (pressPos - nodePos).normalized(); const QVector3D nodeToPress = (pressPos - nodePos).normalized();
@@ -397,7 +410,7 @@ void MouseArea3D::applyFreeRotation(QQuick3DNode *node, const QVector3D &startRo
QVector3D finalAxis = (dragVector.x() * yAxis + dragVector.y() * xAxis); QVector3D finalAxis = (dragVector.x() * yAxis + dragVector.y() * xAxis);
qreal degrees = qRadiansToDegrees(qreal(finalAxis.length()) * s_mouseDragMultiplier); qreal degrees = qRadiansToDegrees(qreal(finalAxis.length()) * mouseDragMultiplier());
finalAxis.normalize(); finalAxis.normalize();

View File

@@ -51,7 +51,7 @@ class MouseArea3D : public QQuick3DNode
Q_PROPERTY(bool hovering READ hovering NOTIFY hoveringChanged) Q_PROPERTY(bool hovering READ hovering NOTIFY hoveringChanged)
Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged) Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
Q_PROPERTY(int priority READ priority WRITE setPriority NOTIFY priorityChanged) Q_PROPERTY(int priority READ priority WRITE setPriority NOTIFY priorityChanged)
Q_PROPERTY(int active READ active WRITE setActive NOTIFY activeChanged) Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
Q_PROPERTY(QPointF circlePickArea READ circlePickArea WRITE setCirclePickArea NOTIFY circlePickAreaChanged) Q_PROPERTY(QPointF circlePickArea READ circlePickArea WRITE setCirclePickArea NOTIFY circlePickAreaChanged)
Q_PROPERTY(qreal minAngle READ minAngle WRITE setMinAngle NOTIFY minAngleChanged) Q_PROPERTY(qreal minAngle READ minAngle WRITE setMinAngle NOTIFY minAngleChanged)
Q_PROPERTY(QQuick3DNode *pickNode READ pickNode WRITE setPickNode NOTIFY pickNodeChanged) Q_PROPERTY(QQuick3DNode *pickNode READ pickNode WRITE setPickNode NOTIFY pickNodeChanged)
@@ -77,6 +77,8 @@ public:
qreal minAngle() const; qreal minAngle() const;
QQuick3DNode *pickNode() const; QQuick3DNode *pickNode() const;
static qreal mouseDragMultiplier() { return .02; }
public slots: public slots:
void setView3D(QQuick3DViewport *view3D); void setView3D(QQuick3DViewport *view3D);
void setGrabsMouse(bool grabsMouse); void setGrabsMouse(bool grabsMouse);
@@ -157,7 +159,7 @@ private:
QVector3D getMousePosInPlane(const QPointF &mousePosInView) const; QVector3D getMousePosInPlane(const QPointF &mousePosInView) const;
static MouseArea3D *s_mouseGrab; static MouseArea3D *s_mouseGrab;
bool m_grabsMouse; bool m_grabsMouse = false;
QVector3D m_mousePosInPlane; QVector3D m_mousePosInPlane;
QPointF m_circlePickArea; QPointF m_circlePickArea;
qreal m_minAngle = 0.; qreal m_minAngle = 0.;

View File

@@ -0,0 +1,336 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#ifdef QUICK3D_MODULE
#include "selectionboxgeometry.h"
#include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendercontextcore_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
#include <QtQuick3D/private/qquick3dmodel_p.h>
#include <QtQuick3D/private/qquick3dobject_p_p.h>
#include <QtQuick/qquickwindow.h>
#include <QtCore/qvector.h>
#include <limits>
namespace QmlDesigner {
namespace Internal {
SelectionBoxGeometry::SelectionBoxGeometry()
: QQuick3DGeometry()
{
}
SelectionBoxGeometry::~SelectionBoxGeometry()
{
for (auto &connection : qAsConst(m_connections))
QObject::disconnect(connection);
m_connections.clear();
}
QQuick3DNode *SelectionBoxGeometry::targetNode() const
{
return m_targetNode;
}
QQuick3DNode *SelectionBoxGeometry::rootNode() const
{
return m_rootNode;
}
QQuick3DViewport *SelectionBoxGeometry::view3D() const
{
return m_view3D;
}
bool QmlDesigner::Internal::SelectionBoxGeometry::isEmpty() const
{
return m_isEmpty;
}
QSSGBounds3 SelectionBoxGeometry::bounds() const
{
return m_bounds;
}
void SelectionBoxGeometry::setTargetNode(QQuick3DNode *targetNode)
{
if (m_targetNode == targetNode)
return;
if (m_targetNode)
m_targetNode->disconnect(this);
m_targetNode = targetNode;
if (auto model = qobject_cast<QQuick3DModel *>(m_targetNode)) {
QObject::connect(model, &QQuick3DModel::sourceChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
QObject::connect(model, &QQuick3DModel::geometryChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
}
emit targetNodeChanged();
update();
}
void SelectionBoxGeometry::setRootNode(QQuick3DNode *rootNode)
{
if (m_rootNode == rootNode)
return;
m_rootNode = rootNode;
emit rootNodeChanged();
update();
}
void SelectionBoxGeometry::setView3D(QQuick3DViewport *view)
{
if (m_view3D == view)
return;
m_view3D = view;
emit view3DChanged();
update();
}
QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
{
node = QQuick3DGeometry::updateSpatialNode(node);
QSSGRenderGeometry *geometry = static_cast<QSSGRenderGeometry *>(node);
geometry->clear();
for (auto &connection : qAsConst(m_connections))
QObject::disconnect(connection);
m_connections.clear();
QByteArray vertexData;
QByteArray indexData;
static const float floatMin = std::numeric_limits<float>::lowest();
static const float floatMax = std::numeric_limits<float>::max();
QVector3D minBounds = QVector3D(floatMax, floatMax, floatMax);
QVector3D maxBounds = QVector3D(floatMin, floatMin, floatMin);
if (m_targetNode) {
auto rootPriv = QQuick3DObjectPrivate::get(m_rootNode);
auto targetPriv = QQuick3DObjectPrivate::get(m_targetNode);
auto rootRN = static_cast<QSSGRenderNode *>(rootPriv->spatialNode);
auto targetRN = static_cast<QSSGRenderNode *>(targetPriv->spatialNode);
if (rootRN && targetRN) {
// Explicitly set local transform of root node to target node parent's global transform
// to avoid having to reparent the selection box. This has to be done directly on render
// nodes.
targetRN->parent->calculateGlobalVariables();
QMatrix4x4 m = targetRN->parent->globalTransform;
rootRN->localTransform = m;
rootRN->markDirty(QSSGRenderNode::TransformDirtyFlag::TransformNotDirty);
rootRN->calculateGlobalVariables();
}
getBounds(m_targetNode, vertexData, indexData, minBounds, maxBounds, QMatrix4x4());
} else {
// Fill some dummy data so geometry won't get rejected
appendVertexData(vertexData, indexData, minBounds, maxBounds);
}
geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::F32Type);
geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0,
QSSGRenderGeometry::Attribute::ComponentType::U16Type);
geometry->setStride(12);
geometry->setVertexData(vertexData);
geometry->setIndexData(indexData);
geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
geometry->setBounds(minBounds, maxBounds);
m_bounds = QSSGBounds3(minBounds, maxBounds);
bool empty = minBounds.isNull() && maxBounds.isNull();
if (m_isEmpty != empty) {
m_isEmpty = empty;
// Delay notification until we're done with spatial node updates
QTimer::singleShot(0, this, &SelectionBoxGeometry::isEmptyChanged);
}
return node;
}
void SelectionBoxGeometry::getBounds(QQuick3DNode *node, QByteArray &vertexData,
QByteArray &indexData, QVector3D &minBounds,
QVector3D &maxBounds, const QMatrix4x4 &transform)
{
QMatrix4x4 fullTransform;
auto nodePriv = QQuick3DObjectPrivate::get(node);
auto renderNode = static_cast<QSSGRenderNode *>(nodePriv->spatialNode);
// All transforms are relative to targetNode transform, so its local transform is ignored
if (node != m_targetNode) {
if (renderNode) {
if (renderNode->flags.testFlag(QSSGRenderNode::Flag::TransformDirty))
renderNode->calculateLocalTransform();
fullTransform = transform * renderNode->localTransform;
}
m_connections << QObject::connect(node, &QQuick3DNode::scaleChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::rotationChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::positionChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::pivotChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::orientationChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::rotationOrderChanged,
this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
}
QVector<QVector3D> minBoundsVec;
QVector<QVector3D> maxBoundsVec;
// Check for children
const auto children = node->childItems();
for (const auto child : children) {
if (auto childNode = qobject_cast<QQuick3DNode *>(child)) {
QVector3D newMinBounds = minBounds;
QVector3D newMaxBounds = maxBounds;
getBounds(childNode, vertexData, indexData, newMinBounds, newMaxBounds, fullTransform);
minBoundsVec << newMinBounds;
maxBoundsVec << newMaxBounds;
}
}
// Combine all child bounds
for (const auto &newBounds : qAsConst(minBoundsVec)) {
minBounds.setX(qMin(newBounds.x(), minBounds.x()));
minBounds.setY(qMin(newBounds.y(), minBounds.y()));
minBounds.setZ(qMin(newBounds.z(), minBounds.z()));
}
for (const auto &newBounds : qAsConst(maxBoundsVec)) {
maxBounds.setX(qMax(newBounds.x(), maxBounds.x()));
maxBounds.setY(qMax(newBounds.y(), maxBounds.y()));
maxBounds.setZ(qMax(newBounds.z(), maxBounds.z()));
}
if (auto modelNode = qobject_cast<QQuick3DModel *>(node)) {
if (auto renderModel = static_cast<QSSGRenderModel *>(renderNode)) {
QWindow *window = static_cast<QWindow *>(m_view3D->window());
if (window) {
auto context = QSSGRenderContextInterface::getRenderContextInterface(
quintptr(window));
if (!context.isNull()) {
auto bufferManager = context->bufferManager();
QSSGBounds3 bounds = renderModel->getModelBounds(bufferManager);
QVector3D center = bounds.center();
QVector3D extents = bounds.extents();
QVector3D localMin = center - extents;
QVector3D localMax = center + extents;
// Transform all corners of the local bounding box to find final extent in
// in parent space
auto checkCorner = [&minBounds, &maxBounds, &fullTransform]
(const QVector3D &corner) {
QVector3D mappedCorner = fullTransform.map(corner);
minBounds.setX(qMin(mappedCorner.x(), minBounds.x()));
minBounds.setY(qMin(mappedCorner.y(), minBounds.y()));
minBounds.setZ(qMin(mappedCorner.z(), minBounds.z()));
maxBounds.setX(qMax(mappedCorner.x(), maxBounds.x()));
maxBounds.setY(qMax(mappedCorner.y(), maxBounds.y()));
maxBounds.setZ(qMax(mappedCorner.z(), maxBounds.z()));
};
checkCorner(localMin);
checkCorner(localMax);
checkCorner(QVector3D(localMin.x(), localMin.y(), localMax.z()));
checkCorner(QVector3D(localMin.x(), localMax.y(), localMin.z()));
checkCorner(QVector3D(localMax.x(), localMin.y(), localMin.z()));
checkCorner(QVector3D(localMin.x(), localMax.y(), localMax.z()));
checkCorner(QVector3D(localMax.x(), localMax.y(), localMin.z()));
checkCorner(QVector3D(localMax.x(), localMin.y(), localMax.z()));
}
}
}
}
// Target node and immediate children get selection boxes
if (transform.isIdentity()) {
// Adjust bounds to reduce targetNode pixels obscuring the selection box
QVector3D extents = (maxBounds - minBounds) / 1000.f;
QVector3D minAdjBounds = minBounds - extents;
QVector3D maxAdjBounds = maxBounds + extents;
appendVertexData(vertexData, indexData, minAdjBounds, maxAdjBounds);
}
}
void SelectionBoxGeometry::appendVertexData(QByteArray &vertexData, QByteArray &indexData,
const QVector3D &minBounds, const QVector3D &maxBounds)
{
int initialVertexSize = vertexData.size();
int initialIndexSize = indexData.size();
const int vertexSize = int(sizeof(float)) * 8 * 3; // 8 vertices, 3 floats/vert
quint16 indexAdd = quint16(initialVertexSize / 12);
vertexData.resize(initialVertexSize + vertexSize);
const int indexSize = int(sizeof(quint16)) * 12 * 2; // 12 lines, 2 vert/line
indexData.resize(initialIndexSize + indexSize);
auto dataPtr = reinterpret_cast<float *>(vertexData.data() + initialVertexSize);
auto indexPtr = reinterpret_cast<quint16 *>(indexData.data() + initialIndexSize);
*dataPtr++ = maxBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = maxBounds.z();
*dataPtr++ = minBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = maxBounds.z();
*dataPtr++ = minBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = maxBounds.z();
*dataPtr++ = maxBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = maxBounds.z();
*dataPtr++ = maxBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = minBounds.z();
*dataPtr++ = minBounds.x(); *dataPtr++ = maxBounds.y(); *dataPtr++ = minBounds.z();
*dataPtr++ = minBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = minBounds.z();
*dataPtr++ = maxBounds.x(); *dataPtr++ = minBounds.y(); *dataPtr++ = minBounds.z();
*indexPtr++ = 0 + indexAdd; *indexPtr++ = 1 + indexAdd;
*indexPtr++ = 1 + indexAdd; *indexPtr++ = 2 + indexAdd;
*indexPtr++ = 2 + indexAdd; *indexPtr++ = 3 + indexAdd;
*indexPtr++ = 3 + indexAdd; *indexPtr++ = 0 + indexAdd;
*indexPtr++ = 0 + indexAdd; *indexPtr++ = 4 + indexAdd;
*indexPtr++ = 1 + indexAdd; *indexPtr++ = 5 + indexAdd;
*indexPtr++ = 2 + indexAdd; *indexPtr++ = 6 + indexAdd;
*indexPtr++ = 3 + indexAdd; *indexPtr++ = 7 + indexAdd;
*indexPtr++ = 4 + indexAdd; *indexPtr++ = 5 + indexAdd;
*indexPtr++ = 5 + indexAdd; *indexPtr++ = 6 + indexAdd;
*indexPtr++ = 6 + indexAdd; *indexPtr++ = 7 + indexAdd;
*indexPtr++ = 7 + indexAdd; *indexPtr++ = 4 + indexAdd;
}
}
}
#endif // QUICK3D_MODULE

View File

@@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#ifdef QUICK3D_MODULE
#include <QtQuick3D/private/qquick3dnode_p.h>
#include <QtQuick3D/private/qquick3dgeometry_p.h>
#include <QtQuick3D/private/qquick3dviewport_p.h>
#include <QtQuick3DUtils/private/qssgbounds3_p.h>
namespace QmlDesigner {
namespace Internal {
class SelectionBoxGeometry : public QQuick3DGeometry
{
Q_OBJECT
Q_PROPERTY(QQuick3DNode *targetNode READ targetNode WRITE setTargetNode NOTIFY targetNodeChanged)
Q_PROPERTY(QQuick3DNode *rootNode READ rootNode WRITE setRootNode NOTIFY rootNodeChanged)
Q_PROPERTY(QQuick3DViewport *view3D READ view3D WRITE setView3D NOTIFY view3DChanged)
Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged)
public:
SelectionBoxGeometry();
~SelectionBoxGeometry() override;
QQuick3DNode *targetNode() const;
QQuick3DNode *rootNode() const;
QQuick3DViewport *view3D() const;
bool isEmpty() const;
QSSGBounds3 bounds() const;
public Q_SLOTS:
void setTargetNode(QQuick3DNode *targetNode);
void setRootNode(QQuick3DNode *rootNode);
void setView3D(QQuick3DViewport *view);
Q_SIGNALS:
void targetNodeChanged();
void rootNodeChanged();
void view3DChanged();
void isEmptyChanged();
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
private:
void getBounds(QQuick3DNode *node, QByteArray &vertexData, QByteArray &indexData,
QVector3D &minBounds, QVector3D &maxBounds, const QMatrix4x4 &transform);
void appendVertexData(QByteArray &vertexData, QByteArray &indexData,
const QVector3D &minBounds, const QVector3D &maxBounds);
QQuick3DNode *m_targetNode = nullptr;
QQuick3DViewport *m_view3D = nullptr;
QQuick3DNode *m_rootNode = nullptr;
bool m_isEmpty = true;
QVector<QMetaObject::Connection> m_connections;
QSSGBounds3 m_bounds;
};
}
}
QML_DECLARE_TYPE(QmlDesigner::Internal::SelectionBoxGeometry)
#endif // QUICK3D_MODULE

View File

@@ -62,10 +62,11 @@
#include <drop3dlibraryitemcommand.h> #include <drop3dlibraryitemcommand.h>
#include "dummycontextobject.h" #include "dummycontextobject.h"
#include "../editor3d/cameracontrolhelper.h" #include "../editor3d/generalhelper.h"
#include "../editor3d/mousearea3d.h" #include "../editor3d/mousearea3d.h"
#include "../editor3d/camerageometry.h" #include "../editor3d/camerageometry.h"
#include "../editor3d/gridgeometry.h" #include "../editor3d/gridgeometry.h"
#include "../editor3d/selectionboxgeometry.h"
#include <designersupportdelegate.h> #include <designersupportdelegate.h>
@@ -104,13 +105,13 @@ bool Qt5InformationNodeInstanceServer::eventFilter(QObject *, QEvent *event)
QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine) QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
{ {
auto helper = new QmlDesigner::Internal::CameraControlHelper();
engine->rootContext()->setContextProperty("designStudioNativeCameraControlHelper", helper);
#ifdef QUICK3D_MODULE #ifdef QUICK3D_MODULE
auto helper = new QmlDesigner::Internal::GeneralHelper();
engine->rootContext()->setContextProperty("_generalHelper", helper);
qmlRegisterType<QmlDesigner::Internal::MouseArea3D>("MouseArea3D", 1, 0, "MouseArea3D"); qmlRegisterType<QmlDesigner::Internal::MouseArea3D>("MouseArea3D", 1, 0, "MouseArea3D");
qmlRegisterType<QmlDesigner::Internal::CameraGeometry>("CameraGeometry", 1, 0, "CameraGeometry"); qmlRegisterType<QmlDesigner::Internal::CameraGeometry>("CameraGeometry", 1, 0, "CameraGeometry");
qmlRegisterType<QmlDesigner::Internal::GridGeometry>("GridGeometry", 1, 0, "GridGeometry"); qmlRegisterType<QmlDesigner::Internal::GridGeometry>("GridGeometry", 1, 0, "GridGeometry");
qmlRegisterType<QmlDesigner::Internal::SelectionBoxGeometry>("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry");
#endif #endif
QQmlComponent component(engine, QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml")); QQmlComponent component(engine, QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"));
@@ -136,7 +137,10 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
surfaceFormat.setVersion(4, 1); surfaceFormat.setVersion(4, 1);
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile); surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
window->setFormat(surfaceFormat); window->setFormat(surfaceFormat);
#ifdef QUICK3D_MODULE
helper->setParent(window); helper->setParent(window);
#endif
return window; return window;
} }
@@ -336,13 +340,25 @@ QObject *Qt5InformationNodeInstanceServer::findRootNodeOf3DViewport(
{ {
for (const ServerNodeInstance &instance : instanceList) { for (const ServerNodeInstance &instance : instanceList) {
if (instance.isSubclassOf("QQuick3DViewport")) { if (instance.isSubclassOf("QQuick3DViewport")) {
QObject *rootObj = nullptr;
int viewChildCount = 0;
for (const ServerNodeInstance &child : instanceList) { /* Look for scene node */ for (const ServerNodeInstance &child : instanceList) { /* Look for scene node */
/* The QQuick3DViewport always creates a root node. /* The QQuick3DViewport always creates a root node.
* This root node contains the complete scene. */ * This root node contains the complete scene. */
if (child.isSubclassOf("QQuick3DNode") && child.parent() == instance) if (child.isSubclassOf("QQuick3DNode") && child.parent() == instance) {
return child.internalObject()->property("parent").value<QObject *>(); // Implicit root node is not visible in editor, so there is often another node
// added below it that serves as the actual scene root node.
// If the found root is the only node child of the view, assume that is the case.
++viewChildCount;
if (!rootObj)
rootObj = child.internalObject();
} }
} }
if (viewChildCount == 1)
return rootObj;
else if (rootObj)
return rootObj->property("parent").value<QObject *>();
}
} }
return nullptr; return nullptr;
} }
@@ -599,10 +615,8 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
if (hasInstanceForId(id)) { if (hasInstanceForId(id)) {
ServerNodeInstance instance = instanceForId(id); ServerNodeInstance instance = instanceForId(id);
QObject *object = nullptr; QObject *object = nullptr;
if (instance.isSubclassOf("QQuick3DModel") || instance.isSubclassOf("QQuick3DCamera") if (instance.isSubclassOf("QQuick3DNode"))
|| instance.isSubclassOf("QQuick3DAbstractLight")) {
object = instance.internalObject(); object = instance.internalObject();
}
QMetaObject::invokeMethod(m_editView3D, "selectObject", Q_ARG(QVariant, QMetaObject::invokeMethod(m_editView3D, "selectObject", Q_ARG(QVariant,
objectToVariant(object))); objectToVariant(object)));
return; // TODO: support multi-selection return; // TODO: support multi-selection

View File

@@ -56,17 +56,7 @@ void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNo
InstanceContainer::NodeFlags flags) InstanceContainer::NodeFlags flags)
{ {
ObjectNodeInstance::initialize(objectNodeInstance, flags); ObjectNodeInstance::initialize(objectNodeInstance, flags);
setPickable(true, true, false);
#ifdef QUICK3D_MODULE
if (quick3DNode()) {
QQuick3DObject::Type nodeType = quick3DNode()->type();
if (nodeType == QQuick3DObject::Camera || nodeType == QQuick3DObject::Light
|| nodeType == QQuick3DObject::Model || nodeType == QQuick3DObject::Image
|| nodeType == QQuick3DObject::Text) {
setPropertyVariant("pickable", true); // allow 3D objects to receive mouse clicks
}
}
#endif
} }
Qt5NodeInstanceServer *Quick3DNodeInstance::qt5NodeInstanceServer() const Qt5NodeInstanceServer *Quick3DNodeInstance::qt5NodeInstanceServer() const
@@ -83,6 +73,48 @@ QQuick3DNode *Quick3DNodeInstance::quick3DNode() const
#endif #endif
} }
void Quick3DNodeInstance::setPickable(bool enable, bool checkParent, bool applyToChildren)
{
#ifdef QUICK3D_MODULE
auto node = quick3DNode();
if (node) {
QQuick3DObject::Type nodeType = node->type();
bool parentHidden = false;
if (checkParent) {
// First check if any parent node is already hidden. Never set pickable on that case.
auto parentNode = node->parentNode();
while (parentNode && !parentHidden) {
parentHidden = QQuick3DNodePrivate::get(parentNode)->m_isHiddenInEditor;
parentNode = parentNode->parentNode();
}
}
if (!parentHidden) {
if (applyToChildren) {
auto getQuick3DInstance = [this](QQuick3DObject *obj) -> Quick3DNodeInstance * {
if (nodeInstanceServer()->hasInstanceForObject(obj)) {
ServerNodeInstance instance = nodeInstanceServer()->instanceForObject(obj);
if (instance.isValid() && qobject_cast<QQuick3DNode *>(instance.internalObject()))
return static_cast<Quick3DNodeInstance *>(instance.internalInstance().data());
}
return nullptr;
};
const auto childItems = node->childItems();
for (auto childItem : childItems) {
if (auto quick3dInstance = getQuick3DInstance(childItem)) {
// Don't override explicit block in children
if (!QQuick3DNodePrivate::get(quick3dInstance->quick3DNode())->m_isHiddenInEditor)
quick3dInstance->setPickable(enable, false, true);
}
}
}
if (nodeType == QQuick3DObject::Model)
setPropertyVariant("pickable", enable); // allow 3D objects to receive mouse clicks
}
}
#endif
}
Quick3DNodeInstance::Pointer Quick3DNodeInstance::create(QObject *object) Quick3DNodeInstance::Pointer Quick3DNodeInstance::create(QObject *object)
{ {
Pointer instance(new Quick3DNodeInstance(object)); Pointer instance(new Quick3DNodeInstance(object));
@@ -94,8 +126,12 @@ void Quick3DNodeInstance::setHideInEditor(bool b)
{ {
#ifdef QUICK3D_MODULE #ifdef QUICK3D_MODULE
QQuick3DNodePrivate *privateNode = QQuick3DNodePrivate::get(quick3DNode()); QQuick3DNodePrivate *privateNode = QQuick3DNodePrivate::get(quick3DNode());
if (privateNode) if (privateNode) {
privateNode->setIsHiddenInEditor(b); privateNode->setIsHiddenInEditor(b);
// Hidden objects should not be pickable
setPickable(!b, true, true);
}
#else #else
Q_UNUSED(b) Q_UNUSED(b)
#endif #endif

View File

@@ -53,6 +53,7 @@ protected:
private: private:
Qt5NodeInstanceServer *qt5NodeInstanceServer() const; Qt5NodeInstanceServer *qt5NodeInstanceServer() const;
QQuick3DNode *quick3DNode() const; QQuick3DNode *quick3DNode() const;
void setPickable(bool enable, bool checkParent, bool applyToChildren);
}; };
} // namespace Internal } // namespace Internal

View File

@@ -60,6 +60,7 @@ namespace Internal {
class GraphicsObjectNodeInstance; class GraphicsObjectNodeInstance;
class QmlStateNodeInstance; class QmlStateNodeInstance;
class QuickItemNodeInstance; class QuickItemNodeInstance;
class Quick3DNodeInstance;
} }
class ServerNodeInstance class ServerNodeInstance
@@ -82,6 +83,7 @@ class ServerNodeInstance
friend class QmlDesigner::Internal::ObjectNodeInstance; friend class QmlDesigner::Internal::ObjectNodeInstance;
friend class QmlDesigner::Internal::QmlPropertyChangesNodeInstance; friend class QmlDesigner::Internal::QmlPropertyChangesNodeInstance;
friend class QmlDesigner::Internal::QmlStateNodeInstance; friend class QmlDesigner::Internal::QmlStateNodeInstance;
friend class QmlDesigner::Internal::Quick3DNodeInstance;
public: public:
enum ComponentWrap { enum ComponentWrap {

View File

@@ -8,6 +8,7 @@
<file>mockfiles/GenericBackend.qml</file> <file>mockfiles/GenericBackend.qml</file>
<file>mockfiles/Dialog.qml</file> <file>mockfiles/Dialog.qml</file>
<file>mockfiles/EditView3D.qml</file> <file>mockfiles/EditView3D.qml</file>
<file>mockfiles/EditCameraController.qml</file>
<file>mockfiles/Arrow.qml</file> <file>mockfiles/Arrow.qml</file>
<file>mockfiles/AutoScaleHelper.qml</file> <file>mockfiles/AutoScaleHelper.qml</file>
<file>mockfiles/MoveGizmo.qml</file> <file>mockfiles/MoveGizmo.qml</file>
@@ -23,12 +24,17 @@
<file>mockfiles/ScaleRod.qml</file> <file>mockfiles/ScaleRod.qml</file>
<file>mockfiles/ScaleGizmo.qml</file> <file>mockfiles/ScaleGizmo.qml</file>
<file>mockfiles/ToolBarButton.qml</file> <file>mockfiles/ToolBarButton.qml</file>
<file>mockfiles/ToggleButton.qml</file>
<file>mockfiles/RotateGizmo.qml</file> <file>mockfiles/RotateGizmo.qml</file>
<file>mockfiles/RotateRing.qml</file> <file>mockfiles/RotateRing.qml</file>
<file>mockfiles/SelectionBox.qml</file>
<file>mockfiles/AxisHelper.qml</file>
<file>mockfiles/AxisHelperArm.qml</file>
<file>mockfiles/meshes/arrow.mesh</file> <file>mockfiles/meshes/arrow.mesh</file>
<file>mockfiles/meshes/scalerod.mesh</file> <file>mockfiles/meshes/scalerod.mesh</file>
<file>mockfiles/meshes/ring.mesh</file> <file>mockfiles/meshes/ring.mesh</file>
<file>mockfiles/meshes/ringselect.mesh</file> <file>mockfiles/meshes/ringselect.mesh</file>
<file>mockfiles/meshes/axishelper.mesh</file>
<file>mockfiles/images/editor_camera.png</file> <file>mockfiles/images/editor_camera.png</file>
<file>mockfiles/images/editor_camera@2x.png</file> <file>mockfiles/images/editor_camera@2x.png</file>
<file>mockfiles/images/light-pick-icon.png</file> <file>mockfiles/images/light-pick-icon.png</file>
@@ -53,5 +59,27 @@
<file>mockfiles/images/scale_active@2x.png</file> <file>mockfiles/images/scale_active@2x.png</file>
<file>mockfiles/images/scale_selected.png</file> <file>mockfiles/images/scale_selected.png</file>
<file>mockfiles/images/scale_selected@2x.png</file> <file>mockfiles/images/scale_selected@2x.png</file>
<file>mockfiles/images/directional_light_gradient.png</file>
<file>mockfiles/images/directional_light_gradient@2x.png</file>
<file>mockfiles/images/point_light_gradient.png</file>
<file>mockfiles/images/point_light_gradient@2x.png</file>
<file>mockfiles/images/area_light_gradient.png</file>
<file>mockfiles/images/area_light_gradient@2x.png</file>
<file>mockfiles/images/fit_active.png</file>
<file>mockfiles/images/fit_active@2x.png</file>
<file>mockfiles/images/fit_selected.png</file>
<file>mockfiles/images/fit_selected@2x.png</file>
<file>mockfiles/images/local.png</file>
<file>mockfiles/images/local@2x.png</file>
<file>mockfiles/images/global.png</file>
<file>mockfiles/images/global@2x.png</file>
<file>mockfiles/images/ortho.png</file>
<file>mockfiles/images/ortho@2x.png</file>
<file>mockfiles/images/persp.png</file>
<file>mockfiles/images/persp@2x.png</file>
<file>mockfiles/images/edit_light_off.png</file>
<file>mockfiles/images/edit_light_off@2x.png</file>
<file>mockfiles/images/edit_light_on.png</file>
<file>mockfiles/images/edit_light_on@2x.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -41,7 +41,6 @@ Section {
function getBackendValue(name) function getBackendValue(name)
{ {
print(fontSection.fontName + "_" + name)
return backendValues[fontSection.fontName + "_" + name] return backendValues[fontSection.fontName + "_" + name]
} }

View File

@@ -185,7 +185,9 @@ T.ComboBox {
StudioTheme.Values.maxComboBoxPopupHeight) StudioTheme.Values.maxComboBoxPopupHeight)
padding: StudioTheme.Values.border padding: StudioTheme.Values.border
margins: 0 // If not defined margin will be -1 margins: 0 // If not defined margin will be -1
closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent
| T.Popup.CloseOnEscape | T.Popup.CloseOnReleaseOutside
| T.Popup.CloseOnReleaseOutsideParent
contentItem: ListView { contentItem: ListView {
clip: true clip: true
@@ -242,7 +244,7 @@ T.ComboBox {
}, },
State { State {
name: "edit" name: "edit"
when: myComboBox.edit && myComboBox.editable when: myComboBox.edit && myComboBox.editable && !comboBoxPopup.opened
PropertyChanges { PropertyChanges {
target: myComboBox target: myComboBox
wheelEnabled: true wheelEnabled: true
@@ -250,12 +252,29 @@ T.ComboBox {
PropertyChanges { PropertyChanges {
target: comboBoxInput target: comboBoxInput
selectByMouse: true selectByMouse: true
readOnly: false
} }
PropertyChanges { PropertyChanges {
target: comboBoxBackground target: comboBoxBackground
color: StudioTheme.Values.themeInteraction color: StudioTheme.Values.themeInteraction
border.color: StudioTheme.Values.themeInteraction border.color: StudioTheme.Values.themeInteraction
} }
StateChangeScript {
script: comboBoxPopup.close()
}
},
State {
name: "popup"
when: myComboBox.edit && comboBoxPopup.opened
PropertyChanges {
target: myComboBox
wheelEnabled: true
}
PropertyChanges {
target: comboBoxInput
selectByMouse: false
readOnly: true
}
} }
] ]

View File

@@ -1,3 +1,5 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2019 The Qt Company Ltd.
@@ -22,7 +24,6 @@
** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Window 2.12 import QtQuick.Window 2.12
import QtQuick.Templates 2.12 as T import QtQuick.Templates 2.12 as T
@@ -43,10 +44,11 @@ T.Menu {
overlap: 1 overlap: 1
padding: 0 padding: 0
closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnEscape closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent
| T.Popup.CloseOnEscape | T.Popup.CloseOnReleaseOutside
| T.Popup.CloseOnReleaseOutsideParent
delegate: MenuItem { delegate: MenuItem {}
}
contentItem: ListView { contentItem: ListView {
model: control.contentModel model: control.contentModel

View File

@@ -33,7 +33,9 @@ T.Popup {
property T.Control myControl property T.Control myControl
dim: false dim: false
closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent
| T.Popup.CloseOnEscape | T.Popup.CloseOnReleaseOutside
| T.Popup.CloseOnReleaseOutsideParent
background: Rectangle { background: Rectangle {
color: StudioTheme.Values.themeControlBackground color: StudioTheme.Values.themeControlBackground

View File

@@ -193,6 +193,7 @@ TextInput {
PropertyChanges { PropertyChanges {
target: mouseArea target: mouseArea
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
enabled: false
} }
}, },
State { State {

View File

@@ -237,7 +237,7 @@ bool OpenProjectCommand::run()
Project *project = openProjectSucceeded.project(); Project *project = openProjectSucceeded.project();
project->configureAsExampleProject(); project->configureAsExampleProject();
return CppTools::Tests::TestCase::waitUntilCppModelManagerIsAwareOf(project, timeOutInMs()); return CppTools::Tests::TestCase::waitUntilProjectIsFullyOpened(project, timeOutInMs());
} }
Command::Ptr OpenProjectCommand::parse(BatchFileLineTokenizer &arguments, Command::Ptr OpenProjectCommand::parse(BatchFileLineTokenizer &arguments,

View File

@@ -66,10 +66,6 @@ static QStringList clazyPluginArguments(const ClangDiagnosticConfig diagnosticCo
arguments << XclangArgs({"-add-plugin", arguments << XclangArgs({"-add-plugin",
"clazy", "clazy",
"-plugin-arg-clazy", "-plugin-arg-clazy",
"enable-all-fixits",
"-plugin-arg-clazy",
"no-autowrite-fixits",
"-plugin-arg-clazy",
diagnosticConfig.clazyChecks()}); diagnosticConfig.clazyChecks()});
} }

View File

@@ -33,6 +33,7 @@
#include "clangtoolsdiagnosticmodel.h" #include "clangtoolsdiagnosticmodel.h"
#include "clangtoolsdiagnosticview.h" #include "clangtoolsdiagnosticview.h"
#include "clangtoolslogfilereader.h" #include "clangtoolslogfilereader.h"
#include "clangtoolsplugin.h"
#include "clangtoolsprojectsettings.h" #include "clangtoolsprojectsettings.h"
#include "clangtoolssettings.h" #include "clangtoolssettings.h"
#include "clangtoolsutils.h" #include "clangtoolsutils.h"
@@ -399,6 +400,15 @@ ClangTool::ClangTool()
ApplyFixIts(diagnosticItems).apply(m_diagnosticModel); ApplyFixIts(diagnosticItems).apply(m_diagnosticModel);
}); });
// Open Project Settings
action = new QAction(this);
action->setIcon(Utils::Icons::SETTINGS_TOOLBAR.icon());
//action->setToolTip(tr("Open Project Settings")); // TODO: Uncomment in master.
connect(action, &QAction::triggered, []() {
ProjectExplorerPlugin::activateProjectPanel(Constants::PROJECT_PANEL_ID);
});
m_openProjectSettings = action;
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER); ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the " const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the "
"Clang project to search for diagnostics."); "Clang project to search for diagnostics.");
@@ -424,6 +434,7 @@ ClangTool::ClangTool()
m_perspective.addToolBarAction(m_startAction); m_perspective.addToolBarAction(m_startAction);
m_perspective.addToolBarAction(m_startOnCurrentFileAction); m_perspective.addToolBarAction(m_startOnCurrentFileAction);
m_perspective.addToolBarAction(m_stopAction); m_perspective.addToolBarAction(m_stopAction);
m_perspective.addToolBarAction(m_openProjectSettings);
m_perspective.addToolBarAction(m_loadExported); m_perspective.addToolBarAction(m_loadExported);
m_perspective.addToolBarAction(m_clear); m_perspective.addToolBarAction(m_clear);
m_perspective.addToolBarAction(m_goBack); m_perspective.addToolBarAction(m_goBack);

View File

@@ -129,6 +129,7 @@ private:
Utils::FancyLineEdit *m_filterLineEdit = nullptr; Utils::FancyLineEdit *m_filterLineEdit = nullptr;
QToolButton *m_applyFixitsButton = nullptr; QToolButton *m_applyFixitsButton = nullptr;
QAction *m_openProjectSettings = nullptr;
QAction *m_goBack = nullptr; QAction *m_goBack = nullptr;
QAction *m_goNext = nullptr; QAction *m_goNext = nullptr;
QAction *m_loadExported = nullptr; QAction *m_loadExported = nullptr;

View File

@@ -28,6 +28,8 @@
namespace ClangTools { namespace ClangTools {
namespace Constants { namespace Constants {
const char PROJECT_PANEL_ID[] = "ClangTools";
const char RUN_ON_PROJECT[] = "ClangTools.RunOnProject"; const char RUN_ON_PROJECT[] = "ClangTools.RunOnProject";
const char RUN_ON_CURRENT_FILE[] = "ClangTools.RunOnCurrentFile"; const char RUN_ON_CURRENT_FILE[] = "ClangTools.RunOnCurrentFile";

View File

@@ -347,7 +347,7 @@ public:
int extraOffset = 0) int extraOffset = 0)
: m_node(node) : m_node(node)
, m_fileCache(fileCache) , m_fileCache(fileCache)
, m_filePath(asString(node["FilePath"])) , m_filePath(QDir::cleanPath(asString(node["FilePath"])))
, m_fileOffsetKey(fileOffsetKey) , m_fileOffsetKey(fileOffsetKey)
, m_extraOffset(extraOffset) , m_extraOffset(extraOffset)
{} {}

View File

@@ -67,6 +67,13 @@ using namespace ProjectExplorer;
namespace ClangTools { namespace ClangTools {
namespace Internal { namespace Internal {
static ProjectPanelFactory *m_projectPanelFactoryInstance = nullptr;
ProjectPanelFactory *projectPanelFactory()
{
return m_projectPanelFactoryInstance;
}
class ClangToolsOptionsPage : public IOptionsPage class ClangToolsOptionsPage : public IOptionsPage
{ {
public: public:
@@ -123,8 +130,9 @@ bool ClangToolsPlugin::initialize(const QStringList &arguments, QString *errorSt
ActionManager::registerAction(d->clangTool.startOnCurrentFileAction(), ActionManager::registerAction(d->clangTool.startOnCurrentFileAction(),
Constants::RUN_ON_CURRENT_FILE); Constants::RUN_ON_CURRENT_FILE);
auto panelFactory = new ProjectPanelFactory(); auto panelFactory = m_projectPanelFactoryInstance = new ProjectPanelFactory;
panelFactory->setPriority(100); panelFactory->setPriority(100);
panelFactory->setId(Constants::PROJECT_PANEL_ID);
panelFactory->setDisplayName(tr("Clang Tools")); panelFactory->setDisplayName(tr("Clang Tools"));
panelFactory->setCreateWidgetFunction([](Project *project) { return new ProjectSettingsWidget(project); }); panelFactory->setCreateWidgetFunction([](Project *project) { return new ProjectSettingsWidget(project); });
ProjectPanelFactory::registerFactory(panelFactory); ProjectPanelFactory::registerFactory(panelFactory);

View File

@@ -27,9 +27,13 @@
#include <extensionsystem/iplugin.h> #include <extensionsystem/iplugin.h>
namespace ProjectExplorer { class ProjectPanelFactory; }
namespace ClangTools { namespace ClangTools {
namespace Internal { namespace Internal {
ProjectExplorer::ProjectPanelFactory *projectPanelFactory();
class ClangToolsPlugin : public ExtensionSystem::IPlugin class ClangToolsPlugin : public ExtensionSystem::IPlugin
{ {
Q_OBJECT Q_OBJECT

View File

@@ -34,7 +34,7 @@
namespace ClangTools { namespace ClangTools {
namespace Internal { namespace Internal {
const char diagnosticConfigIdKey[] = "DiagnosticConfigId"; const char diagnosticConfigIdKey[] = "DiagnosticConfig";
class RunSettings class RunSettings
{ {

View File

@@ -318,7 +318,7 @@ class CMakeGeneratorKitAspectWidget : public KitAspectWidget
public: public:
CMakeGeneratorKitAspectWidget(Kit *kit, const ::KitAspect *ki) CMakeGeneratorKitAspectWidget(Kit *kit, const ::KitAspect *ki)
: KitAspectWidget(kit, ki), : KitAspectWidget(kit, ki),
m_label(new QLabel), m_label(new Utils::ElidingLabel),
m_changeButton(new QPushButton) m_changeButton(new QPushButton)
{ {
m_label->setToolTip(ki->description()); m_label->setToolTip(ki->description());
@@ -459,7 +459,7 @@ private:
} }
bool m_ignoreChange = false; bool m_ignoreChange = false;
QLabel *m_label; Utils::ElidingLabel *m_label;
QPushButton *m_changeButton; QPushButton *m_changeButton;
CMakeTool *m_currentTool = nullptr; CMakeTool *m_currentTool = nullptr;
}; };

View File

@@ -226,22 +226,17 @@ QList<CPlusPlus::Document::Ptr> TestCase::waitForFilesInGlobalSnapshot(const QSt
return result; return result;
} }
bool TestCase::waitUntilCppModelManagerIsAwareOf(Project *project, int timeOutInMs) bool TestCase::waitUntilProjectIsFullyOpened(Project *project, int timeOutInMs)
{ {
if (!project) if (!project)
return false; return false;
QElapsedTimer t; return QTest::qWaitFor(
t.start(); [project]() {
return !project->isParsing()
CppModelManager *modelManager = CppModelManager::instance(); && CppModelManager::instance()->projectInfo(project).isValid();
forever { },
if (modelManager->projectInfo(project).isValid()) timeOutInMs);
return true;
if (t.elapsed() > timeOutInMs)
return false;
QCoreApplication::processEvents();
}
} }
bool TestCase::writeFile(const QString &filePath, const QByteArray &contents) bool TestCase::writeFile(const QString &filePath, const QByteArray &contents)
@@ -293,7 +288,7 @@ ProjectInfo ProjectOpenerAndCloser::open(const QString &projectFile, bool config
if (configureAsExampleProject) if (configureAsExampleProject)
project->configureAsExampleProject(); project->configureAsExampleProject();
if (TestCase::waitUntilCppModelManagerIsAwareOf(project)) { if (TestCase::waitUntilProjectIsFullyOpened(project)) {
m_openProjects.append(project); m_openProjects.append(project);
return CppModelManager::instance()->projectInfo(project); return CppModelManager::instance()->projectInfo(project);
} }

View File

@@ -92,8 +92,7 @@ public:
static bool waitForProcessedEditorDocument(const QString &filePath, int timeOutInMs = 5000); static bool waitForProcessedEditorDocument(const QString &filePath, int timeOutInMs = 5000);
enum { defaultTimeOutInMs = 30 * 1000 /*= 30 secs*/ }; enum { defaultTimeOutInMs = 30 * 1000 /*= 30 secs*/ };
static bool waitUntilCppModelManagerIsAwareOf( static bool waitUntilProjectIsFullyOpened(ProjectExplorer::Project *project,
ProjectExplorer::Project *project,
int timeOutInMs = defaultTimeOutInMs); int timeOutInMs = defaultTimeOutInMs);
static CPlusPlus::Document::Ptr waitForFileInGlobalSnapshot( static CPlusPlus::Document::Ptr waitForFileInGlobalSnapshot(
const QString &filePath, const QString &filePath,

View File

@@ -40,10 +40,10 @@
using namespace ProjectExplorer; using namespace ProjectExplorer;
typedef QMap<QString, QStringList> DependencyMap; using DependencyMap = QMap<QString, QStringList>;
typedef CPlusPlus::Document::Ptr DocumentPtr; using DocumentPtr = CPlusPlus::Document::Ptr;
typedef QList<CPlusPlus::Symbol *> SymbolList; using SymbolList = QList<CPlusPlus::Symbol *>;
typedef QList<DocumentPtr> DocumentPtrList; using DocumentPtrList = QList<DocumentPtr>;
static const char setupUiC[] = "setupUi"; static const char setupUiC[] = "setupUi";

View File

@@ -58,14 +58,14 @@ QString FormClassWizard::formSuffix() const
Core::BaseFileWizard *FormClassWizard::create(QWidget *parent, const Core::WizardDialogParameters &parameters) const Core::BaseFileWizard *FormClassWizard::create(QWidget *parent, const Core::WizardDialogParameters &parameters) const
{ {
FormClassWizardDialog *wizardDialog = new FormClassWizardDialog(this, parent); auto wizardDialog = new FormClassWizardDialog(this, parent);
wizardDialog->setPath(parameters.defaultPath()); wizardDialog->setPath(parameters.defaultPath());
return wizardDialog; return wizardDialog;
} }
Core::GeneratedFiles FormClassWizard::generateFiles(const QWizard *w, QString *errorMessage) const Core::GeneratedFiles FormClassWizard::generateFiles(const QWizard *w, QString *errorMessage) const
{ {
const FormClassWizardDialog *wizardDialog = qobject_cast<const FormClassWizardDialog *>(w); auto wizardDialog = qobject_cast<const FormClassWizardDialog *>(w);
const Designer::FormClassWizardParameters params = wizardDialog->parameters(); const Designer::FormClassWizardParameters params = wizardDialog->parameters();
if (params.uiTemplate.isEmpty()) { if (params.uiTemplate.isEmpty()) {
@@ -90,7 +90,8 @@ Core::GeneratedFiles FormClassWizard::generateFiles(const QWizard *w, QString *e
uiFile.setContents(params.uiTemplate); uiFile.setContents(params.uiTemplate);
uiFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute); uiFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute);
QString source, header; QString source;
QString header;
QtDesignerFormClassCodeGenerator::generateCpp(params, &header, &source); QtDesignerFormClassCodeGenerator::generateCpp(params, &header, &source);
sourceFile.setContents(source); sourceFile.setContents(source);

View File

@@ -105,7 +105,7 @@ bool FormEditorPlugin::initialize(const QStringList &arguments, QString *error)
// Ensure that loading designer translations is done before FormEditorW is instantiated // Ensure that loading designer translations is done before FormEditorW is instantiated
const QString locale = ICore::userInterfaceLanguage(); const QString locale = ICore::userInterfaceLanguage();
if (!locale.isEmpty()) { if (!locale.isEmpty()) {
QTranslator *qtr = new QTranslator(this); auto qtr = new QTranslator(this);
const QString &creatorTrPath = ICore::resourcePath() + "/translations"; const QString &creatorTrPath = ICore::resourcePath() + "/translations";
const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
const QString &trFile = "designer_" + locale; const QString &trFile = "designer_" + locale;

View File

@@ -92,7 +92,7 @@ void FormEditorStack::add(const EditorData &data)
// Since we have 1 pixel splitters we enforce no frame // Since we have 1 pixel splitters we enforce no frame
// on the content widget // on the content widget
if (QFrame *frame = qobject_cast<QFrame*>(data.widgetHost)) if (auto frame = qobject_cast<QFrame*>(data.widgetHost))
frame->setFrameStyle(QFrame::NoFrame); frame->setFrameStyle(QFrame::NoFrame);
} }
@@ -122,7 +122,7 @@ EditorData FormEditorStack::activeEditor() const
if (index >= 0) if (index >= 0)
return m_formEditors.at(index); return m_formEditors.at(index);
} }
return EditorData(); return {};
} }
SharedTools::WidgetHost *FormEditorStack::formWindowEditorForFormWindow(const QDesignerFormWindowInterface *fw) const SharedTools::WidgetHost *FormEditorStack::formWindowEditorForFormWindow(const QDesignerFormWindowInterface *fw) const
@@ -173,7 +173,7 @@ void FormEditorStack::formSizeChanged(int w, int h)
// Handle main container resize. // Handle main container resize.
if (Designer::Constants::Internal::debug) if (Designer::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << w << h; qDebug() << Q_FUNC_INFO << w << h;
if (const SharedTools::WidgetHost *wh = qobject_cast<const SharedTools::WidgetHost *>(sender())) { if (auto wh = qobject_cast<const SharedTools::WidgetHost *>(sender())) {
wh->formWindow()->setDirty(true); wh->formWindow()->setDirty(true);
static const QString geometry = "geometry"; static const QString geometry = "geometry";
m_designerCore->propertyEditor()->setPropertyValue(geometry, QRect(0,0,w,h) ); m_designerCore->propertyEditor()->setPropertyValue(geometry, QRect(0,0,w,h) );

View File

@@ -115,7 +115,7 @@ namespace Internal {
class DesignerXmlEditorWidget : public TextEditor::TextEditorWidget class DesignerXmlEditorWidget : public TextEditor::TextEditorWidget
{ {
public: public:
DesignerXmlEditorWidget() {} using TextEditorWidget::TextEditorWidget;
void finalizeInitialization() override void finalizeInitialization() override
{ {
@@ -196,7 +196,7 @@ public:
QDesignerFormEditorInterface *m_formeditor = nullptr; QDesignerFormEditorInterface *m_formeditor = nullptr;
QtCreatorIntegration *m_integration = nullptr; QtCreatorIntegration *m_integration = nullptr;
QDesignerFormWindowManagerInterface *m_fwm = nullptr; QDesignerFormWindowManagerInterface *m_fwm = nullptr;
FormEditorW::InitializationStage m_initStage; FormEditorW::InitializationStage m_initStage = FormEditorW::RegisterPlugins;
QWidget *m_designerSubWindows[DesignerSubWindowCount]; QWidget *m_designerSubWindows[DesignerSubWindowCount];
@@ -229,8 +229,7 @@ static FormEditorData *d = nullptr;
static FormEditorW *m_instance = nullptr; static FormEditorW *m_instance = nullptr;
FormEditorData::FormEditorData() : FormEditorData::FormEditorData() :
m_formeditor(QDesignerComponents::createFormEditor(nullptr)), m_formeditor(QDesignerComponents::createFormEditor(nullptr))
m_initStage(FormEditorW::RegisterPlugins)
{ {
if (Designer::Constants::Internal::debug) if (Designer::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
@@ -409,19 +408,18 @@ void FormEditorData::fullInit()
m_modeWidget = new QWidget; m_modeWidget = new QWidget;
m_modeWidget->setObjectName("DesignerModeWidget"); m_modeWidget->setObjectName("DesignerModeWidget");
QVBoxLayout *layout = new QVBoxLayout; auto layout = new QVBoxLayout(m_modeWidget);
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0); layout->setSpacing(0);
layout->addWidget(m_toolBar); layout->addWidget(m_toolBar);
// Avoid mode switch to 'Edit' mode when the application started by // Avoid mode switch to 'Edit' mode when the application started by
// 'Run' in 'Design' mode emits output. // 'Run' in 'Design' mode emits output.
MiniSplitter *splitter = new MiniSplitter(Qt::Vertical); auto splitter = new MiniSplitter(Qt::Vertical);
splitter->addWidget(m_editorWidget); splitter->addWidget(m_editorWidget);
QWidget *outputPane = new OutputPanePlaceHolder(Core::Constants::MODE_DESIGN, splitter); QWidget *outputPane = new OutputPanePlaceHolder(Core::Constants::MODE_DESIGN, splitter);
outputPane->setObjectName("DesignerOutputPanePlaceHolder"); outputPane->setObjectName("DesignerOutputPanePlaceHolder");
splitter->addWidget(outputPane); splitter->addWidget(outputPane);
layout->addWidget(splitter); layout->addWidget(splitter);
m_modeWidget->setLayout(layout);
Context designerContexts = m_contexts; Context designerContexts = m_contexts;
designerContexts.add(Core::Constants::C_EDITORMANAGER); designerContexts.add(Core::Constants::C_EDITORMANAGER);
@@ -648,9 +646,8 @@ void FormEditorData::setupActions()
QToolBar *FormEditorData::createEditorToolBar() const QToolBar *FormEditorData::createEditorToolBar() const
{ {
QToolBar *editorToolBar = new QToolBar; QToolBar *editorToolBar = new QToolBar;
const QList<Id>::const_iterator cend = m_toolActionIds.constEnd(); for (const auto &id : m_toolActionIds) {
for (QList<Id>::const_iterator it = m_toolActionIds.constBegin(); it != cend; ++it) { Command *cmd = ActionManager::command(id);
Command *cmd = ActionManager::command(*it);
QTC_ASSERT(cmd, continue); QTC_ASSERT(cmd, continue);
QAction *action = cmd->action(); QAction *action = cmd->action();
if (!action->icon().isNull()) // Simplify grid has no action yet if (!action->icon().isNull()) // Simplify grid has no action yet
@@ -735,7 +732,7 @@ QAction *FormEditorData::createEditModeAction(QActionGroup *ag,
const QString &iconName, const QString &iconName,
const QString &keySequence) const QString &keySequence)
{ {
QAction *rc = new QAction(actionName, ag); auto rc = new QAction(actionName, ag);
rc->setCheckable(true); rc->setCheckable(true);
if (!iconName.isEmpty()) if (!iconName.isEmpty())
rc->setIcon(designerIcon(iconName)); rc->setIcon(designerIcon(iconName));
@@ -774,7 +771,7 @@ IEditor *FormEditorData::createEditor()
QTC_ASSERT(form, return nullptr); QTC_ASSERT(form, return nullptr);
QObject::connect(form, &QDesignerFormWindowInterface::toolChanged, [this] (int i) { toolChanged(i); }); QObject::connect(form, &QDesignerFormWindowInterface::toolChanged, [this] (int i) { toolChanged(i); });
SharedTools::WidgetHost *widgetHost = new SharedTools::WidgetHost( /* parent */ nullptr, form); auto widgetHost = new SharedTools::WidgetHost( /* parent */ nullptr, form);
FormWindowEditor *formWindowEditor = m_xmlEditorFactory->create(form); FormWindowEditor *formWindowEditor = m_xmlEditorFactory->create(form);
m_editorWidget->add(widgetHost, formWindowEditor); m_editorWidget->add(widgetHost, formWindowEditor);

View File

@@ -60,8 +60,7 @@ Utils::WizardPage *FormPageFactory::create(ProjectExplorer::JsonWizard *wizard,
QTC_ASSERT(canCreate(typeId), return nullptr); QTC_ASSERT(canCreate(typeId), return nullptr);
FormTemplateWizardPage *page = new FormTemplateWizardPage; return new FormTemplateWizardPage;
return page;
} }
bool FormPageFactory::validateData(Core::Id typeId, const QVariant &data, QString *errorMessage) bool FormPageFactory::validateData(Core::Id typeId, const QVariant &data, QString *errorMessage)

View File

@@ -44,9 +44,7 @@ FormWindowEditor::FormWindowEditor()
addContext(Designer::Constants::C_DESIGNER_XML_EDITOR); addContext(Designer::Constants::C_DESIGNER_XML_EDITOR);
} }
FormWindowEditor::~FormWindowEditor() FormWindowEditor::~FormWindowEditor() = default;
{
}
QWidget *FormWindowEditor::toolBar() QWidget *FormWindowEditor::toolBar()
{ {

View File

@@ -84,7 +84,7 @@ Core::IDocument::OpenResult FormWindowFile::open(QString *errorString, const QSt
Utils::TextFileFormat::ReadResult readResult = read(absfileName, &contents, errorString); Utils::TextFileFormat::ReadResult readResult = read(absfileName, &contents, errorString);
if (readResult == Utils::TextFileFormat::ReadEncodingError) if (readResult == Utils::TextFileFormat::ReadEncodingError)
return OpenResult::CannotHandle; return OpenResult::CannotHandle;
else if (readResult != Utils::TextFileFormat::ReadSuccess) if (readResult != Utils::TextFileFormat::ReadSuccess)
return OpenResult::ReadError; return OpenResult::ReadError;
form->setFileName(absfileName); form->setFileName(absfileName);

View File

@@ -218,18 +218,18 @@ static const Class *findClass(const Namespace *parentNameSpace, const LookupCont
static Function *findDeclaration(const Class *cl, const QString &functionName) static Function *findDeclaration(const Class *cl, const QString &functionName)
{ {
const QString funName = QString::fromUtf8(QMetaObject::normalizedSignature(functionName.toUtf8())); const QString funName = QString::fromUtf8(QMetaObject::normalizedSignature(functionName.toUtf8()));
const unsigned mCount = cl->memberCount(); const int mCount = cl->memberCount();
// we are interested only in declarations (can be decl of function or of a field) // we are interested only in declarations (can be decl of function or of a field)
// we are only interested in declarations of functions // we are only interested in declarations of functions
const Overview overview; const Overview overview;
for (unsigned j = 0; j < mCount; ++j) { // go through all members for (int j = 0; j < mCount; ++j) { // go through all members
if (Declaration *decl = cl->memberAt(j)->asDeclaration()) if (Declaration *decl = cl->memberAt(j)->asDeclaration())
if (Function *fun = decl->type()->asFunctionType()) { if (Function *fun = decl->type()->asFunctionType()) {
// Format signature // Format signature
QString memberFunction = overview.prettyName(fun->name()); QString memberFunction = overview.prettyName(fun->name());
memberFunction += '('; memberFunction += '(';
const uint aCount = fun->argumentCount(); const int aCount = fun->argumentCount();
for (uint i = 0; i < aCount; i++) { // we build argument types string for (int i = 0; i < aCount; i++) { // we build argument types string
const Argument *arg = fun->argumentAt(i)->asArgument(); const Argument *arg = fun->argumentAt(i)->asArgument();
if (i > 0) if (i > 0)
memberFunction += ','; memberFunction += ',';
@@ -350,7 +350,7 @@ static QString addConstRefIfNeeded(const QString &argument)
"unsigned", "qint64", "quint64"}); "unsigned", "qint64", "quint64"});
for (int i = 0; i < nonConstRefs.count(); i++) { for (int i = 0; i < nonConstRefs.count(); i++) {
const QString nonConstRef = nonConstRefs.at(i); const QString &nonConstRef = nonConstRefs.at(i);
if (argument == nonConstRef || argument.startsWith(nonConstRef + ' ')) if (argument == nonConstRef || argument.startsWith(nonConstRef + ' '))
return argument; return argument;
} }
@@ -411,7 +411,7 @@ static QString addParameterNames(const QString &functionSignature, const QString
// included files (going down [maxIncludeDepth] includes) and return a pair // included files (going down [maxIncludeDepth] includes) and return a pair
// of <Class*, Document>. // of <Class*, Document>.
typedef QPair<const Class *, Document::Ptr> ClassDocumentPtrPair; using ClassDocumentPtrPair = QPair<const Class *, Document::Ptr>;
static ClassDocumentPtrPair static ClassDocumentPtrPair
findClassRecursively(const LookupContext &context, const QString &className, findClassRecursively(const LookupContext &context, const QString &className,
@@ -431,7 +431,7 @@ static ClassDocumentPtrPair
for (const QString &include : includedFiles) { for (const QString &include : includedFiles) {
const Snapshot::const_iterator it = docTable.find(include); const Snapshot::const_iterator it = docTable.find(include);
if (it != docTable.end()) { if (it != docTable.end()) {
const Document::Ptr includeDoc = it.value(); const Document::Ptr &includeDoc = it.value();
LookupContext context(includeDoc, docTable); LookupContext context(includeDoc, docTable);
const ClassDocumentPtrPair irc = findClassRecursively(context, className, const ClassDocumentPtrPair irc = findClassRecursively(context, className,
recursionMaxIncludeDepth, namespaceName); recursionMaxIncludeDepth, namespaceName);
@@ -489,7 +489,7 @@ bool QtCreatorIntegration::navigateToSlot(const QString &objectName,
const QStringList &parameterNames, const QStringList &parameterNames,
QString *errorMessage) QString *errorMessage)
{ {
typedef QMap<int, Document::Ptr> DocumentMap; using DocumentMap = QMap<int, Document::Ptr>;
const Utils::FilePath currentUiFile = FormEditorW::activeEditor()->document()->filePath(); const Utils::FilePath currentUiFile = FormEditorW::activeEditor()->document()->filePath();
#if 0 #if 0

View File

@@ -73,10 +73,7 @@ void ResourceHandler::ensureInitialized()
qDebug() << "ResourceHandler::ensureInitialized() origPaths=" << m_originalUiQrcPaths; qDebug() << "ResourceHandler::ensureInitialized() origPaths=" << m_originalUiQrcPaths;
} }
ResourceHandler::~ResourceHandler() ResourceHandler::~ResourceHandler() = default;
{
}
void ResourceHandler::updateResourcesHelper(bool updateProjectResources) void ResourceHandler::updateResourcesHelper(bool updateProjectResources)
{ {

View File

@@ -267,7 +267,7 @@ static McuPackage *createQtForMCUsPackage()
McuPackage::tr("Qt for MCUs SDK"), McuPackage::tr("Qt for MCUs SDK"),
QDir::homePath(), QDir::homePath(),
Utils::HostOsInfo::withExecutableSuffix("bin/qmltocpp"), Utils::HostOsInfo::withExecutableSuffix("bin/qmltocpp"),
"QtMCUSdk"); "QtForMCUsSdk");
result->setEnvironmentVariableName("Qul_DIR"); result->setEnvironmentVariableName("Qul_DIR");
return result; return result;
} }

View File

@@ -168,6 +168,9 @@ void McuSupportOptionsPage::apply()
QTC_ASSERT(m_options->armGccPackage, return); QTC_ASSERT(m_options->armGccPackage, return);
QTC_ASSERT(m_options->qtForMCUsSdkPackage, return); QTC_ASSERT(m_options->qtForMCUsSdkPackage, return);
if (!widget()->isVisible())
return; // Only create/overwrite kits when this option page is shown
const McuTarget *mcuTarget = m_widget->currentMcuTarget(); const McuTarget *mcuTarget = m_widget->currentMcuTarget();
if (!mcuTarget) if (!mcuTarget)
return; return;

View File

@@ -45,8 +45,8 @@ class McuSupportPluginPrivate
{ {
public: public:
McuSupportDeviceFactory deviceFactory; McuSupportDeviceFactory deviceFactory;
EmrunRunConfigurationFactory emrunRunConfigurationFactory; McuSupportRunConfigurationFactory runConfigurationFactory;
RunWorkerFactory emrunRunWorkerFactory{ RunWorkerFactory runWorkerFactory{
makeFlashAndRunWorker(), makeFlashAndRunWorker(),
{ProjectExplorer::Constants::NORMAL_RUN_MODE}, {ProjectExplorer::Constants::NORMAL_RUN_MODE},
{Constants::RUNCONFIGURATION} {Constants::RUNCONFIGURATION}

View File

@@ -103,7 +103,7 @@ RunWorkerFactory::WorkerCreator makeFlashAndRunWorker()
return RunWorkerFactory::make<FlashAndRunWorker>(); return RunWorkerFactory::make<FlashAndRunWorker>();
} }
EmrunRunConfigurationFactory::EmrunRunConfigurationFactory() McuSupportRunConfigurationFactory::McuSupportRunConfigurationFactory()
: FixedRunConfigurationFactory(FlashAndRunConfiguration::tr("Flash and run")) : FixedRunConfigurationFactory(FlashAndRunConfiguration::tr("Flash and run"))
{ {
registerRunConfiguration<FlashAndRunConfiguration>(Constants::RUNCONFIGURATION); registerRunConfiguration<FlashAndRunConfiguration>(Constants::RUNCONFIGURATION);

Some files were not shown because too many files have changed in this diff Show More