1// Copyright (C) 2015 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 "updateaxisactionjob_p.h"
5#include <Qt3DCore/private/qaspectmanager_p.h>
6#include <Qt3DInput/qaction.h>
7#include <Qt3DInput/qaxis.h>
8#include <Qt3DInput/private/qaction_p.h>
9#include <Qt3DInput/private/qaxis_p.h>
10#include <Qt3DInput/private/inputhandler_p.h>
11#include <Qt3DInput/private/inputmanagers_p.h>
12#include <Qt3DInput/private/job_common_p.h>
13
14QT_BEGIN_NAMESPACE
15
16namespace Qt3DInput {
17
18namespace Input {
19
20class UpdateAxisActionJobPrivate : public Qt3DCore::QAspectJobPrivate
21{
22public:
23 UpdateAxisActionJobPrivate() { }
24 ~UpdateAxisActionJobPrivate() override { }
25
26 void postFrame(Qt3DCore::QAspectManager *manager) override;
27
28 QList<QPair<Qt3DCore::QNodeId, bool>> m_triggeredActions;
29 QList<QPair<Qt3DCore::QNodeId, float>> m_triggeredAxis;
30};
31
32UpdateAxisActionJob::UpdateAxisActionJob(qint64 currentTime, InputHandler *handler, HLogicalDevice handle)
33 : Qt3DCore::QAspectJob(*new UpdateAxisActionJobPrivate())
34 , m_currentTime(currentTime)
35 , m_handler(handler)
36 , m_handle(handle)
37{
38 SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateAxisAction, 0)
39}
40
41void UpdateAxisActionJob::run()
42{
43 // Note: we assume axis/action are not really shared:
44 // there's no benefit in sharing those when it comes to computing
45 LogicalDevice *device = m_handler->logicalDeviceManager()->data(handle: m_handle);
46
47 if (!device->isEnabled())
48 return;
49
50 updateAction(device);
51 updateAxis(device);
52}
53
54void UpdateAxisActionJob::updateAction(LogicalDevice *device)
55{
56 Q_D(UpdateAxisActionJob);
57 const auto actionIds = device->actions();
58 d->m_triggeredActions.reserve(asize: actionIds.size());
59
60 for (const Qt3DCore::QNodeId &actionId : actionIds) {
61 bool actionTriggered = false;
62 Action *action = m_handler->actionManager()->lookupResource(id: actionId);
63
64 const auto actionInputIds = action->inputs();
65 for (const Qt3DCore::QNodeId &actionInputId : actionInputIds)
66 actionTriggered |= processActionInput(actionInputId);
67
68 if (action->isEnabled() && (action->actionTriggered() != actionTriggered)) {
69 action->setActionTriggered(actionTriggered);
70 d->m_triggeredActions.push_back(t: {actionId, actionTriggered});
71 }
72 }
73}
74
75bool UpdateAxisActionJob::processActionInput(const Qt3DCore::QNodeId actionInputId)
76{
77 AbstractActionInput *actionInput = m_handler->lookupActionInput(id: actionInputId);
78 Q_ASSERT(actionInput);
79 return actionInput->process(inputHandler: m_handler, currentTime: m_currentTime);
80}
81
82void UpdateAxisActionJob::updateAxis(LogicalDevice *device)
83{
84 Q_D(UpdateAxisActionJob);
85 const auto axisIds = device->axes();
86 d->m_triggeredAxis.reserve(asize: axisIds.size());
87
88 for (const Qt3DCore::QNodeId &axisId : axisIds) {
89 Axis *axis = m_handler->axisManager()->lookupResource(id: axisId);
90 float axisValue = 0.0f;
91
92 const auto axisInputIds = axis->inputs();
93 for (const Qt3DCore::QNodeId &axisInputId : axisInputIds)
94 axisValue += processAxisInput(axisInputId);
95
96 // Clamp the axisValue -1/1
97 axisValue = qMin(a: 1.0f, b: qMax(a: axisValue, b: -1.0f));
98
99 if (axis->isEnabled() && !qFuzzyCompare(p1: axisValue, p2: axis->axisValue())) {
100 axis->setAxisValue(axisValue);
101 d->m_triggeredAxis.push_back(t: {axisId, axisValue});
102 }
103 }
104}
105
106float UpdateAxisActionJob::processAxisInput(const Qt3DCore::QNodeId axisInputId)
107{
108 AnalogAxisInput *analogInput = m_handler->analogAxisInputManager()->lookupResource(id: axisInputId);
109 if (analogInput)
110 return analogInput->process(inputHandler: m_handler, currentTime: m_currentTime);
111
112 ButtonAxisInput *buttonInput = m_handler->buttonAxisInputManager()->lookupResource(id: axisInputId);
113 if (buttonInput)
114 return buttonInput->process(inputHandler: m_handler, currentTime: m_currentTime);
115
116 Q_UNREACHABLE_RETURN(0.0f);
117}
118
119void UpdateAxisActionJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
120{
121 for (const auto &data: std::as_const(t&: m_triggeredActions)) {
122 Qt3DInput::QAction *action = qobject_cast<Qt3DInput::QAction *>(object: manager->lookupNode(id: data.first));
123 if (!action)
124 continue;
125
126 Qt3DInput::QActionPrivate *daction = static_cast<Qt3DInput::QActionPrivate *>(Qt3DCore::QNodePrivate::get(q: action));
127 daction->setActive(data.second);
128 }
129
130 for (const auto &data: std::as_const(t&: m_triggeredAxis)) {
131 Qt3DInput::QAxis *axis = qobject_cast<Qt3DInput::QAxis *>(object: manager->lookupNode(id: data.first));
132 if (!axis)
133 continue;
134
135 Qt3DInput::QAxisPrivate *daxis = static_cast<Qt3DInput::QAxisPrivate *>(Qt3DCore::QNodePrivate::get(q: axis));
136 daxis->setValue(data.second);
137 }
138
139 m_triggeredActions.clear();
140 m_triggeredAxis.clear();
141}
142
143} // Input
144
145} // Qt3DInput
146
147QT_END_NAMESPACE
148

source code of qt3d/src/input/backend/updateaxisactionjob.cpp