all repos — mgba @ 06e6e1a27d75c5111ff81a2aeae9b3c204ca6ec1

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