diff --git a/CHANGES b/CHANGES index f4b19be89..cf6031ce6 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ Features: - Ability to hide individual background layers, or OBJs - Ability to mute individual audio channels + - Palette viewer Bugfixes: - GBA: Fix timers not updating timing when writing to only the reload register - All: Fix sanitize-deb script not cleaning up after itself diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 0f90dc227..7956207a5 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -58,11 +58,13 @@ set(SOURCE_FILES LogView.cpp MultiplayerController.cpp OverrideView.cpp + PaletteView.cpp SavestateButton.cpp SensorView.cpp SettingsView.cpp ShortcutController.cpp ShortcutView.cpp + Swatch.cpp Window.cpp VFileDevice.cpp VideoView.cpp) @@ -73,6 +75,7 @@ qt5_wrap_ui(UI_FILES LoadSaveState.ui LogView.ui OverrideView.ui + PaletteView.ui SensorView.ui SettingsView.ui ShortcutView.ui diff --git a/src/platform/qt/PaletteView.cpp b/src/platform/qt/PaletteView.cpp new file mode 100644 index 000000000..a41732672 --- /dev/null +++ b/src/platform/qt/PaletteView.cpp @@ -0,0 +1,59 @@ +/* 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 "PaletteView.h" + +#include + +using namespace QGBA; + +PaletteView::PaletteView(GameController* controller, QWidget* parent) + : QWidget(parent) + , m_controller(controller) +{ + m_ui.setupUi(this); + + connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(updatePalette())); + m_ui.bgGrid->setDimensions(QSize(16, 16)); + m_ui.objGrid->setDimensions(QSize(16, 16)); + m_ui.selected->setSize(64); + m_ui.selected->setDimensions(QSize(1, 1)); + updatePalette(); + + const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont); + + m_ui.hexcode->setFont(font); + m_ui.value->setFont(font); + m_ui.index->setFont(font); + m_ui.r->setFont(font); + m_ui.g->setFont(font); + m_ui.b->setFont(font); + + connect(m_ui.bgGrid, SIGNAL(indexPressed(int)), this, SLOT(selectIndex(int))); + connect(m_ui.objGrid, &Swatch::indexPressed, [this] (int index) { selectIndex(index + 256); }); +} + +void PaletteView::updatePalette() { + const uint16_t* palette = m_controller->thread()->gba->video.palette; + for (int i = 0; i < 256; ++i) { + m_ui.bgGrid->setColor(i, palette[i]); + m_ui.objGrid->setColor(i, palette[i + 256]); + } +} + +void PaletteView::selectIndex(int index) { + uint16_t color = m_controller->thread()->gba->video.palette[index]; + m_ui.selected->setColor(0, color); + uint32_t r = color & 0x1F; + uint32_t g = (color >> 5) & 0x1F; + uint32_t b = (color >> 10) & 0x1F; + uint32_t hexcode = (r << 19) | (g << 11) | (b << 3); + m_ui.hexcode->setText(tr("#%0").arg(hexcode, 6, 16, QChar('0'))); + m_ui.value->setText(tr("0x%0").arg(color, 4, 16, QChar('0'))); + m_ui.index->setText(tr("%0").arg(index, 3, 10, QChar('0'))); + m_ui.r->setText(tr("0x%0 (%1)").arg(r, 2, 16, QChar('0')).arg(r, 2, 10, QChar('0'))); + m_ui.g->setText(tr("0x%0 (%1)").arg(g, 2, 16, QChar('0')).arg(g, 2, 10, QChar('0'))); + m_ui.b->setText(tr("0x%0 (%1)").arg(b, 2, 16, QChar('0')).arg(b, 2, 10, QChar('0'))); +} diff --git a/src/platform/qt/PaletteView.h b/src/platform/qt/PaletteView.h new file mode 100644 index 000000000..5a4d58252 --- /dev/null +++ b/src/platform/qt/PaletteView.h @@ -0,0 +1,42 @@ +/* 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_PALETTE_VIEW +#define QGBA_PALETTE_VIEW + +#include + +#include "GameController.h" +#include "Swatch.h" + +#include "ui_PaletteView.h" + +class GameController; + +namespace QGBA { + +class Swatch; + +class PaletteView : public QWidget { +Q_OBJECT + +public: + PaletteView(GameController* controller, QWidget* parent = nullptr); + +public slots: + void updatePalette(); + +private slots: + void selectIndex(int); + +private: + Ui::PaletteView m_ui; + + GameController* m_controller; +}; + +} + +#endif diff --git a/src/platform/qt/PaletteView.ui b/src/platform/qt/PaletteView.ui new file mode 100644 index 000000000..79a5c2bec --- /dev/null +++ b/src/platform/qt/PaletteView.ui @@ -0,0 +1,321 @@ + + + PaletteView + + + + 0 + 0 + 452 + 349 + + + + Palette + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Background + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 175 + 175 + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Objects + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 175 + 175 + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Selection + + + + + + + 0 + 0 + + + + + 64 + 64 + + + + + + + + + + + Qt::Vertical + + + + + + + + + Red + + + + + + + Green + + + + + + + Blue + + + + + + + + + 8 + + + + + 0x00 (00) + + + + + + + 0x00 (00) + + + + + + + 0x00 (00) + + + + + + + + + Qt::Vertical + + + + + + + + + 16-bit value + + + + + + + Hex code + + + + + + + Palette index + + + + + + + + + 8 + + + + + 0x0000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + #000000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + QGBA::Swatch + QLabel +
Swatch.h
+
+
+ + +
diff --git a/src/platform/qt/Swatch.cpp b/src/platform/qt/Swatch.cpp new file mode 100644 index 000000000..308bec9cf --- /dev/null +++ b/src/platform/qt/Swatch.cpp @@ -0,0 +1,62 @@ +/* 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 "Swatch.h" + +#include +#include + +using namespace QGBA; + +Swatch::Swatch(QWidget* parent) + : QLabel(parent) +{ + m_size = 10; + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); +} + +void Swatch::setSize(int size) { + m_size = size; + setDimensions(m_dims); +} + +void Swatch::setDimensions(const QSize& size) { + m_dims = size; + m_backing = QPixmap(size * (m_size + 1) - QSize(1, 1)); + m_backing.fill(Qt::transparent); + int elem = size.width() * size.height(); + m_colors.resize(elem); + for (int i = 0; i < elem; ++i) { + updateFill(i); + } +} + +void Swatch::setColor(int index, uint16_t color) { + m_colors[index].setRgb( + (color << 3) & 0xF8, + (color >> 2) & 0xF8, + (color >> 7) & 0xF8); + updateFill(index); +} + +void Swatch::paintEvent(QPaintEvent* event) { + setPixmap(m_backing); + QLabel::paintEvent(event); +} + +void Swatch::mousePressEvent(QMouseEvent* event) { + int x = event->x() / (m_size + 1); + int y = event->y() / (m_size + 1); + emit indexPressed(y * m_dims.width() + x); +} + +void Swatch::updateFill(int index) { + QPainter painter(&m_backing); + int x = index % m_dims.width(); + int y = index / m_dims.width(); + QRect r(x * (m_size + 1), y * (m_size + 1), m_size, m_size); + painter.fillRect(r, m_colors[index]); + update(r); +} diff --git a/src/platform/qt/Swatch.h b/src/platform/qt/Swatch.h new file mode 100644 index 000000000..5a84c3c38 --- /dev/null +++ b/src/platform/qt/Swatch.h @@ -0,0 +1,45 @@ +/* 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_SWATCH +#define QGBA_SWATCH + +#include +#include +#include + +namespace QGBA { + +class Swatch : public QLabel { +Q_OBJECT + +public: + Swatch(QWidget* parent = nullptr); + + void setDimensions(const QSize&); + void setSize(int size); + +public slots: + void setColor(int index, uint16_t); + +signals: + void indexPressed(int index); + +protected: + void paintEvent(QPaintEvent*) override; + void mousePressEvent(QMouseEvent*) override; + +private: + int m_size; + QVector m_colors; + QPixmap m_backing; + QSize m_dims; + + void updateFill(int index); +}; + +} + +#endif diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 762404ff1..84c52ae6d 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -27,6 +27,7 @@ #include "LogView.h" #include "MultiplayerController.h" #include "OverrideView.h" +#include "PaletteView.h" #include "SensorView.h" #include "SettingsView.h" #include "ShortcutController.h" @@ -286,6 +287,11 @@ void Window::openCheatsWindow() { openView(cheatsWindow); } +void Window::openPaletteWindow() { + PaletteView* paletteWindow = new PaletteView(m_controller); + openView(paletteWindow); +} + #ifdef BUILD_SDL void Window::openGamepadWindow() { const char* profile = m_inputController.profileForType(SDL_BINDING_BUTTON); @@ -873,6 +879,13 @@ void Window::setupMenu(QMenuBar* menubar) { addControlledAction(toolsMenu, gamepad, "remapGamepad"); #endif + toolsMenu->addSeparator(); + + QAction* paletteView = new QAction(tr("View &palette..."), toolsMenu); + connect(paletteView, SIGNAL(triggered()), this, SLOT(openPaletteWindow())); + m_gameActions.append(paletteView); + addControlledAction(toolsMenu, paletteView, "paletteWindow"); + ConfigOption* skipBios = m_config->addOption("skipBios"); skipBios->connect([this](const QVariant& value) { m_controller->setSkipBIOS(value.toBool()); diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index 73a17744d..2cbaa960b 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -73,6 +73,8 @@ public slots: void openSensorWindow(); void openCheatsWindow(); + void openPaletteWindow(); + #ifdef BUILD_SDL void openGamepadWindow(); #endif