forked from qt-creator/qt-creator
QmlDesigner: Add support for move gadget to 3D edit view
This proof-of-concept move gadget is based on the move gadget in studio example of QtQuick3D. Change-Id: I1b596443a3e99c16ed214bc464c5367a0f7aa503 Fixes: QDS-1125 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Pasi Keränen <pasi.keranen@qt.io>
This commit is contained in:
126
share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml
Normal file
126
share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml
Normal file
@@ -0,0 +1,126 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 MouseArea3D 1.0
|
||||
|
||||
Model {
|
||||
id: arrow
|
||||
rotationOrder: Node.XYZr
|
||||
source: "meshes/Arrow.mesh"
|
||||
|
||||
property View3D view3D
|
||||
property alias color: material.emissiveColor
|
||||
property Node targetNode: null
|
||||
|
||||
readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering
|
||||
|
||||
property var _pointerPosPressed
|
||||
property var _targetStartPos
|
||||
|
||||
signal positionCommit()
|
||||
|
||||
materials: DefaultMaterial {
|
||||
id: material
|
||||
emissiveColor: mouseAreaFront.hovering ? "white" : Qt.rgba(1.0, 0.0, 0.0, 1.0)
|
||||
lighting: DefaultMaterial.NoLighting
|
||||
}
|
||||
|
||||
function handlePressed(mouseArea, pointerPosition)
|
||||
{
|
||||
if (!targetNode)
|
||||
return;
|
||||
|
||||
var maskedPosition = Qt.vector3d(pointerPosition.x, 0, 0);
|
||||
_pointerPosPressed = mouseArea.mapPositionToScene(maskedPosition);
|
||||
var sp = targetNode.positionInScene;
|
||||
_targetStartPos = Qt.vector3d(sp.x, sp.y, sp.z);
|
||||
}
|
||||
|
||||
function posInParent(mouseArea, pointerPosition)
|
||||
{
|
||||
var maskedPosition = Qt.vector3d(pointerPosition.x, 0, 0);
|
||||
var scenePointerPos = mouseArea.mapPositionToScene(maskedPosition);
|
||||
var sceneRelativeDistance = Qt.vector3d(
|
||||
scenePointerPos.x - _pointerPosPressed.x,
|
||||
scenePointerPos.y - _pointerPosPressed.y,
|
||||
scenePointerPos.z - _pointerPosPressed.z);
|
||||
|
||||
var newScenePos = Qt.vector3d(
|
||||
_targetStartPos.x + sceneRelativeDistance.x,
|
||||
_targetStartPos.y + sceneRelativeDistance.y,
|
||||
_targetStartPos.z + sceneRelativeDistance.z);
|
||||
|
||||
return targetNode.parent.mapPositionFromScene(newScenePos);
|
||||
}
|
||||
|
||||
function handleDragged(mouseArea, pointerPosition)
|
||||
{
|
||||
if (!targetNode)
|
||||
return;
|
||||
|
||||
targetNode.position = posInParent(mouseArea, pointerPosition);
|
||||
}
|
||||
|
||||
function handleReleased(mouseArea, pointerPosition)
|
||||
{
|
||||
if (!targetNode)
|
||||
return;
|
||||
|
||||
targetNode.position = posInParent(mouseArea, pointerPosition);
|
||||
arrow.positionCommit();
|
||||
}
|
||||
|
||||
MouseArea3D {
|
||||
id: mouseAreaYZ
|
||||
view3D: arrow.view3D
|
||||
x: 0
|
||||
y: -1.5
|
||||
width: 12
|
||||
height: 3
|
||||
rotation: Qt.vector3d(0, 90, 0)
|
||||
grabsMouse: targetNode
|
||||
onPressed: arrow.handlePressed(mouseAreaYZ, pointerPosition)
|
||||
onDragged: arrow.handleDragged(mouseAreaYZ, pointerPosition)
|
||||
onReleased: arrow.handleReleased(mouseAreaYZ, pointerPosition)
|
||||
}
|
||||
|
||||
MouseArea3D {
|
||||
id: mouseAreaXZ
|
||||
view3D: arrow.view3D
|
||||
x: 0
|
||||
y: -1.5
|
||||
width: 12
|
||||
height: 3
|
||||
rotation: Qt.vector3d(90, 90, 0)
|
||||
grabsMouse: targetNode
|
||||
onPressed: arrow.handlePressed(mouseAreaXZ, pointerPosition)
|
||||
onDragged: arrow.handleDragged(mouseAreaXZ, pointerPosition)
|
||||
onReleased: arrow.handleReleased(mouseAreaXZ, pointerPosition)
|
||||
}
|
||||
|
||||
}
|
||||
|
85
share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml
Normal file
85
share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml
Normal file
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 MouseArea3D 1.0
|
||||
|
||||
Node {
|
||||
id: overlayNode
|
||||
|
||||
property View3D view3D
|
||||
property Node target: parent
|
||||
property bool autoScale: true
|
||||
|
||||
// Read-only
|
||||
property real relativeScale: 1
|
||||
|
||||
onGlobalTransformChanged: updateScale()
|
||||
onAutoScaleChanged: updateScale()
|
||||
Connections {
|
||||
target: view3D.camera
|
||||
onGlobalTransformChanged: updateScale()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: window
|
||||
onFirstFrameReady: updateScale()
|
||||
}
|
||||
|
||||
function getScale(baseScale)
|
||||
{
|
||||
return Qt.vector3d(baseScale.x * relativeScale, baseScale.y * relativeScale,
|
||||
baseScale.z * relativeScale);
|
||||
}
|
||||
|
||||
function updateScale()
|
||||
{
|
||||
if (!autoScale) {
|
||||
target.scale = Qt.vector3d(1, 1, 1);
|
||||
} else {
|
||||
// Calculate the distance independent scale by first mapping the targets position to
|
||||
// the view. We then measure up a distance on the view (100px) that we use as an
|
||||
// "anchor" distance. Map the two positions back to the target node, and measure the
|
||||
// distance between them now, in the 3D scene. The difference of the two distances,
|
||||
// view and scene, will tell us what the distance independent scale should be.
|
||||
var posInView1 = view3D.mapFrom3DScene(positionInScene);
|
||||
var posInView2 = Qt.vector3d(posInView1.x + 100, posInView1.y, posInView1.z);
|
||||
|
||||
var rayPos1 = view3D.mapTo3DScene(Qt.vector3d(posInView2.x, posInView2.y, 0));
|
||||
var rayPos2 = view3D.mapTo3DScene(Qt.vector3d(posInView2.x, posInView2.y, 10));
|
||||
|
||||
var planeNormal = view3D.camera.forward;
|
||||
var rayHitPos = helper.rayIntersectsPlane(rayPos1, rayPos2, positionInScene,
|
||||
planeNormal);
|
||||
relativeScale = positionInScene.minus(rayHitPos).length() / 100;
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea3D {
|
||||
id: helper
|
||||
view3D: overlayNode.view3D
|
||||
}
|
||||
}
|
@@ -42,7 +42,46 @@ Window {
|
||||
property alias showEditLight: editLightCheckbox.checked
|
||||
property alias usePerspective: usePerspectiveCheckbox.checked
|
||||
|
||||
property Node selectedNode: null
|
||||
|
||||
signal objectClicked(var object)
|
||||
signal commitObjectPosition(var object)
|
||||
|
||||
Node {
|
||||
id: overlayScene
|
||||
|
||||
Camera {
|
||||
id: overlayCamera
|
||||
projectionMode: usePerspectiveCheckbox.checked ? Camera.Perspective
|
||||
: Camera.Orthographic
|
||||
clipFar: editCamera.clipFar
|
||||
position: editCamera.position
|
||||
rotation: editCamera.rotation
|
||||
}
|
||||
|
||||
MoveGizmo {
|
||||
id: moveGizmo
|
||||
scale: autoScale.getScale(Qt.vector3d(5, 5, 5))
|
||||
highlightOnHover: true
|
||||
targetNode: viewWindow.selectedNode
|
||||
position: viewWindow.selectedNode ? viewWindow.selectedNode.positionInScene
|
||||
: Qt.vector3d(0, 0, 0)
|
||||
rotation: globalControl.checked || !viewWindow.selectedNode
|
||||
? Qt.vector3d(0, 0, 0)
|
||||
: viewWindow.selectedNode.rotationInScene
|
||||
|
||||
visible: selectedNode
|
||||
view3D: overlayView
|
||||
|
||||
onPositionCommit: viewWindow.commitObjectPosition(selectedNode)
|
||||
}
|
||||
|
||||
AutoScaleHelper {
|
||||
id: autoScale
|
||||
view3D: overlayView
|
||||
position: moveGizmo.positionInScene
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: sceneBg
|
||||
@@ -55,41 +94,47 @@ Window {
|
||||
var pickResult = editView.pick(eventPoint.scenePosition.x,
|
||||
eventPoint.scenePosition.y);
|
||||
viewWindow.objectClicked(pickResult.objectHit);
|
||||
selectedNode = pickResult.objectHit; // TODO selection needs to come from studio
|
||||
}
|
||||
}
|
||||
|
||||
View3D {
|
||||
id: editView
|
||||
anchors.fill: parent
|
||||
enableWireframeMode: true
|
||||
camera: editCamera
|
||||
|
||||
AxisHelper {
|
||||
id: axisGrid
|
||||
enableXZGrid: true
|
||||
enableAxisLines: false
|
||||
}
|
||||
Node {
|
||||
id: mainSceneHelpers
|
||||
|
||||
PointLight {
|
||||
id: pointLight
|
||||
visible: showEditLight
|
||||
position: editCamera.position
|
||||
}
|
||||
AxisHelper {
|
||||
id: axisGrid
|
||||
enableXZGrid: true
|
||||
enableAxisLines: false
|
||||
}
|
||||
|
||||
Camera {
|
||||
id: editCamera
|
||||
y: 200
|
||||
z: -300
|
||||
clipFar: 100000
|
||||
projectionMode: usePerspective ? Camera.Perspective : Camera.Orthographic
|
||||
}
|
||||
PointLight {
|
||||
id: pointLight
|
||||
visible: showEditLight
|
||||
position: editCamera.position
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
pointLight.setParentItem(editView.scene);
|
||||
editCamera.setParentItem(editView.scene);
|
||||
Camera {
|
||||
id: editCamera
|
||||
y: 200
|
||||
z: -300
|
||||
clipFar: 100000
|
||||
projectionMode: usePerspective ? Camera.Perspective : Camera.Orthographic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
View3D {
|
||||
id: overlayView
|
||||
anchors.fill: parent
|
||||
camera: overlayCamera
|
||||
scene: overlayScene
|
||||
}
|
||||
|
||||
WasdController {
|
||||
id: cameraControl
|
||||
controlledObject: editView.camera
|
||||
@@ -121,6 +166,13 @@ Window {
|
||||
text: qsTr("Use Perspective Projection")
|
||||
onCheckedChanged: cameraControl.forceActiveFocus()
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: globalControl
|
||||
checked: true
|
||||
text: qsTr("Use global orientation")
|
||||
onCheckedChanged: cameraControl.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
|
79
share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml
Normal file
79
share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml
Normal file
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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
|
||||
|
||||
Node {
|
||||
id: arrows
|
||||
|
||||
property View3D view3D
|
||||
property bool highlightOnHover: false
|
||||
property Node targetNode: null
|
||||
|
||||
scale: Qt.vector3d(5, 5, 5)
|
||||
|
||||
property alias arrowX: arrowX
|
||||
property alias arrowY: arrowY
|
||||
property alias arrowZ: arrowZ
|
||||
|
||||
signal positionCommit()
|
||||
|
||||
Arrow {
|
||||
id: arrowX
|
||||
objectName: "Arrow X"
|
||||
rotation: Qt.vector3d(0, -90, 0)
|
||||
targetNode: arrows.targetNode
|
||||
color: highlightOnHover && hovering ? Qt.lighter(Qt.rgba(1, 0, 0, 1))
|
||||
: Qt.rgba(1, 0, 0, 1)
|
||||
view3D: arrows.view3D
|
||||
|
||||
onPositionCommit: arrows.positionCommit()
|
||||
}
|
||||
|
||||
Arrow {
|
||||
id: arrowY
|
||||
objectName: "Arrow Y"
|
||||
rotation: Qt.vector3d(90, 0, 0)
|
||||
targetNode: arrows.targetNode
|
||||
color: highlightOnHover && hovering ? Qt.lighter(Qt.rgba(0, 0, 1, 1))
|
||||
: Qt.rgba(0, 0, 1, 1)
|
||||
view3D: arrows.view3D
|
||||
|
||||
onPositionCommit: arrows.positionCommit()
|
||||
}
|
||||
|
||||
Arrow {
|
||||
id: arrowZ
|
||||
objectName: "Arrow Z"
|
||||
rotation: Qt.vector3d(0, 180, 0)
|
||||
targetNode: arrows.targetNode
|
||||
color: highlightOnHover && hovering ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
|
||||
: Qt.rgba(0, 0.6, 0, 1)
|
||||
view3D: arrows.view3D
|
||||
|
||||
onPositionCommit: arrows.positionCommit()
|
||||
}
|
||||
}
|
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/meshes/Arrow.mesh
Normal file
BIN
share/qtcreator/qml/qmlpuppet/mockfiles/meshes/Arrow.mesh
Normal file
Binary file not shown.
@@ -1,2 +1,5 @@
|
||||
HEADERS += $$PWD/cameracontrolhelper.h
|
||||
SOURCES += $$PWD/cameracontrolhelper.cpp
|
||||
HEADERS += $$PWD/cameracontrolhelper.h \
|
||||
$$PWD/mousearea3d.h
|
||||
|
||||
SOURCES += $$PWD/cameracontrolhelper.cpp \
|
||||
$$PWD/mousearea3d.cpp
|
||||
|
@@ -0,0 +1,251 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 "mousearea3d.h"
|
||||
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtQml/qqmlinfo.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
namespace Internal {
|
||||
|
||||
MouseArea3D *MouseArea3D::s_mouseGrab = nullptr;
|
||||
|
||||
MouseArea3D::MouseArea3D(QQuick3DNode *parent)
|
||||
: QQuick3DNode(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QQuick3DViewport *MouseArea3D::view3D() const
|
||||
{
|
||||
return m_view3D;
|
||||
}
|
||||
|
||||
bool MouseArea3D::hovering() const
|
||||
{
|
||||
return m_hovering;
|
||||
}
|
||||
|
||||
bool MouseArea3D::dragging() const
|
||||
{
|
||||
return m_dragging;
|
||||
}
|
||||
|
||||
bool MouseArea3D::grabsMouse() const
|
||||
{
|
||||
return m_grabsMouse;
|
||||
}
|
||||
|
||||
qreal MouseArea3D::x() const
|
||||
{
|
||||
return m_x;
|
||||
}
|
||||
|
||||
qreal MouseArea3D::y() const
|
||||
{
|
||||
return m_y;
|
||||
}
|
||||
|
||||
qreal MouseArea3D::width() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
qreal MouseArea3D::height() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void MouseArea3D::setView3D(QQuick3DViewport *view3D)
|
||||
{
|
||||
if (m_view3D == view3D)
|
||||
return;
|
||||
|
||||
m_view3D = view3D;
|
||||
emit view3DChanged();
|
||||
}
|
||||
|
||||
void MouseArea3D::setGrabsMouse(bool grabsMouse)
|
||||
{
|
||||
if (m_grabsMouse == grabsMouse)
|
||||
return;
|
||||
|
||||
m_grabsMouse = grabsMouse;
|
||||
emit grabsMouseChanged(grabsMouse);
|
||||
}
|
||||
|
||||
void MouseArea3D::setX(qreal x)
|
||||
{
|
||||
if (qFuzzyCompare(m_x, x))
|
||||
return;
|
||||
|
||||
m_x = x;
|
||||
emit xChanged(x);
|
||||
}
|
||||
|
||||
void MouseArea3D::setY(qreal y)
|
||||
{
|
||||
if (qFuzzyCompare(m_y, y))
|
||||
return;
|
||||
|
||||
m_y = y;
|
||||
emit yChanged(y);
|
||||
}
|
||||
|
||||
void MouseArea3D::setWidth(qreal width)
|
||||
{
|
||||
if (qFuzzyCompare(m_width, width))
|
||||
return;
|
||||
|
||||
m_width = width;
|
||||
emit widthChanged(width);
|
||||
}
|
||||
|
||||
void MouseArea3D::setHeight(qreal height)
|
||||
{
|
||||
if (qFuzzyCompare(m_height, height))
|
||||
return;
|
||||
|
||||
m_height = height;
|
||||
emit heightChanged(height);
|
||||
}
|
||||
|
||||
void MouseArea3D::componentComplete()
|
||||
{
|
||||
if (!m_view3D) {
|
||||
qmlDebug(this) << "property 'view3D' is not set!";
|
||||
return;
|
||||
}
|
||||
m_view3D->setAcceptedMouseButtons(Qt::LeftButton);
|
||||
m_view3D->setAcceptHoverEvents(true);
|
||||
m_view3D->setAcceptTouchEvents(false);
|
||||
m_view3D->installEventFilter(this);
|
||||
}
|
||||
|
||||
QVector3D MouseArea3D::rayIntersectsPlane(const QVector3D &rayPos0,
|
||||
const QVector3D &rayPos1,
|
||||
const QVector3D &planePos,
|
||||
const QVector3D &planeNormal) const
|
||||
{
|
||||
QVector3D rayDirection = rayPos1 - rayPos0;
|
||||
QVector3D rayPos0RelativeToPlane = rayPos0 - planePos;
|
||||
|
||||
float dotPlaneRayDirection = QVector3D::dotProduct(planeNormal, rayDirection);
|
||||
float dotPlaneRayPos0 = -QVector3D::dotProduct(planeNormal, rayPos0RelativeToPlane);
|
||||
|
||||
if (qFuzzyIsNull(dotPlaneRayDirection)) {
|
||||
// The ray is is parallel to the plane. Note that if dotLinePos0 == 0, it
|
||||
// additionally means that the line lies in plane as well. In any case, we
|
||||
// signal that we cannot find a single intersection point.
|
||||
return QVector3D(0, 0, -1);
|
||||
}
|
||||
|
||||
// Since we work with a ray (that has a start), distanceFromLinePos0ToPlane
|
||||
// must be above 0. If it was a line segment (with an end), it also need to be less than 1.
|
||||
// (Note: a third option would be a "line", which is different from a ray or segment in that
|
||||
// it has neither a start, nor an end). Then we wouldn't need to check the distance at all.
|
||||
// But that would also mean that the line could intersect the plane behind the camera, if
|
||||
// the line were directed away from the plane when looking forward.
|
||||
float distanceFromRayPos0ToPlane = dotPlaneRayPos0 / dotPlaneRayDirection;
|
||||
if (distanceFromRayPos0ToPlane <= 0)
|
||||
return QVector3D(0, 0, -1);
|
||||
return rayPos0 + distanceFromRayPos0ToPlane * rayDirection;
|
||||
}
|
||||
|
||||
QVector3D MouseArea3D::getMousePosInPlane(const QPointF &mousePosInView) const
|
||||
{
|
||||
const QVector3D mousePos1(float(mousePosInView.x()), float(mousePosInView.y()), 0);
|
||||
const QVector3D mousePos2(float(mousePosInView.x()), float(mousePosInView.y()), 1);
|
||||
const QVector3D rayPos0 = m_view3D->mapTo3DScene(mousePos1);
|
||||
const QVector3D rayPos1 = m_view3D->mapTo3DScene(mousePos2);
|
||||
const QVector3D globalPlanePosition = mapPositionToScene(QVector3D(0, 0, 0));
|
||||
const QVector3D intersectGlobalPos = rayIntersectsPlane(rayPos0, rayPos1,
|
||||
globalPlanePosition, forward());
|
||||
if (qFuzzyCompare(intersectGlobalPos.z(), -1))
|
||||
return intersectGlobalPos;
|
||||
|
||||
return mapPositionFromScene(intersectGlobalPos);
|
||||
}
|
||||
|
||||
bool MouseArea3D::eventFilter(QObject *, QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::HoverMove: {
|
||||
if (m_grabsMouse && s_mouseGrab && s_mouseGrab != this)
|
||||
break;
|
||||
|
||||
auto const mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
const QVector3D mousePosInPlane = getMousePosInPlane(mouseEvent->pos());
|
||||
if (qFuzzyCompare(mousePosInPlane.z(), -1))
|
||||
break;
|
||||
|
||||
const bool mouseOnTopOfMouseArea =
|
||||
mousePosInPlane.x() >= float(m_x) &&
|
||||
mousePosInPlane.x() <= float(m_x + m_width) &&
|
||||
mousePosInPlane.y() >= float(m_y) &&
|
||||
mousePosInPlane.y() <= float(m_y + m_height);
|
||||
|
||||
const bool buttonPressed = QGuiApplication::mouseButtons().testFlag(Qt::LeftButton);
|
||||
|
||||
// The filter will detect a mouse press on the view, but not a mouse release, since the
|
||||
// former is not accepted by the view, which means that the release will end up being
|
||||
// sent elsewhere. So we need this extra logic inside HoverMove, rather than in
|
||||
// MouseButtonRelease, which would otherwise be more elegant.
|
||||
|
||||
if (m_hovering != mouseOnTopOfMouseArea) {
|
||||
m_hovering = mouseOnTopOfMouseArea;
|
||||
emit hoveringChanged();
|
||||
}
|
||||
|
||||
if (!m_dragging && m_hovering && buttonPressed) {
|
||||
m_dragging = true;
|
||||
emit pressed(mousePosInPlane);
|
||||
emit draggingChanged();
|
||||
} else if (m_dragging && !buttonPressed) {
|
||||
m_dragging = false;
|
||||
emit released(mousePosInPlane);
|
||||
emit draggingChanged();
|
||||
}
|
||||
|
||||
if (m_grabsMouse)
|
||||
s_mouseGrab = m_hovering || m_dragging ? this : nullptr;
|
||||
|
||||
if (m_dragging)
|
||||
emit dragged(mousePosInPlane);
|
||||
|
||||
break; }
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // QUICK3D_MODULE
|
125
share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h
Normal file
125
share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 <QtGui/qvector3d.h>
|
||||
#include <QtCore/qpointer.h>
|
||||
|
||||
#include <QtQuick3D/private/qquick3dnode_p.h>
|
||||
#include <QtQuick3D/private/qquick3dviewport_p.h>
|
||||
#include <QtQuick3D/private/qtquick3dglobal_p.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
namespace Internal {
|
||||
|
||||
class MouseArea3D : public QQuick3DNode
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QQuick3DViewport *view3D READ view3D WRITE setView3D NOTIFY view3DChanged)
|
||||
Q_PROPERTY(bool grabsMouse READ grabsMouse WRITE setGrabsMouse NOTIFY grabsMouseChanged)
|
||||
Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
|
||||
Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
|
||||
Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged)
|
||||
Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged)
|
||||
Q_PROPERTY(bool hovering READ hovering NOTIFY hoveringChanged)
|
||||
Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
|
||||
|
||||
Q_INTERFACES(QQmlParserStatus)
|
||||
|
||||
public:
|
||||
MouseArea3D(QQuick3DNode *parent = nullptr);
|
||||
|
||||
QQuick3DViewport *view3D() const;
|
||||
|
||||
qreal x() const;
|
||||
qreal y() const;
|
||||
qreal width() const;
|
||||
qreal height() const;
|
||||
|
||||
bool hovering() const;
|
||||
bool dragging() const;
|
||||
bool grabsMouse() const;
|
||||
|
||||
public slots:
|
||||
void setView3D(QQuick3DViewport *view3D);
|
||||
void setGrabsMouse(bool grabsMouse);
|
||||
|
||||
void setX(qreal x);
|
||||
void setY(qreal y);
|
||||
void setWidth(qreal width);
|
||||
void setHeight(qreal height);
|
||||
|
||||
Q_INVOKABLE QVector3D rayIntersectsPlane(const QVector3D &rayPos0,
|
||||
const QVector3D &rayPos1,
|
||||
const QVector3D &planePos,
|
||||
const QVector3D &planeNormal) const;
|
||||
|
||||
signals:
|
||||
void view3DChanged();
|
||||
|
||||
void xChanged(qreal x);
|
||||
void yChanged(qreal y);
|
||||
void widthChanged(qreal width);
|
||||
void heightChanged(qreal height);
|
||||
|
||||
void hoveringChanged();
|
||||
void draggingChanged();
|
||||
void pressed(const QVector3D &pointerPosition);
|
||||
void released(const QVector3D &pointerPosition);
|
||||
void dragged(const QVector3D &pointerPosition);
|
||||
void grabsMouseChanged(bool grabsMouse);
|
||||
|
||||
protected:
|
||||
void classBegin() override {}
|
||||
void componentComplete() override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(MouseArea3D)
|
||||
QQuick3DViewport *m_view3D = nullptr;
|
||||
|
||||
qreal m_x;
|
||||
qreal m_y;
|
||||
qreal m_width;
|
||||
qreal m_height;
|
||||
|
||||
bool m_hovering = false;
|
||||
bool m_dragging = false;
|
||||
|
||||
QVector3D getMousePosInPlane(const QPointF &mousePosInView) const;
|
||||
|
||||
static MouseArea3D *s_mouseGrab;
|
||||
bool m_grabsMouse;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
QML_DECLARE_TYPE(QmlDesigner::Internal::MouseArea3D)
|
||||
|
||||
#endif // QUICK3D_MODULE
|
@@ -59,6 +59,7 @@
|
||||
|
||||
#include "dummycontextobject.h"
|
||||
#include "../editor3d/cameracontrolhelper.h"
|
||||
#include "../editor3d/mousearea3d.h"
|
||||
|
||||
#include <designersupportdelegate.h>
|
||||
|
||||
@@ -77,9 +78,13 @@ static QVariant objectToVariant(QObject *object)
|
||||
|
||||
QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
|
||||
{
|
||||
QmlDesigner::Internal::CameraControlHelper *helper = new QmlDesigner::Internal::CameraControlHelper();
|
||||
auto helper = new QmlDesigner::Internal::CameraControlHelper();
|
||||
engine->rootContext()->setContextProperty("designStudioNativeCameraControlHelper", helper);
|
||||
|
||||
#ifdef QUICK3D_MODULE
|
||||
qmlRegisterType<QmlDesigner::Internal::MouseArea3D>("MouseArea3D", 1, 0, "MouseArea3D");
|
||||
#endif
|
||||
|
||||
QQmlComponent component(engine, QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"));
|
||||
|
||||
QWindow *window = qobject_cast<QWindow *>(component.create());
|
||||
@@ -90,6 +95,8 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
|
||||
}
|
||||
|
||||
QObject::connect(window, SIGNAL(objectClicked(QVariant)), this, SLOT(objectClicked(QVariant)));
|
||||
QObject::connect(window, SIGNAL(commitObjectPosition(QVariant)),
|
||||
this, SLOT(handleObjectPositionCommit(QVariant)));
|
||||
|
||||
//For macOS we have to use the 4.1 core profile
|
||||
QSurfaceFormat surfaceFormat = window->requestedFormat();
|
||||
@@ -101,10 +108,29 @@ QObject *Qt5InformationNodeInstanceServer::createEditView3D(QQmlEngine *engine)
|
||||
return window;
|
||||
}
|
||||
|
||||
// an object is clicked in the 3D edit view
|
||||
// an object is clicked in the 3D edit view. Null object indicates selection clearing.
|
||||
void Qt5InformationNodeInstanceServer::objectClicked(const QVariant &object)
|
||||
{
|
||||
selectInstance(instanceForObject(object.value<QObject *>()));
|
||||
auto obj = object.value<QObject *>();
|
||||
ServerNodeInstance instance;
|
||||
if (obj)
|
||||
instance = instanceForObject(obj);
|
||||
selectInstance(instance);
|
||||
}
|
||||
|
||||
void Qt5InformationNodeInstanceServer::handleObjectPositionCommit(const QVariant &object)
|
||||
{
|
||||
QObject *obj = object.value<QObject *>();
|
||||
if (obj) {
|
||||
ServerNodeInstance instance = instanceForObject(obj);
|
||||
QVector<InstancePropertyValueTriple> modifiedpropertyList;
|
||||
InstancePropertyValueTriple propTriple;
|
||||
propTriple.instance = instance;
|
||||
propTriple.propertyName = "position";
|
||||
propTriple.propertyValue = obj->property(propTriple.propertyName.constData());
|
||||
modifiedpropertyList.append(propTriple);
|
||||
nodeInstanceClient()->valuesModified(createValuesModifiedCommand(modifiedpropertyList));
|
||||
}
|
||||
}
|
||||
|
||||
Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
|
||||
|
@@ -44,8 +44,9 @@ public:
|
||||
void removeSharedMemory(const RemoveSharedMemoryCommand &command) override;
|
||||
void changeSelection(const ChangeSelectionCommand &command) override;
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void objectClicked(const QVariant &object);
|
||||
void handleObjectPositionCommit(const QVariant &object);
|
||||
|
||||
protected:
|
||||
void collectItemChangesAndSendChangeCommands() override;
|
||||
|
@@ -8,5 +8,9 @@
|
||||
<file>mockfiles/GenericBackend.qml</file>
|
||||
<file>mockfiles/Dialog.qml</file>
|
||||
<file>mockfiles/EditView3D.qml</file>
|
||||
<file>mockfiles/Arrow.qml</file>
|
||||
<file>mockfiles/AutoScaleHelper.qml</file>
|
||||
<file>mockfiles/MoveGizmo.qml</file>
|
||||
<file>mockfiles/meshes/Arrow.mesh</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@@ -108,6 +108,7 @@ extend_qtc_executable(qml2puppet
|
||||
SOURCES_PREFIX "${SRCDIR}/qml2puppet/editor3d"
|
||||
SOURCES
|
||||
cameracontrolhelper.cpp cameracontrolhelper.h
|
||||
mousearea3d.cpp mousearea3d.h
|
||||
)
|
||||
|
||||
extend_qtc_executable(qml2puppet
|
||||
|
@@ -197,6 +197,8 @@ QtcTool {
|
||||
"instances/servernodeinstance.h",
|
||||
"editor3d/cameracontrolhelper.cpp",
|
||||
"editor3d/cameracontrolhelper.h",
|
||||
"editor3d/mousearea3d.cpp",
|
||||
"editor3d/mousearea3d.h",
|
||||
"qml2puppetmain.cpp",
|
||||
]
|
||||
}
|
||||
|
Reference in New Issue
Block a user