Pokered Save Editor 2
Pokemon Red & Blue save file editor - Qt 6 C++/QML
Toggle main menu visibility
Loading...
Searching...
No Matches
tilesetengine.cpp
Go to the documentation of this file.
1
/*
2
* Copyright 2020 Twilight
3
*
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
7
*
8
* http://www.apache.org/licenses/LICENSE-2.0
9
*
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
15
*/
16
22
23
#include "
./tilesetengine.h
"
24
#include <QStringList>
25
#include <QColor>
26
#include <QVector>
27
#include <QPainter>
28
29
QImage
TilesetEngine::getTileset
(QString name)
30
{
31
// Make lowercase and replace spaces
32
QString nameFixed = name.toLower().replace(
" "
,
"_"
);
33
return
QImage(
":/assets/tilesets/"
+ nameFixed +
".png"
)
34
.convertToFormat(QImage::Format::Format_ARGB32);
35
}
36
37
QImage
TilesetEngine::getFlower
(
int
frame)
38
{
39
// Frame 0: flower2
40
// Frame 1: flower3
41
// Frame 2: flower1
42
// Frame 3: flower1
43
44
// returns frame 0-3 no matter frame number
45
int
subFrame = frame % 4;
46
int
ind;
47
48
if
(subFrame == 0)
49
ind = 2;
50
else
if
(subFrame == 1)
51
ind = 3;
52
else
53
ind = 1;
54
55
return
QImage(
":/assets/tilesets/_flower"
+ QString::number(ind) +
".png"
)
56
.convertToFormat(QImage::Format::Format_ARGB32);
57
}
58
59
QImage
TilesetEngine::getFont
()
60
{
61
return
QImage(
":/assets/tilesets/_font.png"
)
62
.convertToFormat(QImage::Format::Format_ARGB32);
63
}
64
65
QPixmap
TilesetEngine::buildTilesetFullDebug
(QString
id
)
66
{
67
auto
idParts =
id
.split(
"/"
, Qt::SkipEmptyParts);
68
69
// Has to have all 4 parts unconditionally
70
if
(idParts.size() < 4) {
71
// Return error red
72
auto
tmp =
blankImage
();
73
tmp.fill(QColor(255, 0, 0, 0));
74
return
QPixmap::fromImage(tmp);
75
}
76
77
// Is outdoor? and use font? Also get frame
78
bool
outdoorType = idParts.at(1).toLower() ==
"outdoor"
;
79
bool
useFont = idParts.at(2).toLower() ==
"font"
;
80
int
frame = idParts.at(3).toInt();
81
82
// Get or create blank images as needed for each layer
83
auto
tilesetImg =
getTileset
(idParts.at(0));
84
85
auto
fontImg = (useFont)
86
?
getFont
()
87
:
blankImage
();
88
auto
flowerImg = (outdoorType)
89
?
getFlower
(frame)
90
:
blankImage
();
91
92
// Prepare tileset image
93
QImage tileset =
blankImage
();
94
//tileset.fill(QColor("white"));
95
96
// Stack requested and retrieved tileset layers
97
QPainter p(&tileset);
98
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
99
p.drawImage(0, 0, tilesetImg);
100
p.drawImage(0, 0, fontImg);
101
p.drawImage(0, 0, flowerImg);
102
103
// Post-Process if applicable
104
if
(outdoorType) {
105
// Copy water tile out to it's own image
106
auto
waterTile = tileset.copy(4 *
tileWidth
, 1 *
tileHeight
,
107
tileWidth
,
tileHeight
);
108
109
// Process water tile
110
waterTile =
postProcessWave
(waterTile, frame);
111
112
// Copy back into the tileset
113
p.drawImage(4 *
tileWidth
, 1 *
tileHeight
, waterTile);
114
}
115
116
return
QPixmap::fromImage(tileset);
117
}
118
119
QVector<QPixmap>
TilesetEngine::buildTileset
(QString
id
)
120
{
121
// Use internal debug function to manually and slowly create it
122
auto
tileset =
buildTilesetFullDebug
(
id
).toImage();
123
124
// Convert to an array of tiles
125
QVector<QPixmap> ret =
getTiles
(tileset);
126
127
// Return a newly built array of tiles
128
return
ret;
129
}
130
131
QVector<QPixmap>
TilesetEngine::getTiles
(QImage tilemap)
132
{
133
QVector<QPixmap> ret;
134
135
int
tilesX =
width
/ 8;
136
int
tilesY =
height
/ 8;
137
138
for
(
int
tileY = 0; tileY < tilesY; tileY++) {
139
for
(
int
tileX = 0; tileX < tilesX; tileX++) {
140
int
startX = tileX * 8;
141
int
startY = tileY * 8;
142
143
auto
tile = tilemap.copy(startX, startY, 8, 8);
144
ret.append(QPixmap::fromImage(tile));
145
}
146
}
147
148
return
ret;
149
}
150
151
QImage
TilesetEngine::blankImage
()
152
{
153
auto
img = QImage(
width
,
height
, QImage::Format::Format_ARGB32);
154
img.fill(QColor(0, 0, 0, 0));
155
return
img;
156
}
157
158
QImage
TilesetEngine::postProcessWaveOnce
(QImage tile)
159
{
160
// Holds a line of pixels as a buffer
161
QVector<QColor> line;
162
QImage lineImg;
163
164
// Finished image, pre-fill white
165
QImage ret = QImage(
tileWidth
,
tileHeight
, QImage::Format::Format_ARGB32);
166
ret.fill(QColor(
"white"
));
167
168
// Loop through each line of the tile
169
for
(
int
y = 0; y <
tileHeight
; y++) {
170
171
// Copy out each line
172
lineImg = tile.copy(0, y,
tileWidth
, 1);
173
174
// Convert it to pixels
175
for
(
int
x = 0; x <
tileWidth
; x++) {
176
line.append(lineImg.pixelColor(x, 0));
177
}
178
179
// Convert it back to an image offset by 1
180
for
(
int
x = 0; x <
tileWidth
; x++) {
181
182
// Calculate a -1 offset
183
// We want to shift the row of pixels right by 1 and wrap around
184
// We start at pixel #0 and move forward, the first pixel though
185
// is replaced with the last pixel thus creating a left-shift wrap around
186
187
int
xOff = x - 1;
188
if
(xOff < 0)
189
xOff =
tileWidth
- 1;
190
191
ret.setPixelColor(x, y, line.at(xOff));
192
}
193
194
line.clear();
195
}
196
197
return
ret;
198
}
199
200
QImage
TilesetEngine::postProcessWave
(QImage tile,
int
frame)
201
{
202
// frame #0 = 0 shift
203
// frame #1 = 1 shift
204
// frame #2 = 2 shift
205
// frame #3 = 3 shift
206
// frame #4 = 4 shift
207
// frame #5 = 3 shift
208
// frame #6 = 2 shift
209
// frame #7 = 1 shift
210
211
// Get frame index 0-7 no matter frame number
212
int
subFrame = frame % 8;
213
214
int
count = subFrame;
215
if
(subFrame > 4)
216
count = (8 - count);
217
218
QImage ret = tile;
219
220
for
(
int
i = 0; i < count; i++)
221
ret =
postProcessWaveOnce
(ret);
222
223
return
ret;
224
}
TilesetEngine::width
static constexpr int width
Tileset image width (px).
Definition
tilesetengine.h:79
TilesetEngine::blankImage
static QImage blankImage()
A blank transparent tile-sized image.
Definition
tilesetengine.cpp:151
TilesetEngine::postProcessWaveOnce
static QImage postProcessWaveOnce(QImage tile)
One increment of the water-wave shift.
Definition
tilesetengine.cpp:158
TilesetEngine::postProcessWave
static QImage postProcessWave(QImage tile, int frame)
Apply the wave effect for frame (see note).
Definition
tilesetengine.cpp:200
TilesetEngine::height
static constexpr int height
Tileset image height (px).
Definition
tilesetengine.h:80
TilesetEngine::buildTileset
static QVector< QPixmap > buildTileset(QString id)
Build the per-tile pixmaps for id (format above).
Definition
tilesetengine.cpp:119
TilesetEngine::tileWidth
static constexpr int tileWidth
Tile width (px).
Definition
tilesetengine.h:81
TilesetEngine::buildTilesetFullDebug
static QPixmap buildTilesetFullDebug(QString id)
Definition
tilesetengine.cpp:65
TilesetEngine::getFont
static QImage getFont()
The font overlay image.
Definition
tilesetengine.cpp:59
TilesetEngine::getFlower
static QImage getFlower(int frame)
The animated flower overlay for frame (see note).
Definition
tilesetengine.cpp:37
TilesetEngine::getTiles
static QVector< QPixmap > getTiles(QImage tilemap)
Slice a tilemap image into per-tile pixmaps.
Definition
tilesetengine.cpp:131
TilesetEngine::tileHeight
static constexpr int tileHeight
Tile height (px).
Definition
tilesetengine.h:82
TilesetEngine::getTileset
static QImage getTileset(QString name)
Load a tileset image by name (case-insensitive; spaces -> underscores).
Definition
tilesetengine.cpp:29
tilesetengine.h
projects
app
src
engine
tilesetengine.cpp
Generated by
1.17.0