diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index fcbeb204b..577a343b1 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -67,6 +67,7 @@ set(SOURCE_FILES LogView.cpp MemoryModel.cpp MemoryView.cpp + MessagePainter.cpp MultiplayerController.cpp OverrideView.cpp PaletteView.cpp diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 94f80b1ff..532c4c05a 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -135,8 +135,8 @@ void DisplayGL::resizePainter() { PainterGL::PainterGL(QGLWidget* parent) : m_gl(parent) , m_active(false) - , m_messageTimer(this) , m_context(nullptr) + , m_messagePainter(nullptr) { GBAGLContextCreate(&m_backend); m_backend.d.swap = [](VideoBackend* v) { @@ -146,14 +146,6 @@ PainterGL::PainterGL(QGLWidget* parent) m_backend.d.user = this; m_backend.d.filter = false; m_backend.d.lockAspectRatio = false; - m_messageFont.setFamily("Source Code Pro"); - m_messageFont.setStyleHint(QFont::Monospace); - m_messageFont.setPixelSize(13); - connect(&m_messageTimer, SIGNAL(timeout()), this, SLOT(clearMessage())); - m_messageTimer.setSingleShot(true); - m_messageTimer.setInterval(5000); - - clearMessage(); } void PainterGL::setContext(GBAThread* context) { @@ -171,22 +163,8 @@ void PainterGL::setBacking(const uint32_t* backing) { void PainterGL::resize(const QSize& size) { m_size = size; - int w = m_size.width(); - int h = m_size.height(); - int drawW = w; - int drawH = h; - if (m_backend.d.lockAspectRatio) { - if (w * 2 > h * 3) { - drawW = h * 3 / 2; - } else if (w * 2 < h * 3) { - drawH = w * 2 / 3; - } - } - m_world.reset(); - m_world.translate((w - drawW) / 2, (h - drawH) / 2); - m_world.scale(qreal(drawW) / VIDEO_HORIZONTAL_PIXELS, qreal(drawH) / VIDEO_VERTICAL_PIXELS); - m_message.prepare(m_world, m_messageFont); if (m_active) { + m_messagePainter->resize(size, m_backend.d.lockAspectRatio); forceDraw(); } } @@ -194,6 +172,7 @@ void PainterGL::resize(const QSize& size) { void PainterGL::lockAspectRatio(bool lock) { m_backend.d.lockAspectRatio = lock; if (m_active) { + m_messagePainter->resize(m_size, m_backend.d.lockAspectRatio); forceDraw(); } } @@ -206,6 +185,8 @@ void PainterGL::filter(bool filter) { } void PainterGL::start() { + m_messagePainter = new MessagePainter(this); + m_messagePainter->resize(m_size, m_backend.d.lockAspectRatio); m_gl->makeCurrent(); m_backend.d.init(&m_backend.d, reinterpret_cast(m_gl->winId())); m_gl->doneCurrent(); @@ -239,6 +220,9 @@ void PainterGL::stop() { m_backend.d.deinit(&m_backend.d); m_gl->doneCurrent(); m_gl->context()->moveToThread(m_gl->thread()); + m_messagePainter->clearMessage(); + delete m_messagePainter; + m_messagePainter = nullptr; moveToThread(m_gl->thread()); } @@ -259,28 +243,9 @@ void PainterGL::performDraw() { m_backend.d.resized(&m_backend.d, m_size.width() * r, m_size.height() * r); m_backend.d.drawFrame(&m_backend.d); m_painter.endNativePainting(); - m_painter.setWorldTransform(m_world); - m_painter.setRenderHint(QPainter::Antialiasing); - m_painter.setFont(m_messageFont); - m_painter.setPen(Qt::black); - m_painter.translate(1, VIDEO_VERTICAL_PIXELS - m_messageFont.pixelSize() - 1); - for (int i = 0; i < 16; ++i) { - m_painter.save(); - m_painter.translate(cos(i * M_PI / 8.0) * 0.8, sin(i * M_PI / 8.0) * 0.8); - m_painter.drawStaticText(0, 0, m_message); - m_painter.restore(); - } - m_painter.setPen(Qt::white); - m_painter.drawStaticText(0, 0, m_message); + m_messagePainter->paint(&m_painter); } void PainterGL::showMessage(const QString& message) { - m_message.setText(message); - m_message.prepare(m_world, m_messageFont); - m_messageTimer.stop(); - m_messageTimer.start(); -} - -void PainterGL::clearMessage() { - m_message.setText(QString()); + m_messagePainter->showMessage(message); } diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index edf84dcf3..16c7a1d0c 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -8,8 +8,9 @@ #include "Display.h" +#include "MessagePainter.h" + #include -#include #include #include @@ -86,21 +87,17 @@ public slots: void filter(bool filter); void showMessage(const QString& message); - void clearMessage(); private: void performDraw(); QPainter m_painter; - QStaticText m_message; QGLWidget* m_gl; bool m_active; - QTimer m_messageTimer; GBAThread* m_context; GBAGLContext m_backend; QSize m_size; - QTransform m_world; - QFont m_messageFont; + MessagePainter* m_messagePainter; }; } diff --git a/src/platform/qt/DisplayQt.cpp b/src/platform/qt/DisplayQt.cpp index bb5679f50..438c44e47 100644 --- a/src/platform/qt/DisplayQt.cpp +++ b/src/platform/qt/DisplayQt.cpp @@ -46,6 +46,10 @@ void DisplayQt::framePosted(const uint32_t* buffer) { #endif } +void DisplayQt::showMessage(const QString& message) { + m_messagePainter.showMessage(message); +} + void DisplayQt::paintEvent(QPaintEvent*) { QPainter painter(this); painter.fillRect(QRect(QPoint(), size()), Qt::black); @@ -54,10 +58,12 @@ void DisplayQt::paintEvent(QPaintEvent*) { } QSize s = size(); QSize ds = s; - if (s.width() * 2 > s.height() * 3) { - ds.setWidth(s.height() * 3 / 2); - } else if (s.width() * 2 < s.height() * 3) { - ds.setHeight(s.width() * 2 / 3); + if (m_lockAspectRatio) { + if (s.width() * 2 > s.height() * 3) { + ds.setWidth(s.height() * 3 / 2); + } else if (s.width() * 2 < s.height() * 3) { + ds.setHeight(s.width() * 2 / 3); + } } QPoint origin = QPoint((s.width() - ds.width()) / 2, (s.height() - ds.height()) / 2); QRect full(origin, ds); @@ -67,4 +73,9 @@ void DisplayQt::paintEvent(QPaintEvent*) { #else painter.drawImage(full, m_backing.rgbSwapped(), QRect(0, 0, 240, 160)); #endif + m_messagePainter.paint(&painter); +} + +void DisplayQt::resizeEvent(QResizeEvent*) { + m_messagePainter.resize(size(), m_lockAspectRatio); } diff --git a/src/platform/qt/DisplayQt.h b/src/platform/qt/DisplayQt.h index 999a79652..e10b13b08 100644 --- a/src/platform/qt/DisplayQt.h +++ b/src/platform/qt/DisplayQt.h @@ -7,6 +7,7 @@ #define QGBA_DISPLAY_QT #include "Display.h" +#include "MessagePainter.h" #include #include @@ -31,15 +32,17 @@ public slots: void filter(bool filter) override; void framePosted(const uint32_t*) override; - void showMessage(const QString& message) override {}; + void showMessage(const QString& message) override; protected: virtual void paintEvent(QPaintEvent*) override; + virtual void resizeEvent(QResizeEvent*) override;; private: QImage m_backing; bool m_lockAspectRatio; bool m_filter; + MessagePainter m_messagePainter; }; } diff --git a/src/platform/qt/MessagePainter.cpp b/src/platform/qt/MessagePainter.cpp new file mode 100644 index 000000000..a7dc53710 --- /dev/null +++ b/src/platform/qt/MessagePainter.cpp @@ -0,0 +1,77 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "MessagePainter.h" + +#include + +#include + +extern "C" { +#include "gba/video.h" +} + +using namespace QGBA; + +MessagePainter::MessagePainter(QObject* parent) + : QObject(parent) + , m_messageTimer(this) +{ + m_messageFont.setFamily("Source Code Pro"); + m_messageFont.setStyleHint(QFont::Monospace); + m_messageFont.setPixelSize(13); + connect(&m_messageTimer, SIGNAL(timeout()), this, SLOT(clearMessage())); + m_messageTimer.setSingleShot(true); + m_messageTimer.setInterval(5000); + + clearMessage(); +} + +void MessagePainter::resize(const QSize& size, bool lockAspectRatio) { + int w = size.width(); + int h = size.height(); + int drawW = w; + int drawH = h; + if (lockAspectRatio) { + if (w * 2 > h * 3) { + drawW = h * 3 / 2; + } else if (w * 2 < h * 3) { + drawH = w * 2 / 3; + } + } + m_world.reset(); + m_world.translate((w - drawW) / 2, (h - drawH) / 2); + m_world.scale(qreal(drawW) / VIDEO_HORIZONTAL_PIXELS, qreal(drawH) / VIDEO_VERTICAL_PIXELS); + m_message.prepare(m_world, m_messageFont); +} + +void MessagePainter::paint(QPainter* painter) { + painter->setWorldTransform(m_world); + painter->setRenderHint(QPainter::Antialiasing); + painter->setFont(m_messageFont); + painter->setPen(Qt::black); + painter->translate(1, VIDEO_VERTICAL_PIXELS - m_messageFont.pixelSize() - 1); + const static int ITERATIONS = 11; + for (int i = 0; i < ITERATIONS; ++i) { + painter->save(); + painter->translate(cos(i * 2.0 * M_PI / ITERATIONS) * 0.8, sin(i * 2.0 * M_PI / ITERATIONS) * 0.8); + painter->drawStaticText(0, 0, m_message); + painter->restore(); + } + painter->setPen(Qt::white); + painter->drawStaticText(0, 0, m_message); +} + +void MessagePainter::showMessage(const QString& message) { + m_message.setText(message); + m_message.prepare(m_world, m_messageFont); + m_messageTimer.stop(); + m_messageTimer.start(); +} + +void MessagePainter::clearMessage() { + m_message.setText(QString()); + m_messageTimer.stop(); +} diff --git a/src/platform/qt/MessagePainter.h b/src/platform/qt/MessagePainter.h new file mode 100644 index 000000000..d0be66bbd --- /dev/null +++ b/src/platform/qt/MessagePainter.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef QGBA_MESSAGE_PAINTER +#define QGBA_MESSAGE_PAINTER + +#include +#include +#include + +namespace QGBA { + +class MessagePainter : public QObject { +Q_OBJECT + +public: + MessagePainter(QObject* parent = nullptr); + + void resize(const QSize& size, bool lockAspectRatio); + void paint(QPainter* painter); + +public slots: + void showMessage(const QString& message); + void clearMessage(); + +private: + QStaticText m_message; + QTimer m_messageTimer; + QTransform m_world; + QFont m_messageFont; +}; + +} + +#endif