Merge pull request #713 from GriffinRichards/custom-json-data

Preserve custom JSON data
This commit is contained in:
GriffinR
2025-04-13 22:40:46 -04:00
committed by GitHub
27 changed files with 487 additions and 394 deletions

View File

@@ -323,6 +323,7 @@ public:
this->tilesetsHaveCallback = true;
this->tilesetsHaveIsCompressed = true;
this->setTransparentPixelsBlack = true;
this->preserveMatchingOnlyData = false;
this->filePaths.clear();
this->eventIconPaths.clear();
this->pokemonIconPaths.clear();
@@ -389,6 +390,7 @@ public:
bool tilesetsHaveCallback;
bool tilesetsHaveIsCompressed;
bool setTransparentPixelsBlack;
bool preserveMatchingOnlyData;
int metatileAttributesSize;
uint32_t metatileBehaviorMask;
uint32_t metatileTerrainTypeMask;

View File

@@ -10,6 +10,7 @@
#include <QPointer>
#include "orderedjson.h"
#include "parseutil.h"
class Project;
@@ -139,15 +140,14 @@ public:
Event::Type getEventType() const { return this->eventType; }
virtual OrderedJson::object buildEventJson(Project *project) = 0;
virtual bool loadFromJson(const QJsonObject &json, Project *project) = 0;
virtual bool loadFromJson(QJsonObject json, Project *project) = 0;
virtual void setDefaultValues(Project *project);
virtual QSet<QString> getExpectedFields() = 0;
void readCustomAttributes(const QJsonObject &json);
void addCustomAttributesTo(OrderedJson::object *obj) const;
const QMap<QString, QJsonValue> getCustomAttributes() const { return this->customAttributes; }
void setCustomAttributes(const QMap<QString, QJsonValue> newCustomAttributes) { this->customAttributes = newCustomAttributes; }
QJsonObject getCustomAttributes() const { return this->customAttributes; }
void setCustomAttributes(const QJsonObject &newCustomAttributes) { this->customAttributes = newCustomAttributes; }
virtual void loadPixmap(Project *project);
@@ -191,12 +191,16 @@ protected:
// When deleting events like this we want to warn the user that the #define may also be deleted.
QString idName;
QMap<QString, QJsonValue> customAttributes;
QJsonObject customAttributes;
QPixmap pixmap;
DraggablePixmapItem *pixmapItem = nullptr;
QPointer<EventFrame> eventFrame;
static QString readString(QJsonObject *object, const QString &key) { return ParseUtil::jsonToQString(object->take(key)); }
static int readInt(QJsonObject *object, const QString &key) { return ParseUtil::jsonToInt(object->take(key)); }
static bool readBool(QJsonObject *object, const QString &key) { return ParseUtil::jsonToBool(object->take(key)); }
};
@@ -219,7 +223,7 @@ public:
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
virtual bool loadFromJson(QJsonObject json, Project *project) override;
virtual void setDefaultValues(Project *project) override;
@@ -286,7 +290,7 @@ public:
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
virtual bool loadFromJson(QJsonObject json, Project *project) override;
virtual void setDefaultValues(Project *project) override;
@@ -324,7 +328,7 @@ public:
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
virtual bool loadFromJson(QJsonObject json, Project *project) override;
virtual void setDefaultValues(Project *project) override;
@@ -361,7 +365,7 @@ public:
virtual EventFrame *createEventFrame() override = 0;
virtual OrderedJson::object buildEventJson(Project *project) override = 0;
virtual bool loadFromJson(const QJsonObject &json, Project *project) override = 0;
virtual bool loadFromJson(QJsonObject json, Project *project) override = 0;
virtual void setDefaultValues(Project *project) override = 0;
@@ -389,7 +393,7 @@ public:
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
virtual bool loadFromJson(QJsonObject json, Project *project) override;
virtual void setDefaultValues(Project *project) override;
@@ -429,7 +433,7 @@ public:
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
virtual bool loadFromJson(QJsonObject json, Project *project) override;
virtual void setDefaultValues(Project *project) override;
@@ -460,7 +464,7 @@ public:
virtual EventFrame *createEventFrame() override = 0;
virtual OrderedJson::object buildEventJson(Project *project) override = 0;
virtual bool loadFromJson(const QJsonObject &json, Project *project) override = 0;
virtual bool loadFromJson(QJsonObject json, Project *project) override = 0;
virtual void setDefaultValues(Project *project) override = 0;
@@ -487,7 +491,7 @@ public:
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
virtual bool loadFromJson(QJsonObject json, Project *project) override;
virtual void setDefaultValues(Project *project) override;
@@ -522,7 +526,7 @@ public:
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
virtual bool loadFromJson(QJsonObject json, Project *project) override;
virtual void setDefaultValues(Project *project) override;
@@ -567,7 +571,7 @@ public:
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
virtual bool loadFromJson(QJsonObject json, Project *project) override;
virtual void setDefaultValues(Project *project) override;
@@ -599,12 +603,15 @@ public:
virtual EventFrame *createEventFrame() override;
virtual OrderedJson::object buildEventJson(Project *project) override;
virtual bool loadFromJson(const QJsonObject &, Project *) override;
virtual bool loadFromJson(QJsonObject json, Project *project) override;
virtual void setDefaultValues(Project *project) override;
virtual QSet<QString> getExpectedFields() override;
void setHostMapName(QString newHostMapName) { this->hostMapName = newHostMapName; }
QString getHostMapName() const;
void setRespawnMapName(QString newRespawnMapName) { this->respawnMapName = newRespawnMapName; }
QString getRespawnMapName() const { return this->respawnMapName; }
@@ -614,6 +621,7 @@ public:
private:
QString respawnMapName;
QString respawnNPC;
QString hostMapName; // Only needed if the host map fails to load.
};

View File

@@ -100,8 +100,8 @@ public:
bool hasUnsavedChanges() const;
void pruneEditHistory();
void setCustomAttributes(const QMap<QString, QJsonValue> &attributes) { m_customAttributes = attributes; }
QMap<QString, QJsonValue> customAttributes() const { return m_customAttributes; }
void setCustomAttributes(const QJsonObject &attributes) { m_customAttributes = attributes; }
QJsonObject customAttributes() const { return m_customAttributes; }
private:
QString m_name;
@@ -110,7 +110,7 @@ private:
QString m_sharedScriptsMap = "";
QStringList m_scriptsFileLabels;
QMap<QString, QJsonValue> m_customAttributes;
QJsonObject m_customAttributes;
MapHeader *m_header = nullptr;
Layout *m_layout = nullptr;

View File

@@ -5,6 +5,7 @@
#include <QString>
#include <QObject>
#include <QMap>
#include <QJsonObject>
class Project;
class Map;
@@ -34,6 +35,9 @@ public:
int offset() const { return m_offset; }
void setOffset(int offset, bool mirror = true);
QJsonObject customData() const { return m_customData; }
void setCustomData(const QJsonObject &customData) { m_customData = customData; }
MapConnection* findMirror();
MapConnection* createMirror();
@@ -55,6 +59,7 @@ private:
QString m_targetMapName;
QString m_direction;
int m_offset;
QJsonObject m_customData;
void markMapEdited();
Map* getMap(const QString& mapName) const;

View File

@@ -42,6 +42,8 @@ public:
Tileset *tileset_primary = nullptr;
Tileset *tileset_secondary = nullptr;
QJsonObject customData;
Blockdata blockdata;
QImage image;

View File

@@ -58,7 +58,7 @@ public:
QMap<QString, int> readCDefinesByRegex(const QString &filename, const QSet<QString> &regexList, QString *error = nullptr);
QMap<QString, int> readCDefinesByName(const QString &filename, const QSet<QString> &names, QString *error = nullptr);
QStringList readCDefineNames(const QString &filename, const QSet<QString> &regexList, QString *error = nullptr);
tsl::ordered_map<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString>& = {});
OrderedMap<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString>& = {});
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);
QStringList getLabelValues(const QList<QStringList>&, const QString&);
bool tryParseJsonFile(QJsonDocument *out, const QString &filepath, QString *error = nullptr);

View File

@@ -56,8 +56,8 @@ public:
bool loadLayout(poryjson::Json);
bool loadEntries();
void setEntries(QMap<QString, MapSectionEntry> *entries) { this->region_map_entries = entries; }
void setEntries(const QMap<QString, MapSectionEntry> &entries) { *(this->region_map_entries) = entries; }
void setEntries(QHash<QString, MapSectionEntry> *entries) { this->region_map_entries = entries; }
void setEntries(const QHash<QString, MapSectionEntry> &entries) { *(this->region_map_entries) = entries; }
void clearEntries() { this->region_map_entries->clear(); }
MapSectionEntry getEntry(QString section);
void setEntry(QString section, MapSectionEntry entry);
@@ -151,7 +151,7 @@ signals:
void mapNeedsDisplaying();
private:
QMap<QString, MapSectionEntry> *region_map_entries = nullptr;
QHash<QString, MapSectionEntry> *region_map_entries = nullptr;
QString alias = "";

View File

@@ -153,7 +153,7 @@ private:
/// ClearEntries
class ClearEntries : public QUndoCommand {
public:
ClearEntries(RegionMap *map, QMap<QString, MapSectionEntry>, QUndoCommand *parent = nullptr);
ClearEntries(RegionMap *map, QHash<QString, MapSectionEntry>, QUndoCommand *parent = nullptr);
void undo() override;
void redo() override;
@@ -163,7 +163,7 @@ public:
private:
RegionMap *map;
QMap<QString, MapSectionEntry> entries;
QHash<QString, MapSectionEntry> entries;
};
#endif // REGIONMAPEDITCOMMANDS_H

View File

@@ -3,7 +3,7 @@
#define GUARD_WILDMONINFO_H
#include <QtWidgets>
#include "orderedmap.h"
#include "orderedjson.h"
class WildPokemon {
public:
@@ -13,22 +13,26 @@ public:
int minLevel;
int maxLevel;
QString species;
OrderedJson::object customData;
};
struct WildMonInfo {
bool active = false;
int encounterRate = 0;
QVector<WildPokemon> wildPokemon;
OrderedJson::object customData;
};
struct WildPokemonHeader {
tsl::ordered_map<QString, WildMonInfo> wildMons;
OrderedMap<QString, WildMonInfo> wildMons;
OrderedJson::object customData;
};
struct EncounterField {
QString name; // Ex: "fishing_mons"
QVector<int> encounterRates;
tsl::ordered_map<QString, QVector<int>> groups; // Ex: "good_rod", {2, 3, 4}
OrderedMap<QString, QVector<int>> groups; // Ex: "good_rod", {2, 3, 4}
OrderedJson::object customData;
};
typedef QVector<EncounterField> EncounterFields;

View File

@@ -99,7 +99,7 @@ public:
// Array and object typedefs
typedef QVector<Json> array;
typedef tsl::ordered_map<QString, Json> object;
typedef OrderedMap<QString, Json> object;
// Constructors for the various types of JSON value.
Json() noexcept; // NUL
@@ -132,7 +132,22 @@ public:
int>::type = 0>
Json(const V & v) : Json(array(v.begin(), v.end())) {}
static const Json fromQJsonValue(QJsonValue value);
static Json fromQJsonValue(const QJsonValue &value);
static void append(Json::array *array, const QJsonArray &addendum) {
for (const auto &i : addendum) array->push_back(fromQJsonValue(i));
}
static void append(Json::array *array, const Json::array &addendum) {
for (const auto &i : addendum) array->push_back(i);
}
static void append(Json::object *object, const QJsonObject &addendum) {
for (auto it = addendum.constBegin(); it != addendum.constEnd(); it++)
(*object)[it.key()] = fromQJsonValue(it.value());
}
static void append(Json::object *object, const Json::object &addendum) {
for (auto it = addendum.cbegin(); it != addendum.cend(); it++)
(*object)[it.key()] = it.value();
}
// This prevents Json(some_pointer) from accidentally producing a bool. Use
// Json(bool(some_pointer)) if that behavior is desired.

View File

@@ -1977,6 +1977,14 @@ public:
size_type erase(const K& key, std::size_t precalculated_hash) {
return m_ht.erase(key, precalculated_hash);
}
// Naive solution for take, should probably be replaced with one that does a single lookup and no unnecessary insertion.
// We want to mirror the behavior of QMap::take, which returns a default-constructed value if the key is not present.
T take(const key_type& key) {
typename ValueSelect::value_type value = m_ht[key];
m_ht.erase(key);
return value;
}
@@ -2404,4 +2412,7 @@ private:
} // end namespace tsl
template<class Key, class T>
using OrderedMap = tsl::ordered_map<Key, T>;
#endif

View File

@@ -62,7 +62,6 @@ public:
QStringList mapSectionIdNames;
QMap<uint32_t, QString> encounterTypeToName;
QMap<uint32_t, QString> terrainTypeToName;
QMap<QString, MapSectionEntry> regionMapEntries;
QMap<QString, QMap<QString, uint16_t>> metatileLabelsMap;
QMap<QString, uint16_t> unusedMetatileLabels;
QMap<QString, uint32_t> metatileBehaviorMap;
@@ -72,7 +71,6 @@ public:
QSet<QString> modifiedFiles;
bool usingAsmTilesets;
QSet<QString> disabledSettingsNames;
QSet<QString> topLevelMapFields;
int pokemonMinLevel;
int pokemonMaxLevel;
int maxEncounterRate;
@@ -144,12 +142,11 @@ public:
QString getNewHealLocationName(const Map* map) const;
bool readWildMonData();
tsl::ordered_map<QString, tsl::ordered_map<QString, WildPokemonHeader>> wildMonData;
OrderedMap<QString, OrderedMap<QString, WildPokemonHeader>> wildMonData;
QString wildMonTableName;
QVector<EncounterField> wildMonFields;
QVector<QString> encounterGroupLabels;
QVector<poryjson::Json::object> extraEncounterGroups;
bool readSpeciesIconPaths();
QString getDefaultSpeciesIconPath(const QString &species);
@@ -157,15 +154,14 @@ public:
bool addNewMapsec(const QString &idName, const QString &displayName = QString());
void removeMapsec(const QString &idName);
QString getMapsecDisplayName(const QString &idName) const { return this->mapSectionDisplayNames.value(idName); }
QString getMapsecDisplayName(const QString &idName) const { return this->locationData.value(idName).displayName; }
void setMapsecDisplayName(const QString &idName, const QString &displayName);
bool hasUnsavedChanges();
bool hasUnsavedDataChanges = false;
void initTopLevelMapFields();
bool readMapJson(const QString &mapName, QJsonDocument * out);
bool loadMapEvent(Map *map, const QJsonObject &json, Event::Type defaultType = Event::Type::None);
bool loadMapEvent(Map *map, QJsonObject json, Event::Type defaultType = Event::Type::None);
bool loadMapData(Map*);
bool readMapLayouts();
Layout *loadLayout(QString layoutId);
@@ -240,6 +236,11 @@ public:
static QString getExistingFilepath(QString filepath);
void applyParsedLimits();
void setRegionMapEntries(const QHash<QString, MapSectionEntry> &entries);
QHash<QString, MapSectionEntry> getRegionMapEntries() const;
QSet<QString> getTopLevelMapFields() const;
static QString getEmptyMapDefineName();
static QString getDynamicMapDefineName();
static QString getDynamicMapName();
@@ -262,12 +263,20 @@ public:
static QString getMapGroupPrefix();
private:
QHash<QString, QString> mapSectionDisplayNames;
QMap<QString, qint64> modifiedFileTimestamps;
QMap<QString, QString> facingDirections;
QHash<QString, QString> speciesToIconPath;
QHash<QString, Map*> maps;
// Fields for preserving top-level JSON data that Porymap isn't expecting.
QJsonObject customLayoutsData;
QJsonObject customMapSectionsData;
QJsonObject customMapGroupsData;
QJsonObject customHealLocationsData;
OrderedJson::object customWildMonData;
OrderedJson::object customWildMonGroupData;
OrderedJson::array extraEncounterGroups;
// Maps/layouts represented in these sets have been fully loaded from the project.
// If a valid map name / layout id is not in these sets, a Map / Layout object exists
// for it in Project::maps / Project::mapLayouts, but it has been minimally populated
@@ -291,6 +300,15 @@ private:
};
QMap<QString, EventGraphics*> eventGraphicsMap;
// The extra data that can be associated with each MAPSEC name.
struct LocationData
{
MapSectionEntry map;
QString displayName;
QJsonObject custom;
};
QHash<QString, LocationData> locationData;
void updateLayout(Layout *);
void setNewLayoutBlockdata(Layout *layout);

View File

@@ -13,8 +13,8 @@ public:
explicit CustomAttributesTable(QWidget *parent = nullptr);
~CustomAttributesTable() {};
QMap<QString, QJsonValue> getAttributes() const;
void setAttributes(const QMap<QString, QJsonValue> &attributes);
QJsonObject getAttributes() const;
void setAttributes(const QJsonObject &attributes);
void addNewAttribute(const QString &key, const QJsonValue &value);
bool deleteSelectedAttributes();

View File

@@ -54,7 +54,7 @@ private:
Project *project;
RegionMap *region_map = nullptr;
tsl::ordered_map<QString, RegionMap *> region_maps;
OrderedMap<QString, RegionMap *> region_maps;
QString configFilepath;
@@ -95,7 +95,7 @@ private:
void saveConfig();
bool loadRegionMapEntries();
bool saveRegionMapEntries();
QMap<QString, MapSectionEntry> region_map_entries;
QHash<QString, MapSectionEntry> region_map_entries;
bool buildConfigDialog();
poryjson::Json configRegionMapDialog();