all repos — mgba @ 33098926577f52a74730de1708a427e275a9bc88

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 "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}