all repos — mgba @ 4cb243f15c011264e3b4e84100f6e4a050c4a623

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