Merge pull request #3 from huderlem/maps

Fix map connections, warps, and map event saving
This commit is contained in:
yenatch 2018-02-12 21:53:19 -05:00 committed by GitHub
commit 7f761a5051
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 208 additions and 115 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
pretmap.pro.user pretmap.pro.user
*.autosave

View file

@ -39,10 +39,6 @@ public:
values.insert(key, value); values.insert(key, value);
} }
bool is_hidden_item() {
return getInt("type") >= 5;
}
QMap<QString, QString> values; QMap<QString, QString> values;
QPixmap pixmap; QPixmap pixmap;
}; };

View file

@ -504,13 +504,16 @@ void MainWindow::updateSelectedObjects() {
field_labels["property"] = "Property"; field_labels["property"] = "Property";
field_labels["sight_radius"] = "Sight Radius"; field_labels["sight_radius"] = "Sight Radius";
field_labels["destination_warp"] = "Destination Warp"; field_labels["destination_warp"] = "Destination Warp";
field_labels["destination_map"] = "Destination Map"; field_labels["destination_map_name"] = "Destination Map";
field_labels["coord_unknown1"] = "Unknown 1"; field_labels["coord_unknown1"] = "Unknown 1";
field_labels["coord_unknown2"] = "Unknown 2"; field_labels["coord_unknown2"] = "Unknown 2";
field_labels["type"] = "Type"; field_labels["type"] = "Type";
field_labels["item"] = "Item"; field_labels["item"] = "Item";
field_labels["item_unknown5"] = "Unknown 5"; field_labels["item_unknown5"] = "Unknown 5";
field_labels["item_unknown6"] = "Unknown 6"; field_labels["item_unknown6"] = "Unknown 6";
field_labels["weather"] = "Weather";
field_labels["flag"] = "Flag";
field_labels["secret_base_map"] = "Secret Base Map";
QStringList fields; QStringList fields;
@ -542,22 +545,26 @@ void MainWindow::updateSelectedObjects() {
} }
else if (event_type == "warp") { else if (event_type == "warp") {
fields << "destination_warp"; fields << "destination_warp";
fields << "destination_map"; fields << "destination_map_name";
} }
else if (event_type == "trap") { else if (event_type == "trap") {
fields << "script_label"; fields << "script_label";
fields << "coord_unknown1"; fields << "coord_unknown1";
fields << "coord_unknown2"; fields << "coord_unknown2";
} }
else if (event_type == "trap_weather") {
fields << "weather";
}
else if (event_type == "sign") { else if (event_type == "sign") {
fields << "type"; fields << "type";
fields << "script_label"; fields << "script_label";
} }
else if (event_type == "hidden item") { else if (event_type == "event_hidden_item") {
fields << "type";
fields << "item"; fields << "item";
fields << "item_unknown5"; fields << "flag";
fields << "item_unknown6"; }
else if (event_type == "event_secret_base") {
fields << "secret_base_map";
} }
for (QString key : fields) { for (QString key : fields) {
@ -568,7 +575,7 @@ void MainWindow::updateSelectedObjects() {
combo->setEditable(true); combo->setEditable(true);
QString value = item->event->get(key); QString value = item->event->get(key);
if (key == "destination_map") { if (key == "destination_map_name") {
if (!editor->project->mapNames->contains(value)) { if (!editor->project->mapNames->contains(value)) {
combo->addItem(value); combo->addItem(value);
} }

45
map.cpp
View file

@ -4,6 +4,7 @@
#include <QDebug> #include <QDebug>
#include <QPainter> #include <QPainter>
#include <QImage> #include <QImage>
#include <QRegularExpression>
Map::Map(QObject *parent) : QObject(parent) Map::Map(QObject *parent) : QObject(parent)
{ {
@ -16,6 +17,24 @@ Map::Map(QObject *parent) : QObject(parent)
paint_elevation = 3; paint_elevation = 3;
} }
void Map::setName(QString mapName) {
name = mapName;
constantName = mapConstantFromName(mapName);
}
QString Map::mapConstantFromName(QString mapName) {
// Transform map names of the form 'GraniteCave_B1F` into map constants like 'MAP_GRANITE_CAVE_B1F'.
QString nameWithUnderscores = mapName.replace(QRegularExpression("([a-z])([A-Z])"), "\\1_\\2");
QString withMapAndUppercase = "MAP_" + nameWithUnderscores.toUpper();
QString constantName = withMapAndUppercase.replace(QRegularExpression("_+"), "_");
// Handle special cases.
// SSTidal needs to be SS_TIDAL, rather than SSTIDAL
constantName = constantName.replace("SSTIDAL", "SS_TIDAL");
return constantName;
}
int Map::getWidth() { int Map::getWidth() {
return width.toInt(nullptr, 0); return width.toInt(nullptr, 0);
} }
@ -138,22 +157,26 @@ QImage Map::getMetatileImage(int tile) {
for (int x = 0; x < 2; x++) { for (int x = 0; x < 2; x++) {
Tile tile_ = metatile->tiles->value((y * 2) + x + (layer * 4)); Tile tile_ = metatile->tiles->value((y * 2) + x + (layer * 4));
QImage tile_image = getMetatileTile(tile_.tile); QImage tile_image = getMetatileTile(tile_.tile);
//if (tile_image.isNull()) { if (tile_image.isNull()) {
// continue; // Some metatiles specify tiles that are outside the valid range.
//} // These are treated as completely transparent, so they can be skipped without
//if (blockTileset->palettes) { // being drawn.
QList<QRgb> palette = palettes.value(tile_.palette); continue;
for (int j = 0; j < palette.length(); j++) { }
tile_image.setColor(j, palette.value(j));
} // Colorize the metatile tiles with its palette.
//} QList<QRgb> palette = palettes.value(tile_.palette);
//QVector<QRgb> vector = palette.toVector(); for (int j = 0; j < palette.length(); j++) {
//tile_image.setColorTable(vector); tile_image.setColor(j, palette.value(j));
}
// The top layer of the metatile has its last color displayed at transparent.
if (layer > 0) { if (layer > 0) {
QColor color(tile_image.color(15)); QColor color(tile_image.color(15));
color.setAlpha(0); color.setAlpha(0);
tile_image.setColor(15, color.rgba()); tile_image.setColor(15, color.rgba());
} }
QPoint origin = QPoint(x*8, y*8); QPoint origin = QPoint(x*8, y*8);
metatile_painter.drawImage(origin, tile_image.mirrored(tile_.xflip == 1, tile_.yflip == 1)); metatile_painter.drawImage(origin, tile_image.mirrored(tile_.xflip == 1, tile_.yflip == 1));
} }

3
map.h
View file

@ -75,6 +75,7 @@ public:
public: public:
QString name; QString name;
QString constantName;
QString attributes_label; QString attributes_label;
QString events_label; QString events_label;
QString scripts_label; QString scripts_label;
@ -102,6 +103,8 @@ public:
Blockdata* blockdata = NULL; Blockdata* blockdata = NULL;
public: public:
void setName(QString mapName);
static QString mapConstantFromName(QString mapName);
int getWidth(); int getWidth();
int getHeight(); int getHeight();
Tileset* getBlockTileset(int); Tileset* getBlockTileset(int);

View file

@ -31,7 +31,7 @@ QString Project::getProjectTitle() {
Map* Project::loadMap(QString map_name) { Map* Project::loadMap(QString map_name) {
Map *map = new Map; Map *map = new Map;
map->name = map_name; map->setName(map_name);
readMapHeader(map); readMapHeader(map);
readMapAttributes(map); readMapAttributes(map);
getTilesets(map); getTilesets(map);
@ -66,8 +66,13 @@ void Project::loadMapConnections(Map *map) {
Connection *connection = new Connection; Connection *connection = new Connection;
connection->direction = command.value(1); connection->direction = command.value(1);
connection->offset = command.value(2); connection->offset = command.value(2);
connection->map_name = command.value(3); QString mapConstant = command.value(3);
map->connections.append(connection); if (mapConstantsToMapNames.contains(mapConstant)) {
connection->map_name = mapConstantsToMapNames[mapConstant];
map->connections.append(connection);
} else {
qDebug() << QString("Failed to find connected map for map constant '%1'").arg(mapConstant);
}
} }
} }
} }
@ -512,9 +517,15 @@ void Project::readMapGroups() {
} else if (macro == ".4byte") { } else if (macro == ".4byte") {
if (group != -1) { if (group != -1) {
for (int j = 1; j < params.length(); j++) { for (int j = 1; j < params.length(); j++) {
QString mapName = params.value(j);
QStringList *list = groupedMaps->value(group); QStringList *list = groupedMaps->value(group);
list->append(params.value(j)); list->append(mapName);
maps->append(params.value(j)); maps->append(mapName);
// Build the mapping and reverse mapping between map constants and map names.
QString mapConstant = Map::mapConstantFromName(mapName);
mapConstantsToMapNames.insert(mapConstant, mapName);
mapNamesToMapConstants.insert(mapName, mapConstant);
} }
} }
} }
@ -654,9 +665,9 @@ void Project::loadObjectPixmaps(QList<Event*> objects) {
object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(0, 0, 16, 16); object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(0, 0, 16, 16);
} else if (event_type == "warp") { } else if (event_type == "warp") {
object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(16, 0, 16, 16); object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(16, 0, 16, 16);
} else if (event_type == "trap") { } else if (event_type == "trap" || event_type == "trap_weather") {
object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(32, 0, 16, 16); object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(32, 0, 16, 16);
} else if (event_type == "sign" || event_type == "hidden item") { } else if (event_type == "sign" || event_type == "event_hidden_item" || event_type == "event_secret_base") {
object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(48, 0, 16, 16); object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(48, 0, 16, 16);
} }
@ -687,85 +698,107 @@ void Project::saveMapEvents(Map *map) {
QString path = root + QString("/data/maps/events/%1.inc").arg(map->name); QString path = root + QString("/data/maps/events/%1.inc").arg(map->name);
QString text = ""; QString text = "";
text += QString("%1::\n").arg(map->object_events_label); if (map->events["object"].length() > 0) {
for (int i = 0; i < map->events["object"].length(); i++) { text += QString("%1::\n").arg(map->object_events_label);
Event *object_event = map->events["object"].value(i); for (int i = 0; i < map->events["object"].length(); i++) {
int radius_x = object_event->getInt("radius_x"); Event *object_event = map->events["object"].value(i);
int radius_y = object_event->getInt("radius_y"); int radius_x = object_event->getInt("radius_x");
QString radius = QString("%1").arg((radius_x & 0xf) + ((radius_y & 0xf) << 4)); int radius_y = object_event->getInt("radius_y");
uint16_t x = object_event->getInt("x"); QString radius = QString("%1").arg((radius_x & 0xf) + ((radius_y & 0xf) << 4));
uint16_t y = object_event->getInt("y"); uint16_t x = object_event->getInt("x");
uint16_t y = object_event->getInt("y");
text += QString("\tobject_event %1").arg(i + 1); text += QString("\tobject_event %1").arg(i + 1);
text += QString(", %1").arg(object_event->get("sprite")); text += QString(", %1").arg(object_event->get("sprite"));
text += QString(", %1").arg(object_event->get("replacement")); text += QString(", %1").arg(object_event->get("replacement"));
text += QString(", %1").arg(x & 0xff); text += QString(", %1").arg(x & 0xff);
text += QString(", %1").arg((x >> 8) & 0xff); text += QString(", %1").arg((x >> 8) & 0xff);
text += QString(", %1").arg(y & 0xff); text += QString(", %1").arg(y & 0xff);
text += QString(", %1").arg((y >> 8) & 0xff); text += QString(", %1").arg((y >> 8) & 0xff);
text += QString(", %1").arg(object_event->get("elevation")); text += QString(", %1").arg(object_event->get("elevation"));
text += QString(", %1").arg(object_event->get("behavior")); text += QString(", %1").arg(object_event->get("behavior"));
text += QString(", %1").arg(radius); text += QString(", %1").arg(radius);
text += QString(", 0"); text += QString(", 0");
text += QString(", %1").arg(object_event->get("property")); text += QString(", %1").arg(object_event->get("property"));
text += QString(", 0"); text += QString(", 0");
text += QString(", %1").arg(object_event->get("sight_radius")); text += QString(", %1").arg(object_event->get("sight_radius"));
text += QString(", 0"); text += QString(", 0");
text += QString(", %1").arg(object_event->get("script_label")); text += QString(", %1").arg(object_event->get("script_label"));
text += QString(", %1").arg(object_event->get("event_flag")); text += QString(", %1").arg(object_event->get("event_flag"));
text += QString(", 0"); text += QString(", 0");
text += QString(", 0"); text += QString(", 0");
text += "\n";
}
text += "\n"; text += "\n";
} }
text += "\n";
text += QString("%1::\n").arg(map->warps_label); if (map->events["warp"].length() > 0) {
for (Event *warp : map->events["warp"]) { text += QString("%1::\n").arg(map->warps_label);
text += QString("\twarp_def %1").arg(warp->get("x")); for (Event *warp : map->events["warp"]) {
text += QString(", %1").arg(warp->get("y")); text += QString("\twarp_def %1").arg(warp->get("x"));
text += QString(", %1").arg(warp->get("elevation")); text += QString(", %1").arg(warp->get("y"));
text += QString(", %1").arg(warp->get("destination_warp")); text += QString(", %1").arg(warp->get("elevation"));
text += QString(", %1").arg(warp->get("destination_map")); text += QString(", %1").arg(warp->get("destination_warp"));
text += QString(", %1").arg(mapNamesToMapConstants[warp->get("destination_map_name")]);
text += "\n";
}
text += "\n"; text += "\n";
} }
text += "\n";
text += QString("%1::\n").arg(map->coord_events_label); if (map->events["trap"].length() + map->events["trap_weather"].length() > 0) {
for (Event *coords : map->events["trap"]) { text += QString("%1::\n").arg(map->coord_events_label);
text += QString("\tcoord_event %1").arg(coords->get("x")); for (Event *coords : map->events["trap"]) {
text += QString(", %1").arg(coords->get("y")); text += QString("\tcoord_event %1").arg(coords->get("x"));
text += QString(", %1").arg(coords->get("elevation")); text += QString(", %1").arg(coords->get("y"));
text += QString(", 0"); text += QString(", %1").arg(coords->get("elevation"));
text += QString(", %1").arg(coords->get("coord_unknown1")); text += QString(", 0");
text += QString(", %1").arg(coords->get("coord_unknown2")); text += QString(", %1").arg(coords->get("coord_unknown1"));
text += QString(", 0"); text += QString(", %1").arg(coords->get("coord_unknown2"));
text += QString(", %1").arg(coords->get("script_label")); text += QString(", 0");
text += QString(", %1").arg(coords->get("script_label"));
text += "\n";
}
for (Event *coords : map->events["trap_weather"]) {
text += QString("\tcoord_weather_event %1").arg(coords->get("x"));
text += QString(", %1").arg(coords->get("y"));
text += QString(", %1").arg(coords->get("elevation"));
text += QString(", %1").arg(coords->get("weather"));
text += "\n";
}
text += "\n"; text += "\n";
} }
text += "\n";
text += QString("%1::\n").arg(map->bg_events_label); if (map->events["sign"].length() +
for (Event *sign : map->events["sign"]) { map->events["event_hidden_item"].length() +
text += QString("\tbg_event %1").arg(sign->get("x")); map->events["event_secret_base"].length() > 0)
text += QString(", %1").arg(sign->get("y")); {
text += QString(", %1").arg(sign->get("elevation")); text += QString("%1::\n").arg(map->bg_events_label);
text += QString(", %1").arg(sign->get("type")); for (Event *sign : map->events["sign"]) {
text += QString(", 0"); text += QString("\tbg_event %1").arg(sign->get("x"));
text += QString(", %1").arg(sign->get("script_label")); text += QString(", %1").arg(sign->get("y"));
text += QString(", %1").arg(sign->get("elevation"));
text += QString(", %1").arg(sign->get("type"));
text += QString(", 0");
text += QString(", %1").arg(sign->get("script_label"));
text += "\n";
}
for (Event *item : map->events["event_hidden_item"]) {
text += QString("\tbg_hidden_item_event %1").arg(item->get("x"));
text += QString(", %1").arg(item->get("y"));
text += QString(", %1").arg(item->get("elevation"));
text += QString(", %1").arg(item->get("item"));
text += QString(", %1").arg(item->get("flag"));
text += "\n";
}
for (Event *item : map->events["event_secret_base"]) {
text += QString("\tbg_secret_base_event %1").arg(item->get("x"));
text += QString(", %1").arg(item->get("y"));
text += QString(", %1").arg(item->get("elevation"));
text += QString(", %1").arg(item->get("secret_base_map"));
text += "\n";
}
text += "\n"; text += "\n";
} }
for (Event *item : map->events["hidden item"]) {
text += QString("\tbg_event %1").arg(item->get("x"));
text += QString(", %1").arg(item->get("y"));
text += QString(", %1").arg(item->get("elevation"));
text += QString(", %1").arg(item->get("type"));
text += QString(", 0");
text += QString(", %1").arg(item->get("item"));
text += QString(", %1").arg(item->get("item_unknown5"));
text += QString(", %1").arg(item->get("item_unknown6"));
text += "\n";
}
text += "\n";
text += QString("%1::\n").arg(map->events_label); text += QString("%1::\n").arg(map->events_label);
text += QString("\tmap_events %1, %2, %3, %4\n") text += QString("\tmap_events %1, %2, %3, %4\n")
@ -846,15 +879,22 @@ void Project::readMapEvents(Map *map) {
warp->put("y", command.value(i++)); warp->put("y", command.value(i++));
warp->put("elevation", command.value(i++)); warp->put("elevation", command.value(i++));
warp->put("destination_warp", command.value(i++)); warp->put("destination_warp", command.value(i++));
warp->put("destination_map", command.value(i++));
warp->put("event_type", "warp"); // Ensure the warp destination map constant is valid before adding it to the warps.
map->events["warp"].append(warp); QString mapConstant = command.value(i++);
if (mapConstantsToMapNames.contains(mapConstant)) {
warp->put("destination_map_name", mapConstantsToMapNames[mapConstant]);
warp->put("event_type", "warp");
map->events["warp"].append(warp);
} else {
qDebug() << QString("Destination map constant '%1' is invalid for warp").arg(mapConstant);
}
} }
} }
QList<QStringList> *coords = getLabelMacros(parse(text), map->coord_events_label); QList<QStringList> *coords = getLabelMacros(parse(text), map->coord_events_label);
map->events["trap"].clear(); map->events["trap"].clear();
map->events["trap_weather"].clear();
for (QStringList command : *coords) { for (QStringList command : *coords) {
if (command.value(0) == "coord_event") { if (command.value(0) == "coord_event") {
Event *coord = new Event; Event *coord = new Event;
@ -877,12 +917,23 @@ void Project::readMapEvents(Map *map) {
coord->put("event_type", "trap"); coord->put("event_type", "trap");
map->events["trap"].append(coord); map->events["trap"].append(coord);
} else if (command.value(0) == "coord_weather_event") {
Event *coord = new Event;
coord->put("map_name", map->name);
int i = 1;
coord->put("x", command.value(i++));
coord->put("y", command.value(i++));
coord->put("elevation", command.value(i++));
coord->put("weather", command.value(i++));
coord->put("event_type", "trap_weather");
map->events["trap_weather"].append(coord);
} }
} }
QList<QStringList> *bgs = getLabelMacros(parse(text), map->bg_events_label); QList<QStringList> *bgs = getLabelMacros(parse(text), map->bg_events_label);
map->events["hidden item"].clear();
map->events["sign"].clear(); map->events["sign"].clear();
map->events["event_hidden_item"].clear();
map->events["event_secret_base"].clear();
for (QStringList command : *bgs) { for (QStringList command : *bgs) {
if (command.value(0) == "bg_event") { if (command.value(0) == "bg_event") {
Event *bg = new Event; Event *bg = new Event;
@ -893,23 +944,33 @@ void Project::readMapEvents(Map *map) {
bg->put("elevation", command.value(i++)); bg->put("elevation", command.value(i++));
bg->put("type", command.value(i++)); bg->put("type", command.value(i++));
i++; i++;
if (bg->is_hidden_item()) { bg->put("script_label", command.value(i++));
bg->put("item", command.value(i++)); //sign_unknown7
bg->put("item_unknown5", command.value(i++)); bg->put("event_type", "sign");
bg->put("item_unknown6", command.value(i++)); map->events["sign"].append(bg);
} else if (command.value(0) == "bg_hidden_item_event") {
bg->put("event_type", "hidden item"); Event *bg = new Event;
map->events["hidden item"].append(bg); bg->put("map_name", map->name);
} else { int i = 1;
bg->put("script_label", command.value(i++)); bg->put("x", command.value(i++));
//sign_unknown7 bg->put("y", command.value(i++));
bg->put("elevation", command.value(i++));
bg->put("event_type", "sign"); bg->put("item", command.value(i++));
map->events["sign"].append(bg); bg->put("flag", command.value(i++));
} bg->put("event_type", "event_hidden_item");
map->events["event_hidden_item"].append(bg);
} else if (command.value(0) == "bg_secret_base_event") {
Event *bg = new Event;
bg->put("map_name", map->name);
int i = 1;
bg->put("x", command.value(i++));
bg->put("y", command.value(i++));
bg->put("elevation", command.value(i++));
bg->put("secret_base_map", command.value(i++));
bg->put("event_type", "event_secret_base");
map->events["event_secret_base"].append(bg);
} }
} }
} }
QStringList Project::readCArray(QString text, QString label) { QStringList Project::readCArray(QString text, QString label) {

View file

@ -15,6 +15,8 @@ public:
QStringList *groupNames = NULL; QStringList *groupNames = NULL;
QList<QStringList*> *groupedMapNames = NULL; QList<QStringList*> *groupedMapNames = NULL;
QStringList *mapNames = NULL; QStringList *mapNames = NULL;
QMap<QString, QString> mapConstantsToMapNames;
QMap<QString, QString> mapNamesToMapConstants;
QMap<QString, Map*> *map_cache; QMap<QString, Map*> *map_cache;
Map* loadMap(QString); Map* loadMap(QString);