1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt3D module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
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 Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qaxisaccumulator.h" |
41 | #include "qaxisaccumulator_p.h" |
42 | |
43 | #include <Qt3DInput/qaxis.h> |
44 | #include <Qt3DCore/qnodecreatedchange.h> |
45 | |
46 | QT_BEGIN_NAMESPACE |
47 | |
48 | namespace Qt3DInput { |
49 | |
50 | /*! |
51 | Constructs a new QAxisAccumulator instance with \a parent. |
52 | \class Qt3DInput::QAxisAccumulator |
53 | \inmodule Qt3DInput |
54 | \inherits Qt3DCore::QComponent |
55 | \brief QAxisAccumulator processes velocity or acceleration data from a QAxis. |
56 | \since 5.8 |
57 | |
58 | A Qt3DInput::QAxis reports the current position of an axis on an input |
59 | device. When the axis is returned to its neutral position the value of that |
60 | axis returns to 0. Often, it is required to have the input from an axis |
61 | control a variable in other ways, for example treating the value from the |
62 | Qt3DInput::QAxis as a velocity (first derivative with respect to time) or |
63 | as an acceleration (second derivative with respect to time). This can be |
64 | done with user code or with a Qt3DLogic::QFrameAction but those approached |
65 | are not ideal as they add more work to the main thread and are inherently |
66 | imperative. The Qt3DInput::QAxisAccumulator class allows for this common |
67 | task to be performed on the Qt 3D backend and be specified in a declarative |
68 | manner. |
69 | */ |
70 | |
71 | /*! |
72 | \qmltype AxisAccumulator |
73 | \inqmlmodule Qt3D.Input |
74 | \instantiates Qt3DInput::QAxisAccumulator |
75 | \brief QML frontend for the Qt3DInput::QAxisAccumulator C++ class. |
76 | \since 5.8 |
77 | |
78 | An Axis reports the current position of an axis on an input device. When the |
79 | axis is returned to its neutral position the value of that axis returns to 0. |
80 | Often, it is required to have the input from an axis control a variable in |
81 | other ways, for example treating the value from the Axis as a velocity (first |
82 | derivative with respect to time) or as an acceleration (second derivative with |
83 | respect to time). This can be done with user code or with a FrameAction but |
84 | those approached are not ideal as they add more work to the main thread and |
85 | are inherently imperative. The AxisAccumulator class allows for this common |
86 | task to be performed on the Qt 3D backend and be specified in a declarative |
87 | manner. |
88 | */ |
89 | |
90 | /*! |
91 | \qmlproperty int Qt3D.Input::Axis::value |
92 | \readonly |
93 | |
94 | Holds the value accumulated from the sourceAxis. |
95 | */ |
96 | |
97 | /*! |
98 | * \enum Qt3DInput::QAxisAccumulator::SourceAxisType |
99 | * |
100 | * \value Velocity |
101 | * \value Acceleration |
102 | */ |
103 | |
104 | /*! \internal */ |
105 | QAxisAccumulatorPrivate::QAxisAccumulatorPrivate() |
106 | : Qt3DCore::QComponentPrivate() |
107 | , m_sourceAxis(nullptr) |
108 | , m_sourceAxisType(QAxisAccumulator::Velocity) |
109 | , m_scale(1.0f) |
110 | , m_value(0.0f) |
111 | , m_velocity(0.0f) |
112 | { |
113 | } |
114 | |
115 | /*! \internal */ |
116 | void QAxisAccumulatorPrivate::setValue(float value) |
117 | { |
118 | if (value != m_value) { |
119 | Q_Q(QAxisAccumulator); |
120 | m_value = value; |
121 | const bool wasBlocked = q->blockNotifications(block: true); |
122 | emit q->valueChanged(value: m_value); |
123 | q->blockNotifications(block: wasBlocked); |
124 | } |
125 | } |
126 | |
127 | /*! \internal */ |
128 | void QAxisAccumulatorPrivate::setVelocity(float velocity) |
129 | { |
130 | if (velocity != m_velocity) { |
131 | Q_Q(QAxisAccumulator); |
132 | m_velocity = velocity; |
133 | const bool wasBlocked = q->blockNotifications(block: true); |
134 | emit q->velocityChanged(value: m_velocity); |
135 | q->blockNotifications(block: wasBlocked); |
136 | } |
137 | } |
138 | |
139 | /*! |
140 | Constructs a new QAxisAccumulator instance with parent \a parent. |
141 | */ |
142 | QAxisAccumulator::QAxisAccumulator(Qt3DCore::QNode *parent) |
143 | : Qt3DCore::QComponent(*new QAxisAccumulatorPrivate, parent) |
144 | { |
145 | } |
146 | |
147 | /*! \internal */ |
148 | QAxisAccumulator::~QAxisAccumulator() |
149 | { |
150 | } |
151 | |
152 | /*! |
153 | \qmlproperty Axis Qt3D.Input::AxisAccumulator::sourceAxis |
154 | |
155 | The Axis for which the accumulator should integrate axis values. |
156 | */ |
157 | |
158 | /*! |
159 | \return QAxis for which the accumulator should integrate axis values. |
160 | */ |
161 | QAxis *QAxisAccumulator::sourceAxis() const |
162 | { |
163 | Q_D(const QAxisAccumulator); |
164 | return d->m_sourceAxis; |
165 | } |
166 | |
167 | /*! |
168 | \qmlproperty SourceAxisType Qt3D.Input::AxisAccumulator::sourceAxisType |
169 | |
170 | The sourceAxisType property specifies how the accumulator treats the values |
171 | from the source axis. |
172 | */ |
173 | |
174 | /*! |
175 | \return how the accumulator treats the value of the sourceAxis. |
176 | */ |
177 | QAxisAccumulator::SourceAxisType QAxisAccumulator::sourceAxisType() const |
178 | { |
179 | Q_D(const QAxisAccumulator); |
180 | return d->m_sourceAxisType; |
181 | } |
182 | |
183 | /*! |
184 | \qmlproperty real Qt3D.Input::AxisAccumulator::value |
185 | |
186 | The amount to scale the axis value by when accumulating. This can be |
187 | thought of as the maximum velocity or acceleration the axis can |
188 | control. |
189 | */ |
190 | |
191 | /*! |
192 | \property Qt3DInput::QAxisAccumulator::value |
193 | Returns the accumulated (integrated) value. |
194 | */ |
195 | float QAxisAccumulator::value() const |
196 | { |
197 | Q_D(const QAxisAccumulator); |
198 | return d->m_value; |
199 | } |
200 | |
201 | /*! |
202 | \qmlproperty real Qt3D.Input::Axis::velocity |
203 | \readonly |
204 | |
205 | Returns the velocity. If the sourceAxisType is set to Velocity this is |
206 | simply the value of the source axis multiplied by the scale. If the |
207 | sourceAxisType is set to Acceleration, the velocity is integrated using the |
208 | source axis' value as an acceleration. |
209 | */ |
210 | |
211 | /*! |
212 | Returns the velocity. If the sourceAxisType is set to Velocity this is |
213 | simply the value of the source axis multiplied by the scale. If the |
214 | sourceAxisType is set to Acceleration, the velocity is integrated using |
215 | the source axis' value as an acceleration. |
216 | */ |
217 | float QAxisAccumulator::velocity() const |
218 | { |
219 | Q_D(const QAxisAccumulator); |
220 | return d->m_velocity; |
221 | } |
222 | |
223 | /*! |
224 | \qmlproperty real Qt3D.Input::Axis::scale |
225 | |
226 | The amount to scale the axis value by when accumulating. This can be |
227 | thought of as the maximum velocity or acceleration the axis can |
228 | control. |
229 | */ |
230 | |
231 | /*! |
232 | The amount to scale the axis value by when accumulating. This can be |
233 | thought of as the maximum velocity or acceleration the axis can |
234 | control. |
235 | |
236 | \return the amount the input axis values are scaled by. |
237 | */ |
238 | float QAxisAccumulator::scale() const |
239 | { |
240 | Q_D(const QAxisAccumulator); |
241 | return d->m_scale; |
242 | } |
243 | |
244 | /*! |
245 | Sets the source axis from which the accumulator should receive values from to |
246 | \a sourceAxis. How these values are treated is controlled by the sourceAxisType |
247 | and scale properties. |
248 | */ |
249 | void QAxisAccumulator::setSourceAxis(QAxis *sourceAxis) |
250 | { |
251 | Q_D(QAxisAccumulator); |
252 | if (d->m_sourceAxis == sourceAxis) |
253 | return; |
254 | |
255 | if (d->m_sourceAxis) |
256 | d->unregisterDestructionHelper(node: d->m_sourceAxis); |
257 | |
258 | if (sourceAxis && !sourceAxis->parent()) |
259 | sourceAxis->setParent(this); |
260 | d->m_sourceAxis = sourceAxis; |
261 | |
262 | // Ensures proper bookkeeping |
263 | if (d->m_sourceAxis) |
264 | d->registerDestructionHelper(node: d->m_sourceAxis, func: &QAxisAccumulator::setSourceAxis, d->m_sourceAxis); |
265 | |
266 | emit sourceAxisChanged(sourceAxis); |
267 | } |
268 | |
269 | /*! |
270 | Sets how the accumulator treats the values originating from the \a sourceAxisType. |
271 | */ |
272 | void QAxisAccumulator::setSourceAxisType(QAxisAccumulator::SourceAxisType sourceAxisType) |
273 | { |
274 | Q_D(QAxisAccumulator); |
275 | if (d->m_sourceAxisType == sourceAxisType) |
276 | return; |
277 | |
278 | d->m_sourceAxisType = sourceAxisType; |
279 | emit sourceAxisTypeChanged(sourceAxisType); |
280 | } |
281 | |
282 | void QAxisAccumulator::setScale(float scale) |
283 | { |
284 | Q_D(QAxisAccumulator); |
285 | if (d->m_scale == scale) |
286 | return; |
287 | |
288 | d->m_scale = scale; |
289 | emit scaleChanged(scale); |
290 | } |
291 | |
292 | // TODO Unused remove in Qt6 |
293 | void QAxisAccumulator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) |
294 | { |
295 | } |
296 | |
297 | /*! \internal */ |
298 | Qt3DCore::QNodeCreatedChangeBasePtr QAxisAccumulator::createNodeCreationChange() const |
299 | { |
300 | auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAxisAccumulatorData>::create(arguments: this); |
301 | auto &data = creationChange->data; |
302 | Q_D(const QAxisAccumulator); |
303 | data.sourceAxisId = qIdForNode(node: d->m_sourceAxis); |
304 | data.sourceAxisType = d->m_sourceAxisType; |
305 | data.scale = d->m_scale; |
306 | return creationChange; |
307 | } |
308 | |
309 | } // namespace Qt3DInput |
310 | |
311 | QT_END_NAMESPACE |
312 | |