diff --git a/CHANGELOG.md b/CHANGELOG.md
index f536df56..da41ed29 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
### Changed
- Overhauled the region map editor, adding support for tilemaps, and significant customization. Also now supports pokefirered.
+- The Custom Attributes table for map headers and events now supports types other than strings.
- If an object event is inanimate, it will always render using its first frame.
- Unused metatile attribute bits are preserved instead of being cleared.
- The wild encounter editor is automatically disabled if the encounter JSON data cannot be read
@@ -42,6 +43,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
- The number and order of entries in the heal location data tables can now be changed arbitrarily, and independently of each other.
- The metatile behavior is now displayed in the bottom bar mouseover text.
- Removed some unnecessary error logs from the scripting API and added new useful ones.
+- If any JSON data is the incorrect type Porymap will now attempt to convert it.
### Fixed
- Fix events losing their assigned script when the script autocomplete is used.
diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui
index 2e1ddda6..52772b99 100644
--- a/forms/mainwindow.ui
+++ b/forms/mainwindow.ui
@@ -2276,14 +2276,14 @@
-
-
+
Allow Dig & Escape Rope
-
-
+
<html><head/><body><p>Allows the player to use Dig or Escape Rope</p></body></html>
@@ -2388,7 +2388,7 @@
Custom fields will be added to the map.json file for the current map.
- false
+ true
false
@@ -2405,6 +2405,11 @@
false
+
+
+ Type
+
+
Key
diff --git a/include/core/events.h b/include/core/events.h
index 912fe0c7..ba437c6c 100644
--- a/include/core/events.h
+++ b/include/core/events.h
@@ -151,8 +151,8 @@ public:
virtual QSet getExpectedFields() = 0;
void readCustomValues(QJsonObject values);
void addCustomValuesTo(OrderedJson::object *obj);
- QMap getCustomValues() { return this->customValues; }
- void setCustomValues(QMap newCustomValues) { this->customValues = newCustomValues; }
+ const QMap getCustomValues() { return this->customValues; }
+ void setCustomValues(const QMap newCustomValues) { this->customValues = newCustomValues; }
virtual void loadPixmap(Project *project) = 0;
@@ -173,6 +173,7 @@ public:
int getEventIndex();
+ static QString eventGroupToString(Event::Group group);
static QString eventTypeToString(Event::Type type);
static Event::Type eventTypeFromString(QString type);
@@ -192,7 +193,7 @@ protected:
int spriteHeight = 16;
bool usingSprite = false;
- QMap customValues;
+ QMap customValues;
QPixmap pixmap;
DraggablePixmapItem *pixmapItem = nullptr;
@@ -340,12 +341,12 @@ public:
void setDestinationMap(QString newDestinationMap) { this->destinationMap = newDestinationMap; }
QString getDestinationMap() { return this->destinationMap; }
- void setDestinationWarpID(int newDestinationWarpID) { this->destinationWarpID = newDestinationWarpID; }
- int getDestinationWarpID() { return this->destinationWarpID; }
+ void setDestinationWarpID(QString newDestinationWarpID) { this->destinationWarpID = newDestinationWarpID; }
+ QString getDestinationWarpID() { return this->destinationWarpID; }
private:
QString destinationMap;
- int destinationWarpID = 0;
+ QString destinationWarpID;
};
diff --git a/include/core/map.h b/include/core/map.h
index 2b10e6cf..24bcfd9e 100644
--- a/include/core/map.h
+++ b/include/core/map.h
@@ -42,23 +42,23 @@ public:
QString song;
QString layoutId;
QString location;
- QString requiresFlash;
- QString isFlyable;
+ bool requiresFlash;
QString weather;
QString type;
- QString show_location;
- QString allowRunning;
- QString allowBiking;
- QString allowEscapeRope;
+ bool show_location;
+ bool allowRunning;
+ bool allowBiking;
+ bool allowEscaping;
int floorNumber = 0;
QString battle_scene;
QString sharedEventsMap = "";
QString sharedScriptsMap = "";
- QMap customHeaders;
+ QMap customHeaders;
MapLayout *layout;
bool isPersistedToFile = true;
bool hasUnsavedDataChanges = false;
bool needsLayoutDir = true;
+ bool needsHealLocation = false;
QImage collision_image;
QPixmap collision_pixmap;
QImage image;
diff --git a/include/core/mapconnection.h b/include/core/mapconnection.h
index b6be238e..11aa0e59 100644
--- a/include/core/mapconnection.h
+++ b/include/core/mapconnection.h
@@ -8,7 +8,7 @@
class MapConnection {
public:
QString direction;
- QString offset;
+ int offset;
QString map_name;
};
diff --git a/include/core/maplayout.h b/include/core/maplayout.h
index 888e5372..13215fff 100644
--- a/include/core/maplayout.h
+++ b/include/core/maplayout.h
@@ -14,10 +14,10 @@ public:
static QString layoutConstantFromName(QString mapName);
QString id;
QString name;
- QString width;
- QString height;
- QString border_width;
- QString border_height;
+ int width;
+ int height;
+ int border_width;
+ int border_height;
QString border_path;
QString blockdata_path;
QString tileset_primary_label;
diff --git a/include/core/parseutil.h b/include/core/parseutil.h
index 97bf2e71..298325ee 100644
--- a/include/core/parseutil.h
+++ b/include/core/parseutil.h
@@ -72,7 +72,11 @@ public:
static QString removeLineComments(QString text, const QStringList &commentSymbols);
static QStringList splitShellCommand(QStringView command);
+ static int gameStringToInt(QString gameString, bool * ok = nullptr);
static bool gameStringToBool(QString gameString, bool * ok = nullptr);
+ static QString jsonToQString(QJsonValue value, bool * ok = nullptr);
+ static int jsonToInt(QJsonValue value, bool * ok = nullptr);
+ static bool jsonToBool(QJsonValue value, bool * ok = nullptr);
private:
QString root;
diff --git a/include/lib/orderedjson.h b/include/lib/orderedjson.h
index 17dafe10..c13ec13c 100644
--- a/include/lib/orderedjson.h
+++ b/include/lib/orderedjson.h
@@ -60,6 +60,9 @@
#include
#include
#include
+#include
+#include
+#include
#include
#include
@@ -129,6 +132,8 @@ public:
int>::type = 0>
Json(const V & v) : Json(array(v.begin(), v.end())) {}
+ static const Json fromQJsonValue(QJsonValue value);
+
// This prevents Json(some_pointer) from accidentally producing a bool. Use
// Json(bool(some_pointer)) if that behavior is desired.
Json(void *) = delete;
diff --git a/include/mainwindow.h b/include/mainwindow.h
index 84290f7a..b8653d58 100644
--- a/include/mainwindow.h
+++ b/include/mainwindow.h
@@ -196,7 +196,7 @@ private slots:
void on_checkBox_ShowLocation_stateChanged(int selected);
void on_checkBox_AllowRunning_stateChanged(int selected);
void on_checkBox_AllowBiking_stateChanged(int selected);
- void on_checkBox_AllowEscapeRope_stateChanged(int selected);
+ void on_checkBox_AllowEscaping_stateChanged(int selected);
void on_spinBox_FloorNumber_valueChanged(int offset);
void on_actionUse_Encounter_Json_triggered(bool checked);
void on_actionMonitor_Project_Files_triggered(bool checked);
@@ -219,6 +219,7 @@ private slots:
void on_toolButton_deleteObject_clicked();
void addNewEvent(Event::Type type);
+ void tryAddEventTab(QWidget * tab, Event::Group group);
void displayEventTabs();
void updateSelectedObjects();
void updateObjects();
@@ -387,6 +388,7 @@ private:
void redrawMetatileSelection();
QObjectList shortcutableObjects() const;
+ void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false);
};
enum MapListUserRoles {
diff --git a/include/project.h b/include/project.h
index bc42ddb5..28c3a296 100644
--- a/include/project.h
+++ b/include/project.h
@@ -26,8 +26,9 @@ struct EventGraphics
bool inanimate;
};
-static QString NONE_MAP_CONSTANT = "MAP_NONE";
-static QString NONE_MAP_NAME = "None";
+// The constant and displayed name of the special map value used by warps with multiple potential destinations
+static QString DYNAMIC_MAP_CONSTANT = "MAP_DYNAMIC";
+static QString DYNAMIC_MAP_NAME = "Dynamic";
class Project : public QObject
{
@@ -136,7 +137,7 @@ public:
bool readSpeciesIconPaths();
QMap speciesToIconPath;
- QMap getTopLevelMapFields();
+ QSet getTopLevelMapFields();
bool loadMapData(Map*);
bool readMapLayouts();
bool loadLayout(MapLayout *);
diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h
index a4cdf4e2..e12296af 100644
--- a/include/ui/connectionpixmapitem.h
+++ b/include/ui/connectionpixmapitem.h
@@ -15,7 +15,7 @@ public:
setFlag(ItemSendsGeometryChanges);
this->initialX = x;
this->initialY = y;
- this->initialOffset = connection->offset.toInt();
+ this->initialOffset = connection->offset;
this->baseMapWidth = baseMapWidth;
this->baseMapHeight = baseMapHeight;
}
diff --git a/include/ui/customattributestable.h b/include/ui/customattributestable.h
index bf9334d0..f17f4877 100644
--- a/include/ui/customattributestable.h
+++ b/include/ui/customattributestable.h
@@ -12,11 +12,15 @@ public:
explicit CustomAttributesTable(Event *event, QWidget *parent = nullptr);
~CustomAttributesTable();
+ static const QMap getAttributes(QTableWidget * table);
+ static QJsonValue pickType(QWidget * parent, bool * ok = nullptr);
+ static void addAttribute(QTableWidget * table, QString key, QJsonValue value, bool isNew = false);
+ static bool deleteSelectedAttributes(QTableWidget * table);
+
private:
Event *event;
QTableWidget *table;
void resizeVertically();
- QMap getTableFields();
};
#endif // CUSTOMATTRIBUTESTABLE_H
diff --git a/include/ui/eventframes.h b/include/ui/eventframes.h
index 181ac141..a85a8f08 100644
--- a/include/ui/eventframes.h
+++ b/include/ui/eventframes.h
@@ -133,7 +133,7 @@ public:
public:
NoScrollComboBox *combo_dest_map;
- NoScrollSpinBox *spinner_dest_warp;
+ NoScrollComboBox *combo_dest_warp;
private:
WarpEvent *warp;
diff --git a/src/core/events.cpp b/src/core/events.cpp
index 9f08174f..bf67c566 100644
--- a/src/core/events.cpp
+++ b/src/core/events.cpp
@@ -43,7 +43,7 @@ void Event::readCustomValues(QJsonObject values) {
QSet expectedFields = this->getExpectedFields();
for (QString key : values.keys()) {
if (!expectedFields.contains(key)) {
- this->customValues[key] = values[key].toString();
+ this->customValues[key] = values[key];
}
}
}
@@ -51,7 +51,7 @@ void Event::readCustomValues(QJsonObject values) {
void Event::addCustomValuesTo(OrderedJson::object *obj) {
for (QString key : this->customValues.keys()) {
if (!obj->contains(key)) {
- (*obj)[key] = this->customValues[key];
+ (*obj)[key] = OrderedJson::fromQJsonValue(this->customValues[key]);
}
}
}
@@ -60,6 +60,23 @@ void Event::modify() {
this->map->modify();
}
+QString Event::eventGroupToString(Event::Group group) {
+ switch (group) {
+ case Event::Group::Object:
+ return "Object";
+ case Event::Group::Warp:
+ return "Warp";
+ case Event::Group::Coord:
+ return "Trigger";
+ case Event::Group::Bg:
+ return "BG";
+ case Event::Group::Heal:
+ return "Healspot";
+ default:
+ return "";
+ }
+}
+
QString Event::eventTypeToString(Event::Type type) {
switch (type) {
case Event::Type::Object:
@@ -163,17 +180,17 @@ OrderedJson::object ObjectEvent::buildEventJson(Project *) {
}
bool ObjectEvent::loadFromJson(QJsonObject json, Project *) {
- this->setX(json["x"].toInt());
- this->setY(json["y"].toInt());
- this->setElevation(json["elevation"].toInt());
- this->setGfx(json["graphics_id"].toString());
- this->setMovement(json["movement_type"].toString());
- this->setRadiusX(json["movement_range_x"].toInt());
- this->setRadiusY(json["movement_range_y"].toInt());
- this->setTrainerType(json["trainer_type"].toString());
- this->setSightRadiusBerryTreeID(json["trainer_sight_or_berry_tree_id"].toString());
- this->setScript(json["script"].toString());
- this->setFlag(json["flag"].toString());
+ this->setX(ParseUtil::jsonToInt(json["x"]));
+ this->setY(ParseUtil::jsonToInt(json["y"]));
+ this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
+ this->setGfx(ParseUtil::jsonToQString(json["graphics_id"]));
+ this->setMovement(ParseUtil::jsonToQString(json["movement_type"]));
+ this->setRadiusX(ParseUtil::jsonToInt(json["movement_range_x"]));
+ this->setRadiusY(ParseUtil::jsonToInt(json["movement_range_y"]));
+ this->setTrainerType(ParseUtil::jsonToQString(json["trainer_type"]));
+ this->setSightRadiusBerryTreeID(ParseUtil::jsonToQString(json["trainer_sight_or_berry_tree_id"]));
+ this->setScript(ParseUtil::jsonToQString(json["script"]));
+ this->setFlag(ParseUtil::jsonToQString(json["flag"]));
this->readCustomValues(json);
@@ -220,7 +237,7 @@ void ObjectEvent::loadPixmap(Project *project) {
// Invalid gfx constant.
// If this is a number, try to use that instead.
bool ok;
- int altGfx = this->gfx.toInt(&ok);
+ int altGfx = ParseUtil::gameStringToInt(this->gfx, &ok);
if (ok && (altGfx < project->gfxDefines.count())) {
eventGfx = project->eventGraphicsMap.value(project->gfxDefines.key(altGfx, "NULL"), nullptr);
}
@@ -311,20 +328,20 @@ OrderedJson::object CloneObjectEvent::buildEventJson(Project *project) {
}
bool CloneObjectEvent::loadFromJson(QJsonObject json, Project *project) {
- this->setX(json["x"].toInt());
- this->setY(json["y"].toInt());
- this->setGfx(json["graphics_id"].toString());
- this->setTargetID(json["target_local_id"].toInt());
+ this->setX(ParseUtil::jsonToInt(json["x"]));
+ this->setY(ParseUtil::jsonToInt(json["y"]));
+ this->setGfx(ParseUtil::jsonToQString(json["graphics_id"]));
+ this->setTargetID(ParseUtil::jsonToInt(json["target_local_id"]));
// Ensure the target map constant is valid before adding it to the events.
- QString mapConstant = json["target_map"].toString();
+ QString mapConstant = ParseUtil::jsonToQString(json["target_map"]);
if (project->mapConstantsToMapNames.contains(mapConstant)) {
this->setTargetMap(project->mapConstantsToMapNames.value(mapConstant));
- } else if (mapConstant == NONE_MAP_CONSTANT) {
- this->setTargetMap(NONE_MAP_NAME);
+ } else if (mapConstant == DYNAMIC_MAP_CONSTANT) {
+ this->setTargetMap(DYNAMIC_MAP_NAME);
} else {
- logError(QString("Destination map constant '%1' is invalid").arg(mapConstant));
- return false;
+ logWarn(QString("Target Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(DYNAMIC_MAP_CONSTANT));
+ this->setTargetMap(DYNAMIC_MAP_NAME);
}
this->readCustomValues(json);
@@ -421,20 +438,20 @@ OrderedJson::object WarpEvent::buildEventJson(Project *project) {
}
bool WarpEvent::loadFromJson(QJsonObject json, Project *project) {
- this->setX(json["x"].toInt());
- this->setY(json["y"].toInt());
- this->setElevation(json["elevation"].toInt());
- this->setDestinationWarpID(json["dest_warp_id"].toInt());
+ this->setX(ParseUtil::jsonToInt(json["x"]));
+ this->setY(ParseUtil::jsonToInt(json["y"]));
+ this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
+ this->setDestinationWarpID(ParseUtil::jsonToQString(json["dest_warp_id"]));
// Ensure the warp destination map constant is valid before adding it to the warps.
- QString mapConstant = json["dest_map"].toString();
+ QString mapConstant = ParseUtil::jsonToQString(json["dest_map"]);
if (project->mapConstantsToMapNames.contains(mapConstant)) {
this->setDestinationMap(project->mapConstantsToMapNames.value(mapConstant));
- } else if (mapConstant == NONE_MAP_CONSTANT) {
- this->setDestinationMap(NONE_MAP_NAME);
+ } else if (mapConstant == DYNAMIC_MAP_CONSTANT) {
+ this->setDestinationMap(DYNAMIC_MAP_NAME);
} else {
- logError(QString("Destination map constant '%1' is invalid for warp").arg(mapConstant));
- return false;
+ logWarn(QString("Destination Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(DYNAMIC_MAP_CONSTANT));
+ this->setDestinationMap(DYNAMIC_MAP_NAME);
}
this->readCustomValues(json);
@@ -444,7 +461,7 @@ bool WarpEvent::loadFromJson(QJsonObject json, Project *project) {
void WarpEvent::setDefaultValues(Project *) {
if (this->getMap()) this->setDestinationMap(this->getMap()->name);
- this->setDestinationWarpID(0);
+ this->setDestinationWarpID("0");
this->setElevation(0);
}
@@ -515,12 +532,12 @@ OrderedJson::object TriggerEvent::buildEventJson(Project *) {
}
bool TriggerEvent::loadFromJson(QJsonObject json, Project *) {
- this->setX(json["x"].toInt());
- this->setY(json["y"].toInt());
- this->setElevation(json["elevation"].toInt());
- this->setScriptVar(json["var"].toString());
- this->setScriptVarValue(json["var_value"].toString());
- this->setScriptLabel(json["script"].toString());
+ this->setX(ParseUtil::jsonToInt(json["x"]));
+ this->setY(ParseUtil::jsonToInt(json["y"]));
+ this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
+ this->setScriptVar(ParseUtil::jsonToQString(json["var"]));
+ this->setScriptVarValue(ParseUtil::jsonToQString(json["var_value"]));
+ this->setScriptLabel(ParseUtil::jsonToQString(json["script"]));
this->readCustomValues(json);
@@ -589,10 +606,10 @@ OrderedJson::object WeatherTriggerEvent::buildEventJson(Project *) {
}
bool WeatherTriggerEvent::loadFromJson(QJsonObject json, Project *) {
- this->setX(json["x"].toInt());
- this->setY(json["y"].toInt());
- this->setElevation(json["elevation"].toInt());
- this->setWeather(json["weather"].toString());
+ this->setX(ParseUtil::jsonToInt(json["x"]));
+ this->setY(ParseUtil::jsonToInt(json["y"]));
+ this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
+ this->setWeather(ParseUtil::jsonToQString(json["weather"]));
this->readCustomValues(json);
@@ -665,11 +682,11 @@ OrderedJson::object SignEvent::buildEventJson(Project *) {
}
bool SignEvent::loadFromJson(QJsonObject json, Project *) {
- this->setX(json["x"].toInt());
- this->setY(json["y"].toInt());
- this->setElevation(json["elevation"].toInt());
- this->setFacingDirection(json["player_facing_dir"].toString());
- this->setScriptLabel(json["script"].toString());
+ this->setX(ParseUtil::jsonToInt(json["x"]));
+ this->setY(ParseUtil::jsonToInt(json["y"]));
+ this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
+ this->setFacingDirection(ParseUtil::jsonToQString(json["player_facing_dir"]));
+ this->setScriptLabel(ParseUtil::jsonToQString(json["script"]));
this->readCustomValues(json);
@@ -746,16 +763,16 @@ OrderedJson::object HiddenItemEvent::buildEventJson(Project *) {
}
bool HiddenItemEvent::loadFromJson(QJsonObject json, Project *) {
- this->setX(json["x"].toInt());
- this->setY(json["y"].toInt());
- this->setElevation(json["elevation"].toInt());
- this->setItem(json["item"].toString());
- this->setFlag(json["flag"].toString());
+ this->setX(ParseUtil::jsonToInt(json["x"]));
+ this->setY(ParseUtil::jsonToInt(json["y"]));
+ this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
+ this->setItem(ParseUtil::jsonToQString(json["item"]));
+ this->setFlag(ParseUtil::jsonToQString(json["flag"]));
if (projectConfig.getHiddenItemQuantityEnabled()) {
- this->setQuantity(json["quantity"].toInt());
+ this->setQuantity(ParseUtil::jsonToInt(json["quantity"]));
}
if (projectConfig.getHiddenItemRequiresItemfinderEnabled()) {
- this->setUnderfoot(json["underfoot"].toBool());
+ this->setUnderfoot(ParseUtil::jsonToBool(json["underfoot"]));
}
this->readCustomValues(json);
@@ -834,10 +851,10 @@ OrderedJson::object SecretBaseEvent::buildEventJson(Project *) {
}
bool SecretBaseEvent::loadFromJson(QJsonObject json, Project *) {
- this->setX(json["x"].toInt());
- this->setY(json["y"].toInt());
- this->setElevation(json["elevation"].toInt());
- this->setBaseID(json["secret_base_id"].toString());
+ this->setX(ParseUtil::jsonToInt(json["x"]));
+ this->setY(ParseUtil::jsonToInt(json["y"]));
+ this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
+ this->setBaseID(ParseUtil::jsonToQString(json["secret_base_id"]));
this->readCustomValues(json);
diff --git a/src/core/map.cpp b/src/core/map.cpp
index e12793b8..8080682e 100644
--- a/src/core/map.cpp
+++ b/src/core/map.cpp
@@ -310,10 +310,10 @@ void Map::setDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool
setNewDimensionsBlockdata(newWidth, newHeight);
}
- int oldWidth = layout->width.toInt();
- int oldHeight = layout->height.toInt();
- layout->width = QString::number(newWidth);
- layout->height = QString::number(newHeight);
+ int oldWidth = layout->width;
+ int oldHeight = layout->height;
+ layout->width = newWidth;
+ layout->height = newHeight;
if (enableScriptCallback && (oldWidth != newWidth || oldHeight != newHeight)) {
Scripting::cb_MapResized(oldWidth, oldHeight, newWidth, newHeight);
@@ -328,10 +328,10 @@ void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata,
setNewBorderDimensionsBlockdata(newWidth, newHeight);
}
- int oldWidth = layout->border_width.toInt();
- int oldHeight = layout->border_height.toInt();
- layout->border_width = QString::number(newWidth);
- layout->border_height = QString::number(newHeight);
+ int oldWidth = layout->border_width;
+ int oldHeight = layout->border_height;
+ layout->border_width = newWidth;
+ layout->border_height = newHeight;
if (enableScriptCallback && (oldWidth != newWidth || oldHeight != newHeight)) {
Scripting::cb_BorderResized(oldWidth, oldHeight, newWidth, newHeight);
diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp
index 8b1a1d3f..310017be 100644
--- a/src/core/maplayout.cpp
+++ b/src/core/maplayout.cpp
@@ -16,17 +16,17 @@ QString MapLayout::layoutConstantFromName(QString mapName) {
}
int MapLayout::getWidth() {
- return width.toInt(nullptr, 0);
+ return width;
}
int MapLayout::getHeight() {
- return height.toInt(nullptr, 0);
+ return height;
}
int MapLayout::getBorderWidth() {
- return border_width.toInt(nullptr, 0);
+ return border_width;
}
int MapLayout::getBorderHeight() {
- return border_height.toInt(nullptr, 0);
+ return border_height;
}
diff --git a/src/core/mapparser.cpp b/src/core/mapparser.cpp
index 88592ab0..986c2c24 100644
--- a/src/core/mapparser.cpp
+++ b/src/core/mapparser.cpp
@@ -70,10 +70,10 @@ MapLayout *MapParser::parse(QString filepath, bool *error, Project *project)
}
MapLayout *mapLayout = new MapLayout();
- mapLayout->width = QString::number(mapWidth);
- mapLayout->height = QString::number(mapHeight);
- mapLayout->border_width = (borderWidth == 0) ? QString::number(2) : QString::number(borderWidth);
- mapLayout->border_height = (borderHeight == 0) ? QString::number(2) : QString::number(borderHeight);
+ mapLayout->width = mapWidth;
+ mapLayout->height = mapHeight;
+ mapLayout->border_width = (borderWidth == 0) ? DEFAULT_BORDER_WIDTH : borderWidth;
+ mapLayout->border_height = (borderHeight == 0) ? DEFAULT_BORDER_HEIGHT : borderHeight;
QList tilesets = project->tilesetLabelsOrdered;
diff --git a/src/core/parseutil.cpp b/src/core/parseutil.cpp
index 9c2be360..1f933e7c 100644
--- a/src/core/parseutil.cpp
+++ b/src/core/parseutil.cpp
@@ -404,13 +404,17 @@ QMap ParseUtil::readNamedIndexCArray(const QString &filename,
return map;
}
-bool ParseUtil::gameStringToBool(QString gameString, bool * ok) {
+int ParseUtil::gameStringToInt(QString gameString, bool * ok) {
if (ok) *ok = true;
if (QString::compare(gameString, "TRUE", Qt::CaseInsensitive) == 0)
- return true;
+ return 1;
if (QString::compare(gameString, "FALSE", Qt::CaseInsensitive) == 0)
- return false;
- return gameString.toInt(ok) != 0;
+ return 0;
+ return gameString.toInt(ok);
+}
+
+bool ParseUtil::gameStringToBool(QString gameString, bool * ok) {
+ return gameStringToInt(gameString, ok) != 0;
}
QMap> ParseUtil::readCStructs(const QString &filename, const QString &label, const QHash memberMap) {
@@ -522,6 +526,48 @@ bool ParseUtil::ensureFieldsExist(const QJsonObject &obj, const QList &
return true;
}
+// QJsonValues are strictly typed, and so will not attempt any implicit conversions.
+// The below functions are for attempting to convert a JSON value read from the user's
+// project to a QString, int, or bool (whichever Porymap expects).
+QString ParseUtil::jsonToQString(QJsonValue value, bool * ok) {
+ if (ok) *ok = true;
+ switch (value.type())
+ {
+ case QJsonValue::String: return value.toString();
+ case QJsonValue::Double: return QString::number(value.toInt());
+ case QJsonValue::Bool: return QString::number(value.toBool());
+ default: break;
+ }
+ if (ok) *ok = false;
+ return QString();
+}
+
+int ParseUtil::jsonToInt(QJsonValue value, bool * ok) {
+ if (ok) *ok = true;
+ switch (value.type())
+ {
+ case QJsonValue::String: return ParseUtil::gameStringToInt(value.toString(), ok);
+ case QJsonValue::Double: return value.toInt();
+ case QJsonValue::Bool: return value.toBool();
+ default: break;
+ }
+ if (ok) *ok = false;
+ return 0;
+}
+
+bool ParseUtil::jsonToBool(QJsonValue value, bool * ok) {
+ if (ok) *ok = true;
+ switch (value.type())
+ {
+ case QJsonValue::String: return ParseUtil::gameStringToBool(value.toString(), ok);
+ case QJsonValue::Double: return value.toInt() != 0;
+ case QJsonValue::Bool: return value.toBool();
+ default: break;
+ }
+ if (ok) *ok = false;
+ return false;
+}
+
int ParseUtil::getScriptLineNumber(const QString &filePath, const QString &scriptLabel) {
if (scriptLabel.isEmpty())
return 0;
diff --git a/src/editor.cpp b/src/editor.cpp
index cdd1619f..77380aab 100644
--- a/src/editor.cpp
+++ b/src/editor.cpp
@@ -10,6 +10,7 @@
#include "editcommands.h"
#include "config.h"
#include "scripting.h"
+#include "customattributestable.h"
#include
#include
#include
@@ -176,7 +177,7 @@ void Editor::setEditingConnections() {
bool controlsEnabled = selected_connection_item != nullptr;
setConnectionEditControlsEnabled(controlsEnabled);
if (selected_connection_item) {
- onConnectionOffsetChanged(selected_connection_item->connection->offset.toInt());
+ onConnectionOffsetChanged(selected_connection_item->connection->offset);
setConnectionMap(selected_connection_item->connection->map_name);
setCurrentConnectionDirection(selected_connection_item->connection->direction);
}
@@ -774,7 +775,7 @@ void Editor::setCurrentConnectionDirection(QString curDirection) {
selected_connection_item->connection->direction = curDirection;
QPixmap pixmap = connected_map->renderConnection(*selected_connection_item->connection, map->layout);
- int offset = selected_connection_item->connection->offset.toInt(nullptr, 0);
+ int offset = selected_connection_item->connection->offset;
selected_connection_item->initialOffset = offset;
int x = 0, y = 0;
if (selected_connection_item->connection->direction == "up") {
@@ -820,7 +821,7 @@ void Editor::updateCurrentConnectionDirection(QString curDirection) {
void Editor::onConnectionMoved(MapConnection* connection) {
updateMirroredConnectionOffset(connection);
- onConnectionOffsetChanged(connection->offset.toInt());
+ onConnectionOffsetChanged(connection->offset);
maskNonVisibleConnectionTiles();
}
@@ -834,7 +835,7 @@ void Editor::onConnectionOffsetChanged(int newOffset) {
void Editor::setConnectionEditControlValues(MapConnection* connection) {
QString mapName = connection ? connection->map_name : "";
QString direction = connection ? connection->direction : "";
- int offset = connection ? connection->offset.toInt() : 0;
+ int offset = connection ? connection->offset : 0;
ui->comboBox_ConnectedMap->blockSignals(true);
ui->comboBox_ConnectionDirection->blockSignals(true);
@@ -883,7 +884,7 @@ void Editor::onConnectionItemSelected(ConnectionPixmapItem* connectionItem) {
setConnectionEditControlValues(selected_connection_item->connection);
ui->spinBox_ConnectionOffset->setMaximum(selected_connection_item->getMaxOffset());
ui->spinBox_ConnectionOffset->setMinimum(selected_connection_item->getMinOffset());
- onConnectionOffsetChanged(selected_connection_item->connection->offset.toInt());
+ onConnectionOffsetChanged(selected_connection_item->connection->offset);
}
void Editor::setSelectedConnectionFromMap(QString mapName) {
@@ -1565,7 +1566,7 @@ void Editor::createConnectionItem(MapConnection* connection, bool hide) {
}
QPixmap pixmap = connected_map->renderConnection(*connection, map->layout);
- int offset = connection->offset.toInt(nullptr, 0);
+ int offset = connection->offset;
int x = 0, y = 0;
if (connection->direction == "up") {
x = offset * 16;
@@ -1728,7 +1729,7 @@ void Editor::updateConnectionOffset(int offset) {
selected_connection_item->blockSignals(true);
offset = qMin(offset, selected_connection_item->getMaxOffset());
offset = qMax(offset, selected_connection_item->getMinOffset());
- selected_connection_item->connection->offset = QString::number(offset);
+ selected_connection_item->connection->offset = offset;
if (selected_connection_item->connection->direction == "up" || selected_connection_item->connection->direction == "down") {
selected_connection_item->setX(selected_connection_item->initialX + (offset - selected_connection_item->initialOffset) * 16);
} else if (selected_connection_item->connection->direction == "left" || selected_connection_item->connection->direction == "right") {
@@ -1747,7 +1748,7 @@ void Editor::setConnectionMap(QString mapName) {
if (!selected_connection_item)
return;
- if (mapName.isEmpty() || mapName == NONE_MAP_NAME) {
+ if (mapName.isEmpty() || mapName == DYNAMIC_MAP_NAME) {
removeCurrentConnection();
return;
}
@@ -1783,7 +1784,7 @@ void Editor::addNewConnection() {
MapConnection* newConnection = new MapConnection;
newConnection->direction = minDirection;
- newConnection->offset = "0";
+ newConnection->offset = 0;
newConnection->map_name = defaultMapName;
map->connections.append(newConnection);
createConnectionItem(newConnection, true);
@@ -1851,7 +1852,7 @@ void Editor::updateMirroredConnection(MapConnection* connection, QString origina
otherMap->connections.append(mirrorConnection);
}
- mirrorConnection->offset = QString::number(-connection->offset.toInt());
+ mirrorConnection->offset = -connection->offset;
}
void Editor::removeCurrentConnection() {
@@ -1899,7 +1900,7 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) {
}
}
- if (mapName.isEmpty() || mapName == NONE_MAP_NAME) {
+ if (mapName.isEmpty() || mapName == DYNAMIC_MAP_NAME) {
// Remove dive/emerge connection
if (connection) {
map->connections.removeOne(connection);
@@ -1909,7 +1910,7 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) {
if (!connection) {
connection = new MapConnection;
connection->direction = direction;
- connection->offset = "0";
+ connection->offset = 0;
connection->map_name = mapName;
map->connections.append(connection);
updateMirroredConnection(connection, connection->direction, connection->map_name);
@@ -1952,17 +1953,7 @@ void Editor::toggleBorderVisibility(bool visible, bool enableScriptCallback)
void Editor::updateCustomMapHeaderValues(QTableWidget *table)
{
- QMap fields;
- for (int row = 0; row < table->rowCount(); row++) {
- QString keyStr = "";
- QString valueStr = "";
- QTableWidgetItem *key = table->item(row, 0);
- QTableWidgetItem *value = table->item(row, 1);
- if (key) keyStr = key->text();
- if (value) valueStr = value->text();
- fields[keyStr] = valueStr;
- }
- map->customHeaders = fields;
+ map->customHeaders = CustomAttributesTable::getAttributes(table);
emit editedMapData();
}
diff --git a/src/lib/orderedjson.cpp b/src/lib/orderedjson.cpp
index 699c8d12..025607ca 100644
--- a/src/lib/orderedjson.cpp
+++ b/src/lib/orderedjson.cpp
@@ -308,6 +308,33 @@ const Json & JsonArray::operator[] (int i) const {
else return m_value[i];
}
+const Json Json::fromQJsonValue(QJsonValue value) {
+ switch (value.type())
+ {
+ default:
+ case QJsonValue::String: return value.toString();
+ case QJsonValue::Double: return value.toInt();
+ case QJsonValue::Bool: return value.toBool();
+ case QJsonValue::Array:
+ {
+ QJsonArray qArr = value.toArray();
+ Json::array arr;
+ for (const auto &i: qArr)
+ arr.push_back(Json::fromQJsonValue(i));
+ return arr;
+ }
+ case QJsonValue::Object:
+ {
+ QJsonObject qObj = value.toObject();
+ Json::object obj;
+ for (auto it = qObj.constBegin(); it != qObj.constEnd(); it++)
+ obj[it.key()] = Json::fromQJsonValue(it.value());
+ return obj;
+ }
+ }
+}
+
+
/* * * * * * * * * * * * * * * * * * * *
* Comparison
*/
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 9c8098b0..3c10824f 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -381,28 +381,28 @@ void MainWindow::setProjectSpecificUIVisibility()
case BaseGameVersion::pokeruby:
ui->checkBox_AllowRunning->setVisible(false);
ui->checkBox_AllowBiking->setVisible(false);
- ui->checkBox_AllowEscapeRope->setVisible(false);
+ ui->checkBox_AllowEscaping->setVisible(false);
ui->label_AllowRunning->setVisible(false);
ui->label_AllowBiking->setVisible(false);
- ui->label_AllowEscapeRope->setVisible(false);
+ ui->label_AllowEscaping->setVisible(false);
ui->actionRegion_Map_Editor->setVisible(true);
break;
case BaseGameVersion::pokeemerald:
ui->checkBox_AllowRunning->setVisible(true);
ui->checkBox_AllowBiking->setVisible(true);
- ui->checkBox_AllowEscapeRope->setVisible(true);
+ ui->checkBox_AllowEscaping->setVisible(true);
ui->label_AllowRunning->setVisible(true);
ui->label_AllowBiking->setVisible(true);
- ui->label_AllowEscapeRope->setVisible(true);
+ ui->label_AllowEscaping->setVisible(true);
ui->actionRegion_Map_Editor->setVisible(true);
break;
case BaseGameVersion::pokefirered:
ui->checkBox_AllowRunning->setVisible(true);
ui->checkBox_AllowBiking->setVisible(true);
- ui->checkBox_AllowEscapeRope->setVisible(true);
+ ui->checkBox_AllowEscaping->setVisible(true);
ui->label_AllowRunning->setVisible(true);
ui->label_AllowBiking->setVisible(true);
- ui->label_AllowEscapeRope->setVisible(true);
+ ui->label_AllowEscaping->setVisible(true);
ui->actionRegion_Map_Editor->setVisible(true);
break;
}
@@ -719,6 +719,10 @@ void MainWindow::refreshMapScene()
}
void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_group) {
+ // Can't warp to dynamic maps
+ if (map_name == DYNAMIC_MAP_NAME)
+ return;
+
// Ensure valid destination map name.
if (!editor->project->mapNames.contains(map_name)) {
logError(QString("Invalid map name '%1'").arg(map_name));
@@ -737,10 +741,10 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_
}
// Select the target event.
- event_id -= Event::getIndexOffset(event_group);
+ int index = event_id - Event::getIndexOffset(event_group);
QList events = editor->map->events[event_group];
- if (event_id < events.length() && event_id >= 0) {
- Event *event = events.at(event_id);
+ if (index < events.length() && index >= 0) {
+ Event *event = events.at(index);
for (DraggablePixmapItem *item : editor->getObjects()) {
if (item->event == event) {
editor->selected_events->clear();
@@ -748,6 +752,9 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_
editor->updateSelectedEvents();
}
}
+ } else {
+ // Can still warp to this map, but can't select the specified event
+ logWarn(QString("%1 %2 doesn't exist on map '%3'").arg(Event::eventGroupToString(event_group)).arg(event_id).arg(map_name));
}
}
@@ -769,13 +776,13 @@ void MainWindow::displayMapProperties() {
const QSignalBlocker blockerA(ui->checkBox_AllowRunning);
const QSignalBlocker blockerB(ui->checkBox_AllowBiking);
const QSignalBlocker blockerC(ui->spinBox_FloorNumber);
- const QSignalBlocker blockerD(ui->checkBox_AllowEscapeRope);
+ const QSignalBlocker blockerD(ui->checkBox_AllowEscaping);
ui->checkBox_Visibility->setChecked(false);
ui->checkBox_ShowLocation->setChecked(false);
ui->checkBox_AllowRunning->setChecked(false);
ui->checkBox_AllowBiking->setChecked(false);
- ui->checkBox_AllowEscapeRope->setChecked(false);
+ ui->checkBox_AllowEscaping->setChecked(false);
if (!editor || !editor->map || !editor->project) {
ui->frame_3->setEnabled(false);
return;
@@ -793,27 +800,24 @@ void MainWindow::displayMapProperties() {
ui->comboBox_Song->setCurrentText(map->song);
ui->comboBox_Location->setCurrentText(map->location);
- ui->checkBox_Visibility->setChecked(ParseUtil::gameStringToBool(map->requiresFlash));
+ ui->checkBox_Visibility->setChecked(map->requiresFlash);
ui->comboBox_Weather->setCurrentText(map->weather);
ui->comboBox_Type->setCurrentText(map->type);
ui->comboBox_BattleScene->setCurrentText(map->battle_scene);
- ui->checkBox_ShowLocation->setChecked(ParseUtil::gameStringToBool(map->show_location));
+ ui->checkBox_ShowLocation->setChecked(map->show_location);
if (projectConfig.getBaseGameVersion() != BaseGameVersion::pokeruby) {
- ui->checkBox_AllowRunning->setChecked(ParseUtil::gameStringToBool(map->allowRunning));
- ui->checkBox_AllowBiking->setChecked(ParseUtil::gameStringToBool(map->allowBiking));
- ui->checkBox_AllowEscapeRope->setChecked(ParseUtil::gameStringToBool(map->allowEscapeRope));
+ ui->checkBox_AllowRunning->setChecked(map->allowRunning);
+ ui->checkBox_AllowBiking->setChecked(map->allowBiking);
+ ui->checkBox_AllowEscaping->setChecked(map->allowEscaping);
}
ui->spinBox_FloorNumber->setValue(map->floorNumber);
// Custom fields table.
ui->tableWidget_CustomHeaderFields->blockSignals(true);
ui->tableWidget_CustomHeaderFields->setRowCount(0);
- for (auto it = map->customHeaders.begin(); it != map->customHeaders.end(); it++) {
- int rowIndex = ui->tableWidget_CustomHeaderFields->rowCount();
- ui->tableWidget_CustomHeaderFields->insertRow(rowIndex);
- ui->tableWidget_CustomHeaderFields->setItem(rowIndex, 0, new QTableWidgetItem(it.key()));
- ui->tableWidget_CustomHeaderFields->setItem(rowIndex, 1, new QTableWidgetItem(it.value()));
- }
+ for (auto it = map->customHeaders.begin(); it != map->customHeaders.end(); it++)
+ CustomAttributesTable::addAttribute(ui->tableWidget_CustomHeaderFields, it.key(), it.value());
+ ui->tableWidget_CustomHeaderFields->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->tableWidget_CustomHeaderFields->blockSignals(false);
}
@@ -860,12 +864,7 @@ void MainWindow::on_comboBox_BattleScene_currentTextChanged(const QString &battl
void MainWindow::on_checkBox_Visibility_stateChanged(int selected)
{
if (editor && editor->map) {
- bool checked = selected == Qt::Checked;
- if (checked) {
- editor->map->requiresFlash = "TRUE";
- } else {
- editor->map->requiresFlash = "FALSE";
- }
+ editor->map->requiresFlash = (selected == Qt::Checked);
markMapEdited();
}
}
@@ -873,12 +872,7 @@ void MainWindow::on_checkBox_Visibility_stateChanged(int selected)
void MainWindow::on_checkBox_ShowLocation_stateChanged(int selected)
{
if (editor && editor->map) {
- bool checked = selected == Qt::Checked;
- if (checked) {
- editor->map->show_location = "TRUE";
- } else {
- editor->map->show_location = "FALSE";
- }
+ editor->map->show_location = (selected == Qt::Checked);
markMapEdited();
}
}
@@ -886,12 +880,7 @@ void MainWindow::on_checkBox_ShowLocation_stateChanged(int selected)
void MainWindow::on_checkBox_AllowRunning_stateChanged(int selected)
{
if (editor && editor->map) {
- bool checked = selected == Qt::Checked;
- if (checked) {
- editor->map->allowRunning = "1";
- } else {
- editor->map->allowRunning = "0";
- }
+ editor->map->allowRunning = (selected == Qt::Checked);
markMapEdited();
}
}
@@ -899,25 +888,15 @@ void MainWindow::on_checkBox_AllowRunning_stateChanged(int selected)
void MainWindow::on_checkBox_AllowBiking_stateChanged(int selected)
{
if (editor && editor->map) {
- bool checked = selected == Qt::Checked;
- if (checked) {
- editor->map->allowBiking = "1";
- } else {
- editor->map->allowBiking = "0";
- }
+ editor->map->allowBiking = (selected == Qt::Checked);
markMapEdited();
}
}
-void MainWindow::on_checkBox_AllowEscapeRope_stateChanged(int selected)
+void MainWindow::on_checkBox_AllowEscaping_stateChanged(int selected)
{
if (editor && editor->map) {
- bool checked = selected == Qt::Checked;
- if (checked) {
- editor->map->allowEscapeRope = "1";
- } else {
- editor->map->allowEscapeRope = "0";
- }
+ editor->map->allowEscaping = (selected == Qt::Checked);
markMapEdited();
}
}
@@ -1202,7 +1181,7 @@ void MainWindow::onNewMapCreated() {
sortMapList();
setMap(newMapName, true);
- if (ParseUtil::gameStringToBool(newMap->isFlyable)) {
+ if (newMap->needsHealLocation) {
addNewEvent(Event::Type::HealLocation);
editor->project->saveHealLocations(newMap);
editor->save();
@@ -1605,8 +1584,8 @@ void MainWindow::paste() {
}
QJsonArray metatilesArray = pasteObject["metatile_selection"].toArray();
QJsonArray collisionsArray = pasteObject["collision_selection"].toArray();
- int width = pasteObject["width"].toInt();
- int height = pasteObject["height"].toInt();
+ int width = ParseUtil::jsonToInt(pasteObject["width"]);
+ int height = ParseUtil::jsonToInt(pasteObject["height"]);
QList metatiles;
QList> collisions;
for (auto tile : metatilesArray) {
@@ -1912,25 +1891,20 @@ void MainWindow::addNewEvent(Event::Type type) {
}
}
+void MainWindow::tryAddEventTab(QWidget * tab, Event::Group group) {
+ if (editor->map->events.value(group).length())
+ ui->tabWidget_EventType->addTab(tab, QString("%1s").arg(Event::eventGroupToString(group)));
+}
+
void MainWindow::displayEventTabs() {
const QSignalBlocker blocker(ui->tabWidget_EventType);
ui->tabWidget_EventType->clear();
-
- if (editor->map->events.value(Event::Group::Object).length())
- ui->tabWidget_EventType->addTab(eventTabObjectWidget, "Objects");
-
- if (editor->map->events.value(Event::Group::Warp).length())
- ui->tabWidget_EventType->addTab(eventTabWarpWidget, "Warps");
-
- if (editor->map->events.value(Event::Group::Coord).length())
- ui->tabWidget_EventType->addTab(eventTabTriggerWidget, "Triggers");
-
- if (editor->map->events.value(Event::Group::Bg).length())
- ui->tabWidget_EventType->addTab(eventTabBGWidget, "BGs");
-
- if (editor->map->events.value(Event::Group::Heal).length())
- ui->tabWidget_EventType->addTab(eventTabHealspotWidget, "Healspots");
+ tryAddEventTab(eventTabObjectWidget, Event::Group::Object);
+ tryAddEventTab(eventTabWarpWidget, Event::Group::Warp);
+ tryAddEventTab(eventTabTriggerWidget, Event::Group::Coord);
+ tryAddEventTab(eventTabBGWidget, Event::Group::Bg);
+ tryAddEventTab(eventTabHealspotWidget, Event::Group::Heal);
}
void MainWindow::updateObjects() {
@@ -2785,33 +2759,18 @@ void MainWindow::togglePreferenceSpecificUi() {
void MainWindow::on_pushButton_AddCustomHeaderField_clicked()
{
- int rowIndex = this->ui->tableWidget_CustomHeaderFields->rowCount();
- this->ui->tableWidget_CustomHeaderFields->insertRow(rowIndex);
- this->ui->tableWidget_CustomHeaderFields->selectRow(rowIndex);
- this->editor->updateCustomMapHeaderValues(this->ui->tableWidget_CustomHeaderFields);
+ bool ok;
+ QJsonValue value = CustomAttributesTable::pickType(this, &ok);
+ if (ok){
+ CustomAttributesTable::addAttribute(this->ui->tableWidget_CustomHeaderFields, "", value, true);
+ this->editor->updateCustomMapHeaderValues(this->ui->tableWidget_CustomHeaderFields);
+ }
}
void MainWindow::on_pushButton_DeleteCustomHeaderField_clicked()
{
- int rowCount = this->ui->tableWidget_CustomHeaderFields->rowCount();
- if (rowCount > 0) {
- QModelIndexList indexList = ui->tableWidget_CustomHeaderFields->selectionModel()->selectedIndexes();
- QList persistentIndexes;
- for (QModelIndex index : indexList) {
- QPersistentModelIndex persistentIndex(index);
- persistentIndexes.append(persistentIndex);
- }
-
- for (QPersistentModelIndex index : persistentIndexes) {
- this->ui->tableWidget_CustomHeaderFields->removeRow(index.row());
- }
-
- if (this->ui->tableWidget_CustomHeaderFields->rowCount() > 0) {
- this->ui->tableWidget_CustomHeaderFields->selectRow(0);
- }
-
+ if (CustomAttributesTable::deleteSelectedAttributes(this->ui->tableWidget_CustomHeaderFields))
this->editor->updateCustomMapHeaderValues(this->ui->tableWidget_CustomHeaderFields);
- }
}
void MainWindow::on_tableWidget_CustomHeaderFields_cellChanged(int, int)
diff --git a/src/project.cpp b/src/project.cpp
index fb542c28..f5f58261 100644
--- a/src/project.cpp
+++ b/src/project.cpp
@@ -142,36 +142,36 @@ void Project::setNewMapConnections(Map *map) {
map->connections.clear();
}
-static QMap defaultTopLevelMapFields {
- {"id", true},
- {"name", true},
- {"layout", true},
- {"music", true},
- {"region_map_section", true},
- {"requires_flash", true},
- {"weather", true},
- {"map_type", true},
- {"show_map_name", true},
- {"battle_scene", true},
- {"connections", true},
- {"object_events", true},
- {"warp_events", true},
- {"coord_events", true},
- {"bg_events", true},
- {"shared_events_map", true},
- {"shared_scripts_map", true},
+const QSet defaultTopLevelMapFields = {
+ "id",
+ "name",
+ "layout",
+ "music",
+ "region_map_section",
+ "requires_flash",
+ "weather",
+ "map_type",
+ "show_map_name",
+ "battle_scene",
+ "connections",
+ "object_events",
+ "warp_events",
+ "coord_events",
+ "bg_events",
+ "shared_events_map",
+ "shared_scripts_map",
};
-QMap Project::getTopLevelMapFields() {
- QMap topLevelMapFields = defaultTopLevelMapFields;
+QSet Project::getTopLevelMapFields() {
+ QSet topLevelMapFields = defaultTopLevelMapFields;
if (projectConfig.getBaseGameVersion() != BaseGameVersion::pokeruby) {
- topLevelMapFields.insert("allow_cycling", true);
- topLevelMapFields.insert("allow_escaping", true);
- topLevelMapFields.insert("allow_running", true);
+ topLevelMapFields.insert("allow_cycling");
+ topLevelMapFields.insert("allow_escaping");
+ topLevelMapFields.insert("allow_running");
}
if (projectConfig.getFloorNumberEnabled()) {
- topLevelMapFields.insert("floor_number", true);
+ topLevelMapFields.insert("floor_number");
}
return topLevelMapFields;
}
@@ -190,25 +190,25 @@ bool Project::loadMapData(Map* map) {
QJsonObject mapObj = mapDoc.object();
- map->song = mapObj["music"].toString();
- map->layoutId = mapObj["layout"].toString();
- map->location = mapObj["region_map_section"].toString();
- map->requiresFlash = QString::number(mapObj["requires_flash"].toBool());
- map->weather = mapObj["weather"].toString();
- map->type = mapObj["map_type"].toString();
- map->requiresFlash = QString::number(mapObj["requires_flash"].toBool());
- map->show_location = QString::number(mapObj["show_map_name"].toBool());
- map->battle_scene = mapObj["battle_scene"].toString();
+ map->song = ParseUtil::jsonToQString(mapObj["music"]);
+ map->layoutId = ParseUtil::jsonToQString(mapObj["layout"]);
+ map->location = ParseUtil::jsonToQString(mapObj["region_map_section"]);
+ map->requiresFlash = ParseUtil::jsonToBool(mapObj["requires_flash"]);
+ map->weather = ParseUtil::jsonToQString(mapObj["weather"]);
+ map->type = ParseUtil::jsonToQString(mapObj["map_type"]);
+ map->show_location = ParseUtil::jsonToBool(mapObj["show_map_name"]);
+ map->battle_scene = ParseUtil::jsonToQString(mapObj["battle_scene"]);
+
if (projectConfig.getBaseGameVersion() != BaseGameVersion::pokeruby) {
- map->allowBiking = QString::number(mapObj["allow_cycling"].toBool());
- map->allowEscapeRope = QString::number(mapObj["allow_escaping"].toBool());
- map->allowRunning = QString::number(mapObj["allow_running"].toBool());
+ map->allowBiking = ParseUtil::jsonToBool(mapObj["allow_cycling"]);
+ map->allowEscaping = ParseUtil::jsonToBool(mapObj["allow_escaping"]);
+ map->allowRunning = ParseUtil::jsonToBool(mapObj["allow_running"]);
}
if (projectConfig.getFloorNumberEnabled()) {
- map->floorNumber = mapObj["floor_number"].toInt();
+ map->floorNumber = ParseUtil::jsonToInt(mapObj["floor_number"]);
}
- map->sharedEventsMap = mapObj["shared_events_map"].toString();
- map->sharedScriptsMap = mapObj["shared_scripts_map"].toString();
+ map->sharedEventsMap = ParseUtil::jsonToQString(mapObj["shared_events_map"]);
+ map->sharedScriptsMap = ParseUtil::jsonToQString(mapObj["shared_scripts_map"]);
// Events
map->events[Event::Group::Object].clear();
@@ -217,7 +217,7 @@ bool Project::loadMapData(Map* map) {
for (int i = 0; i < objectEventsArr.size(); i++) {
QJsonObject event = objectEventsArr[i].toObject();
// If clone objects are not enabled then no type field is present
- QString type = hasCloneObjects ? event["type"].toString() : "object";
+ QString type = hasCloneObjects ? ParseUtil::jsonToQString(event["type"]) : "object";
if (type.isEmpty() || type == "object") {
ObjectEvent *object = new ObjectEvent();
object->loadFromJson(event, this);
@@ -252,7 +252,7 @@ bool Project::loadMapData(Map* map) {
QJsonArray coordEventsArr = mapObj["coord_events"].toArray();
for (int i = 0; i < coordEventsArr.size(); i++) {
QJsonObject event = coordEventsArr[i].toObject();
- QString type = event["type"].toString();
+ QString type = ParseUtil::jsonToQString(event["type"]);
if (type == "trigger") {
TriggerEvent *coord = new TriggerEvent();
coord->loadFromJson(event, this);
@@ -270,7 +270,7 @@ bool Project::loadMapData(Map* map) {
QJsonArray bgEventsArr = mapObj["bg_events"].toArray();
for (int i = 0; i < bgEventsArr.size(); i++) {
QJsonObject event = bgEventsArr[i].toObject();
- QString type = event["type"].toString();
+ QString type = ParseUtil::jsonToQString(event["type"]);
if (type == "sign") {
SignEvent *bg = new SignEvent();
bg->loadFromJson(event, this);
@@ -319,9 +319,9 @@ bool Project::loadMapData(Map* map) {
for (int i = 0; i < connectionsArr.size(); i++) {
QJsonObject connectionObj = connectionsArr[i].toObject();
MapConnection *connection = new MapConnection;
- connection->direction = connectionObj["direction"].toString();
- connection->offset = QString::number(connectionObj["offset"].toInt());
- QString mapConstant = connectionObj["map"].toString();
+ connection->direction = ParseUtil::jsonToQString(connectionObj["direction"]);
+ connection->offset = ParseUtil::jsonToInt(connectionObj["offset"]);
+ QString mapConstant = ParseUtil::jsonToQString(connectionObj["map"]);
if (mapConstantsToMapNames.contains(mapConstant)) {
connection->map_name = mapConstantsToMapNames.value(mapConstant);
map->connections.append(connection);
@@ -332,10 +332,10 @@ bool Project::loadMapData(Map* map) {
}
// Check for custom fields
- QMap baseFields = this->getTopLevelMapFields();
+ QSet baseFields = this->getTopLevelMapFields();
for (QString key : mapObj.keys()) {
if (!baseFields.contains(key)) {
- map->customHeaders.insert(key, mapObj[key].toString());
+ map->customHeaders.insert(key, mapObj[key]);
}
}
@@ -355,7 +355,7 @@ QString Project::readMapLayoutId(QString map_name) {
}
QJsonObject mapObj = mapDoc.object();
- return mapObj["layout"].toString();
+ return ParseUtil::jsonToQString(mapObj["layout"]);
}
QString Project::readMapLocation(QString map_name) {
@@ -371,23 +371,21 @@ QString Project::readMapLocation(QString map_name) {
}
QJsonObject mapObj = mapDoc.object();
- return mapObj["region_map_section"].toString();
+ return ParseUtil::jsonToQString(mapObj["region_map_section"]);
}
void Project::setNewMapHeader(Map* map, int mapIndex) {
map->layoutId = QString("%1").arg(mapIndex);
map->location = mapSectionValueToName.value(0);
- map->requiresFlash = "FALSE";
+ map->requiresFlash = false;
map->weather = weatherNames.value(0, "WEATHER_NONE");
map->type = mapTypes.value(0, "MAP_TYPE_NONE");
map->song = defaultSong;
- if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby) {
- map->show_location = "TRUE";
- } else {
- map->allowBiking = "1";
- map->allowEscapeRope = "0";
- map->allowRunning = "1";
- map->show_location = "1";
+ map->show_location = true;
+ if (projectConfig.getBaseGameVersion() != BaseGameVersion::pokeruby) {
+ map->allowBiking = true;
+ map->allowEscaping = false;
+ map->allowRunning = true;
}
if (projectConfig.getFloorNumberEnabled()) {
map->floorNumber = 0;
@@ -445,7 +443,7 @@ bool Project::readMapLayouts() {
return false;
}
- layoutsLabel = layoutsObj["layouts_table_label"].toString();
+ layoutsLabel = ParseUtil::jsonToQString(layoutsObj["layouts_table_label"]);
if (layoutsLabel.isNull()) {
layoutsLabel = "gMapLayouts";
logWarn(QString("'layouts_table_label' value is missing from %1. Defaulting to %2")
@@ -477,61 +475,61 @@ bool Project::readMapLayouts() {
return false;
}
MapLayout *layout = new MapLayout();
- layout->id = layoutObj["id"].toString();
+ layout->id = ParseUtil::jsonToQString(layoutObj["id"]);
if (layout->id.isEmpty()) {
logError(QString("Missing 'id' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
return false;
}
- layout->name = layoutObj["name"].toString();
+ layout->name = ParseUtil::jsonToQString(layoutObj["name"]);
if (layout->name.isEmpty()) {
logError(QString("Missing 'name' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
return false;
}
- int lwidth = layoutObj["width"].toInt();
+ int lwidth = ParseUtil::jsonToInt(layoutObj["width"]);
if (lwidth <= 0) {
logError(QString("Invalid layout 'width' value '%1' on layout %2 in %3. Must be greater than 0.").arg(lwidth).arg(i).arg(layoutsFilepath));
return false;
}
- layout->width = QString::number(lwidth);
- int lheight = layoutObj["height"].toInt();
+ layout->width = lwidth;
+ int lheight = ParseUtil::jsonToInt(layoutObj["height"]);
if (lheight <= 0) {
logError(QString("Invalid layout 'height' value '%1' on layout %2 in %3. Must be greater than 0.").arg(lheight).arg(i).arg(layoutsFilepath));
return false;
}
- layout->height = QString::number(lheight);
+ layout->height = lheight;
if (useCustomBorderSize) {
- int bwidth = layoutObj["border_width"].toInt();
+ int bwidth = ParseUtil::jsonToInt(layoutObj["border_width"]);
if (bwidth <= 0) { // 0 is an expected border width/height that should be handled, GF used it for the RS layouts in FRLG
logWarn(QString("Invalid layout 'border_width' value '%1' on layout %2 in %3. Must be greater than 0. Using default (%4) instead.").arg(bwidth).arg(i).arg(layoutsFilepath).arg(DEFAULT_BORDER_WIDTH));
bwidth = DEFAULT_BORDER_WIDTH;
}
- layout->border_width = QString::number(bwidth);
- int bheight = layoutObj["border_height"].toInt();
+ layout->border_width = bwidth;
+ int bheight = ParseUtil::jsonToInt(layoutObj["border_height"]);
if (bheight <= 0) {
logWarn(QString("Invalid layout 'border_height' value '%1' on layout %2 in %3. Must be greater than 0. Using default (%4) instead.").arg(bheight).arg(i).arg(layoutsFilepath).arg(DEFAULT_BORDER_HEIGHT));
bheight = DEFAULT_BORDER_HEIGHT;
}
- layout->border_height = QString::number(bheight);
+ layout->border_height = bheight;
} else {
- layout->border_width = QString::number(DEFAULT_BORDER_WIDTH);
- layout->border_height = QString::number(DEFAULT_BORDER_HEIGHT);
+ layout->border_width = DEFAULT_BORDER_WIDTH;
+ layout->border_height = DEFAULT_BORDER_HEIGHT;
}
- layout->tileset_primary_label = layoutObj["primary_tileset"].toString();
+ layout->tileset_primary_label = ParseUtil::jsonToQString(layoutObj["primary_tileset"]);
if (layout->tileset_primary_label.isEmpty()) {
logError(QString("Missing 'primary_tileset' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
return false;
}
- layout->tileset_secondary_label = layoutObj["secondary_tileset"].toString();
+ layout->tileset_secondary_label = ParseUtil::jsonToQString(layoutObj["secondary_tileset"]);
if (layout->tileset_secondary_label.isEmpty()) {
logError(QString("Missing 'secondary_tileset' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
return false;
}
- layout->border_path = layoutObj["border_filepath"].toString();
+ layout->border_path = ParseUtil::jsonToQString(layoutObj["border_filepath"]);
if (layout->border_path.isEmpty()) {
logError(QString("Missing 'border_filepath' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
return false;
}
- layout->blockdata_path = layoutObj["blockdata_filepath"].toString();
+ layout->blockdata_path = ParseUtil::jsonToQString(layoutObj["blockdata_filepath"]);
if (layout->blockdata_path.isEmpty()) {
logError(QString("Missing 'blockdata_filepath' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
return false;
@@ -566,11 +564,11 @@ void Project::saveMapLayouts() {
OrderedJson::object layoutObj;
layoutObj["id"] = layout->id;
layoutObj["name"] = layout->name;
- layoutObj["width"] = layout->width.toInt(nullptr, 0);
- layoutObj["height"] = layout->height.toInt(nullptr, 0);
+ layoutObj["width"] = layout->width;
+ layoutObj["height"] = layout->height;
if (useCustomBorderSize) {
- layoutObj["border_width"] = layout->border_width.toInt(nullptr, 0);
- layoutObj["border_height"] = layout->border_height.toInt(nullptr, 0);
+ layoutObj["border_width"] = layout->border_width;
+ layoutObj["border_height"] = layout->border_height;
}
layoutObj["primary_tileset"] = layout->tileset_primary_label;
layoutObj["secondary_tileset"] = layout->tileset_secondary_label;
@@ -597,10 +595,10 @@ void Project::setNewMapLayout(Map* map) {
MapLayout *layout = new MapLayout();
layout->id = MapLayout::layoutConstantFromName(map->name);
layout->name = QString("%1_Layout").arg(map->name);
- layout->width = QString::number(getDefaultMapSize());
- layout->height = QString::number(getDefaultMapSize());
- layout->border_width = QString::number(DEFAULT_BORDER_WIDTH);
- layout->border_height = QString::number(DEFAULT_BORDER_HEIGHT);
+ layout->width = getDefaultMapSize();
+ layout->height = getDefaultMapSize();
+ layout->border_width = DEFAULT_BORDER_WIDTH;
+ layout->border_height = DEFAULT_BORDER_HEIGHT;
layout->border_path = QString("%2%1/border.bin").arg(map->name).arg(projectConfig.getFilePath(ProjectFilePath::data_layouts_folders));
layout->blockdata_path = QString("%2%1/map.bin").arg(map->name).arg(projectConfig.getFilePath(ProjectFilePath::data_layouts_folders));
layout->tileset_primary_label = tilesetLabels["primary"].value(0, "gTileset_General");
@@ -1254,11 +1252,11 @@ void Project::saveMap(Map *map) {
QJsonObject newLayoutObj;
newLayoutObj["id"] = map->layout->id;
newLayoutObj["name"] = map->layout->name;
- newLayoutObj["width"] = map->layout->width.toInt();
- newLayoutObj["height"] = map->layout->height.toInt();
+ newLayoutObj["width"] = map->layout->width;
+ newLayoutObj["height"] = map->layout->height;
if (projectConfig.getUseCustomBorderSize()) {
- newLayoutObj["border_width"] = map->layout->border_width.toInt();
- newLayoutObj["border_height"] = map->layout->border_height.toInt();
+ newLayoutObj["border_width"] = map->layout->border_width;
+ newLayoutObj["border_height"] = map->layout->border_height;
}
newLayoutObj["primary_tileset"] = map->layout->tileset_primary_label;
newLayoutObj["secondary_tileset"] = map->layout->tileset_secondary_label;
@@ -1283,15 +1281,15 @@ void Project::saveMap(Map *map) {
mapObj["layout"] = map->layout->id;
mapObj["music"] = map->song;
mapObj["region_map_section"] = map->location;
- mapObj["requires_flash"] = ParseUtil::gameStringToBool(map->requiresFlash);
+ mapObj["requires_flash"] = map->requiresFlash;
mapObj["weather"] = map->weather;
mapObj["map_type"] = map->type;
if (projectConfig.getBaseGameVersion() != BaseGameVersion::pokeruby) {
- mapObj["allow_cycling"] = ParseUtil::gameStringToBool(map->allowBiking);
- mapObj["allow_escaping"] = ParseUtil::gameStringToBool(map->allowEscapeRope);
- mapObj["allow_running"] = ParseUtil::gameStringToBool(map->allowRunning);
+ mapObj["allow_cycling"] = map->allowBiking;
+ mapObj["allow_escaping"] = map->allowEscaping;
+ mapObj["allow_running"] = map->allowRunning;
}
- mapObj["show_map_name"] = ParseUtil::gameStringToBool(map->show_location);
+ mapObj["show_map_name"] = map->show_location;
if (projectConfig.getFloorNumberEnabled()) {
mapObj["floor_number"] = map->floorNumber;
}
@@ -1304,7 +1302,7 @@ void Project::saveMap(Map *map) {
if (mapNamesToMapConstants.contains(connection->map_name)) {
OrderedJson::object connectionObj;
connectionObj["map"] = this->mapNamesToMapConstants.value(connection->map_name);
- connectionObj["offset"] = connection->offset.toInt();
+ connectionObj["offset"] = connection->offset;
connectionObj["direction"] = connection->direction;
connectionsArr.append(connectionObj);
} else {
@@ -1363,7 +1361,7 @@ void Project::saveMap(Map *map) {
// Custom header fields.
for (QString key : map->customHeaders.keys()) {
- mapObj[key] = map->customHeaders[key];
+ mapObj[key] = OrderedJson::fromQJsonValue(map->customHeaders[key]);
}
OrderedJson mapJson(mapObj);
@@ -1765,12 +1763,12 @@ bool Project::readMapGroups() {
QStringList maps;
QStringList groups;
for (int groupIndex = 0; groupIndex < mapGroupOrder.size(); groupIndex++) {
- QString groupName = mapGroupOrder.at(groupIndex).toString();
+ QString groupName = ParseUtil::jsonToQString(mapGroupOrder.at(groupIndex));
QJsonArray mapNames = mapGroupsObj.value(groupName).toArray();
groupedMaps.append(QStringList());
groups.append(groupName);
for (int j = 0; j < mapNames.size(); j++) {
- QString mapName = mapNames.at(j).toString();
+ QString mapName = ParseUtil::jsonToQString(mapNames.at(j));
mapGroups.insert(mapName, groupIndex);
groupedMaps[groupIndex].append(mapName);
maps.append(mapName);
@@ -1782,9 +1780,9 @@ bool Project::readMapGroups() {
}
}
- mapConstantsToMapNames.insert(NONE_MAP_CONSTANT, NONE_MAP_NAME);
- mapNamesToMapConstants.insert(NONE_MAP_NAME, NONE_MAP_CONSTANT);
- maps.append(NONE_MAP_NAME);
+ mapConstantsToMapNames.insert(DYNAMIC_MAP_CONSTANT, DYNAMIC_MAP_NAME);
+ mapNamesToMapConstants.insert(DYNAMIC_MAP_NAME, DYNAMIC_MAP_CONSTANT);
+ maps.append(DYNAMIC_MAP_NAME);
groupNames = groups;
groupedMapNames = groupedMaps;
diff --git a/src/scriptapi/apimap.cpp b/src/scriptapi/apimap.cpp
index 9451d1ee..b133a74b 100644
--- a/src/scriptapi/apimap.cpp
+++ b/src/scriptapi/apimap.cpp
@@ -831,7 +831,7 @@ void MainWindow::setLocation(QString location) {
bool MainWindow::getRequiresFlash() {
if (!this->editor || !this->editor->map)
return false;
- return ParseUtil::gameStringToBool(this->editor->map->requiresFlash);
+ return this->editor->map->requiresFlash;
}
void MainWindow::setRequiresFlash(bool require) {
@@ -891,7 +891,7 @@ void MainWindow::setBattleScene(QString battleScene) {
bool MainWindow::getShowLocationName() {
if (!this->editor || !this->editor->map)
return false;
- return ParseUtil::gameStringToBool(this->editor->map->show_location);
+ return this->editor->map->show_location;
}
void MainWindow::setShowLocationName(bool show) {
@@ -903,7 +903,7 @@ void MainWindow::setShowLocationName(bool show) {
bool MainWindow::getAllowRunning() {
if (!this->editor || !this->editor->map)
return false;
- return ParseUtil::gameStringToBool(this->editor->map->allowRunning);
+ return this->editor->map->allowRunning;
}
void MainWindow::setAllowRunning(bool allow) {
@@ -915,7 +915,7 @@ void MainWindow::setAllowRunning(bool allow) {
bool MainWindow::getAllowBiking() {
if (!this->editor || !this->editor->map)
return false;
- return ParseUtil::gameStringToBool(this->editor->map->allowBiking);
+ return this->editor->map->allowBiking;
}
void MainWindow::setAllowBiking(bool allow) {
@@ -927,13 +927,13 @@ void MainWindow::setAllowBiking(bool allow) {
bool MainWindow::getAllowEscaping() {
if (!this->editor || !this->editor->map)
return false;
- return ParseUtil::gameStringToBool(this->editor->map->allowEscapeRope);
+ return this->editor->map->allowEscaping;
}
void MainWindow::setAllowEscaping(bool allow) {
if (!this->ui)
return;
- this->ui->checkBox_AllowEscapeRope->setChecked(allow);
+ this->ui->checkBox_AllowEscaping->setChecked(allow);
}
int MainWindow::getFloorNumber() {
diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp
index 221c1911..3fd09dda 100644
--- a/src/ui/connectionpixmapitem.cpp
+++ b/src/ui/connectionpixmapitem.cpp
@@ -56,7 +56,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari
y = this->initialY;
}
- this->connection->offset = QString::number(newOffset);
+ this->connection->offset = newOffset;
emit connectionMoved(this->connection);
return QPointF(x, y);
}
diff --git a/src/ui/customattributestable.cpp b/src/ui/customattributestable.cpp
index 4c41a104..83667483 100644
--- a/src/ui/customattributestable.cpp
+++ b/src/ui/customattributestable.cpp
@@ -1,10 +1,12 @@
#include "customattributestable.h"
+#include "parseutil.h"
#include
#include
#include
#include
#include
#include
+#include
CustomAttributesTable::CustomAttributesTable(Event *event, QWidget *parent) :
QFrame(parent)
@@ -28,52 +30,34 @@ CustomAttributesTable::CustomAttributesTable(Event *event, QWidget *parent) :
layout->addWidget(buttonsFrame);
this->table = new QTableWidget(this);
- this->table->setColumnCount(2);
- this->table->setHorizontalHeaderLabels(QStringList({"Key", "Value"}));
+ this->table->setColumnCount(3);
+ this->table->setHorizontalHeaderLabels(QStringList({"Type", "Key", "Value"}));
this->table->horizontalHeader()->setStretchLastSection(true);
layout->addWidget(this->table);
- QMap customValues = this->event->getCustomValues();
- for (auto it = customValues.begin(); it != customValues.end(); it++) {
- int rowIndex = this->table->rowCount();
- this->table->insertRow(rowIndex);
- this->table->setItem(rowIndex, 0, new QTableWidgetItem(it.key()));
- this->table->setItem(rowIndex, 1, new QTableWidgetItem(it.value()));
- }
+ QMap customValues = this->event->getCustomValues();
+ for (auto it = customValues.begin(); it != customValues.end(); it++)
+ CustomAttributesTable::addAttribute(this->table, it.key(), it.value());
connect(addButton, &QPushButton::clicked, [=]() {
- int rowIndex = this->table->rowCount();
- this->table->insertRow(rowIndex);
- this->table->selectRow(rowIndex);
- this->event->setCustomValues(this->getTableFields());
- this->resizeVertically();
+ bool ok;
+ QJsonValue value = CustomAttributesTable::pickType(this, &ok);
+ if (ok){
+ CustomAttributesTable::addAttribute(this->table, "", value, true);
+ this->event->setCustomValues(CustomAttributesTable::getAttributes(this->table));
+ this->resizeVertically();
+ }
});
connect(deleteButton, &QPushButton::clicked, [=]() {
- int rowCount = this->table->rowCount();
- if (rowCount > 0) {
- QModelIndexList indexList = this->table->selectionModel()->selectedIndexes();
- QList persistentIndexes;
- for (QModelIndex index : indexList) {
- QPersistentModelIndex persistentIndex(index);
- persistentIndexes.append(persistentIndex);
- }
-
- for (QPersistentModelIndex index : persistentIndexes) {
- this->table->removeRow(index.row());
- }
-
- if (this->table->rowCount() > 0) {
- this->table->selectRow(0);
- }
-
- this->event->setCustomValues(this->getTableFields());
+ if (CustomAttributesTable::deleteSelectedAttributes(this->table)) {
+ this->event->setCustomValues(CustomAttributesTable::getAttributes(this->table));
this->resizeVertically();
}
});
connect(this->table, &QTableWidget::cellChanged, [=]() {
- this->event->setCustomValues(this->getTableFields());
+ this->event->setCustomValues(CustomAttributesTable::getAttributes(this->table));
});
this->resizeVertically();
@@ -83,20 +67,6 @@ CustomAttributesTable::~CustomAttributesTable()
{
}
-QMap CustomAttributesTable::getTableFields() {
- QMap fields;
- for (int row = 0; row < table->rowCount(); row++) {
- QString keyStr = "";
- QString valueStr = "";
- QTableWidgetItem *key = table->item(row, 0);
- QTableWidgetItem *value = table->item(row, 1);
- if (key) keyStr = key->text();
- if (value) valueStr = value->text();
- fields[keyStr] = valueStr;
- }
- return fields;
-}
-
void CustomAttributesTable::resizeVertically() {
int horizontalHeaderHeight = this->table->horizontalHeader()->height();
int rowHeight = 0;
@@ -112,3 +82,125 @@ void CustomAttributesTable::resizeVertically() {
this->table->setMinimumHeight(totalHeight);
this->table->setMaximumHeight(totalHeight);
}
+
+const QMap CustomAttributesTable::getAttributes(QTableWidget * table) {
+ QMap fields;
+ if (!table) return fields;
+
+ for (int row = 0; row < table->rowCount(); row++) {
+ QString key = "";
+ QTableWidgetItem *typeItem = table->item(row, 0);
+ QTableWidgetItem *keyItem = table->item(row, 1);
+ QTableWidgetItem *valueItem = table->item(row, 2);
+
+ if (keyItem) key = keyItem->text();
+ if (key.isEmpty() || !typeItem || !valueItem)
+ continue;
+
+ // Read from the table data which JSON type to save the value as
+ QJsonValue::Type type = static_cast(typeItem->data(Qt::UserRole).toInt());
+ QJsonValue value;
+ switch (type)
+ {
+ case QJsonValue::String:
+ value = QJsonValue(valueItem->text());
+ break;
+ case QJsonValue::Double:
+ value = QJsonValue(valueItem->text().toInt());
+ break;
+ case QJsonValue::Bool:
+ value = QJsonValue(valueItem->checkState() == Qt::Checked);
+ break;
+ default:
+ // All other types will just be preserved
+ value = valueItem->data(Qt::UserRole).toJsonValue();
+ break;
+ }
+ fields[key] = value;
+ }
+ return fields;
+}
+
+QJsonValue CustomAttributesTable::pickType(QWidget * parent, bool * ok) {
+ const QMap valueTypes = {
+ {"String", QJsonValue(QString(""))},
+ {"Number", QJsonValue(0)},
+ {"Boolean", QJsonValue(false)},
+ };
+ QStringList typeNames = valueTypes.keys();
+ QString selection = QInputDialog::getItem(parent, "", "Choose Value Type", typeNames, typeNames.indexOf("String"), false, ok);
+ return valueTypes.value(selection);
+}
+
+void CustomAttributesTable::addAttribute(QTableWidget * table, QString key, QJsonValue value, bool isNew) {
+ if (!table) return;
+ QTableWidgetItem * valueItem;
+ QJsonValue::Type type = value.type();
+ switch (type)
+ {
+ case QJsonValue::String:
+ case QJsonValue::Double:
+ valueItem = new QTableWidgetItem(ParseUtil::jsonToQString(value));
+ break;
+ case QJsonValue::Bool:
+ valueItem = new QTableWidgetItem("");
+ valueItem->setCheckState(value.toBool() ? Qt::Checked : Qt::Unchecked);
+ valueItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+ break;
+ default:
+ valueItem = new QTableWidgetItem("This value cannot be edited from this table");
+ valueItem->setFlags(Qt::ItemIsSelectable);
+ valueItem->setData(Qt::UserRole, value); // Preserve the value for writing to the file
+ break;
+ }
+
+ const QHash typeToName = {
+ {QJsonValue::Bool, "Bool"},
+ {QJsonValue::Double, "Number"},
+ {QJsonValue::String, "String"},
+ {QJsonValue::Array, "Array"},
+ {QJsonValue::Object, "Object"},
+ {QJsonValue::Null, "Null"},
+ {QJsonValue::Undefined, "Null"},
+ };
+ QTableWidgetItem * typeItem = new QTableWidgetItem(typeToName[type]);
+ typeItem->setFlags(Qt::ItemIsEnabled);
+ typeItem->setData(Qt::UserRole, type); // Record the type for writing to the file
+ typeItem->setTextAlignment(Qt::AlignCenter);
+
+ int rowIndex = table->rowCount();
+ table->insertRow(rowIndex);
+ table->setItem(rowIndex, 0, typeItem);
+ table->setItem(rowIndex, 1, new QTableWidgetItem(key));
+ table->setItem(rowIndex, 2, valueItem);
+
+ if (isNew) {
+ valueItem->setText(""); // Erase the "0" in new numbers
+ table->selectRow(rowIndex);
+ }
+}
+
+bool CustomAttributesTable::deleteSelectedAttributes(QTableWidget * table) {
+ if (!table)
+ return false;
+
+ int rowCount = table->rowCount();
+ if (rowCount <= 0)
+ return false;
+
+ QModelIndexList indexList = table->selectionModel()->selectedIndexes();
+ QList persistentIndexes;
+ for (QModelIndex index : indexList) {
+ QPersistentModelIndex persistentIndex(index);
+ persistentIndexes.append(persistentIndex);
+ }
+
+ for (QPersistentModelIndex index : persistentIndexes) {
+ table->removeRow(index.row());
+ }
+
+ if (table->rowCount() > 0) {
+ table->selectRow(0);
+ }
+ return true;
+}
diff --git a/src/ui/draggablepixmapitem.cpp b/src/ui/draggablepixmapitem.cpp
index ef749a07..9e7ab855 100644
--- a/src/ui/draggablepixmapitem.cpp
+++ b/src/ui/draggablepixmapitem.cpp
@@ -85,23 +85,17 @@ void DraggablePixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
if (eventType == Event::Type::Warp) {
WarpEvent *warp = dynamic_cast(this->event);
QString destMap = warp->getDestinationMap();
- if (destMap != NONE_MAP_NAME) {
- emit editor->warpEventDoubleClicked(destMap, warp->getDestinationWarpID(), Event::Group::Warp);
- }
+ int warpId = ParseUtil::gameStringToInt(warp->getDestinationWarpID());
+ emit editor->warpEventDoubleClicked(destMap, warpId, Event::Group::Warp);
}
else if (eventType == Event::Type::CloneObject) {
CloneObjectEvent *clone = dynamic_cast(this->event);
- QString destMap = clone->getTargetMap();
- if (destMap != NONE_MAP_NAME) {
- emit editor->warpEventDoubleClicked(destMap, clone->getTargetID(), Event::Group::Object);
- }
+ emit editor->warpEventDoubleClicked(clone->getTargetMap(), clone->getTargetID(), Event::Group::Object);
}
else if (eventType == Event::Type::SecretBase) {
SecretBaseEvent *base = dynamic_cast(this->event);
QString baseId = base->getBaseID();
QString destMap = editor->project->mapConstantsToMapNames.value("MAP_" + baseId.left(baseId.lastIndexOf("_")));
- if (destMap != NONE_MAP_NAME) {
- emit editor->warpEventDoubleClicked(destMap, 0, Event::Group::Warp);
- }
+ emit editor->warpEventDoubleClicked(destMap, 0, Event::Group::Warp);
}
}
diff --git a/src/ui/eventframes.cpp b/src/ui/eventframes.cpp
index c3f254c1..c90f3934 100644
--- a/src/ui/eventframes.cpp
+++ b/src/ui/eventframes.cpp
@@ -507,9 +507,9 @@ void WarpFrame::setup() {
// desination warp id
QFormLayout *l_form_dest_warp = new QFormLayout();
- this->spinner_dest_warp = new NoScrollSpinBox(this);
- this->spinner_dest_warp->setToolTip("The warp id on the destination map.");
- l_form_dest_warp->addRow("Destination Warp", this->spinner_dest_warp);
+ this->combo_dest_warp = new NoScrollComboBox(this);
+ this->combo_dest_warp->setToolTip("The warp id on the destination map.");
+ l_form_dest_warp->addRow("Destination Warp", this->combo_dest_warp);
this->layout_contents->addLayout(l_form_dest_warp);
// custom attributes
@@ -529,9 +529,9 @@ void WarpFrame::connectSignals() {
});
// dest id
- this->spinner_dest_warp->disconnect();
- connect(this->spinner_dest_warp, QOverload::of(&QSpinBox::valueChanged), [this](int value) {
- this->warp->setDestinationWarpID(value);
+ this->combo_dest_warp->disconnect();
+ connect(this->combo_dest_warp, &QComboBox::currentTextChanged, [this](const QString &text) {
+ this->warp->setDestinationWarpID(text);
this->warp->modify();
});
}
@@ -553,7 +553,7 @@ void WarpFrame::initialize() {
}
// dest id
- this->spinner_dest_warp->setValue(this->warp->getDestinationWarpID());
+ this->combo_dest_warp->setCurrentText(this->warp->getDestinationWarpID());
}
void WarpFrame::populate(Project *project) {
diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp
index 7f2d0581..5c5e4b78 100644
--- a/src/ui/mapimageexporter.cpp
+++ b/src/ui/mapimageexporter.cpp
@@ -241,7 +241,7 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu
continue;
int x = cur.x;
int y = cur.y;
- int offset = connection->offset.toInt(nullptr, 0);
+ int offset = connection->offset;
Map *connectionMap = this->editor->project->loadMap(connection->map_name);
if (connection->direction == "up") {
x += offset;
diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp
index 1450d9c8..1ffabf68 100644
--- a/src/ui/newmappopup.cpp
+++ b/src/ui/newmappopup.cpp
@@ -117,8 +117,8 @@ void NewMapPopup::setDefaultValues(int groupNum, QString mapSec) {
ui->comboBox_Song->addItems(project->songNames);
if (existingLayout) {
- ui->spinBox_NewMap_Width->setValue(project->mapLayouts.value(layoutId)->width.toInt(nullptr, 0));
- ui->spinBox_NewMap_Height->setValue(project->mapLayouts.value(layoutId)->height.toInt(nullptr, 0));
+ ui->spinBox_NewMap_Width->setValue(project->mapLayouts.value(layoutId)->width);
+ ui->spinBox_NewMap_Height->setValue(project->mapLayouts.value(layoutId)->height);
ui->comboBox_NewMap_Primary_Tileset->setCurrentText(project->mapLayouts.value(layoutId)->tileset_primary_label);
ui->comboBox_NewMap_Secondary_Tileset->setCurrentText(project->mapLayouts.value(layoutId)->tileset_secondary_label);
ui->spinBox_NewMap_Width->setDisabled(true);
@@ -155,8 +155,8 @@ void NewMapPopup::setDefaultValuesImportMap(MapLayout *mapLayout) {
ui->comboBox_Song->addItems(project->songNames);
- ui->spinBox_NewMap_Width->setValue(mapLayout->width.toInt(nullptr, 0));
- ui->spinBox_NewMap_Height->setValue(mapLayout->height.toInt(nullptr, 0));
+ ui->spinBox_NewMap_Width->setValue(mapLayout->width);
+ ui->spinBox_NewMap_Height->setValue(mapLayout->height);
ui->comboBox_NewMap_Primary_Tileset->setCurrentText(mapLayout->tileset_primary_label);
ui->comboBox_NewMap_Secondary_Tileset->setCurrentText(mapLayout->tileset_secondary_label);
@@ -207,8 +207,8 @@ void NewMapPopup::setDefaultValuesProjectConfig(bool importedMap, MapLayout *map
}
if (projectConfig.getUseCustomBorderSize()) {
if (importedMap) {
- ui->spinBox_NewMap_BorderWidth->setValue(mapLayout->border_width.toInt(nullptr, 0));
- ui->spinBox_NewMap_BorderHeight->setValue(mapLayout->border_height.toInt(nullptr, 0));
+ ui->spinBox_NewMap_BorderWidth->setValue(mapLayout->border_width);
+ ui->spinBox_NewMap_BorderHeight->setValue(mapLayout->border_height);
}
ui->spinBox_NewMap_BorderWidth->setVisible(true);
ui->spinBox_NewMap_BorderHeight->setVisible(true);
@@ -265,9 +265,9 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
newMap->type = this->ui->comboBox_NewMap_Type->currentText();
newMap->location = this->ui->comboBox_NewMap_Location->currentText();
newMap->song = this->ui->comboBox_Song->currentText();
- newMap->requiresFlash = "0";
+ newMap->requiresFlash = false;
newMap->weather = this->project->weatherNames.value(0, "WEATHER_NONE");
- newMap->show_location = this->ui->checkBox_NewMap_Show_Location->isChecked() ? "1" : "0";
+ newMap->show_location = this->ui->checkBox_NewMap_Show_Location->isChecked();
newMap->battle_scene = this->project->mapBattleScenes.value(0, "MAP_BATTLE_SCENE_NORMAL");
if (this->existingLayout) {
@@ -277,14 +277,14 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
layout = new MapLayout;
layout->id = MapLayout::layoutConstantFromName(newMapName);
layout->name = QString("%1_Layout").arg(newMap->name);
- layout->width = QString::number(this->ui->spinBox_NewMap_Width->value());
- layout->height = QString::number(this->ui->spinBox_NewMap_Height->value());
+ layout->width = this->ui->spinBox_NewMap_Width->value();
+ layout->height = this->ui->spinBox_NewMap_Height->value();
if (projectConfig.getUseCustomBorderSize()) {
- layout->border_width = QString::number(this->ui->spinBox_NewMap_BorderWidth->value());
- layout->border_height = QString::number(this->ui->spinBox_NewMap_BorderHeight->value());
+ layout->border_width = this->ui->spinBox_NewMap_BorderWidth->value();
+ layout->border_height = this->ui->spinBox_NewMap_BorderHeight->value();
} else {
- layout->border_width = QString::number(DEFAULT_BORDER_WIDTH);
- layout->border_height = QString::number(DEFAULT_BORDER_HEIGHT);
+ layout->border_width = DEFAULT_BORDER_WIDTH;
+ layout->border_height = DEFAULT_BORDER_HEIGHT;
}
layout->tileset_primary_label = this->ui->comboBox_NewMap_Primary_Tileset->currentText();
layout->tileset_secondary_label = this->ui->comboBox_NewMap_Secondary_Tileset->currentText();
@@ -300,13 +300,13 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
}
if (this->ui->checkBox_NewMap_Flyable->isChecked()) {
- newMap->isFlyable = "TRUE";
+ newMap->needsHealLocation = true;
}
if (projectConfig.getBaseGameVersion() != BaseGameVersion::pokeruby) {
- newMap->allowRunning = this->ui->checkBox_NewMap_Allow_Running->isChecked() ? "1" : "0";
- newMap->allowBiking = this->ui->checkBox_NewMap_Allow_Biking->isChecked() ? "1" : "0";
- newMap->allowEscapeRope = this->ui->checkBox_NewMap_Allow_Escape_Rope->isChecked() ? "1" : "0";
+ newMap->allowRunning = this->ui->checkBox_NewMap_Allow_Running->isChecked();
+ newMap->allowBiking = this->ui->checkBox_NewMap_Allow_Biking->isChecked();
+ newMap->allowEscaping = this->ui->checkBox_NewMap_Allow_Escape_Rope->isChecked();
}
if (projectConfig.getFloorNumberEnabled()) {
newMap->floorNumber = this->ui->spinBox_NewMap_Floor_Number->value();
diff --git a/src/ui/prefab.cpp b/src/ui/prefab.cpp
index e9e3b3b0..87bae518 100644
--- a/src/ui/prefab.cpp
+++ b/src/ui/prefab.cpp
@@ -46,14 +46,14 @@ void Prefab::loadPrefabs() {
if (prefabObj.isEmpty())
continue;
- int width = prefabObj["width"].toInt();
- int height = prefabObj["height"].toInt();
+ int width = ParseUtil::jsonToInt(prefabObj["width"]);
+ int height = ParseUtil::jsonToInt(prefabObj["height"]);
if (width <= 0 || height <= 0)
continue;
- QString name = prefabObj["name"].toString();
- QString primaryTileset = prefabObj["primary_tileset"].toString();
- QString secondaryTileset = prefabObj["secondary_tileset"].toString();
+ QString name = ParseUtil::jsonToQString(prefabObj["name"]);
+ QString primaryTileset = ParseUtil::jsonToQString(prefabObj["primary_tileset"]);
+ QString secondaryTileset = ParseUtil::jsonToQString(prefabObj["secondary_tileset"]);
MetatileSelection selection;
selection.dimensions = QPoint(width, height);
@@ -65,17 +65,17 @@ void Prefab::loadPrefabs() {
QJsonArray metatiles = prefabObj["metatiles"].toArray();
for (int j = 0; j < metatiles.size(); j++) {
QJsonObject metatileObj = metatiles[j].toObject();
- int x = metatileObj["x"].toInt();
- int y = metatileObj["y"].toInt();
+ int x = ParseUtil::jsonToInt(metatileObj["x"]);
+ int y = ParseUtil::jsonToInt(metatileObj["y"]);
if (x < 0 || x >= width || y < 0 || y >= height)
continue;
int index = y * width + x;
- int metatileId = metatileObj["metatile_id"].toInt();
+ int metatileId = ParseUtil::jsonToInt(metatileObj["metatile_id"]);
if (metatileId < 0 || metatileId >= Project::getNumMetatilesTotal())
continue;
- selection.metatileItems[index].metatileId = metatileObj["metatile_id"].toInt();
- selection.collisionItems[index].collision = metatileObj["collision"].toInt();
- selection.collisionItems[index].elevation = metatileObj["elevation"].toInt();
+ selection.metatileItems[index].metatileId = ParseUtil::jsonToInt(metatileObj["metatile_id"]);
+ selection.collisionItems[index].collision = ParseUtil::jsonToInt(metatileObj["collision"]);
+ selection.collisionItems[index].elevation = ParseUtil::jsonToInt(metatileObj["elevation"]);
selection.metatileItems[index].enabled = true;
selection.collisionItems[index].enabled = true;
}
diff --git a/src/ui/regionmapeditor.cpp b/src/ui/regionmapeditor.cpp
index dc2c458e..8257231c 100644
--- a/src/ui/regionmapeditor.cpp
+++ b/src/ui/regionmapeditor.cpp
@@ -125,13 +125,13 @@ bool RegionMapEditor::loadRegionMapEntries() {
for (auto entryRef : object["map_sections"].toArray()) {
QJsonObject entryObject = entryRef.toObject();
- QString entryMapSection = entryObject["map_section"].toString();
+ QString entryMapSection = ParseUtil::jsonToQString(entryObject["map_section"]);
MapSectionEntry entry;
- entry.name = entryObject["name"].toString();
- entry.x = entryObject["x"].toInt();
- entry.y = entryObject["y"].toInt();
- entry.width = entryObject["width"].toInt();
- entry.height = entryObject["height"].toInt();
+ entry.name = ParseUtil::jsonToQString(entryObject["name"]);
+ entry.x = ParseUtil::jsonToInt(entryObject["x"]);
+ entry.y = ParseUtil::jsonToInt(entryObject["y"]);
+ entry.width = ParseUtil::jsonToInt(entryObject["width"]);
+ entry.height = ParseUtil::jsonToInt(entryObject["height"]);
entry.valid = true;
this->region_map_entries[entryMapSection] = entry;
}