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}