all repos — mgba @ 11354ac23ea6cbc41df04f2132e3b44d38c1494a

mGBA Game Boy Advance Emulator

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}