1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Data Visualization module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 or (at your option) any later version |
20 | ** approved by the KDE Free Qt Foundation. The licenses are as published by |
21 | ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
22 | ** included in the packaging of this file. Please review the following |
23 | ** information to ensure the GNU General Public License requirements will |
24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
25 | ** |
26 | ** $QT_END_LICENSE$ |
27 | ** |
28 | ****************************************************************************/ |
29 | |
30 | #include "custominputhandler.h" |
31 | |
32 | #include <QtDataVisualization/Q3DCamera> |
33 | #include <QtCore/qmath.h> |
34 | |
35 | CustomInputHandler::CustomInputHandler(QAbstract3DGraph *graph, QObject *parent) : |
36 | Q3DInputHandler(parent), |
37 | m_highlight(0), |
38 | m_mousePressed(false), |
39 | m_state(StateNormal), |
40 | m_axisX(0), |
41 | m_axisZ(0), |
42 | m_speedModifier(20.0f) |
43 | { |
44 | // Connect to the item selection signal from graph |
45 | connect(sender: graph, signal: &QAbstract3DGraph::selectedElementChanged, receiver: this, |
46 | slot: &CustomInputHandler::handleElementSelected); |
47 | } |
48 | |
49 | void CustomInputHandler::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) |
50 | { |
51 | if (Qt::LeftButton == event->button()) { |
52 | m_highlight->setVisible(false); |
53 | m_mousePressed = true; |
54 | } |
55 | Q3DInputHandler::mousePressEvent(event, mousePos); |
56 | } |
57 | |
58 | //! [1] |
59 | void CustomInputHandler::wheelEvent(QWheelEvent *event) |
60 | { |
61 | float delta = float(event->angleDelta().y()); |
62 | |
63 | m_axisXMinValue += delta; |
64 | m_axisXMaxValue -= delta; |
65 | m_axisZMinValue += delta; |
66 | m_axisZMaxValue -= delta; |
67 | checkConstraints(); |
68 | |
69 | float y = (m_axisXMaxValue - m_axisXMinValue) * m_aspectRatio; |
70 | |
71 | m_axisX->setRange(min: m_axisXMinValue, max: m_axisXMaxValue); |
72 | m_axisY->setRange(min: 100.0f, max: y); |
73 | m_axisZ->setRange(min: m_axisZMinValue, max: m_axisZMaxValue); |
74 | } |
75 | //! [1] |
76 | |
77 | void CustomInputHandler::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) |
78 | { |
79 | // Check if we're trying to drag axis label |
80 | if (m_mousePressed && m_state != StateNormal) { |
81 | setPreviousInputPos(inputPosition()); |
82 | setInputPosition(mousePos); |
83 | handleAxisDragging(); |
84 | } else { |
85 | Q3DInputHandler::mouseMoveEvent(event, mousePos); |
86 | } |
87 | } |
88 | |
89 | void CustomInputHandler::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) |
90 | { |
91 | Q3DInputHandler::mouseReleaseEvent(event, mousePos); |
92 | m_mousePressed = false; |
93 | m_state = StateNormal; |
94 | } |
95 | |
96 | void CustomInputHandler::handleElementSelected(QAbstract3DGraph::ElementType type) |
97 | { |
98 | switch (type) { |
99 | case QAbstract3DGraph::ElementAxisXLabel: |
100 | m_state = StateDraggingX; |
101 | break; |
102 | case QAbstract3DGraph::ElementAxisZLabel: |
103 | m_state = StateDraggingZ; |
104 | break; |
105 | default: |
106 | m_state = StateNormal; |
107 | break; |
108 | } |
109 | } |
110 | |
111 | void CustomInputHandler::handleAxisDragging() |
112 | { |
113 | float distance = 0.0f; |
114 | |
115 | // Get scene orientation from active camera |
116 | float xRotation = scene()->activeCamera()->xRotation(); |
117 | |
118 | // Calculate directional drag multipliers based on rotation |
119 | float xMulX = qCos(v: qDegreesToRadians(degrees: xRotation)); |
120 | float xMulY = qSin(v: qDegreesToRadians(degrees: xRotation)); |
121 | float zMulX = qSin(v: qDegreesToRadians(degrees: xRotation)); |
122 | float zMulY = qCos(v: qDegreesToRadians(degrees: xRotation)); |
123 | |
124 | // Get the drag amount |
125 | QPoint move = inputPosition() - previousInputPos(); |
126 | |
127 | // Adjust axes |
128 | switch (m_state) { |
129 | //! [0] |
130 | case StateDraggingX: |
131 | distance = (move.x() * xMulX - move.y() * xMulY) * m_speedModifier; |
132 | m_axisXMinValue -= distance; |
133 | m_axisXMaxValue -= distance; |
134 | if (m_axisXMinValue < m_areaMinValue) { |
135 | float dist = m_axisXMaxValue - m_axisXMinValue; |
136 | m_axisXMinValue = m_areaMinValue; |
137 | m_axisXMaxValue = m_axisXMinValue + dist; |
138 | } |
139 | if (m_axisXMaxValue > m_areaMaxValue) { |
140 | float dist = m_axisXMaxValue - m_axisXMinValue; |
141 | m_axisXMaxValue = m_areaMaxValue; |
142 | m_axisXMinValue = m_axisXMaxValue - dist; |
143 | } |
144 | m_axisX->setRange(min: m_axisXMinValue, max: m_axisXMaxValue); |
145 | break; |
146 | //! [0] |
147 | case StateDraggingZ: |
148 | distance = (move.x() * zMulX + move.y() * zMulY) * m_speedModifier; |
149 | m_axisZMinValue += distance; |
150 | m_axisZMaxValue += distance; |
151 | if (m_axisZMinValue < m_areaMinValue) { |
152 | float dist = m_axisZMaxValue - m_axisZMinValue; |
153 | m_axisZMinValue = m_areaMinValue; |
154 | m_axisZMaxValue = m_axisZMinValue + dist; |
155 | } |
156 | if (m_axisZMaxValue > m_areaMaxValue) { |
157 | float dist = m_axisZMaxValue - m_axisZMinValue; |
158 | m_axisZMaxValue = m_areaMaxValue; |
159 | m_axisZMinValue = m_axisZMaxValue - dist; |
160 | } |
161 | m_axisZ->setRange(min: m_axisZMinValue, max: m_axisZMaxValue); |
162 | break; |
163 | default: |
164 | break; |
165 | } |
166 | } |
167 | |
168 | void CustomInputHandler::checkConstraints() |
169 | { |
170 | //! [2] |
171 | if (m_axisXMinValue < m_areaMinValue) |
172 | m_axisXMinValue = m_areaMinValue; |
173 | if (m_axisXMaxValue > m_areaMaxValue) |
174 | m_axisXMaxValue = m_areaMaxValue; |
175 | // Don't allow too much zoom in |
176 | if ((m_axisXMaxValue - m_axisXMinValue) < m_axisXMinRange) { |
177 | float adjust = (m_axisXMinRange - (m_axisXMaxValue - m_axisXMinValue)) / 2.0f; |
178 | m_axisXMinValue -= adjust; |
179 | m_axisXMaxValue += adjust; |
180 | } |
181 | //! [2] |
182 | |
183 | if (m_axisZMinValue < m_areaMinValue) |
184 | m_axisZMinValue = m_areaMinValue; |
185 | if (m_axisZMaxValue > m_areaMaxValue) |
186 | m_axisZMaxValue = m_areaMaxValue; |
187 | // Don't allow too much zoom in |
188 | if ((m_axisZMaxValue - m_axisZMinValue) < m_axisZMinRange) { |
189 | float adjust = (m_axisZMinRange - (m_axisZMaxValue - m_axisZMinValue)) / 2.0f; |
190 | m_axisZMinValue -= adjust; |
191 | m_axisZMaxValue += adjust; |
192 | } |
193 | } |
194 | |