mirror of
https://github.com/huderlem/porymap.git
synced 2026-08-24 09:36:11 -05:00
Merge pull request #787 from GriffinRichards/config-json
Replace old config format
This commit is contained in:
521
include/config.h
521
include/config.h
@@ -1,521 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include <QByteArrayList>
|
||||
#include <QSize>
|
||||
#include <QKeySequence>
|
||||
#include <QMultiMap>
|
||||
#include <QDateTime>
|
||||
#include <QUrl>
|
||||
#include <QVersionNumber>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QFontDatabase>
|
||||
#include <QStandardPaths>
|
||||
#include <QColorSpace>
|
||||
#include <set>
|
||||
|
||||
#include "events.h"
|
||||
#include "gridsettings.h"
|
||||
|
||||
extern const QVersionNumber porymapVersion;
|
||||
|
||||
// Distance in pixels from the edge of a GBA screen (240x160) to the center 16x16 pixels.
|
||||
#define GBA_H_DIST_TO_CENTER ((240-16)/2)
|
||||
#define GBA_V_DIST_TO_CENTER ((160-16)/2)
|
||||
|
||||
#define CONFIG_BACKWARDS_COMPATABILITY
|
||||
|
||||
enum ScriptAutocompleteMode {
|
||||
MapOnly,
|
||||
MapAndCommon,
|
||||
All,
|
||||
};
|
||||
|
||||
class KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
bool save();
|
||||
bool load(const QString &dir = QString());
|
||||
|
||||
void setRoot(const QString &dir);
|
||||
QString root() const { return m_root; }
|
||||
QString filepath() const { return m_filepath; }
|
||||
QString filename() const { return m_filename; }
|
||||
|
||||
explicit KeyValueConfigBase(const QString &filename)
|
||||
: m_root(QString()),
|
||||
m_filename(filename),
|
||||
m_filepath(filename)
|
||||
{ };
|
||||
virtual ~KeyValueConfigBase() {};
|
||||
virtual void reset() = 0;
|
||||
protected:
|
||||
virtual void parseConfigKeyValue(QString key, QString value) = 0;
|
||||
virtual QMap<QString, QString> getKeyValueMap() = 0;
|
||||
virtual void init() = 0;
|
||||
virtual void setUnreadKeys() = 0;
|
||||
|
||||
static bool getConfigBool(const QString &key, const QString &value);
|
||||
static int getConfigInteger(const QString &key, const QString &value, int min = INT_MIN, int max = INT_MAX, int defaultValue = 0);
|
||||
static uint32_t getConfigUint32(const QString &key, const QString &value, uint32_t min = 0, uint32_t max = UINT_MAX, uint32_t defaultValue = 0);
|
||||
static QColor getConfigColor(const QString &key, const QString &value, const QColor &defaultValue = QColor(Qt::black));
|
||||
static QString toConfigColor(const QColor &color);
|
||||
|
||||
QString m_root;
|
||||
QString m_filename;
|
||||
QString m_filepath;
|
||||
};
|
||||
|
||||
class PorymapConfig: public KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
PorymapConfig();
|
||||
virtual void reset() override;
|
||||
void addRecentProject(QString project);
|
||||
void setRecentProjects(QStringList projects);
|
||||
QString getRecentProject();
|
||||
QStringList getRecentProjects();
|
||||
void setMainGeometry(QByteArray, QByteArray, QByteArray, QByteArray, QByteArray);
|
||||
void setTilesetEditorGeometry(QByteArray, QByteArray, QByteArray);
|
||||
void setPaletteEditorGeometry(QByteArray, QByteArray);
|
||||
void setRegionMapEditorGeometry(QByteArray, QByteArray);
|
||||
void setProjectSettingsEditorGeometry(QByteArray, QByteArray);
|
||||
void setCustomScriptsEditorGeometry(QByteArray, QByteArray);
|
||||
QMap<QString, QByteArray> getMainGeometry();
|
||||
QMap<QString, QByteArray> getTilesetEditorGeometry();
|
||||
QMap<QString, QByteArray> getPaletteEditorGeometry();
|
||||
QMap<QString, QByteArray> getRegionMapEditorGeometry();
|
||||
QMap<QString, QByteArray> getProjectSettingsEditorGeometry();
|
||||
QMap<QString, QByteArray> getCustomScriptsEditorGeometry();
|
||||
|
||||
static QFont defaultMapListFont() { return QFontDatabase::systemFont(QFontDatabase::FixedFont); }
|
||||
|
||||
bool reopenOnLaunch;
|
||||
bool projectManuallyClosed;
|
||||
int mapListTab;
|
||||
bool mapListEditGroupsEnabled;
|
||||
QMap<int, bool> mapListHideEmptyEnabled;
|
||||
bool mapListLayoutsSorted;
|
||||
bool mapListLocationsSorted;
|
||||
bool prettyCursors;
|
||||
bool mirrorConnectingMaps;
|
||||
bool showDiveEmergeMaps;
|
||||
int diveEmergeMapOpacity;
|
||||
int diveMapOpacity;
|
||||
int emergeMapOpacity;
|
||||
int collisionOpacity;
|
||||
int collisionZoom;
|
||||
int metatilesZoom;
|
||||
int tilesetEditorMetatilesZoom;
|
||||
int tilesetEditorTilesZoom;
|
||||
Qt::Orientation tilesetEditorLayerOrientation;
|
||||
bool showPlayerView;
|
||||
bool showCursorTile;
|
||||
bool showBorder;
|
||||
bool showGrid;
|
||||
bool showTilesetEditorMetatileGrid;
|
||||
bool showTilesetEditorLayerGrid;
|
||||
bool showTilesetEditorDivider;
|
||||
bool showTilesetEditorRawAttributes;
|
||||
bool showPaletteEditorUnusedColors;
|
||||
bool monitorFiles;
|
||||
bool tilesetCheckerboardFill;
|
||||
bool newMapHeaderSectionExpanded;
|
||||
QString theme;
|
||||
QString wildMonChartTheme;
|
||||
QString textEditorOpenFolder;
|
||||
QString textEditorGotoLine;
|
||||
int paletteEditorBitDepth;
|
||||
int projectSettingsTab;
|
||||
ScriptAutocompleteMode scriptAutocompleteMode;
|
||||
bool warpBehaviorWarningDisabled;
|
||||
bool eventDeleteWarningDisabled;
|
||||
bool eventOverlayEnabled;
|
||||
bool checkForUpdates;
|
||||
bool showProjectLoadingScreen;
|
||||
QDateTime lastUpdateCheckTime;
|
||||
QVersionNumber lastUpdateCheckVersion;
|
||||
QMap<QUrl, QDateTime> rateLimitTimes;
|
||||
QGraphicsPixmapItem::ShapeMode eventSelectionShapeMode;
|
||||
QByteArray wildMonChartGeometry;
|
||||
QByteArray newMapDialogGeometry;
|
||||
QByteArray newLayoutDialogGeometry;
|
||||
bool shownInGameReloadMessage;
|
||||
GridSettings gridSettings;
|
||||
// Prefer over QSet to prevent shuffling elements when writing the config file.
|
||||
std::set<LogType> statusBarLogTypes;
|
||||
QFont applicationFont;
|
||||
QFont mapListFont;
|
||||
int imageExportColorSpaceId;
|
||||
QMap<QString,QString> trustedScriptHashes;
|
||||
|
||||
protected:
|
||||
virtual void parseConfigKeyValue(QString key, QString value) override;
|
||||
virtual QMap<QString, QString> getKeyValueMap() override;
|
||||
virtual void init() override {};
|
||||
virtual void setUnreadKeys() override {};
|
||||
|
||||
private:
|
||||
QString stringFromByteArray(const QByteArray&);
|
||||
QByteArray bytesFromString(const QString&);
|
||||
|
||||
QStringList recentProjects;
|
||||
QByteArray mainWindowGeometry;
|
||||
QByteArray mainWindowState;
|
||||
QByteArray mapSplitterState;
|
||||
QByteArray mainSplitterState;
|
||||
QByteArray metatilesSplitterState;
|
||||
QByteArray tilesetEditorGeometry;
|
||||
QByteArray tilesetEditorState;
|
||||
QByteArray tilesetEditorSplitterState;
|
||||
QByteArray paletteEditorGeometry;
|
||||
QByteArray paletteEditorState;
|
||||
QByteArray regionMapEditorGeometry;
|
||||
QByteArray regionMapEditorState;
|
||||
QByteArray projectSettingsEditorGeometry;
|
||||
QByteArray projectSettingsEditorState;
|
||||
QByteArray customScriptsEditorGeometry;
|
||||
QByteArray customScriptsEditorState;
|
||||
};
|
||||
|
||||
extern PorymapConfig porymapConfig;
|
||||
|
||||
enum BaseGameVersion {
|
||||
none,
|
||||
pokeruby,
|
||||
pokefirered,
|
||||
pokeemerald,
|
||||
};
|
||||
|
||||
enum ProjectIdentifier {
|
||||
symbol_facing_directions,
|
||||
symbol_obj_event_gfx_pointers,
|
||||
symbol_pokemon_icon_table,
|
||||
symbol_attribute_table,
|
||||
symbol_tilesets_prefix,
|
||||
symbol_dynamic_map_name,
|
||||
define_obj_event_count,
|
||||
define_min_level,
|
||||
define_max_level,
|
||||
define_max_encounter_rate,
|
||||
define_tiles_primary,
|
||||
define_tiles_total,
|
||||
define_metatiles_primary,
|
||||
define_pals_primary,
|
||||
define_pals_total,
|
||||
define_tiles_per_metatile,
|
||||
define_map_size,
|
||||
define_map_offset_width,
|
||||
define_map_offset_height,
|
||||
define_mask_metatile,
|
||||
define_mask_collision,
|
||||
define_mask_elevation,
|
||||
define_mask_behavior,
|
||||
define_mask_layer,
|
||||
define_attribute_behavior,
|
||||
define_attribute_layer,
|
||||
define_attribute_terrain,
|
||||
define_attribute_encounter,
|
||||
define_metatile_label_prefix,
|
||||
define_heal_locations_prefix,
|
||||
define_layout_prefix,
|
||||
define_map_prefix,
|
||||
define_map_dynamic,
|
||||
define_map_empty,
|
||||
define_map_section_prefix,
|
||||
define_map_section_empty,
|
||||
define_species_prefix,
|
||||
define_species_empty,
|
||||
regex_behaviors,
|
||||
regex_obj_event_gfx,
|
||||
regex_items,
|
||||
regex_flags,
|
||||
regex_vars,
|
||||
regex_movement_types,
|
||||
regex_map_types,
|
||||
regex_battle_scenes,
|
||||
regex_weather,
|
||||
regex_coord_event_weather,
|
||||
regex_secret_bases,
|
||||
regex_sign_facing_directions,
|
||||
regex_trainer_types,
|
||||
regex_music,
|
||||
regex_encounter_types,
|
||||
regex_terrain_types,
|
||||
pals_output_extension,
|
||||
tiles_output_extension,
|
||||
};
|
||||
|
||||
enum ProjectFilePath {
|
||||
data_map_folders,
|
||||
data_scripts_folders,
|
||||
data_layouts_folders,
|
||||
data_primary_tilesets_folders,
|
||||
data_secondary_tilesets_folders,
|
||||
data_event_scripts,
|
||||
json_map_groups,
|
||||
json_layouts,
|
||||
json_wild_encounters,
|
||||
json_heal_locations,
|
||||
json_region_map_entries,
|
||||
json_region_porymap_cfg,
|
||||
tilesets_headers,
|
||||
tilesets_graphics,
|
||||
tilesets_metatiles,
|
||||
tilesets_headers_asm,
|
||||
tilesets_graphics_asm,
|
||||
tilesets_metatiles_asm,
|
||||
data_obj_event_gfx_pointers,
|
||||
data_obj_event_gfx_info,
|
||||
data_obj_event_pic_tables,
|
||||
data_obj_event_gfx,
|
||||
data_pokemon_gfx,
|
||||
constants_global,
|
||||
constants_items,
|
||||
constants_flags,
|
||||
constants_vars,
|
||||
constants_weather,
|
||||
constants_songs,
|
||||
constants_pokemon,
|
||||
constants_map_types,
|
||||
constants_trainer_types,
|
||||
constants_secret_bases,
|
||||
constants_obj_event_movement,
|
||||
constants_obj_events,
|
||||
constants_event_bg,
|
||||
constants_metatile_labels,
|
||||
constants_metatile_behaviors,
|
||||
constants_species,
|
||||
constants_fieldmap,
|
||||
global_fieldmap,
|
||||
fieldmap,
|
||||
initial_facing_table,
|
||||
wild_encounter,
|
||||
pokemon_icon_table,
|
||||
pokemon_gfx,
|
||||
};
|
||||
|
||||
class ProjectConfig: public KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
ProjectConfig();
|
||||
virtual void reset() override {
|
||||
this->baseGameVersion = BaseGameVersion::pokeemerald;
|
||||
// Reset non-version-specific settings
|
||||
this->usePoryScript = false;
|
||||
this->tripleLayerMetatilesEnabled = false;
|
||||
this->defaultMetatileId = 1;
|
||||
this->defaultElevation = 3;
|
||||
this->defaultCollision = 0;
|
||||
this->defaultMapSize = QSize(20,20);
|
||||
this->defaultPrimaryTileset = "gTileset_General";
|
||||
this->prefabFilepath = QString();
|
||||
this->prefabImportPrompted = false;
|
||||
this->tilesetsHaveCallback = true;
|
||||
this->tilesetsHaveIsCompressed = true;
|
||||
this->transparencyColor = QColor(Qt::black);
|
||||
this->preserveMatchingOnlyData = false;
|
||||
this->filePaths.clear();
|
||||
this->eventIconPaths.clear();
|
||||
this->pokemonIconPaths.clear();
|
||||
this->eventsTabIconPath = QString();
|
||||
this->collisionSheetPath = QString();
|
||||
this->collisionSheetSize = QSize(2, 16);
|
||||
this->playerViewDistance = QMargins(GBA_H_DIST_TO_CENTER, GBA_V_DIST_TO_CENTER, GBA_H_DIST_TO_CENTER, GBA_V_DIST_TO_CENTER);
|
||||
this->blockMetatileIdMask = 0x03FF;
|
||||
this->blockCollisionMask = 0x0C00;
|
||||
this->blockElevationMask = 0xF000;
|
||||
this->unusedTileNormal = 0x3014;
|
||||
this->unusedTileCovered = 0x0000;
|
||||
this->unusedTileSplit = 0x0000;
|
||||
this->maxEventsPerGroup = 255;
|
||||
this->forcedMajorVersion = 0;
|
||||
this->metatileSelectorWidth = 8;
|
||||
this->globalConstantsFilepaths.clear();
|
||||
this->globalConstants.clear();
|
||||
this->identifiers.clear();
|
||||
this->readKeys.clear();
|
||||
}
|
||||
static const QMap<ProjectIdentifier, QPair<QString, QString>> defaultIdentifiers;
|
||||
static const QMap<ProjectFilePath, QPair<QString, QString>> defaultPaths;
|
||||
static const QStringList versionStrings;
|
||||
static BaseGameVersion stringToBaseGameVersion(const QString &string);
|
||||
|
||||
static QString getPlayerIconPath(BaseGameVersion baseGameVersion, int character);
|
||||
static QIcon getPlayerIcon(BaseGameVersion baseGameVersion, int character);
|
||||
|
||||
QString projectDir() const { return m_root; } // Alias for root()
|
||||
void reset(BaseGameVersion baseGameVersion);
|
||||
void setFilePath(ProjectFilePath pathId, const QString &path);
|
||||
void setFilePath(const QString &pathId, const QString &path);
|
||||
QString getCustomFilePath(ProjectFilePath pathId);
|
||||
QString getCustomFilePath(const QString &pathId);
|
||||
QString getFilePath(ProjectFilePath pathId);
|
||||
void setIdentifier(ProjectIdentifier id, QString text);
|
||||
void setIdentifier(const QString &id, const QString &text);
|
||||
QString getCustomIdentifier(ProjectIdentifier id);
|
||||
QString getCustomIdentifier(const QString &id);
|
||||
QString getIdentifier(ProjectIdentifier id);
|
||||
QString getBaseGameVersionString(BaseGameVersion version);
|
||||
QString getBaseGameVersionString();
|
||||
int getNumLayersInMetatile();
|
||||
int getNumTilesInMetatile();
|
||||
void setEventIconPath(Event::Group group, const QString &path);
|
||||
QString getEventIconPath(Event::Group group);
|
||||
void setPokemonIconPath(const QString &species, const QString &path);
|
||||
QString getPokemonIconPath(const QString &species);
|
||||
QMap<QString, QString> getPokemonIconPaths();
|
||||
|
||||
BaseGameVersion baseGameVersion;
|
||||
bool usePoryScript;
|
||||
bool useCustomBorderSize;
|
||||
bool eventWeatherTriggerEnabled;
|
||||
bool eventSecretBaseEnabled;
|
||||
bool hiddenItemQuantityEnabled;
|
||||
bool hiddenItemRequiresItemfinderEnabled;
|
||||
bool healLocationRespawnDataEnabled;
|
||||
bool eventCloneObjectEnabled;
|
||||
bool floorNumberEnabled;
|
||||
bool createMapTextFileEnabled;
|
||||
bool tripleLayerMetatilesEnabled;
|
||||
uint16_t defaultMetatileId;
|
||||
uint16_t defaultElevation;
|
||||
uint16_t defaultCollision;
|
||||
QSize defaultMapSize;
|
||||
QList<uint16_t> newMapBorderMetatileIds;
|
||||
QString defaultPrimaryTileset;
|
||||
QString defaultSecondaryTileset;
|
||||
QString prefabFilepath;
|
||||
bool prefabImportPrompted;
|
||||
bool tilesetsHaveCallback;
|
||||
bool tilesetsHaveIsCompressed;
|
||||
QColor transparencyColor;
|
||||
bool preserveMatchingOnlyData;
|
||||
int metatileAttributesSize;
|
||||
uint32_t metatileBehaviorMask;
|
||||
uint32_t metatileTerrainTypeMask;
|
||||
uint32_t metatileEncounterTypeMask;
|
||||
uint32_t metatileLayerTypeMask;
|
||||
uint16_t blockMetatileIdMask;
|
||||
uint16_t blockCollisionMask;
|
||||
uint16_t blockElevationMask;
|
||||
uint16_t unusedTileNormal;
|
||||
uint16_t unusedTileCovered;
|
||||
uint16_t unusedTileSplit;
|
||||
bool mapAllowFlagsEnabled;
|
||||
QString eventsTabIconPath;
|
||||
QString collisionSheetPath;
|
||||
QSize collisionSheetSize;
|
||||
QMargins playerViewDistance;
|
||||
QList<uint32_t> warpBehaviors;
|
||||
int maxEventsPerGroup;
|
||||
int forcedMajorVersion;
|
||||
int metatileSelectorWidth;
|
||||
QStringList globalConstantsFilepaths;
|
||||
QMap<QString,QString> globalConstants;
|
||||
|
||||
protected:
|
||||
virtual void parseConfigKeyValue(QString key, QString value) override;
|
||||
virtual QMap<QString, QString> getKeyValueMap() override;
|
||||
virtual void init() override;
|
||||
virtual void setUnreadKeys() override;
|
||||
|
||||
private:
|
||||
QStringList readKeys;
|
||||
QMap<ProjectIdentifier, QString> identifiers;
|
||||
QMap<ProjectFilePath, QString> filePaths;
|
||||
QMap<Event::Group, QString> eventIconPaths;
|
||||
QMap<QString, QString> pokemonIconPaths;
|
||||
};
|
||||
|
||||
extern ProjectConfig projectConfig;
|
||||
|
||||
class UserConfig: public KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
UserConfig();
|
||||
virtual void reset() override {
|
||||
this->recentMapOrLayout = QString();
|
||||
this->useEncounterJson = true;
|
||||
this->customScripts.clear();
|
||||
this->readKeys.clear();
|
||||
}
|
||||
|
||||
QString projectDir() const { return m_root; } // Alias for root()
|
||||
void parseCustomScripts(QString input);
|
||||
QString outputCustomScripts();
|
||||
void setCustomScripts(QStringList scripts, QList<bool> enabled);
|
||||
QStringList getCustomScriptPaths();
|
||||
QList<bool> getCustomScriptsEnabled();
|
||||
|
||||
QString recentMapOrLayout;
|
||||
bool useEncounterJson;
|
||||
|
||||
protected:
|
||||
virtual void parseConfigKeyValue(QString key, QString value) override;
|
||||
virtual QMap<QString, QString> getKeyValueMap() override;
|
||||
virtual void init() override;
|
||||
virtual void setUnreadKeys() override;
|
||||
#ifdef CONFIG_BACKWARDS_COMPATABILITY
|
||||
friend class ProjectConfig;
|
||||
#endif
|
||||
|
||||
private:
|
||||
QStringList readKeys;
|
||||
QMap<QString, bool> customScripts;
|
||||
};
|
||||
|
||||
extern UserConfig userConfig;
|
||||
|
||||
class QAction;
|
||||
class Shortcut;
|
||||
|
||||
class ShortcutsConfig : public KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
ShortcutsConfig();
|
||||
|
||||
virtual void reset() override {
|
||||
setRoot(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
||||
user_shortcuts.clear();
|
||||
}
|
||||
|
||||
// Call this before applying user shortcuts so that the user can restore defaults.
|
||||
void setDefaultShortcuts(const QObjectList &objects);
|
||||
QList<QKeySequence> defaultShortcuts(const QObject *object) const;
|
||||
|
||||
void setUserShortcuts(const QObjectList &objects);
|
||||
void setUserShortcuts(const QMultiMap<const QObject *, QKeySequence> &objects_keySequences);
|
||||
QList<QKeySequence> userShortcuts(const QObject *object) const;
|
||||
|
||||
protected:
|
||||
virtual void parseConfigKeyValue(QString key, QString value) override;
|
||||
virtual QMap<QString, QString> getKeyValueMap() override;
|
||||
virtual void init() override { };
|
||||
virtual void setUnreadKeys() override { };
|
||||
|
||||
private:
|
||||
QMultiMap<QString, QKeySequence> user_shortcuts;
|
||||
QMultiMap<QString, QKeySequence> default_shortcuts;
|
||||
|
||||
enum StoreType {
|
||||
User,
|
||||
Default
|
||||
};
|
||||
|
||||
QString cfgKey(const QObject *object) const;
|
||||
QList<QKeySequence> currentShortcuts(const QObject *object) const;
|
||||
|
||||
void storeShortcutsFromList(StoreType storeType, const QObjectList &objects);
|
||||
void storeShortcuts(
|
||||
StoreType storeType,
|
||||
const QString &cfgKey,
|
||||
const QList<QKeySequence> &keySequences);
|
||||
};
|
||||
|
||||
extern ShortcutsConfig shortcutsConfig;
|
||||
|
||||
#endif // CONFIG_H
|
||||
5
include/config/config.h
Normal file
5
include/config/config.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include "porymapconfig.h"
|
||||
#include "projectconfig.h"
|
||||
#include "userconfig.h"
|
||||
#include "shortcutsconfig.h"
|
||||
48
include/config/keyvalueconfigbase.h
Normal file
48
include/config/keyvalueconfigbase.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#ifndef KEYVALUECONFIGBASE_H
|
||||
#define KEYVALUECONFIGBASE_H
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
|
||||
#include "fieldmanager.h"
|
||||
|
||||
class KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
explicit KeyValueConfigBase(const QString& filename)
|
||||
: m_root(QString()),
|
||||
m_filename(filename),
|
||||
m_filepath(filename)
|
||||
{ };
|
||||
virtual ~KeyValueConfigBase() {};
|
||||
|
||||
virtual bool save();
|
||||
virtual bool load();
|
||||
|
||||
virtual QJsonObject toJson();
|
||||
virtual void loadFromJson(const QJsonObject& obj);
|
||||
|
||||
void setRoot(const QString& dir);
|
||||
QString root() const { return m_root; }
|
||||
QString filepath() const { return m_filepath; }
|
||||
QString filename() const { return m_filename; }
|
||||
protected:
|
||||
virtual void initializeFromEmpty() {};
|
||||
virtual QJsonObject getDefaultJson() const { return QJsonObject(); }
|
||||
|
||||
virtual FieldManager* getFieldManager() { return nullptr; }
|
||||
|
||||
virtual bool parseJsonKeyValue(const QString& key, const QJsonValue& value);
|
||||
virtual bool parseLegacyKeyValue(const QString& , const QString& ) {return false;}
|
||||
|
||||
QString m_root;
|
||||
QString m_filename;
|
||||
QString m_filepath;
|
||||
private:
|
||||
bool loadLegacy();
|
||||
|
||||
bool m_saveAllFields = false;
|
||||
};
|
||||
|
||||
#endif // KEYVALUECONFIGBASE_H
|
||||
189
include/config/porymapconfig.h
Normal file
189
include/config/porymapconfig.h
Normal file
@@ -0,0 +1,189 @@
|
||||
#pragma once
|
||||
#ifndef PORYMAPCONFIG_H
|
||||
#define PORYMAPCONFIG_H
|
||||
|
||||
#include "keyvalueconfigbase.h"
|
||||
#include "block.h"
|
||||
#include "events.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <QColorSpace>
|
||||
#include <QFontDatabase>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QStandardPaths>
|
||||
|
||||
enum ScriptAutocompleteMode {
|
||||
MapOnly,
|
||||
MapAndCommon,
|
||||
All,
|
||||
};
|
||||
|
||||
class PorymapConfig: public KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
PorymapConfig() : KeyValueConfigBase(QStringLiteral("settings.json")) {
|
||||
setRoot(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
||||
|
||||
// Initialize defaults not available at compile time.
|
||||
this->mapListFont = defaultMapListFont();
|
||||
}
|
||||
|
||||
virtual bool save() override;
|
||||
|
||||
virtual void loadFromJson(const QJsonObject& obj) override;
|
||||
|
||||
void addRecentProject(const QString& project);
|
||||
void setRecentProjects(const QStringList& projects);
|
||||
QString getRecentProject() const;
|
||||
const QStringList& getRecentProjects() const;
|
||||
|
||||
void saveGeometry(const QWidget* widget, const QString& keyPrefix = QString(), bool recursive = true);
|
||||
bool restoreGeometry(QWidget* widget, const QString& keyPrefix = QString(), bool recursive = true) const;
|
||||
|
||||
static QFont defaultMapListFont() { return QFontDatabase::systemFont(QFontDatabase::FixedFont); }
|
||||
|
||||
bool reopenOnLaunch = true;
|
||||
bool projectManuallyClosed = false;
|
||||
int mapListTab = 0;
|
||||
bool mapListEditGroupsEnabled = false;
|
||||
OrderedSet<int> mapListTabsHidingEmptyFolders;
|
||||
bool mapListLayoutsSorted = true;
|
||||
bool mapListLocationsSorted = true;
|
||||
bool prettyCursors = true;
|
||||
bool mirrorConnectingMaps = true;
|
||||
bool showDiveEmergeMaps = false;
|
||||
int diveEmergeMapOpacity = 30;
|
||||
int diveMapOpacity = 15;
|
||||
int emergeMapOpacity = 15;
|
||||
int collisionOpacity = 50;
|
||||
int collisionZoom = 30;
|
||||
int metatilesZoom = 30;
|
||||
int tilesetEditorMetatilesZoom = 30;
|
||||
int tilesetEditorTilesZoom = 30;
|
||||
Qt::Orientation tilesetEditorLayerOrientation = Qt::Vertical;
|
||||
bool showPlayerView = false;
|
||||
bool showCursorTile = true;
|
||||
bool showBorder = true;
|
||||
bool showGrid = false;
|
||||
bool showTilesetEditorMetatileGrid = false;
|
||||
bool showTilesetEditorLayerGrid = true;
|
||||
bool showTilesetEditorDivider = true;
|
||||
bool showTilesetEditorRawAttributes = false;
|
||||
bool showPaletteEditorUnusedColors = false;
|
||||
bool monitorFiles = true;
|
||||
bool tilesetCheckerboardFill = true;
|
||||
bool newMapHeaderSectionExpanded = false;
|
||||
bool displayIdsHexadecimal = true;
|
||||
QString theme = QStringLiteral("default");
|
||||
QString wildMonChartTheme;
|
||||
QString textEditorOpenFolder;
|
||||
QString textEditorGotoLine;
|
||||
int paletteEditorBitDepth = 24;
|
||||
int projectSettingsTab = 0;
|
||||
ScriptAutocompleteMode scriptAutocompleteMode = ScriptAutocompleteMode::MapOnly;
|
||||
bool warpBehaviorWarningDisabled = false;
|
||||
bool eventDeleteWarningDisabled = false;
|
||||
bool eventOverlayEnabled = false;
|
||||
bool checkForUpdates = true;
|
||||
bool showProjectLoadingScreen = true;
|
||||
QDateTime lastUpdateCheckTime;
|
||||
QVersionNumber lastUpdateCheckVersion;
|
||||
QMap<QUrl, QDateTime> rateLimitTimes;
|
||||
QGraphicsPixmapItem::ShapeMode eventSelectionShapeMode = QGraphicsPixmapItem::MaskShape;
|
||||
bool shownInGameReloadMessage = false;
|
||||
GridSettings gridSettings;
|
||||
OrderedSet<LogType> statusBarLogTypes = { LogType::LOG_ERROR, LogType::LOG_WARN };
|
||||
QFont applicationFont;
|
||||
QFont mapListFont;
|
||||
#ifdef Q_OS_MACOS
|
||||
// Since the release of the Retina display, Apple products use the Display P3 color space by default.
|
||||
// If we don't use this for exported images (which by default will either have no color space or the sRGB
|
||||
// color space) then they may appear to have different colors than the same image displayed in Porymap.
|
||||
std::optional<QColorSpace::NamedColorSpace> imageExportColorSpace = QColorSpace::DisplayP3;
|
||||
#else
|
||||
// As of writing Qt has no way to get a reasonable color space from the user's environment,
|
||||
// so we export images without one and let them handle it.
|
||||
std::optional<QColorSpace::NamedColorSpace> imageExportColorSpace = {};
|
||||
#endif
|
||||
QMap<QString,QString> trustedScriptHashes;
|
||||
|
||||
FieldManager* getFieldManager() override {
|
||||
if (!m_fm) {
|
||||
m_fm = std::make_shared<FieldManager>();
|
||||
m_fm->addField(&this->reopenOnLaunch, "reopen_on_launch");
|
||||
m_fm->addField(&this->projectManuallyClosed, "project_manually_closed");
|
||||
m_fm->addField(&this->mapListTab, "map_list_tab", 0, 2);
|
||||
m_fm->addField(&this->mapListEditGroupsEnabled, "map_list_edit_groups_enabled");
|
||||
m_fm->addField(&this->mapListTabsHidingEmptyFolders, "map_list_tabs_hiding_empty_folders");
|
||||
m_fm->addField(&this->mapListLayoutsSorted, "map_list_layouts_sorted");
|
||||
m_fm->addField(&this->mapListLocationsSorted, "map_list_locations_sorted");
|
||||
m_fm->addField(&this->prettyCursors, "pretty_cursors");
|
||||
m_fm->addField(&this->mirrorConnectingMaps, "mirror_connecting_maps");
|
||||
m_fm->addField(&this->showDiveEmergeMaps, "show_dive_emerge_maps");
|
||||
m_fm->addField(&this->diveEmergeMapOpacity, "dive_emerge_map_opacity", 10, 90);
|
||||
m_fm->addField(&this->diveMapOpacity, "dive_map_opacity", 10, 90);
|
||||
m_fm->addField(&this->emergeMapOpacity, "emerge_map_opacity", 10, 90);
|
||||
m_fm->addField(&this->collisionOpacity, "collision_opacity", 0, 100);
|
||||
m_fm->addField(&this->collisionZoom, "collision_zoom", 10, 100);
|
||||
m_fm->addField(&this->metatilesZoom, "metatiles_zoom", 10, 100);
|
||||
m_fm->addField(&this->tilesetEditorMetatilesZoom, "tileset_editor_metatiles_zoom", 10, 100);
|
||||
m_fm->addField(&this->tilesetEditorTilesZoom, "tileset_editor_tiles_zoom", 10, 100);
|
||||
m_fm->addField(&this->tilesetEditorLayerOrientation, "tileset_editor_layer_orientation");
|
||||
m_fm->addField(&this->showPlayerView, "show_player_view");
|
||||
m_fm->addField(&this->showCursorTile, "show_cursor_tile");
|
||||
m_fm->addField(&this->showBorder, "show_border");
|
||||
m_fm->addField(&this->showGrid, "show_grid");
|
||||
m_fm->addField(&this->showTilesetEditorMetatileGrid, "show_tileset_editor_metatile_grid");
|
||||
m_fm->addField(&this->showTilesetEditorLayerGrid, "show_tileset_editor_layer_grid");
|
||||
m_fm->addField(&this->showTilesetEditorDivider, "show_tileset_editor_divider");
|
||||
m_fm->addField(&this->showTilesetEditorRawAttributes, "show_tileset_editor_raw_attributes");
|
||||
m_fm->addField(&this->showPaletteEditorUnusedColors, "show_palette_editor_unused_colors");
|
||||
m_fm->addField(&this->monitorFiles, "monitor_files");
|
||||
m_fm->addField(&this->tilesetCheckerboardFill, "tileset_checkerboard_fill");
|
||||
m_fm->addField(&this->newMapHeaderSectionExpanded, "new_map_header_section_expanded");
|
||||
m_fm->addField(&this->displayIdsHexadecimal, "display_ids_hexadecimal");
|
||||
m_fm->addField(&this->theme, "theme");
|
||||
m_fm->addField(&this->wildMonChartTheme, "wild_mon_chart_theme");
|
||||
m_fm->addField(&this->textEditorOpenFolder, "text_editor_open_folder");
|
||||
m_fm->addField(&this->textEditorGotoLine, "text_editor_goto_line");
|
||||
m_fm->addField(&this->paletteEditorBitDepth, "palette_editor_bit_depth", {24,15});
|
||||
m_fm->addField(&this->projectSettingsTab, "project_settings_tab");
|
||||
m_fm->addField(&this->scriptAutocompleteMode, "script_autocomplete_mode");
|
||||
m_fm->addField(&this->warpBehaviorWarningDisabled, "warp_behavior_warning_disabled");
|
||||
m_fm->addField(&this->eventDeleteWarningDisabled, "event_delete_warning_disabled");
|
||||
m_fm->addField(&this->eventOverlayEnabled, "event_overlay_enabled");
|
||||
m_fm->addField(&this->checkForUpdates, "check_for_updates");
|
||||
m_fm->addField(&this->showProjectLoadingScreen, "show_project_loading_screen");
|
||||
m_fm->addField(&this->lastUpdateCheckTime, "last_update_check_time");
|
||||
m_fm->addField(&this->lastUpdateCheckVersion, "last_update_check_version");
|
||||
m_fm->addField(&this->rateLimitTimes, "rate_limit_times");
|
||||
m_fm->addField(&this->eventSelectionShapeMode, "event_selection_shape_mode");
|
||||
m_fm->addField(&this->shownInGameReloadMessage, "shown_in_game_reload_message");
|
||||
m_fm->addField(&this->gridSettings, "map_grid");
|
||||
m_fm->addField(&this->statusBarLogTypes, "status_bar_log_types");
|
||||
m_fm->addField(&this->applicationFont, "application_font");
|
||||
m_fm->addField(&this->mapListFont, "map_list_font");
|
||||
m_fm->addField(&this->imageExportColorSpace, "image_export_color_space");
|
||||
m_fm->addField(&this->trustedScriptHashes, "trusted_script_hashes");
|
||||
|
||||
m_fm->addField(&this->recentProjects, "recent_projects");
|
||||
m_fm->addField(&this->savedGeometryMap, "geometry");
|
||||
m_fm->addField(&this->geometryVersion, "geometry_version");
|
||||
}
|
||||
return m_fm.get();
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual bool parseLegacyKeyValue(const QString& key, const QString& value) override;
|
||||
virtual QJsonObject getDefaultJson() const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<FieldManager> m_fm = nullptr;
|
||||
QStringList recentProjects;
|
||||
QMap<QString, QByteArray> savedGeometryMap;
|
||||
int geometryVersion = 0;
|
||||
};
|
||||
|
||||
extern PorymapConfig porymapConfig;
|
||||
|
||||
#endif // PORYMAPCONFIG_H
|
||||
276
include/config/projectconfig.h
Normal file
276
include/config/projectconfig.h
Normal file
@@ -0,0 +1,276 @@
|
||||
#pragma once
|
||||
#ifndef PROJECTCONFIG_H
|
||||
#define PROJECTCONFIG_H
|
||||
|
||||
#include "keyvalueconfigbase.h"
|
||||
#include "block.h"
|
||||
#include "events.h"
|
||||
|
||||
enum ProjectIdentifier {
|
||||
symbol_facing_directions,
|
||||
symbol_obj_event_gfx_pointers,
|
||||
symbol_pokemon_icon_table,
|
||||
symbol_attribute_table,
|
||||
symbol_tilesets_prefix,
|
||||
symbol_dynamic_map_name,
|
||||
define_obj_event_count,
|
||||
define_min_level,
|
||||
define_max_level,
|
||||
define_max_encounter_rate,
|
||||
define_tiles_primary,
|
||||
define_tiles_total,
|
||||
define_metatiles_primary,
|
||||
define_pals_primary,
|
||||
define_pals_total,
|
||||
define_tiles_per_metatile,
|
||||
define_map_size,
|
||||
define_map_offset_width,
|
||||
define_map_offset_height,
|
||||
define_mask_metatile,
|
||||
define_mask_collision,
|
||||
define_mask_elevation,
|
||||
define_mask_behavior,
|
||||
define_mask_layer,
|
||||
define_attribute_behavior,
|
||||
define_attribute_layer,
|
||||
define_attribute_terrain,
|
||||
define_attribute_encounter,
|
||||
define_metatile_label_prefix,
|
||||
define_heal_locations_prefix,
|
||||
define_layout_prefix,
|
||||
define_map_prefix,
|
||||
define_map_dynamic,
|
||||
define_map_empty,
|
||||
define_map_section_prefix,
|
||||
define_map_section_empty,
|
||||
define_species_prefix,
|
||||
define_species_empty,
|
||||
regex_behaviors,
|
||||
regex_obj_event_gfx,
|
||||
regex_items,
|
||||
regex_flags,
|
||||
regex_vars,
|
||||
regex_movement_types,
|
||||
regex_map_types,
|
||||
regex_battle_scenes,
|
||||
regex_weather,
|
||||
regex_coord_event_weather,
|
||||
regex_secret_bases,
|
||||
regex_sign_facing_directions,
|
||||
regex_trainer_types,
|
||||
regex_music,
|
||||
regex_encounter_types,
|
||||
regex_terrain_types,
|
||||
pals_output_extension,
|
||||
tiles_output_extension,
|
||||
};
|
||||
|
||||
enum ProjectFilePath {
|
||||
data_map_folders,
|
||||
data_scripts_folders,
|
||||
data_layouts_folders,
|
||||
data_primary_tilesets_folders,
|
||||
data_secondary_tilesets_folders,
|
||||
data_event_scripts,
|
||||
json_map_groups,
|
||||
json_layouts,
|
||||
json_wild_encounters,
|
||||
json_heal_locations,
|
||||
json_region_map_entries,
|
||||
json_region_porymap_cfg,
|
||||
tilesets_headers,
|
||||
tilesets_graphics,
|
||||
tilesets_metatiles,
|
||||
tilesets_headers_asm,
|
||||
tilesets_graphics_asm,
|
||||
tilesets_metatiles_asm,
|
||||
data_obj_event_gfx_pointers,
|
||||
data_obj_event_gfx_info,
|
||||
data_obj_event_pic_tables,
|
||||
data_obj_event_gfx,
|
||||
data_pokemon_gfx,
|
||||
constants_global,
|
||||
constants_items,
|
||||
constants_flags,
|
||||
constants_vars,
|
||||
constants_weather,
|
||||
constants_songs,
|
||||
constants_pokemon,
|
||||
constants_map_types,
|
||||
constants_trainer_types,
|
||||
constants_secret_bases,
|
||||
constants_obj_event_movement,
|
||||
constants_obj_events,
|
||||
constants_event_bg,
|
||||
constants_metatile_labels,
|
||||
constants_metatile_behaviors,
|
||||
constants_species,
|
||||
constants_fieldmap,
|
||||
global_fieldmap,
|
||||
fieldmap,
|
||||
initial_facing_table,
|
||||
wild_encounter,
|
||||
pokemon_icon_table,
|
||||
pokemon_gfx,
|
||||
};
|
||||
|
||||
// Distance in pixels from the edge of a GBA screen (240x160) to the center 16x16 pixels.
|
||||
#define GBA_H_DIST_TO_CENTER ((240-16)/2)
|
||||
#define GBA_V_DIST_TO_CENTER ((160-16)/2)
|
||||
|
||||
class ProjectConfig: public KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
ProjectConfig(const QString& root = QString()) : KeyValueConfigBase(QStringLiteral("porymap.project.json")) {
|
||||
setRoot(root);
|
||||
}
|
||||
ProjectConfig(BaseGame::Version version, const QString& root = QString()) : ProjectConfig(root) {
|
||||
setVersionSpecificDefaults(version);
|
||||
}
|
||||
|
||||
virtual bool save() override;
|
||||
|
||||
virtual void loadFromJson(const QJsonObject& obj) override;
|
||||
|
||||
QString projectDir() const { return m_root; } // Alias for root()
|
||||
void setVersionSpecificDefaults(BaseGame::Version baseGameVersion);
|
||||
|
||||
void setFilePath(ProjectFilePath pathId, const QString& path);
|
||||
void setFilePath(const QString& pathId, const QString& path);
|
||||
QString getCustomFilePath(ProjectFilePath pathId);
|
||||
QString getCustomFilePath(const QString& pathId);
|
||||
QString getFilePath(ProjectFilePath pathId);
|
||||
|
||||
void setIdentifier(ProjectIdentifier id, const QString& text);
|
||||
void setIdentifier(const QString& id, const QString& text);
|
||||
QString getCustomIdentifier(ProjectIdentifier id);
|
||||
QString getCustomIdentifier(const QString& id);
|
||||
QString getIdentifier(ProjectIdentifier id);
|
||||
|
||||
static const QMap<ProjectIdentifier, QPair<QString, QString>> defaultIdentifiers;
|
||||
static const QMap<ProjectFilePath, QPair<QString, QString>> defaultPaths;
|
||||
|
||||
BaseGame::Version baseGameVersion = BaseGame::Version::none;
|
||||
bool usePoryScript = false;
|
||||
bool useCustomBorderSize = false;
|
||||
bool eventWeatherTriggerEnabled = false;
|
||||
bool eventSecretBaseEnabled = false;
|
||||
bool hiddenItemQuantityEnabled = false;
|
||||
bool hiddenItemRequiresItemfinderEnabled = false;
|
||||
bool healLocationRespawnDataEnabled = false;
|
||||
bool eventCloneObjectEnabled = false;
|
||||
bool floorNumberEnabled = false;
|
||||
bool createMapTextFileEnabled = false;
|
||||
bool tripleLayerMetatilesEnabled = false;
|
||||
uint16_t defaultMetatileId = 1;
|
||||
uint16_t defaultElevation = 3;
|
||||
uint16_t defaultCollision = 0;
|
||||
QSize defaultMapSize = QSize(20,20);
|
||||
QList<uint16_t> newMapBorderMetatileIds;
|
||||
QString defaultPrimaryTileset = QStringLiteral("gTileset_General");
|
||||
QString defaultSecondaryTileset;
|
||||
bool tilesetsHaveCallback = true;
|
||||
bool tilesetsHaveIsCompressed = true;
|
||||
QColor transparencyColor = QColorConstants::Black;
|
||||
bool preserveMatchingOnlyData = false;
|
||||
int metatileAttributesSize = 2;
|
||||
uint32_t metatileBehaviorMask = 0;
|
||||
uint32_t metatileTerrainTypeMask = 0;
|
||||
uint32_t metatileEncounterTypeMask = 0;
|
||||
uint32_t metatileLayerTypeMask = 0;
|
||||
uint16_t blockMetatileIdMask = Block::DefaultMetatileIdMask;
|
||||
uint16_t blockCollisionMask = Block::DefaultCollisionMask;
|
||||
uint16_t blockElevationMask = Block::DefaultElevationMask;
|
||||
uint16_t unusedTileNormal = 0x3014;
|
||||
uint16_t unusedTileCovered = 0x0000;
|
||||
uint16_t unusedTileSplit = 0x0000;
|
||||
bool mapAllowFlagsEnabled = true;
|
||||
QString eventsTabIconPath;
|
||||
QString collisionSheetPath;
|
||||
QSize collisionSheetSize = QSize(2, 16);
|
||||
QMargins playerViewDistance = QMargins(GBA_H_DIST_TO_CENTER, GBA_V_DIST_TO_CENTER, GBA_H_DIST_TO_CENTER, GBA_V_DIST_TO_CENTER);
|
||||
OrderedSet<uint32_t> warpBehaviors;
|
||||
int maxEventsPerGroup = 255;
|
||||
int metatileSelectorWidth = 8;
|
||||
QStringList globalConstantsFilepaths;
|
||||
QMap<QString,QString> globalConstants;
|
||||
QList<ScriptSettings> customScripts;
|
||||
QMap<Event::Group, QString> eventIconPaths;
|
||||
QMap<QString, QString> pokemonIconPaths;
|
||||
QVersionNumber minimumVersion;
|
||||
|
||||
FieldManager* getFieldManager() override {
|
||||
if (!m_fm) {
|
||||
m_fm = std::make_shared<FieldManager>();
|
||||
m_fm->addField(&this->baseGameVersion, "base_game_version");
|
||||
m_fm->addField(&this->usePoryScript, "use_poryscript");
|
||||
m_fm->addField(&this->useCustomBorderSize, "use_custom_border_size");
|
||||
m_fm->addField(&this->eventWeatherTriggerEnabled, "enable_event_weather_trigger");
|
||||
m_fm->addField(&this->eventSecretBaseEnabled, "enable_event_secret_base");
|
||||
m_fm->addField(&this->hiddenItemQuantityEnabled, "enable_hidden_item_quantity");
|
||||
m_fm->addField(&this->hiddenItemRequiresItemfinderEnabled, "enable_hidden_item_requires_itemfinder");
|
||||
m_fm->addField(&this->healLocationRespawnDataEnabled, "enable_heal_location_respawn_data");
|
||||
m_fm->addField(&this->eventCloneObjectEnabled, "enable_event_clone_object");
|
||||
m_fm->addField(&this->floorNumberEnabled, "enable_floor_number");
|
||||
m_fm->addField(&this->createMapTextFileEnabled, "create_map_text_file");
|
||||
m_fm->addField(&this->tripleLayerMetatilesEnabled, "enable_triple_layer_metatiles");
|
||||
m_fm->addField<uint16_t>(&this->defaultMetatileId, "default_metatile_id", 0, Block::MaxValue);
|
||||
m_fm->addField<uint16_t>(&this->defaultElevation, "default_elevation", 0, Block::MaxValue);
|
||||
m_fm->addField<uint16_t>(&this->defaultCollision, "default_collision", 0, Block::MaxValue);
|
||||
m_fm->addField(&this->defaultMapSize, "default_map_size");
|
||||
m_fm->addField(&this->newMapBorderMetatileIds, "new_map_border_metatiles");
|
||||
m_fm->addField(&this->defaultPrimaryTileset, "default_primary_tileset");
|
||||
m_fm->addField(&this->defaultSecondaryTileset, "default_secondary_tileset");
|
||||
m_fm->addField(&this->tilesetsHaveCallback, "tilesets_have_callback");
|
||||
m_fm->addField(&this->tilesetsHaveIsCompressed, "tilesets_have_is_compressed");
|
||||
m_fm->addField(&this->transparencyColor, "transparency_color");
|
||||
m_fm->addField(&this->preserveMatchingOnlyData, "preserve_matching_only_data");
|
||||
m_fm->addField(&this->metatileAttributesSize, "metatile_attributes_size");
|
||||
m_fm->addField(&this->metatileBehaviorMask, "metatile_behavior_mask");
|
||||
m_fm->addField(&this->metatileTerrainTypeMask, "metatile_terrain_type_mask");
|
||||
m_fm->addField(&this->metatileEncounterTypeMask, "metatile_encounter_type_mask");
|
||||
m_fm->addField(&this->metatileLayerTypeMask, "metatile_layer_type_mask");
|
||||
m_fm->addField<uint16_t>(&this->blockMetatileIdMask, "block_metatile_id_mask", 0, Block::MaxValue);
|
||||
m_fm->addField<uint16_t>(&this->blockCollisionMask, "block_collision_mask", 0, Block::MaxValue);
|
||||
m_fm->addField<uint16_t>(&this->blockElevationMask, "block_elevation_mask", 0, Block::MaxValue);
|
||||
m_fm->addField<uint16_t>(&this->unusedTileNormal, "unused_tile_normal", 0, Tile::MaxValue);
|
||||
m_fm->addField<uint16_t>(&this->unusedTileCovered, "unused_tile_covered", 0, Tile::MaxValue);
|
||||
m_fm->addField<uint16_t>(&this->unusedTileSplit, "unused_tile_split", 0, Tile::MaxValue);
|
||||
m_fm->addField(&this->mapAllowFlagsEnabled, "enable_map_allow_flags");
|
||||
m_fm->addField(&this->eventsTabIconPath, "events_tab_icon_path");
|
||||
m_fm->addField(&this->collisionSheetPath, "collision_sheet_path");
|
||||
m_fm->addField(&this->collisionSheetSize, "collision_sheet_size", QSize(1,1), QSize(Block::MaxValue, Block::MaxValue));
|
||||
m_fm->addField(&this->playerViewDistance, "player_view_distance", QMargins(0,0,0,0), QMargins(INT_MAX, INT_MAX, INT_MAX, INT_MAX));
|
||||
m_fm->addField(&this->warpBehaviors, "warp_behaviors");
|
||||
m_fm->addField(&this->maxEventsPerGroup, "max_events_per_group", 1, INT_MAX);
|
||||
m_fm->addField(&this->metatileSelectorWidth, "metatile_selector_width", 1, INT_MAX);
|
||||
m_fm->addField(&this->globalConstantsFilepaths, "global_constants_filepaths");
|
||||
m_fm->addField(&this->globalConstants, "global_constants");
|
||||
m_fm->addField(&this->customScripts, "custom_scripts");
|
||||
m_fm->addField(&this->eventIconPaths, "event_icon_paths");
|
||||
m_fm->addField(&this->pokemonIconPaths, "pokemon_icon_paths");
|
||||
m_fm->addField(&this->minimumVersion, "minimum_version");
|
||||
|
||||
m_fm->addField(&this->identifiers, "custom_identifiers");
|
||||
m_fm->addField(&this->filePaths, "custom_file_paths");
|
||||
}
|
||||
return m_fm.get();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool parseLegacyKeyValue(const QString& key, const QString& value) override;
|
||||
virtual QJsonObject getDefaultJson() const override;
|
||||
virtual void initializeFromEmpty() override;
|
||||
|
||||
private:
|
||||
ProjectFilePath reverseDefaultPaths(const QString& str);
|
||||
ProjectIdentifier reverseDefaultIdentifier(const QString& str);
|
||||
|
||||
std::shared_ptr<FieldManager> m_fm = nullptr;
|
||||
QMap<ProjectIdentifier, QString> identifiers;
|
||||
QMap<ProjectFilePath, QString> filePaths;
|
||||
};
|
||||
|
||||
extern ProjectConfig projectConfig;
|
||||
|
||||
#endif // PROJECTCONFIG_H
|
||||
55
include/config/shortcutsconfig.h
Normal file
55
include/config/shortcutsconfig.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
#ifndef SHORTCUTSCONFIG_H
|
||||
#define SHORTCUTSCONFIG_H
|
||||
|
||||
#include "keyvalueconfigbase.h"
|
||||
|
||||
#include <QStandardPaths>
|
||||
|
||||
class QAction;
|
||||
class Shortcut;
|
||||
|
||||
class ShortcutsConfig : public KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
ShortcutsConfig() : KeyValueConfigBase(QStringLiteral("shortcuts.json")) {
|
||||
setRoot(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
||||
}
|
||||
|
||||
virtual QJsonObject toJson() override;
|
||||
virtual void loadFromJson(const QJsonObject& obj) override;
|
||||
|
||||
// Call this before applying user shortcuts so that the user can restore defaults.
|
||||
void setDefaultShortcuts(const QObjectList& objects);
|
||||
QList<QKeySequence> defaultShortcuts(const QObject *object) const;
|
||||
|
||||
void setUserShortcuts(const QObjectList& objects);
|
||||
void setUserShortcuts(const QMultiMap<const QObject *, QKeySequence>& objects_keySequences);
|
||||
QList<QKeySequence> userShortcuts(const QObject *object) const;
|
||||
|
||||
protected:
|
||||
virtual bool parseLegacyKeyValue(const QString& key, const QString& value) override;
|
||||
virtual QJsonObject getDefaultJson() const override;
|
||||
|
||||
private:
|
||||
QMultiMap<QString, QKeySequence> user_shortcuts;
|
||||
QMultiMap<QString, QKeySequence> default_shortcuts;
|
||||
|
||||
enum StoreType {
|
||||
User,
|
||||
Default
|
||||
};
|
||||
|
||||
QString cfgKey(const QObject *object) const;
|
||||
QList<QKeySequence> currentShortcuts(const QObject *object) const;
|
||||
|
||||
void storeShortcutsFromList(StoreType storeType, const QObjectList& objects);
|
||||
void storeShortcuts(
|
||||
StoreType storeType,
|
||||
const QString& cfgKey,
|
||||
const QList<QKeySequence>& keySequences);
|
||||
};
|
||||
|
||||
extern ShortcutsConfig shortcutsConfig;
|
||||
|
||||
#endif // SHORTCUTSCONFIG_H
|
||||
46
include/config/userconfig.h
Normal file
46
include/config/userconfig.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#ifndef USERCONFIG_H
|
||||
#define USERCONFIG_H
|
||||
|
||||
#include "keyvalueconfigbase.h"
|
||||
|
||||
class UserConfig: public KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
UserConfig(const QString& root = QString()) : KeyValueConfigBase(QStringLiteral("porymap.user.json")) {
|
||||
setRoot(root);
|
||||
}
|
||||
|
||||
virtual void loadFromJson(const QJsonObject& obj) override;
|
||||
|
||||
QString projectDir() const { return m_root; } // Alias for root()
|
||||
|
||||
QString recentMapOrLayout;
|
||||
QString prefabsFilepath;
|
||||
bool prefabsImportPrompted = false;
|
||||
bool useEncounterJson = true;
|
||||
QList<ScriptSettings> customScripts;
|
||||
|
||||
protected:
|
||||
virtual bool parseLegacyKeyValue(const QString& key, const QString& value) override;
|
||||
virtual QJsonObject getDefaultJson() const override;
|
||||
|
||||
FieldManager* getFieldManager() override {
|
||||
if (!m_fm) {
|
||||
m_fm = std::make_shared<FieldManager>();
|
||||
m_fm->addField(&this->recentMapOrLayout, "recent_map_or_layout");
|
||||
m_fm->addField(&this->prefabsFilepath, "prefabs_filepath");
|
||||
m_fm->addField(&this->prefabsImportPrompted, "prefabs_import_prompted");
|
||||
m_fm->addField(&this->useEncounterJson, "use_encounter_json");
|
||||
m_fm->addField(&this->customScripts, "custom_scripts");
|
||||
}
|
||||
return m_fm.get();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<FieldManager> m_fm = nullptr;
|
||||
};
|
||||
|
||||
extern UserConfig userConfig;
|
||||
|
||||
#endif // USERCONFIG_H
|
||||
22
include/core/basegame.h
Normal file
22
include/core/basegame.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#ifndef BASEGAMEVERSION_H
|
||||
#define BASEGAMEVERSION_H
|
||||
|
||||
#include <QString>
|
||||
#include <QIcon>
|
||||
|
||||
namespace BaseGame {
|
||||
enum Version {
|
||||
none,
|
||||
pokeruby,
|
||||
pokefirered,
|
||||
pokeemerald,
|
||||
};
|
||||
Version stringToVersion(const QString &string);
|
||||
QString versionToString(Version version);
|
||||
|
||||
QString getPlayerIconPath(Version version, int character);
|
||||
QIcon getPlayerIcon(Version version, int character);
|
||||
};
|
||||
|
||||
#endif // BASEGAMEVERSION_H
|
||||
@@ -26,7 +26,12 @@ public:
|
||||
static uint16_t getMaxCollision();
|
||||
static uint16_t getMaxElevation();
|
||||
|
||||
static const uint16_t maxValue;
|
||||
// Upper limit for metatile ID, collision, and elevation masks. Used externally.
|
||||
static constexpr uint16_t MaxValue = 0xFFFF;
|
||||
|
||||
static constexpr uint16_t DefaultMetatileIdMask = 0x03FF;
|
||||
static constexpr uint16_t DefaultCollisionMask = 0x0C00;
|
||||
static constexpr uint16_t DefaultElevationMask = 0xF000;
|
||||
|
||||
private:
|
||||
uint16_t m_metatileId;
|
||||
|
||||
401
include/core/converter.h
Normal file
401
include/core/converter.h
Normal file
@@ -0,0 +1,401 @@
|
||||
#pragma once
|
||||
#ifndef CONVERTER_H
|
||||
#define CONVERTER_H
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QJsonValue>
|
||||
#include <QUrl>
|
||||
#include <QVariant>
|
||||
#include <QVersionNumber>
|
||||
|
||||
#include "magic_enum.hpp"
|
||||
#include "orderedset.h"
|
||||
#include "scriptsettings.h"
|
||||
#include "gridsettings.h"
|
||||
#include "basegame.h"
|
||||
|
||||
/*
|
||||
These are templates for type conversion to/from JSON,
|
||||
though other type conversions can be implemented here too.
|
||||
|
||||
This is mostly useful when converting the type is complicated,
|
||||
or when the type is generalized away.
|
||||
|
||||
|
||||
## Example Usage ##
|
||||
QSize size;
|
||||
QJsonValue json = Converter<QSize>::toJson(size);
|
||||
QSize sameSize = Converter<QSize>::fromJson(json);
|
||||
|
||||
|
||||
## Adding a new conversion ##
|
||||
To add a new type conversion, add a new 'Converter' template:
|
||||
|
||||
template <>
|
||||
struct Converter<NewType> : DefaultConverter<NewType> {
|
||||
// And re-implement any of the desired conversion functions.
|
||||
// Any functions not implemented will be inherited from DefaultConverter.
|
||||
static QJsonValue toJson(const NewType& value) {
|
||||
// your conversion to JSON
|
||||
return QJsonValue();
|
||||
}
|
||||
static NewType fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
// your conversion from JSON
|
||||
return NewType();
|
||||
}
|
||||
};
|
||||
|
||||
Note: When serializing to/from JSON, anything that can be serialized to/from
|
||||
a string is trivially serializable for JSON. In this case, rather than
|
||||
inheriting from 'DefaultConverter' and reimplementing 'toJson' and 'fromJson',
|
||||
you can inherit from 'DefaultStringConverter' and/or reimplement 'toString'/'fromString'.
|
||||
Appropriately implementing 'toString'/'fromString' has the added benefit that your type
|
||||
can automatically be used as a JSON key if it for example appears as the key in a QMap.
|
||||
|
||||
If a type doesn't support the '<'/'>' operators, 'clamp' can be reimplemented as well to allow
|
||||
the type to be used in range validation.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct DefaultConverter {
|
||||
// Defaults to straightforward QJsonValue construction.
|
||||
// This handles most of the primitive types.
|
||||
static QJsonValue toJson(const T& value) {
|
||||
return QJsonValue(value);
|
||||
}
|
||||
static T fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const QVariant v = json.toVariant();
|
||||
if (!v.canConvert<T>()) {
|
||||
if (errors) errors->append(QString("Can't convert from type '%1'").arg(v.typeName()));
|
||||
// Failed conversion will return a default-constructed object below
|
||||
}
|
||||
return v.value<T>();
|
||||
}
|
||||
|
||||
// Default to identity
|
||||
static QString toString(const T& value) {return value;}
|
||||
static T fromString(const QString& string, QStringList* = nullptr) {return string;}
|
||||
|
||||
static T clamp(const T& value, const T& min, const T& max, QStringList* errors = nullptr) {
|
||||
Q_ASSERT(min <= max);
|
||||
if (value < min) {
|
||||
if (errors) errors->append("Value too low");
|
||||
return min;
|
||||
}
|
||||
if (value > max) {
|
||||
if (errors) errors->append("Value too high");
|
||||
return max;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct Converter : DefaultConverter<T> {};
|
||||
|
||||
// This template implements JSON conversion by first converting the data to/from a string.
|
||||
// This allows any type that can describe how to stringify itself to automatically also
|
||||
// support JSON conversion with no additional work.
|
||||
template <typename T>
|
||||
struct DefaultStringConverter : DefaultConverter<T> {
|
||||
static QJsonValue toJson(const T& value) {
|
||||
return Converter<QString>::toJson(Converter<T>::toString(value));
|
||||
}
|
||||
static T fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto string = Converter<QString>::fromJson(json, errors);
|
||||
return Converter<T>::fromString(string, errors);
|
||||
}
|
||||
// Many types have a 'toString' function, so we default to trying that.
|
||||
static QString toString(const T& value) {
|
||||
return value.toString();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<QUrl> : DefaultStringConverter<QUrl> {};
|
||||
|
||||
template <>
|
||||
struct Converter<QKeySequence> : DefaultStringConverter<QKeySequence> {};
|
||||
|
||||
template <>
|
||||
struct Converter<uint32_t> : DefaultConverter<uint32_t> {
|
||||
// Constructing a QJsonValue from uint32_t is ambiguous, so we need an explicit cast.
|
||||
static QJsonValue toJson(uint32_t value) {
|
||||
return QJsonValue{static_cast<qint64>(value)};
|
||||
}
|
||||
};
|
||||
|
||||
// Template for generic enum values.
|
||||
// Converts JSON -> string/int -> enum, handling the unsafe conversion if the int is out of range of the enum.
|
||||
// Qt has a system for this (Q_ENUM) but they don't use it for all their internal enums, so we use magic_enum instead.
|
||||
template <typename T>
|
||||
struct Converter<T, std::enable_if_t<std::is_enum_v<T>>> : DefaultStringConverter<T> {
|
||||
static QString toString(const T& value) {
|
||||
const std::string s = std::string(magic_enum::enum_name(value));
|
||||
return QString::fromStdString(s);
|
||||
}
|
||||
static T fromString(const QString& string, QStringList* errors = nullptr) {
|
||||
auto e = magic_enum::enum_cast<T>(string.toStdString(), magic_enum::case_insensitive);
|
||||
if (!e.has_value()) {
|
||||
if (errors) errors->append(QString("'%1' is not a named enum value.").arg(string));
|
||||
return magic_enum::enum_value<T>(0);
|
||||
}
|
||||
return e.value();
|
||||
}
|
||||
// When reading from JSON, handle either the named enum or an enum's number value.
|
||||
static T fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
if (json.isString()) return Converter<T>::fromString(json.toString());
|
||||
auto value = Converter<int>::fromJson(json, errors);
|
||||
auto e = magic_enum::enum_cast<T>(value);
|
||||
if (!e.has_value()) {
|
||||
if (errors) errors->append(QString("'%1' is out of range of enum.").arg(QString::number(value)));
|
||||
return magic_enum::enum_value<T>(0);
|
||||
}
|
||||
return e.value();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<QVersionNumber> : DefaultStringConverter<QVersionNumber> {
|
||||
static QVersionNumber fromString(const QString& string, QStringList* = nullptr) {
|
||||
return QVersionNumber::fromString(string);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<QDateTime> : DefaultStringConverter<QDateTime> {
|
||||
static QString toString(const QDateTime& value) {
|
||||
return value.toUTC().toString();
|
||||
}
|
||||
static QDateTime fromString(const QString& string, QStringList* = nullptr) {
|
||||
return QDateTime::fromString(string).toLocalTime();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<QColor> : DefaultStringConverter<QColor> {
|
||||
static QString toString(const QColor& value) {
|
||||
return value.name();
|
||||
}
|
||||
static QColor fromString(const QString& string, QStringList* errors = nullptr) {
|
||||
const QColor color(string);
|
||||
if (!color.isValid()) {
|
||||
if (errors) errors->append(QString("'%1' is not a valid color.").arg(string));
|
||||
return QColorConstants::Black;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<QFont> : DefaultStringConverter<QFont> {
|
||||
static QFont fromString(const QString& string, QStringList* errors = nullptr) {
|
||||
QFont font;
|
||||
if (!font.fromString(string) && errors) {
|
||||
errors->append(QString("'%1' is not a valid font description.").arg(string));
|
||||
}
|
||||
return font;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<BaseGame::Version> : DefaultStringConverter<BaseGame::Version> {
|
||||
static QString toString(const BaseGame::Version& value) {
|
||||
return BaseGame::versionToString(value);
|
||||
}
|
||||
static BaseGame::Version fromString(const QString& string, QStringList* = nullptr) {
|
||||
return BaseGame::stringToVersion(string);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Converter<std::optional<T>> : DefaultConverter<std::optional<T>> {
|
||||
static QJsonValue toJson(const std::optional<T>& optional) {
|
||||
return optional.has_value() ? Converter<T>::toJson(optional.value()) : QJsonValue();
|
||||
}
|
||||
static std::optional<T> fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
if (json.isNull()) return {};
|
||||
return Converter<T>::fromJson(json, errors);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ListConverter : DefaultConverter<QList<T>> {
|
||||
static QJsonValue toJson(const QList<T>& list) {
|
||||
QJsonArray arr;
|
||||
for (auto& elem : list) arr.append(Converter<T>::toJson(elem));
|
||||
return arr;
|
||||
}
|
||||
static QList<T> fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto arr = Converter<QJsonArray>::fromJson(json, errors);
|
||||
QList<T> list;
|
||||
for (const auto& elem : arr) list.append(Converter<T>::fromJson(elem, errors));
|
||||
return list;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Converter<QList<T>> : ListConverter<T> {};
|
||||
|
||||
// Only needed for Qt5
|
||||
template <>
|
||||
struct Converter<QStringList> : ListConverter<QString> {};
|
||||
|
||||
template <typename K, typename V>
|
||||
struct Converter<QMap<K,V>> : DefaultConverter<QMap<K,V>> {
|
||||
static QJsonObject toJson(const QMap<K,V>& map) {
|
||||
QJsonObject obj;
|
||||
for (auto it = map.begin(); it != map.end(); it++) {
|
||||
const QString key = Converter<K>::toString(it.key());
|
||||
obj[key] = Converter<V>::toJson(it.value());
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
static QMap<K,V> fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto obj = Converter<QJsonObject>::fromJson(json, errors);
|
||||
QMap<K,V> map;
|
||||
for (auto it = obj.begin(); it != obj.end(); it++) {
|
||||
const auto key = Converter<K>::fromString(it.key(), errors);
|
||||
map.insert(key, Converter<V>::fromJson(it.value(), errors));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename K, typename V>
|
||||
struct Converter<QMultiMap<K,V>> : DefaultConverter<QMultiMap<K,V>> {
|
||||
static QJsonObject toJson(const QMultiMap<K,V>& map) {
|
||||
QJsonObject obj;
|
||||
for (const auto& uniqueKey : map.uniqueKeys()) {
|
||||
const QString key = Converter<K>::toString(uniqueKey);
|
||||
obj[key] = Converter<QList<V>>::toJson(map.values(uniqueKey));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
static QMultiMap<K,V> fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto obj = Converter<QJsonObject>::fromJson(json, errors);
|
||||
QMultiMap<K,V> map;
|
||||
for (auto it = obj.begin(); it != obj.end(); it++) {
|
||||
const auto key = Converter<K>::fromString(it.key(), errors);
|
||||
const auto values = Converter<QList<V>>::fromJson(it.value(), errors);
|
||||
for (const auto& value : values) map.insert(key, value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Converter<OrderedSet<T>> : DefaultConverter<OrderedSet<T>> {
|
||||
static QJsonValue toJson(const OrderedSet<T>& set) {
|
||||
QJsonArray arr;
|
||||
for (auto& elem : set) arr.append(Converter<T>::toJson(elem));
|
||||
return arr;
|
||||
}
|
||||
static OrderedSet<T> fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto arr = Converter<QJsonArray>::fromJson(json, errors);
|
||||
OrderedSet<T> set;
|
||||
for (const auto& elem : arr) set.insert(Converter<T>::fromJson(elem, errors));
|
||||
return set;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<QSize> : DefaultConverter<QSize> {
|
||||
static QJsonValue toJson(const QSize& value) {
|
||||
QJsonObject obj;
|
||||
obj["width"] = value.width();
|
||||
obj["height"] = value.height();
|
||||
return obj;
|
||||
}
|
||||
static QSize fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto obj = Converter<QJsonObject>::fromJson(json, errors);
|
||||
QSize size;
|
||||
size.setWidth(obj.value("width").toInt());
|
||||
size.setHeight(obj.value("height").toInt());
|
||||
return size;
|
||||
}
|
||||
static QSize clamp(const QSize& value, const QSize& min, const QSize& max, const QStringList* = nullptr) {
|
||||
Q_ASSERT(min.width() <= max.width());
|
||||
Q_ASSERT(min.height() <= max.height());
|
||||
QSize size = value;
|
||||
if (value.width() < min.width() || value.height() < min.height()) size = value.expandedTo(min);
|
||||
if (value.width() > max.width() || value.height() > max.height()) size = value.boundedTo(max);
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<QMargins> : DefaultConverter<QMargins> {
|
||||
static QJsonValue toJson(const QMargins& value) {
|
||||
QJsonObject obj;
|
||||
obj["top"] = value.top();
|
||||
obj["bottom"] = value.bottom();
|
||||
obj["left"] = value.left();
|
||||
obj["right"] = value.right();
|
||||
return obj;
|
||||
}
|
||||
static QMargins fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto obj = Converter<QJsonObject>::fromJson(json, errors);
|
||||
QMargins margins;
|
||||
margins.setTop(obj.value("top").toInt());
|
||||
margins.setBottom(obj.value("bottom").toInt());
|
||||
margins.setLeft(obj.value("left").toInt());
|
||||
margins.setRight(obj.value("right").toInt());
|
||||
return margins;
|
||||
}
|
||||
static QMargins clamp(const QMargins& value, const QMargins& min, const QMargins& max, const QStringList* = nullptr) {
|
||||
Q_ASSERT(min.left() <= max.left());
|
||||
Q_ASSERT(min.right() <= max.right());
|
||||
Q_ASSERT(min.top() <= max.top());
|
||||
Q_ASSERT(min.bottom() <= max.bottom());
|
||||
QMargins margins = value;
|
||||
margins.setLeft( std::clamp(value.left(), min.left(), max.left()));
|
||||
margins.setRight( std::clamp(value.right(), min.right(), max.right()));
|
||||
margins.setTop( std::clamp(value.top(), min.top(), max.top()));
|
||||
margins.setBottom(std::clamp(value.bottom(), min.bottom(), max.bottom()));
|
||||
return margins;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<ScriptSettings> : DefaultConverter<ScriptSettings> {
|
||||
static QJsonValue toJson(const ScriptSettings& value) {
|
||||
QJsonObject obj;
|
||||
obj["path"] = value.path;
|
||||
obj["enabled"] = value.enabled;
|
||||
return obj;
|
||||
}
|
||||
static ScriptSettings fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto obj = Converter<QJsonObject>::fromJson(json, errors);
|
||||
ScriptSettings settings;
|
||||
settings.path = obj.value("path").toString();
|
||||
settings.enabled = obj.value("enabled").toBool();
|
||||
return settings;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<GridSettings> : DefaultConverter<GridSettings> {
|
||||
static QJsonValue toJson(const GridSettings& value) {
|
||||
return value.toJson();
|
||||
}
|
||||
static GridSettings fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto obj = Converter<QJsonObject>::fromJson(json, errors);
|
||||
return GridSettings::fromJson(obj);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<QByteArray> : DefaultConverter<QByteArray> {
|
||||
static QJsonValue toJson(const QByteArray& value) {
|
||||
return QString::fromLocal8Bit(value.toBase64());
|
||||
}
|
||||
static QByteArray fromJson(const QJsonValue& json, QStringList* errors = nullptr) {
|
||||
const auto s = Converter<QString>::fromJson(json, errors);
|
||||
return QByteArray::fromBase64(s.toLocal8Bit());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CONVERTER_H
|
||||
167
include/core/fieldmanager.h
Normal file
167
include/core/fieldmanager.h
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "converter.h"
|
||||
|
||||
// A FieldInterface provides a simple interface for converting a field to/from JSON.
|
||||
// It's constructed with a pointer to some data, and has two functions:
|
||||
// - 'get' returns the pointed-to data, converted to JSON
|
||||
// - 'set' assigns the pointed-to data to a given QJsonValue, with appropriate conversion.
|
||||
// Returns any errors that occur during conversion/assignment.
|
||||
//
|
||||
// A FieldInterface is normally constructed using the 'makeFieldInterface' function:
|
||||
// Example:
|
||||
// int someField = 0;
|
||||
// FieldInterface* fi = makeFieldInterface(&someField);
|
||||
// fi->set(QJsonValue("5")); // someField is now 5
|
||||
//
|
||||
// There are additional implementations of 'makeFieldInterface' that let you specify what valid values are.
|
||||
// Example:
|
||||
// int someField = 0;
|
||||
// int min = 1, max = 4;
|
||||
// FieldInterface* fi = makeFieldInterface(&someField, min, max);
|
||||
// fi->set(QJsonValue("5")); // someField is now 4 (defaults to closest bound), error messages returned
|
||||
// or
|
||||
// QString someField = "";
|
||||
// QList<QString> options = {"hello","hi there"};
|
||||
// FieldInterface* fi = makeFieldInterface(&someField, options);
|
||||
// fi->set(QJsonValue("5")); // someField is now "hello" (defaults to first element), error messages returned
|
||||
|
||||
// Base class lets us use the interface without any type information.
|
||||
class FieldInterface {
|
||||
public:
|
||||
FieldInterface(){};
|
||||
virtual ~FieldInterface() {};
|
||||
virtual QJsonValue get() const = 0;
|
||||
virtual QStringList set(const QJsonValue& json) const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class BasicFieldInterface : public FieldInterface {
|
||||
public:
|
||||
BasicFieldInterface(T* field) : m_field(field) {
|
||||
Q_ASSERT(m_field);
|
||||
};
|
||||
virtual ~BasicFieldInterface() {};
|
||||
virtual QJsonValue get() const override {return Converter<T>::toJson(*m_field);}
|
||||
virtual QStringList set(const QJsonValue& json) const override {
|
||||
QStringList errors;
|
||||
auto value = Converter<T>::fromJson(json, &errors);
|
||||
if (errors.isEmpty()) *m_field = value; // Don't bother changing the value if conversion failed
|
||||
return errors;
|
||||
}
|
||||
protected:
|
||||
T* m_field;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static FieldInterface* makeFieldInterface(T* field) {
|
||||
return new BasicFieldInterface<T>(field);
|
||||
}
|
||||
|
||||
// Create a regular FieldInterface, but override 'set' to use the given min/max.
|
||||
template <typename T>
|
||||
static FieldInterface* makeFieldInterface(T* field, const T& min, const T& max) {
|
||||
class BoundedFieldInterface : public BasicFieldInterface<T> {
|
||||
public:
|
||||
BoundedFieldInterface(T* field, const T& min, const T& max)
|
||||
: BasicFieldInterface<T>(field), m_min(min), m_max(max) {};
|
||||
virtual ~BoundedFieldInterface() {};
|
||||
virtual QStringList set(const QJsonValue& json) const override {
|
||||
QStringList errors;
|
||||
auto value = Converter<T>::fromJson(json, &errors);
|
||||
if (errors.isEmpty()) { // Don't bother changing the value if conversion failed
|
||||
value = Converter<T>::clamp(value, m_min, m_max, &errors);
|
||||
*this->m_field = value;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
private:
|
||||
const T m_min;
|
||||
const T m_max;
|
||||
};
|
||||
return new BoundedFieldInterface(field, min, max);
|
||||
}
|
||||
|
||||
// Create a regular FieldInterface, but override 'set' to use the given 'acceptableValues'.
|
||||
template <typename T>
|
||||
static FieldInterface* makeFieldInterface(T* field, const QList<T>& acceptableValues) {
|
||||
Q_ASSERT(!acceptableValues.isEmpty());
|
||||
class BoundedFieldInterface : public BasicFieldInterface<T> {
|
||||
public:
|
||||
BoundedFieldInterface(T* field, const QList<T>& acceptableValues)
|
||||
: BasicFieldInterface<T>(field),
|
||||
m_acceptableValues(acceptableValues.begin(), acceptableValues.end()),
|
||||
m_defaultValue(acceptableValues.first()) {};
|
||||
virtual ~BoundedFieldInterface() {};
|
||||
virtual QStringList set(const QJsonValue& json) const override {
|
||||
QStringList errors;
|
||||
auto value = Converter<T>::fromJson(json, &errors);
|
||||
if (errors.isEmpty()) {
|
||||
if (!m_acceptableValues.contains(value)) {
|
||||
value = m_defaultValue;
|
||||
errors.append("Invalid value.");
|
||||
}
|
||||
*this->m_field = value;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
private:
|
||||
// The order of the list only matters for determining the default value,
|
||||
// so save that separately and convert the list to a set for better lookup speed.
|
||||
const QSet<T> m_acceptableValues;
|
||||
const T m_defaultValue;
|
||||
};
|
||||
return new BoundedFieldInterface(field, acceptableValues);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FieldManager manages a QHash mapping string keys to FieldInterfaces.
|
||||
// This makes it easy to map many fields to/from JSON without explicitly serializing anything.
|
||||
|
||||
class FieldManager {
|
||||
public:
|
||||
~FieldManager(){ clear(); }
|
||||
|
||||
QStringList setField(const QString& key, const QJsonValue& value) const {
|
||||
auto it = m_fields.find(key);
|
||||
return (it != m_fields.end()) ? it.value()->set(value) : QStringList();
|
||||
}
|
||||
|
||||
QJsonValue getField(const QString& key) const {
|
||||
auto it = m_fields.find(key);
|
||||
return (it != m_fields.end()) ? it.value()->get() : QJsonValue();
|
||||
}
|
||||
|
||||
QJsonObject getFields() const {
|
||||
QJsonObject obj;
|
||||
for (auto it = m_fields.constBegin(); it != m_fields.constEnd(); it++) {
|
||||
obj[it.key()] = it.value()->get();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
qDeleteAll(m_fields);
|
||||
m_fields.clear();
|
||||
}
|
||||
|
||||
bool hasField(const QString& key) const {return m_fields.contains(key);}
|
||||
|
||||
template <typename T>
|
||||
void addField(T* field, const QString& key) {
|
||||
Q_ASSERT(!m_fields.contains(key));
|
||||
m_fields.insert(key, makeFieldInterface<T>(field));
|
||||
}
|
||||
template <typename T>
|
||||
void addField(T* field, const QString& key, const T& min, const T& max) {
|
||||
Q_ASSERT(!m_fields.contains(key));
|
||||
m_fields.insert(key, makeFieldInterface<T>(field, min, max));
|
||||
}
|
||||
template <typename T>
|
||||
void addField(T* field, const QString& key, const QList<T>& acceptableValues) {
|
||||
Q_ASSERT(!m_fields.contains(key));
|
||||
m_fields.insert(key, makeFieldInterface<T>(field, acceptableValues));
|
||||
}
|
||||
|
||||
private:
|
||||
QHash<QString, FieldInterface*> m_fields;
|
||||
};
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <QPixmap>
|
||||
#include <QString>
|
||||
#include <QUndoStack>
|
||||
#include <QJsonObject>
|
||||
|
||||
class Map;
|
||||
class LayoutPixmapItem;
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
#define METATILE_H
|
||||
|
||||
#include "tile.h"
|
||||
#include "config.h"
|
||||
#include "basegame.h"
|
||||
#include "bitpacker.h"
|
||||
#include <QImage>
|
||||
#include <QPoint>
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
|
||||
class Project;
|
||||
|
||||
@@ -41,7 +43,7 @@ public:
|
||||
uint32_t getAttributes() const;
|
||||
uint32_t getAttribute(Metatile::Attr attr) const { return this->attributes.value(attr, 0); }
|
||||
void setAttributes(uint32_t data);
|
||||
void setAttributes(uint32_t data, BaseGameVersion version);
|
||||
void setAttributes(uint32_t data, BaseGame::Version version);
|
||||
void setAttribute(Metatile::Attr attr, uint32_t value);
|
||||
|
||||
// For convenience
|
||||
@@ -56,17 +58,18 @@ public:
|
||||
|
||||
static int getIndexInTileset(int);
|
||||
static QPoint coordFromPixmapCoord(const QPointF &pixelCoord);
|
||||
static uint32_t getDefaultAttributesMask(BaseGameVersion version, Metatile::Attr attr);
|
||||
static uint32_t getDefaultAttributesMask(BaseGame::Version version, Metatile::Attr attr);
|
||||
static uint32_t getMaxAttributesMask();
|
||||
static int getDefaultAttributesSize(BaseGameVersion version);
|
||||
static int getDefaultAttributesSize(BaseGame::Version version);
|
||||
static void setLayout(Project*);
|
||||
static QString getMetatileIdString(uint16_t metatileId);
|
||||
static QString getMetatileIdStrings(const QList<uint16_t> &metatileIds);
|
||||
static QString getLayerName(int layerNum);
|
||||
|
||||
static int numLayers();
|
||||
static constexpr int tileWidth() { return 2; }
|
||||
static constexpr int tileHeight() { return 2; }
|
||||
static constexpr int tilesPerLayer() { return Metatile::tileWidth() * Metatile::tileHeight(); }
|
||||
static int maxTiles() { return Metatile::numLayers() * Metatile::tilesPerLayer(); }
|
||||
static constexpr int pixelWidth() { return Metatile::tileWidth() * Tile::pixelWidth(); }
|
||||
static constexpr int pixelHeight() { return Metatile::tileHeight() * Tile::pixelHeight(); }
|
||||
static constexpr QSize pixelSize() { return QSize(pixelWidth(), pixelHeight()); }
|
||||
|
||||
31
include/core/orderedset.h
Normal file
31
include/core/orderedset.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#ifndef ORDERED_SET_H
|
||||
#define ORDERED_SET_H
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <set>
|
||||
|
||||
template <typename T>
|
||||
class OrderedSet : public std::set<T>
|
||||
{
|
||||
using std::set<T>::set;
|
||||
|
||||
public:
|
||||
// Not introduced to std::set until C++20
|
||||
#if __cplusplus < 202002L
|
||||
bool contains(const T& value) const {
|
||||
return this->find(value) != this->end();
|
||||
}
|
||||
#endif
|
||||
QSet<T> toQSet() const {
|
||||
return QSet<T>(this->begin(), this->end());
|
||||
}
|
||||
static QSet<T> fromQSet(const QSet<T>& set) {
|
||||
return OrderedSet<T>(set.begin(), set.end());
|
||||
}
|
||||
bool isEmpty() const {
|
||||
return this->empty();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ORDERED_SET_H
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "map.h"
|
||||
#include "tilemaptileselector.h"
|
||||
#include "history.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QString>
|
||||
|
||||
27
include/core/scriptsettings.h
Normal file
27
include/core/scriptsettings.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#ifndef SCRIPTSETTINGS_H
|
||||
#define SCRIPTSETTINGS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
// Holds the basic user-provided information about a plug-in script.
|
||||
struct ScriptSettings {
|
||||
QString path;
|
||||
bool enabled = true;
|
||||
|
||||
// Scripts can either by specific to the project, or specific to the user.
|
||||
// This allows projects to send scripts downstream to their users,
|
||||
// while still allowing them to use their own personal scripts.
|
||||
bool userOnly = true;
|
||||
|
||||
static QStringList filter(const QList<ScriptSettings>& scripts) {
|
||||
QStringList paths;
|
||||
for (auto& script : scripts) {
|
||||
if (script.enabled) paths.append(script.path);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SCRIPTSETTINGS_H
|
||||
@@ -5,9 +5,6 @@
|
||||
#include <QObject>
|
||||
#include <QSize>
|
||||
|
||||
// TODO: Replace once config refactoring is complete.
|
||||
extern bool ConfigDisplayIdsHexadecimal;
|
||||
|
||||
class Tile
|
||||
{
|
||||
public:
|
||||
@@ -30,7 +27,8 @@ public:
|
||||
QString toString() const;
|
||||
static QString getTileIdString(uint16_t tileId);
|
||||
|
||||
static const uint16_t maxValue;
|
||||
// Upper limit for raw value (i.e., uint16_t max).
|
||||
static constexpr uint16_t MaxValue = 0xFFFF;
|
||||
|
||||
static constexpr int pixelWidth() { return 8; }
|
||||
static constexpr int pixelHeight() { return 8; }
|
||||
|
||||
@@ -18,9 +18,21 @@ namespace Util {
|
||||
void setErrorStylesheet(QLineEdit *lineEdit, bool isError);
|
||||
QString toStylesheetString(const QFont &font);
|
||||
void show(QWidget *w);
|
||||
QColorSpace toColorSpace(int colorSpaceInt);
|
||||
QString mkpath(const QString& dirPath);
|
||||
QString getFileHash(const QString &filepath);
|
||||
|
||||
// Given a QMap<T,QString>, erases all entries with empty strings.
|
||||
// Returns the number of entries erased.
|
||||
template <typename T>
|
||||
int removeEmptyStrings(QMap<T,QString> *map) {
|
||||
if (!map) return 0;
|
||||
int numRemoved = 0;
|
||||
for (auto it = map->begin(); it != map->end();) {
|
||||
if (it.value().isEmpty()) it = map->erase(it);
|
||||
else {it++; numRemoved++;}
|
||||
}
|
||||
return numRemoved;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTILITY_H
|
||||
|
||||
9
include/core/version.h
Normal file
9
include/core/version.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#ifndef VERSION_H
|
||||
#define VERSION_H
|
||||
|
||||
#include <QVersionNumber>
|
||||
|
||||
extern const QVersionNumber porymapVersion;
|
||||
|
||||
#endif // VERSION_H
|
||||
1549
include/lib/magic_enum.hpp
Normal file
1549
include/lib/magic_enum.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -440,7 +440,7 @@ private:
|
||||
void initShortcuts();
|
||||
void initExtraShortcuts();
|
||||
void loadUserSettings();
|
||||
void restoreWindowState();
|
||||
void resizeWithinScreen();
|
||||
void setTheme(QString);
|
||||
void updateTilesetEditor();
|
||||
Event::Group getEventGroupFromTabWidget(QWidget *tab);
|
||||
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
void clearHealLocations();
|
||||
|
||||
bool sanityCheck();
|
||||
int getSupportedMajorVersion(QString *errorOut = nullptr);
|
||||
QVersionNumber getMinimumVersion(QString *errorOut = nullptr) const;
|
||||
bool load();
|
||||
|
||||
QMap<QString, Tileset*> tilesetCache;
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
Q_INVOKABLE bool getBorderVisibility();
|
||||
Q_INVOKABLE void setSmartPathsEnabled(bool visible);
|
||||
Q_INVOKABLE bool getSmartPathsEnabled();
|
||||
Q_INVOKABLE QList<QString> getCustomScripts();
|
||||
static Q_INVOKABLE QList<QString> getCustomScripts();
|
||||
Q_INVOKABLE QList<int> getMetatileLayerOrder();
|
||||
Q_INVOKABLE void setMetatileLayerOrder(const QList<int> &order);
|
||||
Q_INVOKABLE QList<float> getMetatileLayerOpacity();
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
#ifndef CITYMAPPIXMAPITEM_H
|
||||
#define CITYMAPPIXMAPITEM_H
|
||||
|
||||
#include "tilemaptileselector.h"
|
||||
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QByteArray>
|
||||
#include <QVector>
|
||||
|
||||
class CityMapPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
using QGraphicsPixmapItem::paint;
|
||||
|
||||
public:
|
||||
CityMapPixmapItem(QString fname, TilemapTileSelector *tile_selector) {
|
||||
this->file = fname;
|
||||
this->tile_selector = tile_selector;
|
||||
setAcceptHoverEvents(true);
|
||||
init();
|
||||
}
|
||||
TilemapTileSelector *tile_selector;
|
||||
|
||||
QString file;
|
||||
|
||||
QByteArray data;
|
||||
|
||||
void init();
|
||||
void save();
|
||||
void create(QString);
|
||||
virtual void paint(QGraphicsSceneMouseEvent *);
|
||||
virtual void draw();
|
||||
int getIndexAt(int, int);
|
||||
int width();
|
||||
int height();
|
||||
|
||||
QVector<uint8_t> getTiles();
|
||||
void setTiles(QVector<uint8_t>);
|
||||
|
||||
private:
|
||||
int width_;
|
||||
int height_;
|
||||
|
||||
signals:
|
||||
void mouseEvent(QGraphicsSceneMouseEvent *, CityMapPixmapItem *);
|
||||
void hoveredRegionMapTileChanged(int x, int y);
|
||||
void hoveredRegionMapTileCleared();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
#endif // CITYMAPPIXMAPITEM_H
|
||||
@@ -33,7 +33,7 @@ private:
|
||||
bool hasUnsavedChanges = false;
|
||||
const QString baseDir;
|
||||
|
||||
void displayScript(const QString &filepath, bool enabled);
|
||||
void displayScript(const ScriptSettings &settings);
|
||||
void displayNewScript(QString filepath);
|
||||
QString chooseScript(QString dir);
|
||||
void removeScript(QListWidgetItem * item);
|
||||
@@ -46,7 +46,6 @@ private:
|
||||
int prompt(const QString &text, QMessageBox::StandardButton defaultButton);
|
||||
void save();
|
||||
void closeEvent(QCloseEvent*);
|
||||
void restoreWindowState();
|
||||
void initShortcuts();
|
||||
QObjectList shortcutableObjects() const;
|
||||
void openManual();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define CUSTOMSCRIPTSLISTITEM_H
|
||||
|
||||
#include <QFrame>
|
||||
#include "scriptsettings.h"
|
||||
|
||||
namespace Ui {
|
||||
class CustomScriptsListItem;
|
||||
@@ -13,9 +14,26 @@ class CustomScriptsListItem : public QFrame
|
||||
|
||||
public:
|
||||
explicit CustomScriptsListItem(QWidget *parent = nullptr);
|
||||
explicit CustomScriptsListItem(const ScriptSettings& settings, QWidget *parent = nullptr);
|
||||
~CustomScriptsListItem();
|
||||
|
||||
public:
|
||||
void setSettings(const ScriptSettings& settings);
|
||||
ScriptSettings getSettings() const;
|
||||
|
||||
void setPath(const QString& text);
|
||||
QString path() const;
|
||||
|
||||
void setScriptEnabled(bool enabled);
|
||||
bool scriptEnabled() const;
|
||||
|
||||
signals:
|
||||
void clickedChooseScript();
|
||||
void clickedEditScript();
|
||||
void clickedDeleteScript();
|
||||
void toggledEnable(bool checked);
|
||||
void pathEdited(const QString& text);
|
||||
|
||||
private:
|
||||
Ui::CustomScriptsListItem *ui;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <QObject>
|
||||
#include <QEvent>
|
||||
#include <QSet>
|
||||
|
||||
|
||||
/// Ctrl+Wheel = zoom
|
||||
@@ -16,7 +17,6 @@ public slots:
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Emits a signal when a window gets activated / regains focus
|
||||
class ActiveWindowFilter : public QObject {
|
||||
Q_OBJECT
|
||||
@@ -27,3 +27,15 @@ public:
|
||||
signals:
|
||||
void activated();
|
||||
};
|
||||
|
||||
|
||||
class GeometrySaver : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
GeometrySaver(QObject *parent, bool enableLogging = true)
|
||||
: QObject(parent), m_loggingEnabled(enableLogging) {}
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
private:
|
||||
bool m_loggingEnabled = true;
|
||||
QSet<QObject*> m_shown;
|
||||
};
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include <QAbstractButton>
|
||||
#include <QJsonObject>
|
||||
#include "metatile.h"
|
||||
|
||||
class GridSettings {
|
||||
public:
|
||||
explicit GridSettings() {};
|
||||
constexpr GridSettings() {};
|
||||
~GridSettings() {};
|
||||
|
||||
enum Style {
|
||||
@@ -17,15 +19,18 @@ public:
|
||||
Dots,
|
||||
};
|
||||
|
||||
uint width = 16;
|
||||
uint height = 16;
|
||||
uint width = Metatile::pixelWidth();
|
||||
uint height = Metatile::pixelHeight();
|
||||
int offsetX = 0;
|
||||
int offsetY = 0;
|
||||
Style style = Style::Solid;
|
||||
QColor color = Qt::black;
|
||||
QColor color = QColorConstants::Black;
|
||||
QVector<qreal> getHorizontalDashPattern() const { return this->getDashPattern(this->width); }
|
||||
QVector<qreal> getVerticalDashPattern() const { return this->getDashPattern(this->height); }
|
||||
|
||||
QJsonObject toJson() const;
|
||||
static GridSettings fromJson(const QJsonObject &obj);
|
||||
|
||||
static QString getStyleName(Style style);
|
||||
static GridSettings::Style getStyleFromName(const QString &name);
|
||||
private:
|
||||
|
||||
@@ -84,7 +84,12 @@ private:
|
||||
QImage m_previewImage;
|
||||
bool m_previewUpdateQueued = false;
|
||||
QList<int> m_layerOrder;
|
||||
ProjectConfig m_savedConfig;
|
||||
struct SavedConfigSettings {
|
||||
QColor transparencyColor;
|
||||
uint16_t unusedTileNormal = 0;
|
||||
uint16_t unusedTileCovered = 0;
|
||||
uint16_t unusedTileSplit = 0;
|
||||
} m_savedConfig;
|
||||
QList<QRadioButton*> m_transparencyButtons;
|
||||
|
||||
void populate(const Settings &settings);
|
||||
|
||||
@@ -54,7 +54,6 @@ private:
|
||||
void commitEditHistory();
|
||||
void commitEditHistory(int paletteId);
|
||||
void updateEditHistoryActions();
|
||||
void restoreWindowState();
|
||||
void invalidateCache();
|
||||
void closeEvent(QCloseEvent*);
|
||||
void setColorInputTitles(bool show);
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
void addPrefab(MetatileSelection selection, Layout *layout, QString name);
|
||||
void updatePrefabUi(QPointer<Layout> layout);
|
||||
void clearPrefabUi();
|
||||
bool tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version, QString filepath = "");
|
||||
bool tryImportDefaultPrefabs(QWidget * parent, BaseGame::Version version, QString filepath = "");
|
||||
|
||||
private:
|
||||
QPointer<MetatileSelector> selector;
|
||||
|
||||
@@ -40,7 +40,6 @@ private:
|
||||
|
||||
void initUi();
|
||||
void connectSignals();
|
||||
void restoreWindowState();
|
||||
void save();
|
||||
void refresh();
|
||||
void closeEvent(QCloseEvent*);
|
||||
@@ -72,6 +71,7 @@ private:
|
||||
void addNewGlobalConstant();
|
||||
void addGlobalConstant(const QString &name, const QString &expression);
|
||||
QMap<QString,QString> getGlobalConstants();
|
||||
BaseGame::Version getBaseGameVersion() const;
|
||||
|
||||
private slots:
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define REGIONMAPEDITOR_H
|
||||
|
||||
#include "regionmappixmapitem.h"
|
||||
#include "citymappixmapitem.h"
|
||||
#include "regionmaplayoutpixmapitem.h"
|
||||
#include "regionmapentriespixmapitem.h"
|
||||
#include "regionmap.h"
|
||||
@@ -118,7 +117,6 @@ private:
|
||||
void setRegionMap(RegionMap *map);
|
||||
void setLocations(const QStringList &locations);
|
||||
|
||||
void restoreWindowState();
|
||||
void closeEvent(QCloseEvent* event);
|
||||
|
||||
void setTileHFlip(bool enabled);
|
||||
|
||||
@@ -114,7 +114,6 @@ private:
|
||||
void initMetatileLayersItem();
|
||||
void initShortcuts();
|
||||
void initExtraShortcuts();
|
||||
void restoreWindowState();
|
||||
void initMetatileHistory();
|
||||
void setTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel);
|
||||
void reset();
|
||||
|
||||
@@ -19,8 +19,6 @@ public:
|
||||
explicit WildMonChart(QWidget *parent, const EncounterTableModel *table);
|
||||
~WildMonChart();
|
||||
|
||||
virtual void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
public slots:
|
||||
void setTable(const EncounterTableModel *table);
|
||||
void clearTable();
|
||||
|
||||
Reference in New Issue
Block a user