all repos — mgba @ 038d21debd6885a7ae74fd2bf24869eafa50d6da

mGBA Game Boy Advance Emulator

src/platform/qt/TileView.cpp (view raw)

  1/* Copyright (c) 2013-2016 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 "TileView.h"
  7
  8#include "CoreController.h"
  9#include "GBAApp.h"
 10
 11#include <QAction>
 12#include <QClipboard>
 13#include <QFontDatabase>
 14#include <QTimer>
 15
 16#ifdef M_CORE_GB
 17#include <mgba/internal/gb/gb.h>
 18#endif
 19
 20using namespace QGBA;
 21
 22TileView::TileView(std::shared_ptr<CoreController> controller, QWidget* parent)
 23	: AssetView(controller, parent)
 24	, m_controller(controller)
 25{
 26	m_ui.setupUi(this);
 27	m_ui.tile->setController(controller);
 28
 29	connect(m_ui.tiles, &TilePainter::indexPressed, m_ui.tile, &AssetTile::selectIndex);
 30	connect(m_ui.tiles, &TilePainter::needsRedraw, this, [this]() {
 31		updateTiles(true);
 32	});
 33	connect(m_ui.paletteId, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &TileView::updatePalette);
 34
 35	switch (m_controller->platform()) {
 36#ifdef M_CORE_GBA
 37	case PLATFORM_GBA:
 38		m_ui.tile->setBoundary(2048, 0, 2);
 39		break;
 40#endif
 41#ifdef M_CORE_GB
 42	case PLATFORM_GB:
 43		m_ui.palette256->setEnabled(false);
 44		m_ui.tile->setBoundary(1024, 0, 0);
 45		break;
 46#endif
 47	default:
 48		return;
 49	}
 50
 51	connect(m_ui.palette256, &QAbstractButton::toggled, [this](bool selected) {
 52		if (selected) {
 53			m_ui.paletteId->setValue(0);
 54		}
 55		switch (m_controller->platform()) {
 56#ifdef M_CORE_GBA
 57		case PLATFORM_GBA:
 58			m_ui.tile->setBoundary(2048 >> selected, selected, selected + 2);
 59			break;
 60#endif
 61#ifdef M_CORE_GB
 62		case PLATFORM_GB:
 63			return;
 64#endif
 65		default:
 66			break;
 67		}
 68		updateTiles(true);
 69	});
 70	connect(m_ui.magnification, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this](int mag) {
 71		if (!m_ui.tileFit->isChecked()) {
 72			m_ui.tiles->setMinimumSize(mag * 8 * m_ui.tilesPerRow->value(), m_ui.tiles->minimumSize().height());
 73		}
 74		updateTiles(true);
 75	});
 76
 77	connect(m_ui.tilesPerRow, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this](int count) {
 78		m_ui.tiles->setMinimumSize(m_ui.magnification->value() * 8 * count, m_ui.tiles->minimumSize().height());
 79		updateTiles(true);
 80	});
 81
 82	connect(m_ui.tileFit, &QAbstractButton::toggled, [this](bool selected) {
 83		if (!selected) {
 84			m_ui.tiles->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
 85			m_ui.tiles->setMinimumSize(m_ui.magnification->value() * 8 * m_ui.tilesPerRow->value(), m_ui.tiles->minimumSize().height());
 86		} else {
 87			m_ui.tiles->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
 88		}
 89		updateTiles(true);
 90	});
 91
 92	connect(m_ui.exportAll, &QAbstractButton::clicked, this, &TileView::exportTiles);
 93	connect(m_ui.exportOne, &QAbstractButton::clicked, this, &TileView::exportTile);
 94	connect(m_ui.copyAll, &QAbstractButton::clicked, this, &TileView::copyTiles);
 95	connect(m_ui.copyOne, &QAbstractButton::clicked, this, &TileView::copyTile);
 96
 97	QAction* exportAll = new QAction(this);
 98	exportAll->setShortcut(QKeySequence::Save);
 99	connect(exportAll, &QAction::triggered, this, &TileView::exportTiles);
100	addAction(exportAll);
101
102	QAction* copyOne = new QAction(this);
103	copyOne->setShortcut(QKeySequence::Copy);
104	connect(copyOne, &QAction::triggered, this, &TileView::copyTile);
105	addAction(copyOne);
106}
107
108#ifdef M_CORE_GBA
109void TileView::updateTilesGBA(bool force) {
110	if (m_ui.palette256->isChecked()) {
111		m_ui.tiles->setTileCount(1536);
112		mTileCache* cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 1);
113		for (int i = 0; i < 1024; ++i) {
114			const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i, 0);
115			if (data) {
116				m_ui.tiles->setTile(i, data);
117			} else if (force) {
118				m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i, 0));
119			}
120		}
121		cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 3);
122		for (int i = 1024; i < 1536; ++i) {
123			const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i - 1024, 0);
124			if (data) {
125				m_ui.tiles->setTile(i, data);
126			} else if (force) {
127				m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i - 1024, 0));
128			}
129		}
130	} else {
131		mTileCache* cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 0);
132		m_ui.tiles->setTileCount(3072);
133		for (int i = 0; i < 2048; ++i) {
134			const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i, m_paletteId);
135			if (data) {
136				m_ui.tiles->setTile(i, data);
137			} else if (force) {
138				m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i, m_paletteId));
139			}
140		}
141		cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 2);
142		for (int i = 2048; i < 3072; ++i) {
143			const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[16 * i], i - 2048, m_paletteId);
144			if (data) {
145				m_ui.tiles->setTile(i, data);
146			} else if (force) {
147				m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i - 2048, m_paletteId));
148			}
149		}
150	}
151}
152#endif
153
154#ifdef M_CORE_GB
155void TileView::updateTilesGB(bool force) {
156	const GB* gb = static_cast<const GB*>(m_controller->thread()->core->board);
157	int count = gb->model >= GB_MODEL_CGB ? 1024 : 512;
158	m_ui.tiles->setTileCount(count);
159	mTileCache* cache = mTileCacheSetGetPointer(&m_cacheSet->tiles, 0);
160	for (int i = 0; i < count; ++i) {
161		const color_t* data = mTileCacheGetTileIfDirty(cache, &m_tileStatus[8 * i], i, m_paletteId);
162		if (data) {
163			m_ui.tiles->setTile(i, data);
164		} else if (force) {
165			m_ui.tiles->setTile(i, mTileCacheGetTile(cache, i, m_paletteId));
166		}
167	}
168}
169#endif
170
171void TileView::updatePalette(int palette) {
172	m_paletteId = palette;
173	m_ui.tile->setPalette(palette);
174	updateTiles(true);
175}
176
177void TileView::exportTiles() {
178	QString filename = GBAApp::app()->getSaveFileName(this, tr("Export tiles"),
179	                                                  tr("Portable Network Graphics (*.png)"));
180	if (filename.isNull()) {
181		return;
182	}
183	CoreController::Interrupter interrupter(m_controller);
184	updateTiles(false);
185	QPixmap pixmap(m_ui.tiles->backing());
186	pixmap.save(filename, "PNG");
187}
188
189void TileView::exportTile() {
190	QString filename = GBAApp::app()->getSaveFileName(this, tr("Export tile"),
191	                                                  tr("Portable Network Graphics (*.png)"));
192	if (filename.isNull()) {
193		return;
194	}
195	CoreController::Interrupter interrupter(m_controller);
196	updateTiles(false);
197	QImage image(m_ui.tile->activeTile());
198	image.save(filename, "PNG");
199}
200
201void TileView::copyTiles() {
202	CoreController::Interrupter interrupter(m_controller);
203	updateTiles(false);
204	QPixmap pixmap();
205	GBAApp::app()->clipboard()->setPixmap(m_ui.tiles->backing());
206}
207
208void TileView::copyTile() {
209	CoreController::Interrupter interrupter(m_controller);
210	updateTiles(false);
211	GBAApp::app()->clipboard()->setImage(m_ui.tile->activeTile());
212}