src/platform/qt/SensorView.cpp (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "SensorView.h"
7
8#include "CoreController.h"
9#include "GamepadAxisEvent.h"
10#include "InputController.h"
11#include "utils.h"
12
13#include <mgba/core/core.h>
14#include <mgba/internal/gba/gba.h>
15
16using namespace QGBA;
17
18SensorView::SensorView(InputController* input, QWidget* parent)
19 : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
20 , m_input(input)
21 , m_rotation(input->rotationSource())
22 {
23 m_ui.setupUi(this);
24
25 connect(m_ui.lightSpin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
26 this, &SensorView::setLuminanceValue);
27 connect(m_ui.lightSlide, &QAbstractSlider::valueChanged, this, &SensorView::setLuminanceValue);
28
29 connect(m_ui.time, &QDateTimeEdit::dateTimeChanged, [this] (const QDateTime&) {
30 m_ui.timeButtons->checkedButton()->clicked();
31 });
32 connect(m_ui.timeNow, &QPushButton::clicked, [this] () {
33 m_ui.time->setDateTime(QDateTime::currentDateTime());
34 });
35
36 m_timer.setInterval(15);
37 connect(&m_timer, &QTimer::timeout, this, &SensorView::updateSensors);
38 if (!m_rotation || !m_rotation->readTiltX || !m_rotation->readTiltY) {
39 m_ui.tilt->hide();
40 } else {
41 m_timer.start();
42 }
43
44 if (!m_rotation || !m_rotation->readGyroZ) {
45 m_ui.gyro->hide();
46 } else {
47 m_timer.start();
48 }
49
50 jiggerer(m_ui.tiltSetX, &InputController::registerTiltAxisX);
51 jiggerer(m_ui.tiltSetY, &InputController::registerTiltAxisY);
52 jiggerer(m_ui.gyroSetX, &InputController::registerGyroAxisX);
53 jiggerer(m_ui.gyroSetY, &InputController::registerGyroAxisY);
54
55 m_ui.gyroSensitivity->setValue(m_input->gyroSensitivity() / 1e8f);
56 connect(m_ui.gyroSensitivity, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value) {
57 m_input->setGyroSensitivity(value * 1e8f);
58 });
59 m_input->stealFocus(this);
60 connect(m_input, &InputController::luminanceValueChanged, this, &SensorView::luminanceValueChanged);
61}
62
63void SensorView::setController(std::shared_ptr<CoreController> controller) {
64 m_controller = controller;
65 connect(m_ui.timeNoOverride, &QAbstractButton::clicked, controller.get(), &CoreController::setRealTime);
66 connect(m_ui.timeFixed, &QRadioButton::clicked, [controller, this] () {
67 controller->setFixedTime(m_ui.time->dateTime().toUTC());
68 });
69 connect(m_ui.timeFakeEpoch, &QRadioButton::clicked, [controller, this] () {
70 controller->setFakeEpoch(m_ui.time->dateTime().toUTC());
71 });
72 m_ui.timeButtons->checkedButton()->clicked();
73
74 connect(controller.get(), &CoreController::stopping, [this]() {
75 m_controller.reset();
76 });
77}
78
79void SensorView::jiggerer(QAbstractButton* button, void (InputController::*setter)(int)) {
80 connect(button, &QAbstractButton::toggled, [this, button, setter](bool checked) {
81 if (!checked) {
82 m_jiggered = nullptr;
83 } else {
84 button->setFocus();
85 m_jiggered = [this, button, setter](int axis) {
86 (m_input->*setter)(axis);
87 button->setChecked(false);
88 button->clearFocus();
89 };
90 }
91 });
92 button->installEventFilter(this);
93}
94
95bool SensorView::event(QEvent* event) {
96 QEvent::Type type = event->type();
97 if (type == QEvent::WindowActivate || type == QEvent::Show) {
98 m_input->stealFocus(this);
99 } else if (type == QEvent::WindowDeactivate || type == QEvent::Hide) {
100 m_input->releaseFocus(this);
101 }
102 return QWidget::event(event);
103}
104
105bool SensorView::eventFilter(QObject*, QEvent* event) {
106 if (event->type() == GamepadAxisEvent::Type()) {
107 GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);
108 gae->accept();
109 if (m_jiggered && gae->direction() != GamepadAxisEvent::NEUTRAL && gae->isNew()) {
110 m_jiggered(gae->axis());
111 }
112 return true;
113 }
114 return false;
115}
116
117void SensorView::updateSensors() {
118 if (m_rotation->sample && (!m_controller || m_controller->isPaused())) {
119 m_rotation->sample(m_rotation);
120 }
121 if (m_rotation->readTiltX && m_rotation->readTiltY) {
122 float x = m_rotation->readTiltX(m_rotation);
123 float y = m_rotation->readTiltY(m_rotation);
124 m_ui.tiltX->setValue(x / 469762048.0f); // TODO: Document this value (0xE0 << 21)
125 m_ui.tiltY->setValue(y / 469762048.0f);
126 }
127 if (m_rotation->readGyroZ) {
128 m_ui.gyroView->setValue(m_rotation->readGyroZ(m_rotation));
129 }
130}
131
132void SensorView::setLuminanceValue(int value) {
133 value = clamp(value, 0, 255);
134 if (m_input) {
135 m_input->setLuminanceValue(value);
136 }
137}
138
139void SensorView::luminanceValueChanged(int value) {
140 bool oldState;
141 oldState = m_ui.lightSpin->blockSignals(true);
142 m_ui.lightSpin->setValue(value);
143 m_ui.lightSpin->blockSignals(oldState);
144
145 oldState = m_ui.lightSlide->blockSignals(true);
146 m_ui.lightSlide->setValue(value);
147 m_ui.lightSlide->blockSignals(oldState);
148}