Merge remote-tracking branch 'origin/4.11'
Conflicts: src/plugins/designer/codemodelhelpers.cpp Change-Id: I78906f2fbbfd27d254589a272ebca423b0b80699
@@ -31,7 +31,6 @@ Prerequisites:
|
||||
* ActiveState Active Perl
|
||||
* MinGW with g++ 5.3 or Visual Studio 2017 or later
|
||||
* jom
|
||||
* Ninja (optional, needed for CMake)
|
||||
* Python 3.5 or later (optional, needed for the python enabled debug helper)
|
||||
* On Mac OS X: latest Xcode
|
||||
* 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,
|
||||
so if later versions don't compile we don't support that version.)
|
||||
* 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)
|
||||
|
||||
The installed toolchains have to match the one Qt was compiled with.
|
||||
|
7
dist/changes-4.11.0.md
vendored
@@ -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 support for Framework paths (QTCREATORBUG-20099)
|
||||
|
||||
### Compilation Database
|
||||
|
||||
* Fixed issue with `/imsvc` compiler option (QTCREATORBUG-23146)
|
||||
|
||||
## Debugging
|
||||
|
||||
### CDB
|
||||
@@ -131,6 +135,7 @@ you can check out from the public Git repository. For example:
|
||||
* Changed to use separate `clang-tidy` executable
|
||||
* Separated diagnostic configuration settings for code model
|
||||
(`C++` > `Code Model`) and analyzer (`Analyzer` > `Clang Tools`)
|
||||
* Fixed invocation of `clazy` with latest `clazy` versions
|
||||
|
||||
## Qt Widget Designer
|
||||
|
||||
@@ -174,6 +179,8 @@ you can check out from the public Git repository. For example:
|
||||
|
||||
* Removed auto-detection of GCC toolchains
|
||||
* 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
|
||||
|
||||
|
@@ -23,7 +23,8 @@ imagedirs = ../images \
|
||||
../../src/plugins/qmldesigner/qmlpreviewplugin/images \
|
||||
../../src/plugins/scxmleditor/common/images \
|
||||
../../src/plugins/texteditor/images \
|
||||
../../src/plugins/valgrind/images
|
||||
../../src/plugins/valgrind/images \
|
||||
../../src/plugins/welcome/images
|
||||
|
||||
exampledirs = ../examples
|
||||
examples.fileextensions += *.qml *.svg
|
||||
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 26 KiB |
@@ -60,6 +60,11 @@
|
||||
Clang tools are delivered and installed with \QC, and therefore you do not
|
||||
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
|
||||
|
||||
To run the Clang tools to analyze an open project:
|
||||
@@ -68,41 +73,25 @@
|
||||
|
||||
\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}
|
||||
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 the files to apply the checks to.
|
||||
|
||||
\li Select \uicontrol Analyze to start the checks.
|
||||
|
||||
\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}
|
||||
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
|
||||
the code editor.
|
||||
|
||||
|
@@ -57,6 +57,10 @@
|
||||
|
||||
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]
|
||||
|
||||
|
||||
@@ -65,7 +69,7 @@
|
||||
\section2 CMake Build Steps
|
||||
|
||||
\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.
|
||||
|
||||
You can add arguments and targets for the build command in
|
||||
|
@@ -61,6 +61,10 @@
|
||||
provide less information to the code model, which will then fail to resolve
|
||||
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:
|
||||
|
||||
\list 1
|
||||
@@ -99,9 +103,14 @@
|
||||
\section1 Editing CMake Configuration Files
|
||||
|
||||
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}.
|
||||
|
||||
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:
|
||||
|
||||
\list
|
||||
|
@@ -150,6 +150,11 @@
|
||||
|
||||
\if defined(qtcreator)
|
||||
\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
|
||||
|
||||
\endlist
|
||||
|
@@ -84,16 +84,18 @@
|
||||
|
||||
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.
|
||||
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}.
|
||||
Select \uicontrol Build > \uicontrol {Build for Run Configuration} to
|
||||
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
|
||||
\uicontrol {Clean Project}. To clean the build directory and then build
|
||||
the project, select \uicontrol Build > \uicontrol {Rebuild All} or
|
||||
\uicontrol {Rebuild Project}. If you use qmake, rebuilding also runs qmake
|
||||
to generate new Makefiles between cleaning and building.
|
||||
\uicontrol {Rebuild Project}.
|
||||
|
||||
To build and clean projects without dependencies, select the
|
||||
\uicontrol {Build Without Dependencies},
|
||||
@@ -101,11 +103,22 @@
|
||||
\uicontrol {Clean Without Dependencies} options in the context menu in the
|
||||
\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 >
|
||||
\uicontrol qmake. To prevent failures on incremental builds, it might make
|
||||
sense to always run qmake before building, even though it means that
|
||||
\section2 Building with CMake
|
||||
|
||||
\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
|
||||
> \uicontrol Options > \uicontrol {Build & Run} > \uicontrol qmake >
|
||||
\uicontrol {Run qmake on every build}.
|
||||
|
@@ -46,7 +46,7 @@ Node {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: designStudioNativeCameraControlHelper
|
||||
target: _generalHelper
|
||||
onOverlayUpdateNeeded: updateScale()
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ Node {
|
||||
|
||||
MouseArea3D {
|
||||
id: helper
|
||||
active: false
|
||||
view3D: overlayNode.view3D
|
||||
}
|
||||
}
|
||||
|
133
share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml
Normal 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()
|
||||
}
|
||||
}
|
@@ -23,40 +23,48 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
import QtQuick 2.0
|
||||
import QtQuick3D 1.0
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QTimer>
|
||||
Node {
|
||||
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 {
|
||||
namespace Internal {
|
||||
class CameraControlHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||
Model {
|
||||
id: posModel
|
||||
|
||||
public:
|
||||
CameraControlHelper();
|
||||
property bool hovering: false
|
||||
property vector3d cameraRotation: armRoot.camRotPos
|
||||
|
||||
bool enabled();
|
||||
void setEnabled(bool enabled);
|
||||
source: "meshes/axishelper.mesh"
|
||||
materials: DefaultMaterial {
|
||||
id: posMat
|
||||
emissiveColor: posModel.hovering ? armRoot.hoverColor : armRoot.color
|
||||
lighting: DefaultMaterial.NoLighting
|
||||
}
|
||||
pickable: true
|
||||
}
|
||||
|
||||
Q_INVOKABLE void requestOverlayUpdate();
|
||||
Q_INVOKABLE QString generateUniqueName(const QString &nameRoot);
|
||||
Model {
|
||||
id: negModel
|
||||
|
||||
public slots:
|
||||
void handleUpdateTimer();
|
||||
|
||||
signals:
|
||||
void updateInputs();
|
||||
void enabledChanged(bool enabled);
|
||||
void overlayUpdateNeeded();
|
||||
|
||||
private:
|
||||
bool m_enabled = false;
|
||||
QTimer m_inputUpdateTimer;
|
||||
QTimer m_overlayUpdateTimer;
|
||||
};
|
||||
property bool hovering: false
|
||||
property vector3d cameraRotation: armRoot.camRotNeg
|
||||
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
@@ -31,21 +31,26 @@ IconGizmo {
|
||||
id: cameraGizmo
|
||||
|
||||
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 viewPortRect: cameraGeometry.viewPortRect
|
||||
|
||||
Model {
|
||||
id: gizmoModel
|
||||
geometry: cameraGeometry
|
||||
visible: cameraGizmo.visible
|
||||
materials: [
|
||||
DefaultMaterial {
|
||||
id: defaultMaterial
|
||||
emissiveColor: cameraGizmo.targetNode === cameraGizmo.selectedNode ? "#FF0000"
|
||||
: "#555555"
|
||||
lighting: DefaultMaterial.NoLighting
|
||||
cullingMode: Material.DisableCulling
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
CameraGeometry {
|
||||
id: cameraGeometry
|
||||
camera: cameraGizmo.targetNode
|
||||
}
|
||||
|
||||
gizmoModel.materials: [
|
||||
DefaultMaterial {
|
||||
id: defaultMaterial
|
||||
emissiveColor: cameraGizmo.targetNode === cameraGizmo.selectedNode ? "#FF0000" : "#555555"
|
||||
lighting: DefaultMaterial.NoLighting
|
||||
cullingMode: Material.DisableCulling
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ Model {
|
||||
property View3D view3D
|
||||
property alias color: material.emissiveColor
|
||||
property Node targetNode: null
|
||||
property bool dragging: false
|
||||
property bool dragging: mouseAreaYZ.dragging || mouseAreaXZ.dragging
|
||||
property bool active: false
|
||||
|
||||
readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering
|
||||
@@ -61,7 +61,6 @@ Model {
|
||||
_pointerPosPressed = mouseArea.mapPositionToScene(maskedPosition);
|
||||
var sp = targetNode.scenePosition;
|
||||
_targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z);
|
||||
dragging = true;
|
||||
pressed(mouseArea);
|
||||
}
|
||||
|
||||
@@ -88,7 +87,6 @@ Model {
|
||||
return;
|
||||
|
||||
released(mouseArea, calcRelativeDistance(mouseArea, scenePos));
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
MouseArea3D {
|
||||
|
128
share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -26,7 +26,6 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Window 2.0
|
||||
import QtQuick3D 1.0
|
||||
import QtQuick3D.Helpers 1.0
|
||||
import QtQuick.Controls 2.0
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
@@ -39,8 +38,8 @@ Window {
|
||||
flags: Qt.WindowStaysOnTopHint | Qt.Window | Qt.WindowTitleHint | Qt.WindowCloseButtonHint
|
||||
|
||||
property alias scene: editView.importScene
|
||||
property alias showEditLight: editLightCheckbox.checked
|
||||
property alias usePerspective: usePerspectiveCheckbox.checked
|
||||
property alias showEditLight: btnEditViewLight.toggled
|
||||
property alias usePerspective: btnPerspective.toggled
|
||||
|
||||
property Node selectedNode: null
|
||||
|
||||
@@ -56,9 +55,14 @@ Window {
|
||||
selectedNode = object;
|
||||
}
|
||||
|
||||
function emitObjectClicked(object) {
|
||||
selectObject(object);
|
||||
objectClicked(object);
|
||||
function handleObjectClicked(object) {
|
||||
var theObject = object;
|
||||
if (btnSelectGroup.selected) {
|
||||
while (theObject && theObject.parent !== scene)
|
||||
theObject = theObject.parent;
|
||||
}
|
||||
selectObject(theObject);
|
||||
objectClicked(theObject);
|
||||
}
|
||||
|
||||
function addLightGizmo(obj)
|
||||
@@ -69,7 +73,7 @@ Window {
|
||||
{"view3D": overlayView, "targetNode": obj,
|
||||
"selectedNode": selectedNode});
|
||||
lightGizmos[lightGizmos.length] = gizmo;
|
||||
gizmo.clicked.connect(emitObjectClicked);
|
||||
gizmo.clicked.connect(handleObjectClicked);
|
||||
gizmo.selectedNode = Qt.binding(function() {return selectedNode;});
|
||||
}
|
||||
}
|
||||
@@ -78,13 +82,13 @@ Window {
|
||||
{
|
||||
var component = Qt.createComponent("CameraGizmo.qml");
|
||||
if (component.status === Component.Ready) {
|
||||
var geometryName = designStudioNativeCameraControlHelper.generateUniqueName("CameraGeometry");
|
||||
var geometryName = _generalHelper.generateUniqueName("CameraGeometry");
|
||||
var gizmo = component.createObject(
|
||||
overlayScene,
|
||||
{"view3D": overlayView, "targetNode": obj, "geometryName": geometryName,
|
||||
"viewPortRect": viewPortRect, "selectedNode": selectedNode});
|
||||
cameraGizmos[cameraGizmos.length] = gizmo;
|
||||
gizmo.clicked.connect(emitObjectClicked);
|
||||
gizmo.clicked.connect(handleObjectClicked);
|
||||
gizmo.viewPortRect = Qt.binding(function() {return viewPortRect;});
|
||||
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
|
||||
// the first frame is rendered, so any initial calls to mapFrom3DScene() will fail.
|
||||
Component.onCompleted: designStudioNativeCameraControlHelper.requestOverlayUpdate();
|
||||
Component.onCompleted: _generalHelper.requestOverlayUpdate();
|
||||
|
||||
onWidthChanged: designStudioNativeCameraControlHelper.requestOverlayUpdate();
|
||||
onHeightChanged: designStudioNativeCameraControlHelper.requestOverlayUpdate();
|
||||
onWidthChanged: _generalHelper.requestOverlayUpdate();
|
||||
onHeightChanged: _generalHelper.requestOverlayUpdate();
|
||||
|
||||
Node {
|
||||
id: overlayScene
|
||||
@@ -114,6 +118,7 @@ Window {
|
||||
clipNear: editOrthoCamera.clipNear
|
||||
position: editOrthoCamera.position
|
||||
rotation: editOrthoCamera.rotation
|
||||
scale: editOrthoCamera.scale
|
||||
}
|
||||
|
||||
MoveGizmo {
|
||||
@@ -123,7 +128,7 @@ Window {
|
||||
targetNode: viewWindow.selectedNode
|
||||
position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition
|
||||
: Qt.vector3d(0, 0, 0)
|
||||
globalOrientation: globalControl.checked
|
||||
globalOrientation: btnLocalGlobal.toggled
|
||||
visible: selectedNode && btnMove.selected
|
||||
view3D: overlayView
|
||||
|
||||
@@ -138,7 +143,7 @@ Window {
|
||||
targetNode: viewWindow.selectedNode
|
||||
position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition
|
||||
: Qt.vector3d(0, 0, 0)
|
||||
globalOrientation: globalControl.checked
|
||||
globalOrientation: false
|
||||
visible: selectedNode && btnScale.selected
|
||||
view3D: overlayView
|
||||
|
||||
@@ -153,7 +158,7 @@ Window {
|
||||
targetNode: viewWindow.selectedNode
|
||||
position: viewWindow.selectedNode ? viewWindow.selectedNode.scenePosition
|
||||
: Qt.vector3d(0, 0, 0)
|
||||
globalOrientation: globalControl.checked
|
||||
globalOrientation: btnLocalGlobal.toggled
|
||||
visible: selectedNode && btnRotate.selected
|
||||
view3D: overlayView
|
||||
|
||||
@@ -169,16 +174,19 @@ Window {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: sceneBg
|
||||
color: "#FFFFFF"
|
||||
anchors.fill: parent
|
||||
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
|
||||
onTapped: {
|
||||
var pickResult = editView.pick(eventPoint.scenePosition.x,
|
||||
eventPoint.scenePosition.y);
|
||||
emitObjectClicked(pickResult.objectHit);
|
||||
handleObjectClicked(pickResult.objectHit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,6 +208,12 @@ Window {
|
||||
step: 50
|
||||
}
|
||||
|
||||
SelectionBox {
|
||||
id: selectionBox
|
||||
view3D: editView
|
||||
targetNode: viewWindow.selectedNode
|
||||
}
|
||||
|
||||
PointLight {
|
||||
id: editLight
|
||||
visible: showEditLight
|
||||
@@ -209,11 +223,14 @@ Window {
|
||||
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 {
|
||||
id: editPerspectiveCamera
|
||||
z: -600
|
||||
y: 200
|
||||
rotation.x: 30
|
||||
y: 600
|
||||
rotation.x: 45
|
||||
clipFar: 100000
|
||||
clipNear: 1
|
||||
}
|
||||
@@ -221,10 +238,10 @@ Window {
|
||||
OrthographicCamera {
|
||||
id: editOrthoCamera
|
||||
z: -600
|
||||
y: 200
|
||||
rotation.x: 30
|
||||
y: 600
|
||||
rotation.x: 45
|
||||
clipFar: 100000
|
||||
clipNear: 1
|
||||
clipNear: -10000
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,14 +257,12 @@ Window {
|
||||
id: gizmoLabel
|
||||
targetNode: moveGizmo.visible ? moveGizmo : scaleGizmo
|
||||
targetView: overlayView
|
||||
offsetX: 0
|
||||
offsetY: 45
|
||||
visible: targetNode.dragging
|
||||
|
||||
Rectangle {
|
||||
color: "white"
|
||||
x: -width / 2
|
||||
y: -height
|
||||
y: -height - 8
|
||||
width: gizmoLabelText.width + 4
|
||||
height: gizmoLabelText.height + 4
|
||||
border.width: 1
|
||||
@@ -273,19 +288,11 @@ Window {
|
||||
}
|
||||
}
|
||||
|
||||
WasdController {
|
||||
EditCameraController {
|
||||
id: cameraControl
|
||||
controlledObject: editView.camera
|
||||
acceptedButtons: Qt.RightButton
|
||||
|
||||
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()
|
||||
}
|
||||
camera: editView.camera
|
||||
anchors.fill: parent
|
||||
view3d: editView
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,7 +308,8 @@ Window {
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
property var group: [btnSelectItem, btnSelectGroup, btnMove, btnRotate, btnScale]
|
||||
property var groupSelect: [btnSelectGroup, btnSelectItem]
|
||||
property var groupTransform: [btnMove, btnRotate, btnScale]
|
||||
|
||||
ToolBarButton {
|
||||
id: btnSelectItem
|
||||
@@ -310,7 +318,7 @@ Window {
|
||||
shortcut: "Q"
|
||||
currentShortcut: selected ? "" : shortcut
|
||||
tool: "item_selection"
|
||||
buttonsGroup: col.group
|
||||
buttonsGroup: col.groupSelect
|
||||
}
|
||||
|
||||
ToolBarButton {
|
||||
@@ -319,7 +327,7 @@ Window {
|
||||
shortcut: "Q"
|
||||
currentShortcut: btnSelectItem.currentShortcut === shortcut ? "" : shortcut
|
||||
tool: "group_selection"
|
||||
buttonsGroup: col.group
|
||||
buttonsGroup: col.groupSelect
|
||||
}
|
||||
|
||||
Rectangle { // separator
|
||||
@@ -331,11 +339,12 @@ Window {
|
||||
|
||||
ToolBarButton {
|
||||
id: btnMove
|
||||
selected: true
|
||||
tooltip: qsTr("Move current selection")
|
||||
shortcut: "M"
|
||||
shortcut: "W"
|
||||
currentShortcut: shortcut
|
||||
tool: "move"
|
||||
buttonsGroup: col.group
|
||||
buttonsGroup: col.groupTransform
|
||||
}
|
||||
|
||||
ToolBarButton {
|
||||
@@ -344,60 +353,96 @@ Window {
|
||||
shortcut: "E"
|
||||
currentShortcut: shortcut
|
||||
tool: "rotate"
|
||||
buttonsGroup: col.group
|
||||
buttonsGroup: col.groupTransform
|
||||
}
|
||||
|
||||
ToolBarButton {
|
||||
id: btnScale
|
||||
tooltip: qsTr("Scale current selection")
|
||||
shortcut: "T"
|
||||
shortcut: "R"
|
||||
currentShortcut: shortcut
|
||||
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 {
|
||||
y: 8
|
||||
AxisHelper {
|
||||
anchors.right: parent.right
|
||||
CheckBox {
|
||||
id: editLightCheckbox
|
||||
checked: false
|
||||
text: qsTr("Use Edit View Light")
|
||||
onCheckedChanged: cameraControl.forceActiveFocus()
|
||||
anchors.top: parent.top
|
||||
width: 100
|
||||
height: width
|
||||
editCameraCtrl: cameraControl
|
||||
selectedNode : viewWindow.selectedNode ? selectionBox.model : null
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: usePerspectiveCheckbox
|
||||
checked: true
|
||||
text: qsTr("Use Perspective Projection")
|
||||
onCheckedChanged: {
|
||||
// Since WasdController always acts on active camera, we need to update pos/rot
|
||||
// to the other camera when we change
|
||||
if (checked) {
|
||||
editPerspectiveCamera.position = editOrthoCamera.position;
|
||||
editPerspectiveCamera.rotation = editOrthoCamera.rotation;
|
||||
} else {
|
||||
editOrthoCamera.position = editPerspectiveCamera.position;
|
||||
editOrthoCamera.rotation = editPerspectiveCamera.rotation;
|
||||
}
|
||||
designStudioNativeCameraControlHelper.requestOverlayUpdate();
|
||||
cameraControl.forceActiveFocus();
|
||||
}
|
||||
Rectangle { // top controls bar
|
||||
color: "#aa000000"
|
||||
width: 265
|
||||
height: btnPerspective.height + 10
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 100
|
||||
|
||||
ToggleButton {
|
||||
id: btnPerspective
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 5
|
||||
tooltip: qsTr("Toggle Perspective / Orthographic Projection")
|
||||
states: [{iconId: "ortho", text: qsTr("Orthographic")}, {iconId: "persp", text: qsTr("Perspective")}]
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: globalControl
|
||||
checked: true
|
||||
text: qsTr("Use Global Orientation")
|
||||
onCheckedChanged: cameraControl.forceActiveFocus()
|
||||
ToggleButton {
|
||||
id: btnLocalGlobal
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 5
|
||||
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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ Node {
|
||||
materials: [
|
||||
DefaultMaterial {
|
||||
id: mainGridMaterial
|
||||
emissiveColor: "#e6e6e6"
|
||||
emissiveColor: "#cccccc"
|
||||
lighting: DefaultMaterial.NoLighting
|
||||
cullingMode: Material.DisableCulling
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick3D 1.0
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
Node {
|
||||
id: iconGizmo
|
||||
@@ -34,8 +35,8 @@ Node {
|
||||
property Node targetNode: null
|
||||
property Node selectedNode: null
|
||||
|
||||
property alias gizmoModel: gizmoModel
|
||||
property alias iconSource: iconImage.source
|
||||
property alias overlayColor: colorOverlay.color
|
||||
|
||||
signal positionCommit()
|
||||
signal clicked(Node node)
|
||||
@@ -44,30 +45,25 @@ Node {
|
||||
rotation: targetNode ? targetNode.sceneRotation : Qt.vector3d(0, 0, 0)
|
||||
visible: targetNode ? targetNode.visible : false
|
||||
|
||||
Model {
|
||||
id: gizmoModel
|
||||
visible: iconGizmo.visible
|
||||
}
|
||||
Overlay2D {
|
||||
id: gizmoLabel
|
||||
targetNode: gizmoModel
|
||||
id: iconOverlay
|
||||
targetNode: iconGizmo
|
||||
targetView: view3D
|
||||
offsetX: 0
|
||||
offsetY: 0
|
||||
visible: iconGizmo.visible && !isBehindCamera
|
||||
parent: view3D
|
||||
|
||||
Rectangle {
|
||||
id: iconRect
|
||||
width: iconImage.width
|
||||
height: iconImage.height
|
||||
x: -width / 2
|
||||
y: -height
|
||||
y: -height / 2
|
||||
color: "transparent"
|
||||
border.color: "#7777ff"
|
||||
border.width: iconGizmo.selectedNode === iconGizmo.targetNode
|
||||
|| (iconGizmo.highlightOnHover && iconMouseArea.containsMouse) ? 2 : 0
|
||||
border.width: iconGizmo.selectedNode !== iconGizmo.targetNode
|
||||
&& iconGizmo.highlightOnHover && iconMouseArea.containsMouse ? 2 : 0
|
||||
radius: 5
|
||||
opacity: iconGizmo.selectedNode === iconGizmo.targetNode ? 0.3 : 1
|
||||
opacity: iconGizmo.selectedNode === iconGizmo.targetNode ? 0.2 : 1
|
||||
Image {
|
||||
id: iconImage
|
||||
fillMode: Image.Pad
|
||||
@@ -81,6 +77,15 @@ Node {
|
||||
? Qt.LeftButton : Qt.NoButton
|
||||
}
|
||||
}
|
||||
ColorOverlay {
|
||||
id: colorOverlay
|
||||
anchors.fill: parent
|
||||
cached: true
|
||||
source: iconImage
|
||||
color: "transparent"
|
||||
opacity: 0.6
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,14 +29,13 @@ import QtQuick3D 1.0
|
||||
IconGizmo {
|
||||
id: lightGizmo
|
||||
|
||||
iconSource: "qrc:///qtquickplugin/mockfiles/images/light-pick-icon.png"
|
||||
gizmoModel.source: "#Sphere"
|
||||
gizmoModel.scale: Qt.vector3d(0.10, 0.10, 0.10)
|
||||
gizmoModel.materials: [
|
||||
DefaultMaterial {
|
||||
id: defaultMaterial
|
||||
emissiveColor: "yellow"
|
||||
lighting: DefaultMaterial.NoLighting
|
||||
}
|
||||
]
|
||||
iconSource: targetNode
|
||||
? targetNode instanceof DirectionalLight
|
||||
? "qrc:///qtquickplugin/mockfiles/images/directional_light_gradient.png"
|
||||
: targetNode instanceof AreaLight
|
||||
? "qrc:///qtquickplugin/mockfiles/images/area_light_gradient.png"
|
||||
: "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png"
|
||||
: "qrc:///qtquickplugin/mockfiles/images/point_light_gradient.png"
|
||||
|
||||
overlayColor: targetNode ? targetNode.color : "transparent"
|
||||
}
|
||||
|
@@ -31,8 +31,7 @@ Item {
|
||||
property Node targetNode
|
||||
property View3D targetView
|
||||
|
||||
property real offsetX: 0
|
||||
property real offsetY: 0
|
||||
property vector3d offset: Qt.vector3d(0, 0, 0)
|
||||
|
||||
property bool isBehindCamera
|
||||
|
||||
@@ -49,14 +48,16 @@ Item {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: designStudioNativeCameraControlHelper
|
||||
target: _generalHelper
|
||||
onOverlayUpdateNeeded: updateOverlay()
|
||||
}
|
||||
|
||||
function updateOverlay()
|
||||
{
|
||||
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)
|
||||
: Qt.vector3d(0, 0, 0);
|
||||
root.x = viewPos.x;
|
||||
|
@@ -34,7 +34,7 @@ Model {
|
||||
property alias color: gizmoMaterial.emissiveColor
|
||||
property alias priority: mouseArea.priority
|
||||
property Node targetNode: null
|
||||
property bool dragging: false
|
||||
property bool dragging: mouseArea.dragging
|
||||
property bool active: false
|
||||
|
||||
readonly property bool hovering: mouseArea.hovering
|
||||
@@ -65,7 +65,6 @@ Model {
|
||||
_pointerPosPressed = mouseArea.mapPositionToScene(scenePos);
|
||||
var sp = targetNode.scenePosition;
|
||||
_targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z);
|
||||
dragging = true;
|
||||
pressed(mouseArea);
|
||||
}
|
||||
|
||||
@@ -91,7 +90,6 @@ Model {
|
||||
return;
|
||||
|
||||
released(mouseArea, calcRelativeDistance(mouseArea, scenePos));
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
MouseArea3D {
|
||||
|
@@ -134,8 +134,7 @@ Node {
|
||||
targetNode: rotateGizmo.targetNode
|
||||
color: highlightOnHover && (hovering || dragging) ? Qt.lighter(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(0.994, 0.994, 0.994)
|
||||
scale: Qt.vector3d(1.1, 1.1, 1.1)
|
||||
priority: 10
|
||||
view3D: rotateGizmo.view3D
|
||||
active: rotateGizmo.visible
|
||||
|
@@ -33,7 +33,7 @@ Model {
|
||||
property View3D view3D
|
||||
property alias color: material.emissiveColor
|
||||
property Node targetNode: null
|
||||
property bool dragging: false
|
||||
property bool dragging: mouseAreaMain.dragging
|
||||
property bool active: false
|
||||
property alias hovering: mouseAreaMain.hovering
|
||||
property alias priority: mouseAreaMain.priority
|
||||
@@ -80,7 +80,6 @@ Model {
|
||||
_targetPosOnScreen = view3D.mapFrom3DScene(targetNode.scenePosition);
|
||||
_targetPosOnScreen.z = 0;
|
||||
_pointerPosPressed = Qt.vector3d(screenPos.x, screenPos.y, 0);
|
||||
dragging = true;
|
||||
_trackBall = angle < 0.1;
|
||||
|
||||
// Recreate vector so we don't follow the changes in targetNode.rotation
|
||||
@@ -108,7 +107,6 @@ Model {
|
||||
|
||||
applyLocalRotation(screenPos);
|
||||
rotateCommit();
|
||||
dragging = false;
|
||||
currentAngle = 0;
|
||||
currentMousePos = screenPos;
|
||||
}
|
||||
|
66
share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml
Normal 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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
70
share/qtcreator/qml/qmlpuppet/mockfiles/ToggleButton.qml
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -34,6 +34,7 @@ Rectangle {
|
||||
property string currentShortcut
|
||||
property string tool
|
||||
property variant buttonsGroup: []
|
||||
property bool togglable: true
|
||||
|
||||
id: root
|
||||
width: img.width + 5
|
||||
@@ -71,6 +72,11 @@ Rectangle {
|
||||
root.buttonsGroup[i].selected = false;
|
||||
|
||||
root.selected = true;
|
||||
|
||||
if (!root.togglable) {
|
||||
// Deselect button after a short while (selection acts as simple click indicator)
|
||||
_generalHelper.delayedPropertySet(root, 200, "selected", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.4 KiB |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/edit_light_on.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.7 KiB |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active.png
Normal file
After Width: | Height: | Size: 266 B |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_active@2x.png
Normal file
After Width: | Height: | Size: 386 B |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/fit_selected.png
Normal file
After Width: | Height: | Size: 266 B |
After Width: | Height: | Size: 386 B |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/global.png
Normal file
After Width: | Height: | Size: 433 B |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/global@2x.png
Normal file
After Width: | Height: | Size: 561 B |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/local.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/local@2x.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/ortho@2x.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/persp.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/images/persp@2x.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.6 KiB |
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/meshes/axishelper.mesh
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -1,9 +1,11 @@
|
||||
HEADERS += $$PWD/cameracontrolhelper.h \
|
||||
HEADERS += $$PWD/generalhelper.h \
|
||||
$$PWD/mousearea3d.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/camerageometry.cpp \
|
||||
$$PWD/gridgeometry.cpp
|
||||
$$PWD/gridgeometry.cpp \
|
||||
$$PWD/selectionboxgeometry.cpp
|
||||
|
@@ -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 ¤tPos)
|
||||
{
|
||||
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 ¤tPos,
|
||||
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
|
@@ -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 ¤tPos);
|
||||
Q_INVOKABLE QVector3D panCamera(QQuick3DCamera *camera, const QMatrix4x4 startTransform,
|
||||
const QVector3D &startPosition, const QVector3D &startLookAt,
|
||||
const QVector3D &pressPos, const QVector3D ¤tPos,
|
||||
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
|
@@ -37,7 +37,6 @@ namespace QmlDesigner {
|
||||
namespace Internal {
|
||||
|
||||
MouseArea3D *MouseArea3D::s_mouseGrab = nullptr;
|
||||
static const qreal s_mouseDragMultiplier = .02;
|
||||
|
||||
MouseArea3D::MouseArea3D(QQuick3DNode *parent)
|
||||
: QQuick3DNode(parent)
|
||||
@@ -124,6 +123,13 @@ void MouseArea3D::setGrabsMouse(bool grabsMouse)
|
||||
return;
|
||||
|
||||
m_grabsMouse = grabsMouse;
|
||||
|
||||
if (!m_grabsMouse && s_mouseGrab == this) {
|
||||
setDragging(false);
|
||||
setHovering(false);
|
||||
s_mouseGrab = nullptr;
|
||||
}
|
||||
|
||||
emit grabsMouseChanged();
|
||||
}
|
||||
|
||||
@@ -133,6 +139,13 @@ void MouseArea3D::setActive(bool active)
|
||||
return;
|
||||
|
||||
m_active = active;
|
||||
|
||||
if (!m_active && s_mouseGrab == this) {
|
||||
setDragging(false);
|
||||
setHovering(false);
|
||||
s_mouseGrab = nullptr;
|
||||
}
|
||||
|
||||
emit activeChanged();
|
||||
}
|
||||
|
||||
@@ -340,7 +353,7 @@ qreal QmlDesigner::Internal::MouseArea3D::getNewRotationAngle(
|
||||
dragDir = (screenDragDir - nodePos).normalized();
|
||||
const QVector3D pressToCurrent = (currentPos - pressPos);
|
||||
float magnitude = QVector3D::dotProduct(pressToCurrent, dragDir);
|
||||
qreal angle = -s_mouseDragMultiplier * qreal(magnitude);
|
||||
qreal angle = -mouseDragMultiplier() * qreal(magnitude);
|
||||
return angle;
|
||||
} else {
|
||||
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);
|
||||
|
||||
qreal degrees = qRadiansToDegrees(qreal(finalAxis.length()) * s_mouseDragMultiplier);
|
||||
qreal degrees = qRadiansToDegrees(qreal(finalAxis.length()) * mouseDragMultiplier());
|
||||
|
||||
finalAxis.normalize();
|
||||
|
||||
|
@@ -51,7 +51,7 @@ class MouseArea3D : public QQuick3DNode
|
||||
Q_PROPERTY(bool hovering READ hovering NOTIFY hoveringChanged)
|
||||
Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
|
||||
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(qreal minAngle READ minAngle WRITE setMinAngle NOTIFY minAngleChanged)
|
||||
Q_PROPERTY(QQuick3DNode *pickNode READ pickNode WRITE setPickNode NOTIFY pickNodeChanged)
|
||||
@@ -77,6 +77,8 @@ public:
|
||||
qreal minAngle() const;
|
||||
QQuick3DNode *pickNode() const;
|
||||
|
||||
static qreal mouseDragMultiplier() { return .02; }
|
||||
|
||||
public slots:
|
||||
void setView3D(QQuick3DViewport *view3D);
|
||||
void setGrabsMouse(bool grabsMouse);
|
||||
@@ -157,7 +159,7 @@ private:
|
||||
QVector3D getMousePosInPlane(const QPointF &mousePosInView) const;
|
||||
|
||||
static MouseArea3D *s_mouseGrab;
|
||||
bool m_grabsMouse;
|
||||
bool m_grabsMouse = false;
|
||||
QVector3D m_mousePosInPlane;
|
||||
QPointF m_circlePickArea;
|
||||
qreal m_minAngle = 0.;
|
||||
|
@@ -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
|
@@ -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
|
@@ -62,10 +62,11 @@
|
||||
#include <drop3dlibraryitemcommand.h>
|
||||
|
||||
#include "dummycontextobject.h"
|
||||
#include "../editor3d/cameracontrolhelper.h"
|
||||
#include "../editor3d/generalhelper.h"
|
||||
#include "../editor3d/mousearea3d.h"
|
||||
#include "../editor3d/camerageometry.h"
|
||||
#include "../editor3d/gridgeometry.h"
|
||||
#include "../editor3d/selectionboxgeometry.h"
|
||||
|
||||
#include <designersupportdelegate.h>
|
||||
|
||||
@@ -104,13 +105,13 @@ bool Qt5InformationNodeInstanceServer::eventFilter(QObject *, QEvent *event)
|
||||
|
||||
QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
|
||||
{
|
||||
auto helper = new QmlDesigner::Internal::CameraControlHelper();
|
||||
engine->rootContext()->setContextProperty("designStudioNativeCameraControlHelper", helper);
|
||||
|
||||
#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::CameraGeometry>("CameraGeometry", 1, 0, "CameraGeometry");
|
||||
qmlRegisterType<QmlDesigner::Internal::GridGeometry>("GridGeometry", 1, 0, "GridGeometry");
|
||||
qmlRegisterType<QmlDesigner::Internal::SelectionBoxGeometry>("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry");
|
||||
#endif
|
||||
|
||||
QQmlComponent component(engine, QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"));
|
||||
@@ -136,7 +137,10 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
|
||||
surfaceFormat.setVersion(4, 1);
|
||||
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
|
||||
window->setFormat(surfaceFormat);
|
||||
|
||||
#ifdef QUICK3D_MODULE
|
||||
helper->setParent(window);
|
||||
#endif
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -336,13 +340,25 @@ QObject *Qt5InformationNodeInstanceServer::findRootNodeOf3DViewport(
|
||||
{
|
||||
for (const ServerNodeInstance &instance : instanceList) {
|
||||
if (instance.isSubclassOf("QQuick3DViewport")) {
|
||||
QObject *rootObj = nullptr;
|
||||
int viewChildCount = 0;
|
||||
for (const ServerNodeInstance &child : instanceList) { /* Look for scene node */
|
||||
/* The QQuick3DViewport always creates a root node.
|
||||
* This root node contains the complete scene. */
|
||||
if (child.isSubclassOf("QQuick3DNode") && child.parent() == instance)
|
||||
return child.internalObject()->property("parent").value<QObject *>();
|
||||
if (child.isSubclassOf("QQuick3DNode") && child.parent() == instance) {
|
||||
// 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;
|
||||
}
|
||||
@@ -599,10 +615,8 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
|
||||
if (hasInstanceForId(id)) {
|
||||
ServerNodeInstance instance = instanceForId(id);
|
||||
QObject *object = nullptr;
|
||||
if (instance.isSubclassOf("QQuick3DModel") || instance.isSubclassOf("QQuick3DCamera")
|
||||
|| instance.isSubclassOf("QQuick3DAbstractLight")) {
|
||||
if (instance.isSubclassOf("QQuick3DNode"))
|
||||
object = instance.internalObject();
|
||||
}
|
||||
QMetaObject::invokeMethod(m_editView3D, "selectObject", Q_ARG(QVariant,
|
||||
objectToVariant(object)));
|
||||
return; // TODO: support multi-selection
|
||||
|
@@ -56,17 +56,7 @@ void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNo
|
||||
InstanceContainer::NodeFlags flags)
|
||||
{
|
||||
ObjectNodeInstance::initialize(objectNodeInstance, flags);
|
||||
|
||||
#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
|
||||
setPickable(true, true, false);
|
||||
}
|
||||
|
||||
Qt5NodeInstanceServer *Quick3DNodeInstance::qt5NodeInstanceServer() const
|
||||
@@ -83,6 +73,48 @@ QQuick3DNode *Quick3DNodeInstance::quick3DNode() const
|
||||
#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)
|
||||
{
|
||||
Pointer instance(new Quick3DNodeInstance(object));
|
||||
@@ -94,8 +126,12 @@ void Quick3DNodeInstance::setHideInEditor(bool b)
|
||||
{
|
||||
#ifdef QUICK3D_MODULE
|
||||
QQuick3DNodePrivate *privateNode = QQuick3DNodePrivate::get(quick3DNode());
|
||||
if (privateNode)
|
||||
if (privateNode) {
|
||||
privateNode->setIsHiddenInEditor(b);
|
||||
|
||||
// Hidden objects should not be pickable
|
||||
setPickable(!b, true, true);
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(b)
|
||||
#endif
|
||||
|
@@ -53,6 +53,7 @@ protected:
|
||||
private:
|
||||
Qt5NodeInstanceServer *qt5NodeInstanceServer() const;
|
||||
QQuick3DNode *quick3DNode() const;
|
||||
void setPickable(bool enable, bool checkParent, bool applyToChildren);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -60,6 +60,7 @@ namespace Internal {
|
||||
class GraphicsObjectNodeInstance;
|
||||
class QmlStateNodeInstance;
|
||||
class QuickItemNodeInstance;
|
||||
class Quick3DNodeInstance;
|
||||
}
|
||||
|
||||
class ServerNodeInstance
|
||||
@@ -82,6 +83,7 @@ class ServerNodeInstance
|
||||
friend class QmlDesigner::Internal::ObjectNodeInstance;
|
||||
friend class QmlDesigner::Internal::QmlPropertyChangesNodeInstance;
|
||||
friend class QmlDesigner::Internal::QmlStateNodeInstance;
|
||||
friend class QmlDesigner::Internal::Quick3DNodeInstance;
|
||||
|
||||
public:
|
||||
enum ComponentWrap {
|
||||
|
@@ -8,6 +8,7 @@
|
||||
<file>mockfiles/GenericBackend.qml</file>
|
||||
<file>mockfiles/Dialog.qml</file>
|
||||
<file>mockfiles/EditView3D.qml</file>
|
||||
<file>mockfiles/EditCameraController.qml</file>
|
||||
<file>mockfiles/Arrow.qml</file>
|
||||
<file>mockfiles/AutoScaleHelper.qml</file>
|
||||
<file>mockfiles/MoveGizmo.qml</file>
|
||||
@@ -23,12 +24,17 @@
|
||||
<file>mockfiles/ScaleRod.qml</file>
|
||||
<file>mockfiles/ScaleGizmo.qml</file>
|
||||
<file>mockfiles/ToolBarButton.qml</file>
|
||||
<file>mockfiles/ToggleButton.qml</file>
|
||||
<file>mockfiles/RotateGizmo.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/scalerod.mesh</file>
|
||||
<file>mockfiles/meshes/ring.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@2x.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_selected.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>
|
||||
</RCC>
|
||||
|
@@ -41,7 +41,6 @@ Section {
|
||||
|
||||
function getBackendValue(name)
|
||||
{
|
||||
print(fontSection.fontName + "_" + name)
|
||||
return backendValues[fontSection.fontName + "_" + name]
|
||||
}
|
||||
|
||||
|
@@ -185,7 +185,9 @@ T.ComboBox {
|
||||
StudioTheme.Values.maxComboBoxPopupHeight)
|
||||
padding: StudioTheme.Values.border
|
||||
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 {
|
||||
clip: true
|
||||
@@ -242,7 +244,7 @@ T.ComboBox {
|
||||
},
|
||||
State {
|
||||
name: "edit"
|
||||
when: myComboBox.edit && myComboBox.editable
|
||||
when: myComboBox.edit && myComboBox.editable && !comboBoxPopup.opened
|
||||
PropertyChanges {
|
||||
target: myComboBox
|
||||
wheelEnabled: true
|
||||
@@ -250,12 +252,29 @@ T.ComboBox {
|
||||
PropertyChanges {
|
||||
target: comboBoxInput
|
||||
selectByMouse: true
|
||||
readOnly: false
|
||||
}
|
||||
PropertyChanges {
|
||||
target: comboBoxBackground
|
||||
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
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
@@ -1,3 +1,5 @@
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
@@ -22,7 +24,6 @@
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Window 2.12
|
||||
import QtQuick.Templates 2.12 as T
|
||||
@@ -43,10 +44,11 @@ T.Menu {
|
||||
overlap: 1
|
||||
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 {
|
||||
model: control.contentModel
|
||||
|
@@ -33,7 +33,9 @@ T.Popup {
|
||||
property T.Control myControl
|
||||
|
||||
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 {
|
||||
color: StudioTheme.Values.themeControlBackground
|
||||
|
@@ -193,6 +193,7 @@ TextInput {
|
||||
PropertyChanges {
|
||||
target: mouseArea
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
State {
|
||||
|
@@ -237,7 +237,7 @@ bool OpenProjectCommand::run()
|
||||
Project *project = openProjectSucceeded.project();
|
||||
project->configureAsExampleProject();
|
||||
|
||||
return CppTools::Tests::TestCase::waitUntilCppModelManagerIsAwareOf(project, timeOutInMs());
|
||||
return CppTools::Tests::TestCase::waitUntilProjectIsFullyOpened(project, timeOutInMs());
|
||||
}
|
||||
|
||||
Command::Ptr OpenProjectCommand::parse(BatchFileLineTokenizer &arguments,
|
||||
|
@@ -66,10 +66,6 @@ static QStringList clazyPluginArguments(const ClangDiagnosticConfig diagnosticCo
|
||||
arguments << XclangArgs({"-add-plugin",
|
||||
"clazy",
|
||||
"-plugin-arg-clazy",
|
||||
"enable-all-fixits",
|
||||
"-plugin-arg-clazy",
|
||||
"no-autowrite-fixits",
|
||||
"-plugin-arg-clazy",
|
||||
diagnosticConfig.clazyChecks()});
|
||||
}
|
||||
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include "clangtoolsdiagnosticmodel.h"
|
||||
#include "clangtoolsdiagnosticview.h"
|
||||
#include "clangtoolslogfilereader.h"
|
||||
#include "clangtoolsplugin.h"
|
||||
#include "clangtoolsprojectsettings.h"
|
||||
#include "clangtoolssettings.h"
|
||||
#include "clangtoolsutils.h"
|
||||
@@ -399,6 +400,15 @@ ClangTool::ClangTool()
|
||||
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);
|
||||
const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the "
|
||||
"Clang project to search for diagnostics.");
|
||||
@@ -424,6 +434,7 @@ ClangTool::ClangTool()
|
||||
m_perspective.addToolBarAction(m_startAction);
|
||||
m_perspective.addToolBarAction(m_startOnCurrentFileAction);
|
||||
m_perspective.addToolBarAction(m_stopAction);
|
||||
m_perspective.addToolBarAction(m_openProjectSettings);
|
||||
m_perspective.addToolBarAction(m_loadExported);
|
||||
m_perspective.addToolBarAction(m_clear);
|
||||
m_perspective.addToolBarAction(m_goBack);
|
||||
|
@@ -129,6 +129,7 @@ private:
|
||||
Utils::FancyLineEdit *m_filterLineEdit = nullptr;
|
||||
QToolButton *m_applyFixitsButton = nullptr;
|
||||
|
||||
QAction *m_openProjectSettings = nullptr;
|
||||
QAction *m_goBack = nullptr;
|
||||
QAction *m_goNext = nullptr;
|
||||
QAction *m_loadExported = nullptr;
|
||||
|
@@ -28,6 +28,8 @@
|
||||
namespace ClangTools {
|
||||
namespace Constants {
|
||||
|
||||
const char PROJECT_PANEL_ID[] = "ClangTools";
|
||||
|
||||
const char RUN_ON_PROJECT[] = "ClangTools.RunOnProject";
|
||||
const char RUN_ON_CURRENT_FILE[] = "ClangTools.RunOnCurrentFile";
|
||||
|
||||
|
@@ -347,7 +347,7 @@ public:
|
||||
int extraOffset = 0)
|
||||
: m_node(node)
|
||||
, m_fileCache(fileCache)
|
||||
, m_filePath(asString(node["FilePath"]))
|
||||
, m_filePath(QDir::cleanPath(asString(node["FilePath"])))
|
||||
, m_fileOffsetKey(fileOffsetKey)
|
||||
, m_extraOffset(extraOffset)
|
||||
{}
|
||||
|
@@ -67,6 +67,13 @@ using namespace ProjectExplorer;
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
static ProjectPanelFactory *m_projectPanelFactoryInstance = nullptr;
|
||||
|
||||
ProjectPanelFactory *projectPanelFactory()
|
||||
{
|
||||
return m_projectPanelFactoryInstance;
|
||||
}
|
||||
|
||||
class ClangToolsOptionsPage : public IOptionsPage
|
||||
{
|
||||
public:
|
||||
@@ -123,8 +130,9 @@ bool ClangToolsPlugin::initialize(const QStringList &arguments, QString *errorSt
|
||||
ActionManager::registerAction(d->clangTool.startOnCurrentFileAction(),
|
||||
Constants::RUN_ON_CURRENT_FILE);
|
||||
|
||||
auto panelFactory = new ProjectPanelFactory();
|
||||
auto panelFactory = m_projectPanelFactoryInstance = new ProjectPanelFactory;
|
||||
panelFactory->setPriority(100);
|
||||
panelFactory->setId(Constants::PROJECT_PANEL_ID);
|
||||
panelFactory->setDisplayName(tr("Clang Tools"));
|
||||
panelFactory->setCreateWidgetFunction([](Project *project) { return new ProjectSettingsWidget(project); });
|
||||
ProjectPanelFactory::registerFactory(panelFactory);
|
||||
|
@@ -27,9 +27,13 @@
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
namespace ProjectExplorer { class ProjectPanelFactory; }
|
||||
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
ProjectExplorer::ProjectPanelFactory *projectPanelFactory();
|
||||
|
||||
class ClangToolsPlugin : public ExtensionSystem::IPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@@ -34,7 +34,7 @@
|
||||
namespace ClangTools {
|
||||
namespace Internal {
|
||||
|
||||
const char diagnosticConfigIdKey[] = "DiagnosticConfigId";
|
||||
const char diagnosticConfigIdKey[] = "DiagnosticConfig";
|
||||
|
||||
class RunSettings
|
||||
{
|
||||
|
@@ -318,7 +318,7 @@ class CMakeGeneratorKitAspectWidget : public KitAspectWidget
|
||||
public:
|
||||
CMakeGeneratorKitAspectWidget(Kit *kit, const ::KitAspect *ki)
|
||||
: KitAspectWidget(kit, ki),
|
||||
m_label(new QLabel),
|
||||
m_label(new Utils::ElidingLabel),
|
||||
m_changeButton(new QPushButton)
|
||||
{
|
||||
m_label->setToolTip(ki->description());
|
||||
@@ -459,7 +459,7 @@ private:
|
||||
}
|
||||
|
||||
bool m_ignoreChange = false;
|
||||
QLabel *m_label;
|
||||
Utils::ElidingLabel *m_label;
|
||||
QPushButton *m_changeButton;
|
||||
CMakeTool *m_currentTool = nullptr;
|
||||
};
|
||||
|
@@ -226,22 +226,17 @@ QList<CPlusPlus::Document::Ptr> TestCase::waitForFilesInGlobalSnapshot(const QSt
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TestCase::waitUntilCppModelManagerIsAwareOf(Project *project, int timeOutInMs)
|
||||
bool TestCase::waitUntilProjectIsFullyOpened(Project *project, int timeOutInMs)
|
||||
{
|
||||
if (!project)
|
||||
return false;
|
||||
|
||||
QElapsedTimer t;
|
||||
t.start();
|
||||
|
||||
CppModelManager *modelManager = CppModelManager::instance();
|
||||
forever {
|
||||
if (modelManager->projectInfo(project).isValid())
|
||||
return true;
|
||||
if (t.elapsed() > timeOutInMs)
|
||||
return false;
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
return QTest::qWaitFor(
|
||||
[project]() {
|
||||
return !project->isParsing()
|
||||
&& CppModelManager::instance()->projectInfo(project).isValid();
|
||||
},
|
||||
timeOutInMs);
|
||||
}
|
||||
|
||||
bool TestCase::writeFile(const QString &filePath, const QByteArray &contents)
|
||||
@@ -293,7 +288,7 @@ ProjectInfo ProjectOpenerAndCloser::open(const QString &projectFile, bool config
|
||||
if (configureAsExampleProject)
|
||||
project->configureAsExampleProject();
|
||||
|
||||
if (TestCase::waitUntilCppModelManagerIsAwareOf(project)) {
|
||||
if (TestCase::waitUntilProjectIsFullyOpened(project)) {
|
||||
m_openProjects.append(project);
|
||||
return CppModelManager::instance()->projectInfo(project);
|
||||
}
|
||||
|
@@ -92,8 +92,7 @@ public:
|
||||
static bool waitForProcessedEditorDocument(const QString &filePath, int timeOutInMs = 5000);
|
||||
|
||||
enum { defaultTimeOutInMs = 30 * 1000 /*= 30 secs*/ };
|
||||
static bool waitUntilCppModelManagerIsAwareOf(
|
||||
ProjectExplorer::Project *project,
|
||||
static bool waitUntilProjectIsFullyOpened(ProjectExplorer::Project *project,
|
||||
int timeOutInMs = defaultTimeOutInMs);
|
||||
static CPlusPlus::Document::Ptr waitForFileInGlobalSnapshot(
|
||||
const QString &filePath,
|
||||
|
@@ -40,10 +40,10 @@
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
typedef QMap<QString, QStringList> DependencyMap;
|
||||
typedef CPlusPlus::Document::Ptr DocumentPtr;
|
||||
typedef QList<CPlusPlus::Symbol *> SymbolList;
|
||||
typedef QList<DocumentPtr> DocumentPtrList;
|
||||
using DependencyMap = QMap<QString, QStringList>;
|
||||
using DocumentPtr = CPlusPlus::Document::Ptr;
|
||||
using SymbolList = QList<CPlusPlus::Symbol *>;
|
||||
using DocumentPtrList = QList<DocumentPtr>;
|
||||
|
||||
static const char setupUiC[] = "setupUi";
|
||||
|
||||
|
@@ -58,14 +58,14 @@ QString FormClassWizard::formSuffix() const
|
||||
|
||||
Core::BaseFileWizard *FormClassWizard::create(QWidget *parent, const Core::WizardDialogParameters ¶meters) const
|
||||
{
|
||||
FormClassWizardDialog *wizardDialog = new FormClassWizardDialog(this, parent);
|
||||
auto wizardDialog = new FormClassWizardDialog(this, parent);
|
||||
wizardDialog->setPath(parameters.defaultPath());
|
||||
return wizardDialog;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (params.uiTemplate.isEmpty()) {
|
||||
@@ -90,7 +90,8 @@ Core::GeneratedFiles FormClassWizard::generateFiles(const QWizard *w, QString *e
|
||||
uiFile.setContents(params.uiTemplate);
|
||||
uiFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute);
|
||||
|
||||
QString source, header;
|
||||
QString source;
|
||||
QString header;
|
||||
|
||||
QtDesignerFormClassCodeGenerator::generateCpp(params, &header, &source);
|
||||
sourceFile.setContents(source);
|
||||
|
@@ -105,7 +105,7 @@ bool FormEditorPlugin::initialize(const QStringList &arguments, QString *error)
|
||||
// Ensure that loading designer translations is done before FormEditorW is instantiated
|
||||
const QString locale = ICore::userInterfaceLanguage();
|
||||
if (!locale.isEmpty()) {
|
||||
QTranslator *qtr = new QTranslator(this);
|
||||
auto qtr = new QTranslator(this);
|
||||
const QString &creatorTrPath = ICore::resourcePath() + "/translations";
|
||||
const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
||||
const QString &trFile = "designer_" + locale;
|
||||
|
@@ -92,7 +92,7 @@ void FormEditorStack::add(const EditorData &data)
|
||||
|
||||
// Since we have 1 pixel splitters we enforce no frame
|
||||
// on the content widget
|
||||
if (QFrame *frame = qobject_cast<QFrame*>(data.widgetHost))
|
||||
if (auto frame = qobject_cast<QFrame*>(data.widgetHost))
|
||||
frame->setFrameStyle(QFrame::NoFrame);
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ EditorData FormEditorStack::activeEditor() const
|
||||
if (index >= 0)
|
||||
return m_formEditors.at(index);
|
||||
}
|
||||
return EditorData();
|
||||
return {};
|
||||
}
|
||||
|
||||
SharedTools::WidgetHost *FormEditorStack::formWindowEditorForFormWindow(const QDesignerFormWindowInterface *fw) const
|
||||
@@ -173,7 +173,7 @@ void FormEditorStack::formSizeChanged(int w, int h)
|
||||
// Handle main container resize.
|
||||
if (Designer::Constants::Internal::debug)
|
||||
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);
|
||||
static const QString geometry = "geometry";
|
||||
m_designerCore->propertyEditor()->setPropertyValue(geometry, QRect(0,0,w,h) );
|
||||
|
@@ -115,7 +115,7 @@ namespace Internal {
|
||||
class DesignerXmlEditorWidget : public TextEditor::TextEditorWidget
|
||||
{
|
||||
public:
|
||||
DesignerXmlEditorWidget() {}
|
||||
using TextEditorWidget::TextEditorWidget;
|
||||
|
||||
void finalizeInitialization() override
|
||||
{
|
||||
@@ -196,7 +196,7 @@ public:
|
||||
QDesignerFormEditorInterface *m_formeditor = nullptr;
|
||||
QtCreatorIntegration *m_integration = nullptr;
|
||||
QDesignerFormWindowManagerInterface *m_fwm = nullptr;
|
||||
FormEditorW::InitializationStage m_initStage;
|
||||
FormEditorW::InitializationStage m_initStage = FormEditorW::RegisterPlugins;
|
||||
|
||||
QWidget *m_designerSubWindows[DesignerSubWindowCount];
|
||||
|
||||
@@ -229,8 +229,7 @@ static FormEditorData *d = nullptr;
|
||||
static FormEditorW *m_instance = nullptr;
|
||||
|
||||
FormEditorData::FormEditorData() :
|
||||
m_formeditor(QDesignerComponents::createFormEditor(nullptr)),
|
||||
m_initStage(FormEditorW::RegisterPlugins)
|
||||
m_formeditor(QDesignerComponents::createFormEditor(nullptr))
|
||||
{
|
||||
if (Designer::Constants::Internal::debug)
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
@@ -409,19 +408,18 @@ void FormEditorData::fullInit()
|
||||
|
||||
m_modeWidget = new QWidget;
|
||||
m_modeWidget->setObjectName("DesignerModeWidget");
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
auto layout = new QVBoxLayout(m_modeWidget);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(m_toolBar);
|
||||
// Avoid mode switch to 'Edit' mode when the application started by
|
||||
// 'Run' in 'Design' mode emits output.
|
||||
MiniSplitter *splitter = new MiniSplitter(Qt::Vertical);
|
||||
auto splitter = new MiniSplitter(Qt::Vertical);
|
||||
splitter->addWidget(m_editorWidget);
|
||||
QWidget *outputPane = new OutputPanePlaceHolder(Core::Constants::MODE_DESIGN, splitter);
|
||||
outputPane->setObjectName("DesignerOutputPanePlaceHolder");
|
||||
splitter->addWidget(outputPane);
|
||||
layout->addWidget(splitter);
|
||||
m_modeWidget->setLayout(layout);
|
||||
|
||||
Context designerContexts = m_contexts;
|
||||
designerContexts.add(Core::Constants::C_EDITORMANAGER);
|
||||
@@ -648,9 +646,8 @@ void FormEditorData::setupActions()
|
||||
QToolBar *FormEditorData::createEditorToolBar() const
|
||||
{
|
||||
QToolBar *editorToolBar = new QToolBar;
|
||||
const QList<Id>::const_iterator cend = m_toolActionIds.constEnd();
|
||||
for (QList<Id>::const_iterator it = m_toolActionIds.constBegin(); it != cend; ++it) {
|
||||
Command *cmd = ActionManager::command(*it);
|
||||
for (const auto &id : m_toolActionIds) {
|
||||
Command *cmd = ActionManager::command(id);
|
||||
QTC_ASSERT(cmd, continue);
|
||||
QAction *action = cmd->action();
|
||||
if (!action->icon().isNull()) // Simplify grid has no action yet
|
||||
@@ -735,7 +732,7 @@ QAction *FormEditorData::createEditModeAction(QActionGroup *ag,
|
||||
const QString &iconName,
|
||||
const QString &keySequence)
|
||||
{
|
||||
QAction *rc = new QAction(actionName, ag);
|
||||
auto rc = new QAction(actionName, ag);
|
||||
rc->setCheckable(true);
|
||||
if (!iconName.isEmpty())
|
||||
rc->setIcon(designerIcon(iconName));
|
||||
@@ -774,7 +771,7 @@ IEditor *FormEditorData::createEditor()
|
||||
QTC_ASSERT(form, return nullptr);
|
||||
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);
|
||||
|
||||
m_editorWidget->add(widgetHost, formWindowEditor);
|
||||
|
@@ -60,8 +60,7 @@ Utils::WizardPage *FormPageFactory::create(ProjectExplorer::JsonWizard *wizard,
|
||||
|
||||
QTC_ASSERT(canCreate(typeId), return nullptr);
|
||||
|
||||
FormTemplateWizardPage *page = new FormTemplateWizardPage;
|
||||
return page;
|
||||
return new FormTemplateWizardPage;
|
||||
}
|
||||
|
||||
bool FormPageFactory::validateData(Core::Id typeId, const QVariant &data, QString *errorMessage)
|
||||
|
@@ -44,9 +44,7 @@ FormWindowEditor::FormWindowEditor()
|
||||
addContext(Designer::Constants::C_DESIGNER_XML_EDITOR);
|
||||
}
|
||||
|
||||
FormWindowEditor::~FormWindowEditor()
|
||||
{
|
||||
}
|
||||
FormWindowEditor::~FormWindowEditor() = default;
|
||||
|
||||
QWidget *FormWindowEditor::toolBar()
|
||||
{
|
||||
|
@@ -84,7 +84,7 @@ Core::IDocument::OpenResult FormWindowFile::open(QString *errorString, const QSt
|
||||
Utils::TextFileFormat::ReadResult readResult = read(absfileName, &contents, errorString);
|
||||
if (readResult == Utils::TextFileFormat::ReadEncodingError)
|
||||
return OpenResult::CannotHandle;
|
||||
else if (readResult != Utils::TextFileFormat::ReadSuccess)
|
||||
if (readResult != Utils::TextFileFormat::ReadSuccess)
|
||||
return OpenResult::ReadError;
|
||||
|
||||
form->setFileName(absfileName);
|
||||
|
@@ -218,18 +218,18 @@ static const Class *findClass(const Namespace *parentNameSpace, const LookupCont
|
||||
static Function *findDeclaration(const Class *cl, const QString &functionName)
|
||||
{
|
||||
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 only interested in declarations of functions
|
||||
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 (Function *fun = decl->type()->asFunctionType()) {
|
||||
// Format signature
|
||||
QString memberFunction = overview.prettyName(fun->name());
|
||||
memberFunction += '(';
|
||||
const uint aCount = fun->argumentCount();
|
||||
for (uint i = 0; i < aCount; i++) { // we build argument types string
|
||||
const int aCount = fun->argumentCount();
|
||||
for (int i = 0; i < aCount; i++) { // we build argument types string
|
||||
const Argument *arg = fun->argumentAt(i)->asArgument();
|
||||
if (i > 0)
|
||||
memberFunction += ',';
|
||||
@@ -350,7 +350,7 @@ static QString addConstRefIfNeeded(const QString &argument)
|
||||
"unsigned", "qint64", "quint64"});
|
||||
|
||||
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 + ' '))
|
||||
return argument;
|
||||
}
|
||||
@@ -411,7 +411,7 @@ static QString addParameterNames(const QString &functionSignature, const QString
|
||||
// included files (going down [maxIncludeDepth] includes) and return a pair
|
||||
// of <Class*, Document>.
|
||||
|
||||
typedef QPair<const Class *, Document::Ptr> ClassDocumentPtrPair;
|
||||
using ClassDocumentPtrPair = QPair<const Class *, Document::Ptr>;
|
||||
|
||||
static ClassDocumentPtrPair
|
||||
findClassRecursively(const LookupContext &context, const QString &className,
|
||||
@@ -431,7 +431,7 @@ static ClassDocumentPtrPair
|
||||
for (const QString &include : includedFiles) {
|
||||
const Snapshot::const_iterator it = docTable.find(include);
|
||||
if (it != docTable.end()) {
|
||||
const Document::Ptr includeDoc = it.value();
|
||||
const Document::Ptr &includeDoc = it.value();
|
||||
LookupContext context(includeDoc, docTable);
|
||||
const ClassDocumentPtrPair irc = findClassRecursively(context, className,
|
||||
recursionMaxIncludeDepth, namespaceName);
|
||||
@@ -489,7 +489,7 @@ bool QtCreatorIntegration::navigateToSlot(const QString &objectName,
|
||||
const QStringList ¶meterNames,
|
||||
QString *errorMessage)
|
||||
{
|
||||
typedef QMap<int, Document::Ptr> DocumentMap;
|
||||
using DocumentMap = QMap<int, Document::Ptr>;
|
||||
|
||||
const Utils::FilePath currentUiFile = FormEditorW::activeEditor()->document()->filePath();
|
||||
#if 0
|
||||
|
@@ -73,10 +73,7 @@ void ResourceHandler::ensureInitialized()
|
||||
qDebug() << "ResourceHandler::ensureInitialized() origPaths=" << m_originalUiQrcPaths;
|
||||
}
|
||||
|
||||
ResourceHandler::~ResourceHandler()
|
||||
{
|
||||
|
||||
}
|
||||
ResourceHandler::~ResourceHandler() = default;
|
||||
|
||||
void ResourceHandler::updateResourcesHelper(bool updateProjectResources)
|
||||
{
|
||||
|
@@ -267,7 +267,7 @@ static McuPackage *createQtForMCUsPackage()
|
||||
McuPackage::tr("Qt for MCUs SDK"),
|
||||
QDir::homePath(),
|
||||
Utils::HostOsInfo::withExecutableSuffix("bin/qmltocpp"),
|
||||
"QtMCUSdk");
|
||||
"QtForMCUsSdk");
|
||||
result->setEnvironmentVariableName("Qul_DIR");
|
||||
return result;
|
||||
}
|
||||
|
@@ -168,6 +168,9 @@ void McuSupportOptionsPage::apply()
|
||||
QTC_ASSERT(m_options->armGccPackage, 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();
|
||||
if (!mcuTarget)
|
||||
return;
|
||||
|
@@ -45,8 +45,8 @@ class McuSupportPluginPrivate
|
||||
{
|
||||
public:
|
||||
McuSupportDeviceFactory deviceFactory;
|
||||
EmrunRunConfigurationFactory emrunRunConfigurationFactory;
|
||||
RunWorkerFactory emrunRunWorkerFactory{
|
||||
McuSupportRunConfigurationFactory runConfigurationFactory;
|
||||
RunWorkerFactory runWorkerFactory{
|
||||
makeFlashAndRunWorker(),
|
||||
{ProjectExplorer::Constants::NORMAL_RUN_MODE},
|
||||
{Constants::RUNCONFIGURATION}
|
||||
|
@@ -103,7 +103,7 @@ RunWorkerFactory::WorkerCreator makeFlashAndRunWorker()
|
||||
return RunWorkerFactory::make<FlashAndRunWorker>();
|
||||
}
|
||||
|
||||
EmrunRunConfigurationFactory::EmrunRunConfigurationFactory()
|
||||
McuSupportRunConfigurationFactory::McuSupportRunConfigurationFactory()
|
||||
: FixedRunConfigurationFactory(FlashAndRunConfiguration::tr("Flash and run"))
|
||||
{
|
||||
registerRunConfiguration<FlashAndRunConfiguration>(Constants::RUNCONFIGURATION);
|
||||
|