Qt: First pass at a tile view

This commit is contained in:
Jeffrey Pfau 2016-07-22 01:05:49 -07:00
parent 739df1ed74
commit b1f750e441
8 changed files with 448 additions and 0 deletions

View File

@ -102,6 +102,8 @@ set(SOURCE_FILES
ShortcutController.cpp
ShortcutView.cpp
Swatch.cpp
TilePainter.cpp
TileView.cpp
Window.cpp
VFileDevice.cpp
VideoView.cpp)
@ -121,6 +123,7 @@ qt5_wrap_ui(UI_FILES
SettingsView.ui
ShaderSelector.ui
ShortcutView.ui
TileView.ui
VideoView.ui)
set(QT_LIBRARIES)

View File

@ -0,0 +1,40 @@
/* Copyright (c) 2013-2016 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 "TilePainter.h"
#include <QImage>
#include <QMouseEvent>
#include <QPainter>
using namespace QGBA;
TilePainter::TilePainter(QWidget* parent)
: QWidget(parent)
{
m_backing = QPixmap(256, 768);
m_backing.fill(Qt::transparent);
}
void TilePainter::paintEvent(QPaintEvent* event) {
QPainter painter(this);
painter.drawPixmap(QPoint(), m_backing);
}
void TilePainter::mousePressEvent(QMouseEvent* event) {
int x = event->x() / 8;
int y = event->y() / 8;
emit indexPressed(y * 32 + x);
}
void TilePainter::setTile(int index, const uint16_t* data) {
QPainter painter(&m_backing);
int x = index & 31;
int y = index / 32;
QRect r(x * 8, y * 8, 8, 8);
QImage tile(reinterpret_cast<const uchar*>(data), 8, 8, QImage::Format_RGB555);
painter.fillRect(r, tile.rgbSwapped());
update(r);
}

View File

@ -0,0 +1,37 @@
/* Copyright (c) 2013-2016 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_TILE_PAINTER
#define QGBA_TILE_PAINTER
#include <QColor>
#include <QWidget>
#include <QVector>
namespace QGBA {
class TilePainter : public QWidget {
Q_OBJECT
public:
TilePainter(QWidget* parent = nullptr);
public slots:
void setTile(int index, const uint16_t*);
signals:
void indexPressed(int index);
protected:
void paintEvent(QPaintEvent*) override;
void mousePressEvent(QMouseEvent*) override;
private:
QPixmap m_backing;
};
}
#endif

View File

@ -0,0 +1,111 @@
/* Copyright (c) 2013-2016 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 "TileView.h"
#include "GBAApp.h"
#include <QFontDatabase>
extern "C" {
#include "gba/gba.h"
}
using namespace QGBA;
TileView::TileView(GameController* controller, QWidget* parent)
: QWidget(parent)
, m_controller(controller)
, m_paletteId(0)
{
m_ui.setupUi(this);
GBAVideoTileCacheInit(&m_tileCache);
m_ui.preview->setDimensions(QSize(8, 8));
updateTiles();
const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
m_ui.tileId->setFont(font);
m_ui.address->setFont(font);
connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(updateTiles()));
connect(m_controller, SIGNAL(gameStopped(mCoreThread*)), this, SLOT(close()));
connect(m_ui.tiles, SIGNAL(indexPressed(int)), this, SLOT(selectIndex(int)));
connect(m_ui.paletteId, SIGNAL(valueChanged(int)), this, SLOT(updatePalette(int)));
connect(m_ui.palette256, SIGNAL(toggled(bool)), this, SLOT(updateTiles()));
}
TileView::~TileView() {
GBAVideoTileCacheDeinit(&m_tileCache);
}
void TileView::selectIndex(int index) {
const uint16_t* data;
m_ui.tileId->setText(QString::number(index));
if (m_ui.palette256->isChecked()) {
m_ui.address->setText(tr("0x%0").arg(index * 64 | BASE_VRAM, 8, 16, QChar('0')));
if (index < 1024) {
data = GBAVideoTileCacheGetTile256(&m_tileCache, index, 0);
} else {
data = GBAVideoTileCacheGetTile256(&m_tileCache, index, 1);
}
} else {
m_ui.address->setText(tr("0x%0").arg(index * 32 | BASE_VRAM, 8, 16, QChar('0')));
if (index < 2048) {
data = GBAVideoTileCacheGetTile16(&m_tileCache, index, m_paletteId);
} else {
data = GBAVideoTileCacheGetTile16(&m_tileCache, index, m_paletteId + 16);
}
}
for (int i = 0; i < 64; ++i) {
m_ui.preview->setColor(i, data[i]);
}
m_ui.preview->update();
}
void TileView::updateTiles() {
if (!m_controller->thread() || !m_controller->thread()->core) {
return;
}
GBA* gba = static_cast<GBA*>(m_controller->thread()->core->board);
GBAVideoTileCacheAssociate(&m_tileCache, &gba->video);
if (m_ui.palette256->isChecked()) {
m_ui.tiles->setMinimumSize(256, 384);
for (int i = 0; i < 1024; ++i) {
const uint16_t* data = GBAVideoTileCacheGetTile256IfDirty(&m_tileCache, i, 0);
if (data) {
m_ui.tiles->setTile(i, data);
}
}
for (int i = 1024; i < 1536; ++i) {
const uint16_t* data = GBAVideoTileCacheGetTile256IfDirty(&m_tileCache, i, 1);
if (data) {
m_ui.tiles->setTile(i, data);
}
}
} else {
m_ui.tiles->setMinimumSize(256, 768);
for (int i = 0; i < 2048; ++i) {
const uint16_t* data = GBAVideoTileCacheGetTile16IfDirty(&m_tileCache, i, m_paletteId);
if (data) {
m_ui.tiles->setTile(i, data);
}
}
for (int i = 2048; i < 3072; ++i) {
const uint16_t* data = GBAVideoTileCacheGetTile16IfDirty(&m_tileCache, i, m_paletteId + 16);
if (data) {
m_ui.tiles->setTile(i, data);
}
}
}
}
void TileView::updatePalette(int palette) {
m_paletteId = palette;
updateTiles();
}

View File

@ -0,0 +1,45 @@
/* Copyright (c) 2013-2016 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_TILE_VIEW
#define QGBA_TILE_VIEW
#include <QWidget>
#include "GameController.h"
#include "ui_TileView.h"
extern "C" {
#include "gba/renderers/tile-cache.h"
}
namespace QGBA {
class TileView : public QWidget {
Q_OBJECT
public:
TileView(GameController* controller, QWidget* parent = nullptr);
virtual ~TileView();
public slots:
void updateTiles();
void updatePalette(int);
private slots:
void selectIndex(int);
private:
Ui::TileView m_ui;
GameController* m_controller;
GBAVideoTileCache m_tileCache;
int m_paletteId;
};
}
#endif

199
src/platform/qt/TileView.ui Normal file
View File

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TileView</class>
<widget class="QWidget" name="TileView">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>288</width>
<height>269</height>
</rect>
</property>
<property name="windowTitle">
<string>Tiles</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QCheckBox" name="palette256">
<property name="text">
<string>256 colors</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Preview</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QGBA::Swatch" name="preview" native="true">
<property name="minimumSize">
<size>
<width>87</width>
<height>87</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Tile #</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="tileId">
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Address</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="address">
<property name="text">
<string>0x06000000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QSlider" name="paletteId">
<property name="maximum">
<number>15</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="3">
<widget class="QScrollArea" name="scrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>16</width>
<height>16</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<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::TilePainter" name="tiles" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QGBA::TilePainter</class>
<extends>QWidget</extends>
<header>TilePainter.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QGBA::Swatch</class>
<extends>QWidget</extends>
<header>Swatch.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -30,6 +30,7 @@
#include "MemoryView.h"
#include "OverrideView.h"
#include "PaletteView.h"
#include "TileView.h"
#include "ROMInfo.h"
#include "SensorView.h"
#include "SettingsView.h"
@ -430,6 +431,11 @@ void Window::openPaletteWindow() {
openView(paletteWindow);
}
void Window::openTileWindow() {
TileView* tileWindow = new TileView(m_controller);
openView(tileWindow);
}
void Window::openMemoryWindow() {
MemoryView* memoryWindow = new MemoryView(m_controller);
openView(memoryWindow);
@ -1288,6 +1294,12 @@ void Window::setupMenu(QMenuBar* menubar) {
m_gbaActions.append(paletteView);
addControlledAction(toolsMenu, paletteView, "paletteWindow");
QAction* tileView = new QAction(tr("View &tiles..."), toolsMenu);
connect(tileView, SIGNAL(triggered()), this, SLOT(openTileWindow()));
m_gameActions.append(tileView);
m_gbaActions.append(tileView);
addControlledAction(toolsMenu, tileView, "tileWindow");
QAction* memoryView = new QAction(tr("View memory..."), toolsMenu);
connect(memoryView, SIGNAL(triggered()), this, SLOT(openMemoryWindow()));
m_gameActions.append(memoryView);

View File

@ -82,6 +82,7 @@ public slots:
void openCheatsWindow();
void openPaletteWindow();
void openTileWindow();
void openMemoryWindow();
void openIOViewer();