|
@@ -882,9 +882,6 @@ void MetatilesPixmapItem::updateSelection(QPointF pos, Qt::MouseButton button) {
|
882
|
882
|
map->paint_tile_index = baseTileY * 8 + baseTileX;
|
883
|
883
|
map->paint_tile_width = abs(map->paint_metatile_initial_x - x) + 1;
|
884
|
884
|
map->paint_tile_height = abs(map->paint_metatile_initial_y - y) + 1;
|
885
|
|
- map->smart_paths_enabled = button == Qt::RightButton
|
886
|
|
- && map->paint_tile_width == 3
|
887
|
|
- && map->paint_tile_height == 3;
|
888
|
885
|
emit map->paintTileChanged(map);
|
889
|
886
|
}
|
890
|
887
|
}
|
|
@@ -1032,7 +1029,7 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
|
1032
|
1029
|
int x = (int)(pos.x()) / 16;
|
1033
|
1030
|
int y = (int)(pos.y()) / 16;
|
1034
|
1031
|
|
1035
|
|
- if (map->smart_paths_enabled) {
|
|
1032
|
+ if (map->smart_paths_enabled && map->paint_tile_width == 3 && map->paint_tile_height == 3) {
|
1036
|
1033
|
paintSmartPath(x, y);
|
1037
|
1034
|
} else {
|
1038
|
1035
|
paintNormal(x, y);
|
|
@@ -1160,11 +1157,163 @@ void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
|
1160
|
1157
|
QPointF pos = event->pos();
|
1161
|
1158
|
int x = (int)(pos.x()) / 16;
|
1162
|
1159
|
int y = (int)(pos.y()) / 16;
|
1163
|
|
- map->floodFill(x, y, map->getSelectedBlockIndex(map->paint_tile_index));
|
|
1160
|
+ Block *block = map->getBlock(x, y);
|
|
1161
|
+ int tile = map->getSelectedBlockIndex(map->paint_tile_index);
|
|
1162
|
+ if (block && block->tile != tile) {
|
|
1163
|
+ if (map->smart_paths_enabled && map->paint_tile_width == 3 && map->paint_tile_height == 3)
|
|
1164
|
+ this->_floodFillSmartPath(x, y);
|
|
1165
|
+ else
|
|
1166
|
+ this->_floodFill(x, y);
|
|
1167
|
+ }
|
|
1168
|
+
|
|
1169
|
+ if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
|
1170
|
+ map->commit();
|
|
1171
|
+ }
|
1164
|
1172
|
draw();
|
1165
|
1173
|
}
|
1166
|
1174
|
}
|
1167
|
1175
|
|
|
1176
|
+void MapPixmapItem::_floodFill(int initialX, int initialY) {
|
|
1177
|
+ QList<QPoint> todo;
|
|
1178
|
+ todo.append(QPoint(initialX, initialY));
|
|
1179
|
+ while (todo.length()) {
|
|
1180
|
+ QPoint point = todo.takeAt(0);
|
|
1181
|
+ int x = point.x();
|
|
1182
|
+ int y = point.y();
|
|
1183
|
+
|
|
1184
|
+ Block *block = map->getBlock(x, y);
|
|
1185
|
+ if (block == NULL) {
|
|
1186
|
+ continue;
|
|
1187
|
+ }
|
|
1188
|
+
|
|
1189
|
+ int xDiff = x - initialX;
|
|
1190
|
+ int yDiff = y - initialY;
|
|
1191
|
+ int i = xDiff % map->paint_tile_width;
|
|
1192
|
+ int j = yDiff % map->paint_tile_height;
|
|
1193
|
+ if (i < 0) i = map->paint_tile_width + i;
|
|
1194
|
+ if (j < 0) j = map->paint_tile_height + j;
|
|
1195
|
+ int tile = map->getSelectedBlockIndex(map->paint_tile_index + i + (j * 8));
|
|
1196
|
+ uint old_tile = block->tile;
|
|
1197
|
+ if (old_tile == tile) {
|
|
1198
|
+ continue;
|
|
1199
|
+ }
|
|
1200
|
+
|
|
1201
|
+ block->tile = tile;
|
|
1202
|
+ map->_setBlock(x, y, *block);
|
|
1203
|
+ if ((block = map->getBlock(x + 1, y)) && block->tile == old_tile) {
|
|
1204
|
+ todo.append(QPoint(x + 1, y));
|
|
1205
|
+ }
|
|
1206
|
+ if ((block = map->getBlock(x - 1, y)) && block->tile == old_tile) {
|
|
1207
|
+ todo.append(QPoint(x - 1, y));
|
|
1208
|
+ }
|
|
1209
|
+ if ((block = map->getBlock(x, y + 1)) && block->tile == old_tile) {
|
|
1210
|
+ todo.append(QPoint(x, y + 1));
|
|
1211
|
+ }
|
|
1212
|
+ if ((block = map->getBlock(x, y - 1)) && block->tile == old_tile) {
|
|
1213
|
+ todo.append(QPoint(x, y - 1));
|
|
1214
|
+ }
|
|
1215
|
+ }
|
|
1216
|
+}
|
|
1217
|
+
|
|
1218
|
+void MapPixmapItem::_floodFillSmartPath(int initialX, int initialY) {
|
|
1219
|
+ // Smart path should never be enabled without a 3x3 block selection.
|
|
1220
|
+ if (map->paint_tile_width != 3 || map->paint_tile_height != 3) return;
|
|
1221
|
+
|
|
1222
|
+ // Shift to the middle tile of the smart path selection.
|
|
1223
|
+ int openTile = map->paint_tile_index + 8 + 1;
|
|
1224
|
+
|
|
1225
|
+ // Flood fill the region with the open tile.
|
|
1226
|
+ QList<QPoint> todo;
|
|
1227
|
+ todo.append(QPoint(initialX, initialY));
|
|
1228
|
+ while (todo.length()) {
|
|
1229
|
+ QPoint point = todo.takeAt(0);
|
|
1230
|
+ int x = point.x();
|
|
1231
|
+ int y = point.y();
|
|
1232
|
+
|
|
1233
|
+ Block *block = map->getBlock(x, y);
|
|
1234
|
+ if (block == NULL) {
|
|
1235
|
+ continue;
|
|
1236
|
+ }
|
|
1237
|
+
|
|
1238
|
+ int tile = map->getSelectedBlockIndex(openTile);
|
|
1239
|
+ uint old_tile = block->tile;
|
|
1240
|
+ if (old_tile == tile) {
|
|
1241
|
+ continue;
|
|
1242
|
+ }
|
|
1243
|
+
|
|
1244
|
+ block->tile = tile;
|
|
1245
|
+ map->_setBlock(x, y, *block);
|
|
1246
|
+ if ((block = map->getBlock(x + 1, y)) && block->tile == old_tile) {
|
|
1247
|
+ todo.append(QPoint(x + 1, y));
|
|
1248
|
+ }
|
|
1249
|
+ if ((block = map->getBlock(x - 1, y)) && block->tile == old_tile) {
|
|
1250
|
+ todo.append(QPoint(x - 1, y));
|
|
1251
|
+ }
|
|
1252
|
+ if ((block = map->getBlock(x, y + 1)) && block->tile == old_tile) {
|
|
1253
|
+ todo.append(QPoint(x, y + 1));
|
|
1254
|
+ }
|
|
1255
|
+ if ((block = map->getBlock(x, y - 1)) && block->tile == old_tile) {
|
|
1256
|
+ todo.append(QPoint(x, y - 1));
|
|
1257
|
+ }
|
|
1258
|
+ }
|
|
1259
|
+
|
|
1260
|
+ // Go back and resolve the flood-filled edge tiles.
|
|
1261
|
+ // Mark tiles as visited while we go.
|
|
1262
|
+ bool visited[map->getWidth() * map->getHeight()];
|
|
1263
|
+ for (int i = 0; i < sizeof visited; i++)
|
|
1264
|
+ visited[i] = false;
|
|
1265
|
+
|
|
1266
|
+ todo.append(QPoint(initialX, initialY));
|
|
1267
|
+ while (todo.length()) {
|
|
1268
|
+ QPoint point = todo.takeAt(0);
|
|
1269
|
+ int x = point.x();
|
|
1270
|
+ int y = point.y();
|
|
1271
|
+ visited[x + y * map->getWidth()] = true;
|
|
1272
|
+
|
|
1273
|
+ Block *block = map->getBlock(x, y);
|
|
1274
|
+ if (block == NULL) {
|
|
1275
|
+ continue;
|
|
1276
|
+ }
|
|
1277
|
+
|
|
1278
|
+ int id = 0;
|
|
1279
|
+ Block *top = map->getBlock(x, y - 1);
|
|
1280
|
+ Block *right = map->getBlock(x + 1, y);
|
|
1281
|
+ Block *bottom = map->getBlock(x, y + 1);
|
|
1282
|
+ Block *left = map->getBlock(x - 1, y);
|
|
1283
|
+
|
|
1284
|
+ // Get marching squares value, to determine which tile to use.
|
|
1285
|
+ if (top && IS_SMART_PATH_TILE(top))
|
|
1286
|
+ id += 1;
|
|
1287
|
+ if (right && IS_SMART_PATH_TILE(right))
|
|
1288
|
+ id += 2;
|
|
1289
|
+ if (bottom && IS_SMART_PATH_TILE(bottom))
|
|
1290
|
+ id += 4;
|
|
1291
|
+ if (left && IS_SMART_PATH_TILE(left))
|
|
1292
|
+ id += 8;
|
|
1293
|
+
|
|
1294
|
+ block->tile = map->getSelectedBlockIndex(map->paint_tile_index + smartPathTable[id]);
|
|
1295
|
+ map->_setBlock(x, y, *block);
|
|
1296
|
+
|
|
1297
|
+ // Visit neighbors if they are smart-path tiles, and don't revisit any.
|
|
1298
|
+ if (!visited[x + 1 + y * map->getWidth()] && (block = map->getBlock(x + 1, y)) && IS_SMART_PATH_TILE(block)) {
|
|
1299
|
+ todo.append(QPoint(x + 1, y));
|
|
1300
|
+ visited[x + 1 + y * map->getWidth()] = true;
|
|
1301
|
+ }
|
|
1302
|
+ if (!visited[x - 1 + y * map->getWidth()] && (block = map->getBlock(x - 1, y)) && IS_SMART_PATH_TILE(block)) {
|
|
1303
|
+ todo.append(QPoint(x - 1, y));
|
|
1304
|
+ visited[x - 1 + y * map->getWidth()] = true;
|
|
1305
|
+ }
|
|
1306
|
+ if (!visited[x + (y + 1) * map->getWidth()] && (block = map->getBlock(x, y + 1)) && IS_SMART_PATH_TILE(block)) {
|
|
1307
|
+ todo.append(QPoint(x, y + 1));
|
|
1308
|
+ visited[x + (y + 1) * map->getWidth()] = true;
|
|
1309
|
+ }
|
|
1310
|
+ if (!visited[x + (y - 1) * map->getWidth()] && (block = map->getBlock(x, y - 1)) && IS_SMART_PATH_TILE(block)) {
|
|
1311
|
+ todo.append(QPoint(x, y - 1));
|
|
1312
|
+ visited[x + (y - 1) * map->getWidth()] = true;
|
|
1313
|
+ }
|
|
1314
|
+ }
|
|
1315
|
+}
|
|
1316
|
+
|
1168
|
1317
|
void MapPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
|
1169
|
1318
|
QPointF pos = event->pos();
|
1170
|
1319
|
int x = (int)(pos.x()) / 16;
|