Qt: Palette viewer

This commit is contained in:
Jeffrey Pfau 2015-04-05 23:46:48 -07:00
parent 97479c4d00
commit cda804656b
9 changed files with 548 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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 <QFontDatabase>
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')));
}

View File

@ -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 <QWidget>
#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

View File

@ -0,0 +1,321 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PaletteView</class>
<widget class="QWidget" name="PaletteView">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>452</width>
<height>349</height>
</rect>
</property>
<property name="windowTitle">
<string>Palette</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Background</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGBA::Swatch" name="bgGrid">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>175</width>
<height>175</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Objects</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGBA::Swatch" name="objGrid">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>175</width>
<height>175</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Selection</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QGBA::Swatch" name="selected">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Red</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Green</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Blue</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="leftMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="r">
<property name="text">
<string>0x00 (00)</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="g">
<property name="text">
<string>0x00 (00)</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="b">
<property name="text">
<string>0x00 (00)</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>16-bit value</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>Hex code</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>Palette index</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="leftMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="value">
<property name="text">
<string>0x0000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="hexcode">
<property name="text">
<string>#000000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="index">
<property name="text">
<string>000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QGBA::Swatch</class>
<extends>QLabel</extends>
<header>Swatch.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -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 <QMouseEvent>
#include <QPainter>
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);
}

45
src/platform/qt/Swatch.h Normal file
View File

@ -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 <QColor>
#include <QLabel>
#include <QVector>
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<QColor> m_colors;
QPixmap m_backing;
QSize m_dims;
void updateFill(int index);
};
}
#endif

View File

@ -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());

View File

@ -73,6 +73,8 @@ public slots:
void openSensorWindow();
void openCheatsWindow();
void openPaletteWindow();
#ifdef BUILD_SDL
void openGamepadWindow();
#endif