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 "GameController.h"
9#include "GamepadAxisEvent.h"
10#include "InputController.h"
11
12#include <mgba/core/core.h>
13#include <mgba/internal/gba/gba.h>
14
15using namespace QGBA;
16
17SensorView::SensorView(GameController* controller, InputController* input, QWidget* parent)
18 : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
19 , m_controller(controller)
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.timeNoOverride, &QAbstractButton::clicked, controller, &GameController::setRealTime);
30 connect(m_ui.timeFixed, &QRadioButton::clicked, [controller, this] () {
31 controller->setFixedTime(m_ui.time->dateTime());
32 });
33 connect(m_ui.timeFakeEpoch, &QRadioButton::clicked, [controller, this] () {
34 controller->setFakeEpoch(m_ui.time->dateTime());
35 });
36 connect(m_ui.time, &QDateTimeEdit::dateTimeChanged, [controller, this] (const QDateTime&) {
37 m_ui.timeButtons->checkedButton()->clicked();
38 });
39 connect(m_ui.timeNow, &QPushButton::clicked, [controller, this] () {
40 m_ui.time->setDateTime(QDateTime::currentDateTime());
41 });
42
43 connect(m_controller, &GameController::luminanceValueChanged, this, &SensorView::luminanceValueChanged);
44
45 m_timer.setInterval(2);
46 connect(&m_timer, &QTimer::timeout, this, &SensorView::updateSensors);
47 if (!m_rotation || !m_rotation->readTiltX || !m_rotation->readTiltY) {
48 m_ui.tilt->hide();
49 } else {
50 m_timer.start();
51 }
52
53 if (!m_rotation || !m_rotation->readGyroZ) {
54 m_ui.gyro->hide();
55 } else {
56 m_timer.start();
57 }
58
59 jiggerer(m_ui.tiltSetX, &InputController::registerTiltAxisX);
60 jiggerer(m_ui.tiltSetY, &InputController::registerTiltAxisY);
61 jiggerer(m_ui.gyroSetX, &InputController::registerGyroAxisX);
62 jiggerer(m_ui.gyroSetY, &InputController::registerGyroAxisY);
63
64 m_ui.gyroSensitivity->setValue(m_input->gyroSensitivity() / 1e8f);
65 connect(m_ui.gyroSensitivity, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value) {
66 m_input->setGyroSensitivity(value * 1e8f);
67 });
68 m_input->stealFocus(this);
69}
70
71void SensorView::jiggerer(QAbstractButton* button, void (InputController::*setter)(int)) {
72 connect(button, &QAbstractButton::toggled, [this, button, setter](bool checked) {
73 if (!checked) {
74 m_jiggered = nullptr;
75 } else {
76 button->setFocus();
77 m_jiggered = [this, button, setter](int axis) {
78 (m_input->*setter)(axis);
79 button->setChecked(false);
80 button->clearFocus();
81 };
82 }
83 });
84 button->installEventFilter(this);
85}
86
87bool SensorView::event(QEvent* event) {
88 QEvent::Type type = event->type();
89 if (type == QEvent::WindowActivate || type == QEvent::Show) {
90 m_input->stealFocus(this);
91 } else if (type == QEvent::WindowDeactivate || type == QEvent::Hide) {
92 m_input->releaseFocus(this);
93 }
94 return QWidget::event(event);
95}
96
97bool SensorView::eventFilter(QObject*, QEvent* event) {
98 if (event->type() == GamepadAxisEvent::Type()) {
99 GamepadAxisEvent* gae = static_cast<GamepadAxisEvent*>(event);
100 gae->accept();
101 if (m_jiggered && gae->direction() != GamepadAxisEvent::NEUTRAL && gae->isNew()) {
102 m_jiggered(gae->axis());
103 }
104 return true;
105 }
106 return false;
107}
108
109void SensorView::updateSensors() {
110 GameController::Interrupter interrupter(m_controller);
111 if (m_rotation->sample &&
112 (!m_controller->isLoaded() || !(static_cast<GBA*>(m_controller->thread()->core->board)->memory.hw.devices & (HW_GYRO | HW_TILT)))) {
113 m_rotation->sample(m_rotation);
114 m_rotation->sample(m_rotation);
115 m_rotation->sample(m_rotation);
116 m_rotation->sample(m_rotation);
117 m_rotation->sample(m_rotation);
118 m_rotation->sample(m_rotation);
119 m_rotation->sample(m_rotation);
120 m_rotation->sample(m_rotation);
121 }
122 if (m_rotation->readTiltX && m_rotation->readTiltY) {
123 float x = m_rotation->readTiltX(m_rotation);
124 float y = m_rotation->readTiltY(m_rotation);
125 m_ui.tiltX->setValue(x / 469762048.0f); // TODO: Document this value (0xE0 << 21)
126 m_ui.tiltY->setValue(y / 469762048.0f);
127 }
128 if (m_rotation->readGyroZ) {
129 m_ui.gyroView->setValue(m_rotation->readGyroZ(m_rotation));
130 }
131}
132
133void SensorView::setLuminanceValue(int value) {
134 value = std::max(0, std::min(value, 255));
135 m_controller->setLuminanceValue(value);
136}
137
138void SensorView::luminanceValueChanged(int value) {
139 bool oldState;
140 oldState = m_ui.lightSpin->blockSignals(true);
141 m_ui.lightSpin->setValue(value);
142 m_ui.lightSpin->blockSignals(oldState);
143
144 oldState = m_ui.lightSlide->blockSignals(true);
145 m_ui.lightSlide->setValue(value);
146 m_ui.lightSlide->blockSignals(oldState);
147}