1// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qaxisaccumulator.h"
5#include "qaxisaccumulator_p.h"
6
7#include <Qt3DInput/qaxis.h>
8
9QT_BEGIN_NAMESPACE
10
11namespace Qt3DInput {
12
13/*!
14 Constructs a new QAxisAccumulator instance with \a parent.
15 \class Qt3DInput::QAxisAccumulator
16 \inmodule Qt3DInput
17 \inherits Qt3DCore::QComponent
18 \brief QAxisAccumulator processes velocity or acceleration data from a QAxis.
19 \since 5.8
20
21 A Qt3DInput::QAxis reports the current position of an axis on an input
22 device. When the axis is returned to its neutral position the value of that
23 axis returns to 0. Often, it is required to have the input from an axis
24 control a variable in other ways, for example treating the value from the
25 Qt3DInput::QAxis as a velocity (first derivative with respect to time) or
26 as an acceleration (second derivative with respect to time). This can be
27 done with user code or with a Qt3DLogic::QFrameAction but those approached
28 are not ideal as they add more work to the main thread and are inherently
29 imperative. The Qt3DInput::QAxisAccumulator class allows for this common
30 task to be performed on the Qt 3D backend and be specified in a declarative
31 manner.
32*/
33
34/*!
35 \qmltype AxisAccumulator
36 \inqmlmodule Qt3D.Input
37 \instantiates Qt3DInput::QAxisAccumulator
38 \brief QML frontend for the Qt3DInput::QAxisAccumulator C++ class.
39 \since 5.8
40
41 An Axis reports the current position of an axis on an input device. When the
42 axis is returned to its neutral position the value of that axis returns to 0.
43 Often, it is required to have the input from an axis control a variable in
44 other ways, for example treating the value from the Axis as a velocity (first
45 derivative with respect to time) or as an acceleration (second derivative with
46 respect to time). This can be done with user code or with a FrameAction but
47 those approached are not ideal as they add more work to the main thread and
48 are inherently imperative. The AxisAccumulator class allows for this common
49 task to be performed on the Qt 3D backend and be specified in a declarative
50 manner.
51*/
52
53/*!
54 \qmlproperty int Qt3D.Input::Axis::value
55 \readonly
56
57 Holds the value accumulated from the sourceAxis.
58*/
59
60/*!
61 * \enum Qt3DInput::QAxisAccumulator::SourceAxisType
62 *
63 * \value Velocity
64 * \value Acceleration
65 */
66
67/*! \internal */
68QAxisAccumulatorPrivate::QAxisAccumulatorPrivate()
69 : Qt3DCore::QComponentPrivate()
70 , m_sourceAxis(nullptr)
71 , m_sourceAxisType(QAxisAccumulator::Velocity)
72 , m_scale(1.0f)
73 , m_value(0.0f)
74 , m_velocity(0.0f)
75{
76}
77
78/*! \internal */
79void QAxisAccumulatorPrivate::setValue(float value)
80{
81 if (value != m_value) {
82 Q_Q(QAxisAccumulator);
83 m_value = value;
84 const bool wasBlocked = q->blockNotifications(block: true);
85 emit q->valueChanged(value: m_value);
86 q->blockNotifications(block: wasBlocked);
87 }
88}
89
90/*! \internal */
91void QAxisAccumulatorPrivate::setVelocity(float velocity)
92{
93 if (velocity != m_velocity) {
94 Q_Q(QAxisAccumulator);
95 m_velocity = velocity;
96 const bool wasBlocked = q->blockNotifications(block: true);
97 emit q->velocityChanged(value: m_velocity);
98 q->blockNotifications(block: wasBlocked);
99 }
100}
101
102/*!
103 Constructs a new QAxisAccumulator instance with parent \a parent.
104 */
105QAxisAccumulator::QAxisAccumulator(Qt3DCore::QNode *parent)
106 : Qt3DCore::QComponent(*new QAxisAccumulatorPrivate, parent)
107{
108}
109
110/*! \internal */
111QAxisAccumulator::~QAxisAccumulator()
112{
113}
114
115/*!
116 \qmlproperty Axis Qt3D.Input::AxisAccumulator::sourceAxis
117
118 The Axis for which the accumulator should integrate axis values.
119 */
120
121/*!
122 \return QAxis for which the accumulator should integrate axis values.
123 */
124QAxis *QAxisAccumulator::sourceAxis() const
125{
126 Q_D(const QAxisAccumulator);
127 return d->m_sourceAxis;
128}
129
130/*!
131 \qmlproperty SourceAxisType Qt3D.Input::AxisAccumulator::sourceAxisType
132
133 The sourceAxisType property specifies how the accumulator treats the values
134 from the source axis.
135 */
136
137/*!
138 \return how the accumulator treats the value of the sourceAxis.
139 */
140QAxisAccumulator::SourceAxisType QAxisAccumulator::sourceAxisType() const
141{
142 Q_D(const QAxisAccumulator);
143 return d->m_sourceAxisType;
144}
145
146/*!
147 \qmlproperty real Qt3D.Input::AxisAccumulator::value
148
149 The amount to scale the axis value by when accumulating. This can be
150 thought of as the maximum velocity or acceleration the axis can
151 control.
152 */
153
154/*!
155 \property Qt3DInput::QAxisAccumulator::value
156 Returns the accumulated (integrated) value.
157 */
158float QAxisAccumulator::value() const
159{
160 Q_D(const QAxisAccumulator);
161 return d->m_value;
162}
163
164/*!
165 \qmlproperty real Qt3D.Input::Axis::velocity
166 \readonly
167
168 Returns the velocity. If the sourceAxisType is set to Velocity this is
169 simply the value of the source axis multiplied by the scale. If the
170 sourceAxisType is set to Acceleration, the velocity is integrated using the
171 source axis' value as an acceleration.
172*/
173
174/*!
175 Returns the velocity. If the sourceAxisType is set to Velocity this is
176 simply the value of the source axis multiplied by the scale. If the
177 sourceAxisType is set to Acceleration, the velocity is integrated using
178 the source axis' value as an acceleration.
179 */
180float QAxisAccumulator::velocity() const
181{
182 Q_D(const QAxisAccumulator);
183 return d->m_velocity;
184}
185
186/*!
187 \qmlproperty real Qt3D.Input::Axis::scale
188
189 The amount to scale the axis value by when accumulating. This can be
190 thought of as the maximum velocity or acceleration the axis can
191 control.
192*/
193
194/*!
195 The amount to scale the axis value by when accumulating. This can be
196 thought of as the maximum velocity or acceleration the axis can
197 control.
198
199 \return the amount the input axis values are scaled by.
200 */
201float QAxisAccumulator::scale() const
202{
203 Q_D(const QAxisAccumulator);
204 return d->m_scale;
205}
206
207/*!
208 Sets the source axis from which the accumulator should receive values from to
209 \a sourceAxis. How these values are treated is controlled by the sourceAxisType
210 and scale properties.
211 */
212void QAxisAccumulator::setSourceAxis(QAxis *sourceAxis)
213{
214 Q_D(QAxisAccumulator);
215 if (d->m_sourceAxis == sourceAxis)
216 return;
217
218 if (d->m_sourceAxis)
219 d->unregisterDestructionHelper(node: d->m_sourceAxis);
220
221 if (sourceAxis && !sourceAxis->parent())
222 sourceAxis->setParent(this);
223 d->m_sourceAxis = sourceAxis;
224
225 // Ensures proper bookkeeping
226 if (d->m_sourceAxis)
227 d->registerDestructionHelper(node: d->m_sourceAxis, func: &QAxisAccumulator::setSourceAxis, d->m_sourceAxis);
228
229 emit sourceAxisChanged(sourceAxis);
230}
231
232/*!
233 Sets how the accumulator treats the values originating from the \a sourceAxisType.
234 */
235void QAxisAccumulator::setSourceAxisType(QAxisAccumulator::SourceAxisType sourceAxisType)
236{
237 Q_D(QAxisAccumulator);
238 if (d->m_sourceAxisType == sourceAxisType)
239 return;
240
241 d->m_sourceAxisType = sourceAxisType;
242 emit sourceAxisTypeChanged(sourceAxisType);
243}
244
245void QAxisAccumulator::setScale(float scale)
246{
247 Q_D(QAxisAccumulator);
248 if (d->m_scale == scale)
249 return;
250
251 d->m_scale = scale;
252 emit scaleChanged(scale);
253}
254
255} // namespace Qt3DInput
256
257QT_END_NAMESPACE
258
259#include "moc_qaxisaccumulator.cpp"
260

source code of qt3d/src/input/frontend/qaxisaccumulator.cpp