ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ccGamepadManager.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "ccGamepadManager.h"
9 
10 #include "GamepadInput.h"
11 #include "ecvMainAppInterface.h"
12 #include "ecvPickOneElementDlg.h"
13 
14 // Qt
15 #include <QAction>
16 #include <QGuiApplication>
17 #include <QMainWindow>
18 #include <QMenu>
19 
21  QObject* parent)
22  : QObject(parent),
23  m_appInterface(appInterface),
24  m_gamepadInput(nullptr),
25  m_menu(nullptr),
26  m_actionEnable(nullptr) {
27  setupMenu();
28  setupGamepadInput(); // DGM:at this point we can only init the gamepadInput
29  // structure (Qt will send a signal when the gamepad
30  // is connected - at least from its point of view)
31  enableDevice(true, true); // DGM: but if it's already connected, we'll have
32  // to 'enable' it ourselves
33 }
34 
36  releaseDevice();
37 
38  if (m_menu) {
39  delete m_menu;
40  }
41 }
42 
43 void ccGamepadManager::showMessage(QString message, bool asWarning) {
44  if (!asWarning) {
45  CVLog::Error(message);
46  } else {
47  CVLog::Warning(message);
48  }
49 }
50 
52  bool silent,
53  int deviceID /*=-1*/) {
54  if (!m_gamepadInput) {
55  assert(false);
57  }
58 
59  if (state) {
60  for (int step = 0; step < 1; ++step) // fake loop for easy break
61  {
62  QGamepadManager* manager = QGamepadManager::instance();
63  if (!manager) {
64  showMessage("[Gamepad] Manager is not accessible?!", silent);
65  state = false;
66  break;
67  }
68 
69  if (deviceID < 0) {
70  CVLog::Print("[Gamepad] Looking for connected gamepads...");
71  QList<int> gamepads;
72  for (int i = 0; i < 3; ++i) {
73  QGuiApplication::processEvents();
74  gamepads = manager->connectedGamepads();
75  if (!gamepads.empty()) {
76  break;
77  }
78  }
79 
80  if (gamepads.empty()) {
81  showMessage("[Gamepad] No device registered", silent);
82  state = false;
83  break;
84  } else {
85  CVLog::Print(QString("[Gamepad] Found %1 gamepad(s)")
86  .arg(gamepads.size()));
87  }
88  deviceID = gamepads.front();
89  if (!silent && gamepads.size() > 1) {
90  // ask the user for the right gamepad
91  ccPickOneElementDlg poeDlg(
92  "Gamepad", "Connected gamepads",
93  m_appInterface ? m_appInterface->getMainWindow()
94  : nullptr);
95  for (int id : gamepads) {
96  QString name = QGamepad(id).name();
97  if (name.isEmpty()) {
98  name = QString("Gamepad #%1").arg(id);
99  }
100  poeDlg.addElement(name);
101  }
102  if (!poeDlg.exec()) {
103  return;
104  }
105  deviceID = gamepads[poeDlg.getSelectedIndex()];
106  }
107  }
108 
109  m_gamepadInput->stop(); // just in case
110  m_gamepadInput->setDeviceId(deviceID);
111 
112  if (m_gamepadInput->isConnected()) {
113  CVLog::Print(QString("[Gamepad] Device %1 is now enabled")
114  .arg(deviceID));
115  m_gamepadInput->start();
116  break;
117  } else {
118  showMessage(QString("[Gamepad] Device %1 is not connected")
119  .arg(deviceID),
120  silent);
121  state = false;
122  break;
123  }
124  }
125  } else if (m_gamepadInput) {
126  if (deviceID >= 0 && m_gamepadInput->deviceId() != deviceID) {
127  // this is not the current device?!
128  return;
129  }
130  m_gamepadInput->stop();
131  CVLog::Warning(QString("[Gamepad] Device %1 is now disabled")
132  .arg(m_gamepadInput->deviceId()));
133  }
134 
135  m_actionEnable->blockSignals(true);
136  m_actionEnable->setChecked(state);
137  m_actionEnable->blockSignals(false);
138 }
139 
141  if (m_gamepadInput == nullptr) return;
142 
143  m_gamepadInput->stop(); // disconnect from the driver
144  m_gamepadInput->disconnect(this); // disconnect from Qt ;)
145 
146  delete m_gamepadInput;
147  m_gamepadInput = nullptr;
148 }
149 
151  if (m_gamepadInput) {
152  assert(false);
153  return;
154  }
155 
156  m_gamepadInput = new GamepadInput(this);
157 
158  connect(m_gamepadInput, &GamepadInput::updated, this,
159  &ccGamepadManager::onGamepadInput, Qt::DirectConnection);
160 
161  connect(m_gamepadInput, &GamepadInput::buttonL1Changed, this,
162  [=]() { m_appInterface->decreasePointSize(); });
163  connect(m_gamepadInput, &GamepadInput::buttonR1Changed, this,
164  [=]() { m_appInterface->increasePointSize(); });
165 
166  connect(m_gamepadInput, &GamepadInput::buttonStartChanged, this,
167  [=](bool state) {
168  if (state) {
169  m_appInterface->setGlobalZoom();
170  }
171  });
172  connect(m_gamepadInput, &GamepadInput::buttonAChanged, this,
173  [=](bool state) {
174  if (state) {
176  }
177  });
178  connect(m_gamepadInput, &GamepadInput::buttonBChanged, this,
179  [=](bool state) {
180  if (state) {
181  m_appInterface->toggleActiveWindowCenteredPerspective();
182  }
183  });
184 
185  QGamepadManager* manager = QGamepadManager::instance();
186  if (manager) {
187  connect(manager, &QGamepadManager::gamepadConnected, this,
188  [&](int deviceId) {
189  CVLog::Print(QString("gamepad device %1 has been connected")
190  .arg(deviceId));
191  // auto-enable the device (if none is enabled yet)
192  if (m_actionEnable && !m_actionEnable->isChecked()) {
193  enableDevice(true, true, deviceId);
194  }
195  });
196 
197  connect(manager, &QGamepadManager::gamepadDisconnected, this,
198  [&](int deviceId) {
199  CVLog::Print(
200  QString("gamepad device %1 has been disconnected")
201  .arg(deviceId));
202  // auto-disable the device (if this device is the one
203  // currently enabled)
204  if (m_actionEnable && m_actionEnable->isChecked() &&
205  m_gamepadInput &&
206  m_gamepadInput->deviceId() == deviceId) {
207  enableDevice(false, true, deviceId);
208  }
209  });
210  } else {
211  assert(false);
212  showMessage("[Gamepad] Manager is not accessible?!", true);
213  }
214 }
215 
217  if (!m_menu) {
218  m_menu = new QMenu("Gamepad");
219  m_menu->setIcon(QIcon(":/CC/images/gamepad.png"));
220  }
221 
222  if (!m_actionEnable) {
223  m_actionEnable = new QAction(tr("Enable"), this);
224  m_actionEnable->setCheckable(true);
225 
226  connect(m_actionEnable, &QAction::toggled,
227  [this](bool state) { enableDevice(state, false); });
228 
229  m_menu->addAction(m_actionEnable);
230  }
231 }
232 
234  assert(m_gamepadInput);
235 
236  QMainWindow* win = m_appInterface->getMainWindow();
237  if (win) {
238  m_gamepadInput->update(win);
239  }
240 }
std::string name
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Print(const char *format,...)
Prints out a formatted message in console.
Definition: CVLog.cpp:113
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
Gaempad handler.
Definition: GamepadInput.h:41
void updated()
void update(QMainWindow *win)
Updates a window with the current gamepad state.
void enableDevice(bool state, bool silent, int deviceID=-1)
ccGamepadManager(ecvMainAppInterface *appInterface, QObject *parent)
void showMessage(QString message, bool asWarning)
Minimal dialog to pick one element in a list (combox box)
void addElement(const QString &elementName)
Add an element to the combo box.
int getSelectedIndex()
Returns the combo box current index (after completion)
Main application interface (for plugins)
virtual void toggleActiveWindowCenteredPerspective()=0
virtual void setGlobalZoom()=0
virtual QMainWindow * getMainWindow()=0
Returns main window.
virtual void decreasePointSize()=0
virtual void increasePointSize()=0
virtual void toggleActiveWindowViewerBasedPerspective()=0