Merge branch 'master' of https://github.com/huderlem/porymap into connections
This commit is contained in:
commit
3bf237ff45
36 changed files with 930 additions and 1417 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -7,10 +7,21 @@ and this project somewhat adheres to [Semantic Versioning](https://semver.org/sp
|
|||
The **"Breaking Changes"** listed below are changes that have been made in the decompilation projects (e.g. pokeemerald), which porymap requires in order to work properly. It also includes changes to the scripting API that may change the behavior of existing porymap scripts. If porymap is used with a project or API script that is not up-to-date with the breaking changes, then porymap will likely break or behave improperly.
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- Add a `Close Project` option
|
||||
- An alert will be displayed when attempting to open a seemingly invalid project.
|
||||
|
||||
### Changed
|
||||
- The base game version is now auto-detected if the project name contains only one of "emerald", "firered/leafgreen", or "ruby/sapphire".
|
||||
- It's now possible to cancel quitting if there are unsaved changes in sub-windows.
|
||||
|
||||
### Fixed
|
||||
- Fix `Add Region Map...` not updating the region map settings file.
|
||||
- Fix some crashes on invalid region map tilesets.
|
||||
- Improve error reporting for invalid region map editor settings.
|
||||
- Fix config files being written before the project is opened successfully.
|
||||
- Fix the map and other project info still displaying if a new project fails to open.
|
||||
- Fix unsaved changes being ignored when quitting (such as with Cmd+Q on macOS).
|
||||
|
||||
## [5.4.1] - 2024-03-21
|
||||
### Fixed
|
||||
|
|
|
@ -2941,6 +2941,7 @@
|
|||
<addaction name="action_Open_Project"/>
|
||||
<addaction name="menuOpen_Recent_Project"/>
|
||||
<addaction name="action_Reload_Project"/>
|
||||
<addaction name="action_Close_Project"/>
|
||||
<addaction name="action_Save"/>
|
||||
<addaction name="action_Save_Project"/>
|
||||
<addaction name="separator"/>
|
||||
|
@ -3295,6 +3296,14 @@
|
|||
<enum>QAction::ApplicationSpecificRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Close_Project">
|
||||
<property name="text">
|
||||
<string>Close Project</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+W</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
|
280
include/config.h
280
include/config.h
|
@ -33,20 +33,17 @@ class KeyValueConfigBase
|
|||
public:
|
||||
void save();
|
||||
void load();
|
||||
void setSaveDisabled(bool disabled);
|
||||
virtual ~KeyValueConfigBase();
|
||||
virtual void reset() = 0;
|
||||
protected:
|
||||
virtual QString getConfigFilepath() = 0;
|
||||
virtual void parseConfigKeyValue(QString key, QString value) = 0;
|
||||
virtual QMap<QString, QString> getKeyValueMap() = 0;
|
||||
virtual void onNewConfigFileCreated() = 0;
|
||||
virtual void init() = 0;
|
||||
virtual void setUnreadKeys() = 0;
|
||||
bool getConfigBool(QString key, QString value);
|
||||
int getConfigInteger(QString key, QString value, int min = INT_MIN, int max = INT_MAX, int defaultValue = 0);
|
||||
uint32_t getConfigUint32(QString key, QString value, uint32_t min = 0, uint32_t max = UINT_MAX, uint32_t defaultValue = 0);
|
||||
private:
|
||||
bool saveDisabled = false;
|
||||
};
|
||||
|
||||
class PorymapConfig: public KeyValueConfigBase
|
||||
|
@ -57,6 +54,7 @@ public:
|
|||
}
|
||||
virtual void reset() override {
|
||||
this->recentProjects.clear();
|
||||
this->projectManuallyClosed = false;
|
||||
this->reopenOnLaunch = true;
|
||||
this->mapSortOrder = MapSortOrder::Group;
|
||||
this->prettyCursors = true;
|
||||
|
@ -86,101 +84,25 @@ public:
|
|||
}
|
||||
void addRecentProject(QString project);
|
||||
void setRecentProjects(QStringList projects);
|
||||
void setReopenOnLaunch(bool enabled);
|
||||
void setMapSortOrder(MapSortOrder order);
|
||||
void setPrettyCursors(bool enabled);
|
||||
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);
|
||||
void setCollisionOpacity(int opacity);
|
||||
void setCollisionZoom(int zoom);
|
||||
void setMetatilesZoom(int zoom);
|
||||
void setTilesetEditorMetatilesZoom(int zoom);
|
||||
void setTilesetEditorTilesZoom(int zoom);
|
||||
void setShowPlayerView(bool enabled);
|
||||
void setShowCursorTile(bool enabled);
|
||||
void setShowBorder(bool enabled);
|
||||
void setShowGrid(bool enabled);
|
||||
void setShowTilesetEditorMetatileGrid(bool enabled);
|
||||
void setShowTilesetEditorLayerGrid(bool enabled);
|
||||
void setMonitorFiles(bool monitor);
|
||||
void setTilesetCheckerboardFill(bool checkerboard);
|
||||
void setTheme(QString theme);
|
||||
void setTextEditorOpenFolder(const QString &command);
|
||||
void setTextEditorGotoLine(const QString &command);
|
||||
void setPaletteEditorBitDepth(int bitDepth);
|
||||
void setProjectSettingsTab(int tab);
|
||||
void setWarpBehaviorWarningDisabled(bool disabled);
|
||||
void setCheckForUpdates(bool enabled);
|
||||
void setLastUpdateCheckTime(QDateTime time);
|
||||
void setLastUpdateCheckVersion(QVersionNumber version);
|
||||
void setRateLimitTimes(QMap<QUrl, QDateTime> map);
|
||||
QString getRecentProject();
|
||||
QStringList getRecentProjects();
|
||||
bool getReopenOnLaunch();
|
||||
MapSortOrder getMapSortOrder();
|
||||
bool getPrettyCursors();
|
||||
QMap<QString, QByteArray> getMainGeometry();
|
||||
QMap<QString, QByteArray> getTilesetEditorGeometry();
|
||||
QMap<QString, QByteArray> getPaletteEditorGeometry();
|
||||
QMap<QString, QByteArray> getRegionMapEditorGeometry();
|
||||
QMap<QString, QByteArray> getProjectSettingsEditorGeometry();
|
||||
QMap<QString, QByteArray> getCustomScriptsEditorGeometry();
|
||||
int getCollisionOpacity();
|
||||
int getCollisionZoom();
|
||||
int getMetatilesZoom();
|
||||
int getTilesetEditorMetatilesZoom();
|
||||
int getTilesetEditorTilesZoom();
|
||||
bool getShowPlayerView();
|
||||
bool getShowCursorTile();
|
||||
bool getShowBorder();
|
||||
bool getShowGrid();
|
||||
bool getShowTilesetEditorMetatileGrid();
|
||||
bool getShowTilesetEditorLayerGrid();
|
||||
bool getMonitorFiles();
|
||||
bool getTilesetCheckerboardFill();
|
||||
QString getTheme();
|
||||
QString getTextEditorOpenFolder();
|
||||
QString getTextEditorGotoLine();
|
||||
int getPaletteEditorBitDepth();
|
||||
int getProjectSettingsTab();
|
||||
bool getWarpBehaviorWarningDisabled();
|
||||
bool getCheckForUpdates();
|
||||
QDateTime getLastUpdateCheckTime();
|
||||
QVersionNumber getLastUpdateCheckVersion();
|
||||
QMap<QUrl, QDateTime> getRateLimitTimes();
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
virtual void parseConfigKeyValue(QString key, QString value) override;
|
||||
virtual QMap<QString, QString> getKeyValueMap() override;
|
||||
virtual void onNewConfigFileCreated() override {};
|
||||
virtual void setUnreadKeys() override {};
|
||||
private:
|
||||
QStringList recentProjects;
|
||||
|
||||
bool reopenOnLaunch;
|
||||
QString stringFromByteArray(QByteArray);
|
||||
QByteArray bytesFromString(QString);
|
||||
bool projectManuallyClosed;
|
||||
MapSortOrder mapSortOrder;
|
||||
bool prettyCursors;
|
||||
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;
|
||||
int collisionOpacity;
|
||||
int collisionZoom;
|
||||
int metatilesZoom;
|
||||
|
@ -204,11 +126,41 @@ private:
|
|||
QDateTime lastUpdateCheckTime;
|
||||
QVersionNumber lastUpdateCheckVersion;
|
||||
QMap<QUrl, QDateTime> rateLimitTimes;
|
||||
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
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(QByteArray);
|
||||
QByteArray bytesFromString(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,
|
||||
|
@ -330,7 +282,7 @@ public:
|
|||
this->baseGameVersion = BaseGameVersion::pokeemerald;
|
||||
// Reset non-version-specific settings
|
||||
this->usePoryScript = false;
|
||||
this->enableTripleLayerMetatiles = false;
|
||||
this->tripleLayerMetatilesEnabled = false;
|
||||
this->defaultMetatileId = 1;
|
||||
this->defaultElevation = 3;
|
||||
this->defaultCollision = 0;
|
||||
|
@ -354,52 +306,11 @@ public:
|
|||
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);
|
||||
|
||||
void reset(BaseGameVersion baseGameVersion);
|
||||
void setBaseGameVersion(BaseGameVersion baseGameVersion);
|
||||
BaseGameVersion getBaseGameVersion();
|
||||
QString getBaseGameVersionString();
|
||||
QString getBaseGameVersionString(BaseGameVersion version);
|
||||
BaseGameVersion stringToBaseGameVersion(QString string, bool * ok = nullptr);
|
||||
void setUsePoryScript(bool usePoryScript);
|
||||
bool getUsePoryScript();
|
||||
void setProjectDir(QString projectDir);
|
||||
QString getProjectDir();
|
||||
void setUseCustomBorderSize(bool enable);
|
||||
bool getUseCustomBorderSize();
|
||||
void setEventWeatherTriggerEnabled(bool enable);
|
||||
bool getEventWeatherTriggerEnabled();
|
||||
void setEventSecretBaseEnabled(bool enable);
|
||||
bool getEventSecretBaseEnabled();
|
||||
void setHiddenItemQuantityEnabled(bool enable);
|
||||
bool getHiddenItemQuantityEnabled();
|
||||
void setHiddenItemRequiresItemfinderEnabled(bool enable);
|
||||
bool getHiddenItemRequiresItemfinderEnabled();
|
||||
void setHealLocationRespawnDataEnabled(bool enable);
|
||||
bool getHealLocationRespawnDataEnabled();
|
||||
void setEventCloneObjectEnabled(bool enable);
|
||||
bool getEventCloneObjectEnabled();
|
||||
void setFloorNumberEnabled(bool enable);
|
||||
bool getFloorNumberEnabled();
|
||||
void setCreateMapTextFileEnabled(bool enable);
|
||||
bool getCreateMapTextFileEnabled();
|
||||
void setTripleLayerMetatilesEnabled(bool enable);
|
||||
bool getTripleLayerMetatilesEnabled();
|
||||
int getNumLayersInMetatile();
|
||||
int getNumTilesInMetatile();
|
||||
void setDefaultMetatileId(uint16_t metatileId);
|
||||
uint16_t getDefaultMetatileId();
|
||||
void setDefaultElevation(uint16_t elevation);
|
||||
uint16_t getDefaultElevation();
|
||||
void setDefaultCollision(uint16_t collision);
|
||||
uint16_t getDefaultCollision();
|
||||
void setNewMapBorderMetatileIds(QList<uint16_t> metatileIds);
|
||||
QList<uint16_t> getNewMapBorderMetatileIds();
|
||||
QString getDefaultPrimaryTileset();
|
||||
QString getDefaultSecondaryTileset();
|
||||
void setDefaultPrimaryTileset(QString tilesetName);
|
||||
void setDefaultSecondaryTileset(QString tilesetName);
|
||||
void setFilePath(const QString &pathId, const QString &path);
|
||||
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);
|
||||
|
@ -408,75 +319,35 @@ public:
|
|||
QString getCustomIdentifier(ProjectIdentifier id);
|
||||
QString getCustomIdentifier(const QString &id);
|
||||
QString getIdentifier(ProjectIdentifier id);
|
||||
void setPrefabFilepath(QString filepath);
|
||||
QString getPrefabFilepath();
|
||||
void setPrefabImportPrompted(bool prompted);
|
||||
bool getPrefabImportPrompted();
|
||||
void setTilesetsHaveCallback(bool has);
|
||||
bool getTilesetsHaveCallback();
|
||||
void setTilesetsHaveIsCompressed(bool has);
|
||||
bool getTilesetsHaveIsCompressed();
|
||||
int getMetatileAttributesSize();
|
||||
void setMetatileAttributesSize(int size);
|
||||
uint32_t getMetatileBehaviorMask();
|
||||
uint32_t getMetatileTerrainTypeMask();
|
||||
uint32_t getMetatileEncounterTypeMask();
|
||||
uint32_t getMetatileLayerTypeMask();
|
||||
void setMetatileBehaviorMask(uint32_t mask);
|
||||
void setMetatileTerrainTypeMask(uint32_t mask);
|
||||
void setMetatileEncounterTypeMask(uint32_t mask);
|
||||
void setMetatileLayerTypeMask(uint32_t mask);
|
||||
uint16_t getBlockMetatileIdMask();
|
||||
uint16_t getBlockCollisionMask();
|
||||
uint16_t getBlockElevationMask();
|
||||
void setBlockMetatileIdMask(uint16_t mask);
|
||||
void setBlockCollisionMask(uint16_t mask);
|
||||
void setBlockElevationMask(uint16_t mask);
|
||||
bool getMapAllowFlagsEnabled();
|
||||
void setMapAllowFlagsEnabled(bool enabled);
|
||||
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);
|
||||
QHash<QString, QString> getPokemonIconPaths();
|
||||
void setCollisionSheetPath(const QString &path);
|
||||
QString getCollisionSheetPath();
|
||||
void setCollisionSheetWidth(int width);
|
||||
int getCollisionSheetWidth();
|
||||
void setCollisionSheetHeight(int height);
|
||||
int getCollisionSheetHeight();
|
||||
void setWarpBehaviors(const QSet<uint32_t> &behaviors);
|
||||
QSet<uint32_t> getWarpBehaviors();
|
||||
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
virtual void parseConfigKeyValue(QString key, QString value) override;
|
||||
virtual QMap<QString, QString> getKeyValueMap() override;
|
||||
virtual void onNewConfigFileCreated() override;
|
||||
virtual void setUnreadKeys() override;
|
||||
private:
|
||||
BaseGameVersion baseGameVersion;
|
||||
QString projectDir;
|
||||
QMap<ProjectIdentifier, QString> identifiers;
|
||||
QMap<ProjectFilePath, QString> filePaths;
|
||||
bool usePoryScript;
|
||||
bool useCustomBorderSize;
|
||||
bool enableEventWeatherTrigger;
|
||||
bool enableEventSecretBase;
|
||||
bool enableHiddenItemQuantity;
|
||||
bool enableHiddenItemRequiresItemfinder;
|
||||
bool enableHealLocationRespawnData;
|
||||
bool enableEventCloneObject;
|
||||
bool enableFloorNumber;
|
||||
bool createMapTextFile;
|
||||
bool enableTripleLayerMetatiles;
|
||||
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;
|
||||
QList<uint16_t> newMapBorderMetatileIds;
|
||||
QString defaultPrimaryTileset;
|
||||
QString defaultSecondaryTileset;
|
||||
QStringList readKeys;
|
||||
QString prefabFilepath;
|
||||
bool prefabImportPrompted;
|
||||
bool tilesetsHaveCallback;
|
||||
|
@ -489,13 +360,25 @@ private:
|
|||
uint16_t blockMetatileIdMask;
|
||||
uint16_t blockCollisionMask;
|
||||
uint16_t blockElevationMask;
|
||||
bool enableMapAllowFlags;
|
||||
QMap<Event::Group, QString> eventIconPaths;
|
||||
QHash<QString, QString> pokemonIconPaths;
|
||||
bool mapAllowFlagsEnabled;
|
||||
QString collisionSheetPath;
|
||||
int collisionSheetWidth;
|
||||
int collisionSheetHeight;
|
||||
QSet<uint32_t> warpBehaviors;
|
||||
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
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;
|
||||
QHash<QString, QString> pokemonIconPaths;
|
||||
};
|
||||
|
||||
extern ProjectConfig projectConfig;
|
||||
|
@ -512,32 +395,29 @@ public:
|
|||
this->customScripts.clear();
|
||||
this->readKeys.clear();
|
||||
}
|
||||
void setRecentMap(const QString &map);
|
||||
QString getRecentMap();
|
||||
void setEncounterJsonActive(bool active);
|
||||
bool getEncounterJsonActive();
|
||||
void setProjectDir(QString projectDir);
|
||||
QString getProjectDir();
|
||||
void parseCustomScripts(QString input);
|
||||
QString outputCustomScripts();
|
||||
void setCustomScripts(QStringList scripts, QList<bool> enabled);
|
||||
QStringList getCustomScriptPaths();
|
||||
QList<bool> getCustomScriptsEnabled();
|
||||
void parseCustomScripts(QString input);
|
||||
QString outputCustomScripts();
|
||||
|
||||
QString projectDir;
|
||||
QString recentMap;
|
||||
bool useEncounterJson;
|
||||
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
virtual void parseConfigKeyValue(QString key, QString value) override;
|
||||
virtual QMap<QString, QString> getKeyValueMap() override;
|
||||
virtual void onNewConfigFileCreated() override;
|
||||
virtual void init() override;
|
||||
virtual void setUnreadKeys() override;
|
||||
#ifdef CONFIG_BACKWARDS_COMPATABILITY
|
||||
friend class ProjectConfig;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
private:
|
||||
QString projectDir;
|
||||
QString recentMap;
|
||||
bool useEncounterJson;
|
||||
QMap<QString, bool> customScripts;
|
||||
QStringList readKeys;
|
||||
QMap<QString, bool> customScripts;
|
||||
};
|
||||
|
||||
extern UserConfig userConfig;
|
||||
|
@ -567,7 +447,7 @@ protected:
|
|||
virtual QString getConfigFilepath() override;
|
||||
virtual void parseConfigKeyValue(QString key, QString value) override;
|
||||
virtual QMap<QString, QString> getKeyValueMap() override;
|
||||
virtual void onNewConfigFileCreated() override { };
|
||||
virtual void init() override { };
|
||||
virtual void setUnreadKeys() override { };
|
||||
|
||||
private:
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
public:
|
||||
Ui::MainWindow* ui;
|
||||
QObject *parent = nullptr;
|
||||
Project *project = nullptr;
|
||||
QPointer<Project> project = nullptr;
|
||||
Map *map = nullptr;
|
||||
Settings *settings;
|
||||
void saveProject();
|
||||
|
@ -106,13 +106,13 @@ public:
|
|||
void updateWarpEventWarnings();
|
||||
bool eventLimitReached(Map *, Event::Type);
|
||||
|
||||
QGraphicsScene *scene = nullptr;
|
||||
QPointer<QGraphicsScene> scene = nullptr;
|
||||
QGraphicsPixmapItem *current_view = nullptr;
|
||||
MapPixmapItem *map_item = nullptr;
|
||||
QPointer<MapPixmapItem> map_item = nullptr;
|
||||
ConnectionPixmapItem* selected_connection_item = nullptr;
|
||||
QList<ConnectionPixmapItem*> connection_items;
|
||||
QGraphicsPathItem *connection_mask = nullptr;
|
||||
CollisionPixmapItem *collision_item = nullptr;
|
||||
QPointer<CollisionPixmapItem> collision_item = nullptr;
|
||||
QGraphicsItemGroup *events_group = nullptr;
|
||||
QList<QGraphicsPixmapItem*> borderItems;
|
||||
QList<QGraphicsLineItem*> gridLines;
|
||||
|
@ -120,16 +120,15 @@ public:
|
|||
CursorTileRect *cursorMapTileRect = nullptr;
|
||||
MapRuler *map_ruler = nullptr;
|
||||
|
||||
QGraphicsScene *scene_metatiles = nullptr;
|
||||
QGraphicsScene *scene_current_metatile_selection = nullptr;
|
||||
QGraphicsScene *scene_selected_border_metatiles = nullptr;
|
||||
QGraphicsScene *scene_collision_metatiles = nullptr;
|
||||
QGraphicsScene *scene_elevation_metatiles = nullptr;
|
||||
MetatileSelector *metatile_selector_item = nullptr;
|
||||
QPointer<QGraphicsScene> scene_metatiles = nullptr;
|
||||
QPointer<QGraphicsScene> scene_current_metatile_selection = nullptr;
|
||||
QPointer<QGraphicsScene> scene_selected_border_metatiles = nullptr;
|
||||
QPointer<QGraphicsScene> scene_collision_metatiles = nullptr;
|
||||
QPointer<MetatileSelector> metatile_selector_item = nullptr;
|
||||
|
||||
BorderMetatilesPixmapItem *selected_border_metatiles_item = nullptr;
|
||||
QPointer<BorderMetatilesPixmapItem> selected_border_metatiles_item = nullptr;
|
||||
CurrentSelectedMetatilesPixmapItem *current_metatile_selection_item = nullptr;
|
||||
MovementPermissionsSelector *movement_permissions_selector_item = nullptr;
|
||||
QPointer<MovementPermissionsSelector> movement_permissions_selector_item = nullptr;
|
||||
|
||||
QList<DraggablePixmapItem *> *selected_events = nullptr;
|
||||
|
||||
|
@ -167,6 +166,18 @@ private:
|
|||
const QImage collisionPlaceholder = QImage(":/images/collisions_unknown.png");
|
||||
QPixmap collisionSheetPixmap;
|
||||
|
||||
void clearMap();
|
||||
void clearMetatileSelector();
|
||||
void clearMovementPermissionSelector();
|
||||
void clearMapMetatiles();
|
||||
void clearMapMovementPermissions();
|
||||
void clearBorderMetatiles();
|
||||
void clearCurrentMetatilesSelection();
|
||||
void clearMapEvents();
|
||||
//void clearMapConnections();
|
||||
void clearMapBorder();
|
||||
void clearMapGrid();
|
||||
void clearWildMonTables();
|
||||
void updateBorderVisibility();
|
||||
QPoint calculateConnectionPosition(const MapConnection &connection, const QPixmap &pixmap);
|
||||
QPixmap getConnectionPixmap(const MapConnection &connection);
|
||||
|
|
|
@ -167,6 +167,7 @@ public slots:
|
|||
private slots:
|
||||
void on_action_Open_Project_triggered();
|
||||
void on_action_Reload_Project_triggered();
|
||||
void on_action_Close_Project_triggered();
|
||||
void on_mapList_activated(const QModelIndex &index);
|
||||
void on_action_Save_Project_triggered();
|
||||
void openWarpMap(QString map_name, int event_id, Event::Group event_group);
|
||||
|
@ -295,7 +296,7 @@ private slots:
|
|||
|
||||
public:
|
||||
Ui::MainWindow *ui;
|
||||
Editor *editor = nullptr;
|
||||
QPointer<Editor> editor = nullptr;
|
||||
|
||||
private:
|
||||
QLabel *label_MapRulerStatus = nullptr;
|
||||
|
@ -333,7 +334,6 @@ private:
|
|||
|
||||
bool isProgrammaticEventTabChange;
|
||||
bool projectHasUnsavedChanges;
|
||||
bool projectOpenFailure = false;
|
||||
bool newMapDefaultsSet = false;
|
||||
|
||||
MapSortOrder mapSortOrder;
|
||||
|
@ -344,16 +344,18 @@ private:
|
|||
bool setMap(QString, bool scrollTreeView = false);
|
||||
void redrawMapScene();
|
||||
void refreshMapScene();
|
||||
bool loadDataStructures();
|
||||
bool loadProjectCombos();
|
||||
bool populateMapList();
|
||||
bool checkProjectSanity();
|
||||
bool loadProjectData();
|
||||
bool setProjectUI();
|
||||
void clearProjectUI();
|
||||
void sortMapList();
|
||||
void openSubWindow(QWidget * window);
|
||||
QString getExistingDirectory(QString);
|
||||
bool openProject(const QString &dir, bool initial = false);
|
||||
bool openProject(QString dir, bool initial = false);
|
||||
bool closeProject();
|
||||
void showProjectOpenFailure();
|
||||
void saveGlobalConfigs();
|
||||
bool setInitialMap();
|
||||
void setRecentMap(QString map_name);
|
||||
QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum);
|
||||
void refreshRecentProjectsMenu();
|
||||
|
||||
|
@ -376,14 +378,13 @@ private:
|
|||
void initMapSortOrder();
|
||||
void initShortcuts();
|
||||
void initExtraShortcuts();
|
||||
void setProjectSpecificUI();
|
||||
void loadUserSettings();
|
||||
void applyMapListFilter(QString filterText);
|
||||
void restoreWindowState();
|
||||
void setTheme(QString);
|
||||
void updateTilesetEditor();
|
||||
Event::Group getEventGroupFromTabWidget(QWidget *tab);
|
||||
void closeSupplementaryWindows();
|
||||
bool closeSupplementaryWindows();
|
||||
void setWindowDisabled(bool);
|
||||
|
||||
void initTilesetEditor();
|
||||
|
|
|
@ -97,6 +97,9 @@ public:
|
|||
DataQualifiers healLocationDataQualifiers;
|
||||
QString healLocationsTableName;
|
||||
|
||||
bool sanityCheck();
|
||||
bool load();
|
||||
|
||||
QMap<QString, Map*> mapCache;
|
||||
Map* loadMap(QString);
|
||||
Map* getMap(QString);
|
||||
|
@ -153,6 +156,7 @@ public:
|
|||
void saveAllMaps();
|
||||
void saveMap(Map*);
|
||||
void saveAllDataStructures();
|
||||
void saveConfig();
|
||||
void saveMapLayouts();
|
||||
void saveMapGroups();
|
||||
void saveWildMonData();
|
||||
|
|
|
@ -30,6 +30,7 @@ class Scripting
|
|||
{
|
||||
public:
|
||||
Scripting(MainWindow *mainWindow);
|
||||
static void stop();
|
||||
static void init(MainWindow *mainWindow);
|
||||
static void populateGlobalObject(MainWindow *mainWindow);
|
||||
static QJSEngine *getEngine();
|
||||
|
|
801
src/config.cpp
801
src/config.cpp
File diff suppressed because it is too large
Load diff
|
@ -47,9 +47,9 @@ uint16_t Block::rawValue() const {
|
|||
}
|
||||
|
||||
void Block::setLayout() {
|
||||
bitsMetatileId.setMask(projectConfig.getBlockMetatileIdMask());
|
||||
bitsCollision.setMask(projectConfig.getBlockCollisionMask());
|
||||
bitsElevation.setMask(projectConfig.getBlockElevationMask());
|
||||
bitsMetatileId.setMask(projectConfig.blockMetatileIdMask);
|
||||
bitsCollision.setMask(projectConfig.blockCollisionMask);
|
||||
bitsElevation.setMask(projectConfig.blockElevationMask);
|
||||
}
|
||||
|
||||
bool Block::operator ==(Block other) const {
|
||||
|
|
|
@ -35,7 +35,7 @@ int Event::getEventIndex() {
|
|||
void Event::setDefaultValues(Project *) {
|
||||
this->setX(0);
|
||||
this->setY(0);
|
||||
this->setElevation(projectConfig.getDefaultElevation());
|
||||
this->setElevation(projectConfig.defaultElevation);
|
||||
}
|
||||
|
||||
void Event::readCustomValues(QJsonObject values) {
|
||||
|
@ -195,7 +195,7 @@ EventFrame *ObjectEvent::createEventFrame() {
|
|||
OrderedJson::object ObjectEvent::buildEventJson(Project *) {
|
||||
OrderedJson::object objectJson;
|
||||
|
||||
if (projectConfig.getEventCloneObjectEnabled()) {
|
||||
if (projectConfig.eventCloneObjectEnabled) {
|
||||
objectJson["type"] = "object";
|
||||
}
|
||||
objectJson["graphics_id"] = this->getGfx();
|
||||
|
@ -259,7 +259,7 @@ const QSet<QString> expectedObjectFields = {
|
|||
QSet<QString> ObjectEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
expectedFields = expectedObjectFields;
|
||||
if (projectConfig.getEventCloneObjectEnabled()) {
|
||||
if (projectConfig.eventCloneObjectEnabled) {
|
||||
expectedFields.insert("type");
|
||||
}
|
||||
expectedFields << "x" << "y";
|
||||
|
@ -788,10 +788,10 @@ OrderedJson::object HiddenItemEvent::buildEventJson(Project *) {
|
|||
hiddenItemJson["elevation"] = this->getElevation();
|
||||
hiddenItemJson["item"] = this->getItem();
|
||||
hiddenItemJson["flag"] = this->getFlag();
|
||||
if (projectConfig.getHiddenItemQuantityEnabled()) {
|
||||
if (projectConfig.hiddenItemQuantityEnabled) {
|
||||
hiddenItemJson["quantity"] = this->getQuantity();
|
||||
}
|
||||
if (projectConfig.getHiddenItemRequiresItemfinderEnabled()) {
|
||||
if (projectConfig.hiddenItemRequiresItemfinderEnabled) {
|
||||
hiddenItemJson["underfoot"] = this->getUnderfoot();
|
||||
}
|
||||
|
||||
|
@ -806,10 +806,10 @@ bool HiddenItemEvent::loadFromJson(QJsonObject json, Project *) {
|
|||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||
this->setItem(ParseUtil::jsonToQString(json["item"]));
|
||||
this->setFlag(ParseUtil::jsonToQString(json["flag"]));
|
||||
if (projectConfig.getHiddenItemQuantityEnabled()) {
|
||||
if (projectConfig.hiddenItemQuantityEnabled) {
|
||||
this->setQuantity(ParseUtil::jsonToInt(json["quantity"]));
|
||||
}
|
||||
if (projectConfig.getHiddenItemRequiresItemfinderEnabled()) {
|
||||
if (projectConfig.hiddenItemRequiresItemfinderEnabled) {
|
||||
this->setUnderfoot(ParseUtil::jsonToBool(json["underfoot"]));
|
||||
}
|
||||
|
||||
|
@ -821,10 +821,10 @@ bool HiddenItemEvent::loadFromJson(QJsonObject json, Project *) {
|
|||
void HiddenItemEvent::setDefaultValues(Project *project) {
|
||||
this->setItem(project->itemNames.value(0, "0"));
|
||||
this->setFlag(project->flagNames.value(0, "0"));
|
||||
if (projectConfig.getHiddenItemQuantityEnabled()) {
|
||||
if (projectConfig.hiddenItemQuantityEnabled) {
|
||||
this->setQuantity(1);
|
||||
}
|
||||
if (projectConfig.getHiddenItemRequiresItemfinderEnabled()) {
|
||||
if (projectConfig.hiddenItemRequiresItemfinderEnabled) {
|
||||
this->setUnderfoot(false);
|
||||
}
|
||||
}
|
||||
|
@ -839,10 +839,10 @@ const QSet<QString> expectedHiddenItemFields = {
|
|||
QSet<QString> HiddenItemEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
expectedFields = expectedHiddenItemFields;
|
||||
if (projectConfig.getHiddenItemQuantityEnabled()) {
|
||||
if (projectConfig.hiddenItemQuantityEnabled) {
|
||||
expectedFields << "quantity";
|
||||
}
|
||||
if (projectConfig.getHiddenItemRequiresItemfinderEnabled()) {
|
||||
if (projectConfig.hiddenItemRequiresItemfinderEnabled) {
|
||||
expectedFields << "underfoot";
|
||||
}
|
||||
expectedFields << "x" << "y";
|
||||
|
@ -930,10 +930,10 @@ OrderedJson::object HealLocationEvent::buildEventJson(Project *) {
|
|||
}
|
||||
|
||||
void HealLocationEvent::setDefaultValues(Project *) {
|
||||
this->setElevation(projectConfig.getDefaultElevation());
|
||||
this->setElevation(projectConfig.defaultElevation);
|
||||
if (!this->getMap())
|
||||
return;
|
||||
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||
bool respawnEnabled = projectConfig.healLocationRespawnDataEnabled;
|
||||
const QString mapConstant = Map::mapConstantFromName(this->getMap()->name, false);
|
||||
const QString prefix = projectConfig.getIdentifier(respawnEnabled ? ProjectIdentifier::define_spawn_prefix
|
||||
: ProjectIdentifier::define_heal_locations_prefix);
|
||||
|
|
|
@ -24,7 +24,7 @@ HealLocation HealLocation::fromEvent(Event *fromEvent) {
|
|||
healLocation.index = event->getIndex();
|
||||
healLocation.x = event->getX();
|
||||
healLocation.y = event->getY();
|
||||
if (projectConfig.getHealLocationRespawnDataEnabled()) {
|
||||
if (projectConfig.healLocationRespawnDataEnabled) {
|
||||
healLocation.respawnNPC = event->getRespawnNPC();
|
||||
healLocation.respawnMap = Map::mapConstantFromName(event->getRespawnMap(), false);
|
||||
}
|
||||
|
|
|
@ -486,9 +486,9 @@ QStringList Map::getScriptLabels(Event::Group group) {
|
|||
}
|
||||
|
||||
QString Map::getScriptsFilePath() const {
|
||||
const bool usePoryscript = projectConfig.getUsePoryScript();
|
||||
const bool usePoryscript = projectConfig.usePoryScript;
|
||||
auto path = QDir::cleanPath(QString("%1/%2/%3/scripts")
|
||||
.arg(projectConfig.getProjectDir())
|
||||
.arg(projectConfig.projectDir)
|
||||
.arg(projectConfig.getFilePath(ProjectFilePath::data_map_folders))
|
||||
.arg(this->name));
|
||||
auto extension = Project::getScriptFileExtension(usePoryscript);
|
||||
|
|
|
@ -100,7 +100,7 @@ uint32_t Metatile::getMaxAttributesMask() {
|
|||
{2, 0xFFFF},
|
||||
{4, 0xFFFFFFFF},
|
||||
};
|
||||
return maxMasks.value(projectConfig.getMetatileAttributesSize(), 0);
|
||||
return maxMasks.value(projectConfig.metatileAttributesSize, 0);
|
||||
}
|
||||
|
||||
void Metatile::setLayout(Project * project) {
|
||||
|
@ -109,10 +109,10 @@ void Metatile::setLayout(Project * project) {
|
|||
for (uint16_t i = Block::getMaxMetatileId(); i > 0; i /= 16)
|
||||
numMetatileIdChars++;
|
||||
|
||||
uint32_t behaviorMask = projectConfig.getMetatileBehaviorMask();
|
||||
uint32_t terrainTypeMask = projectConfig.getMetatileTerrainTypeMask();
|
||||
uint32_t encounterTypeMask = projectConfig.getMetatileEncounterTypeMask();
|
||||
uint32_t layerTypeMask = projectConfig.getMetatileLayerTypeMask();
|
||||
uint32_t behaviorMask = projectConfig.metatileBehaviorMask;
|
||||
uint32_t terrainTypeMask = projectConfig.metatileTerrainTypeMask;
|
||||
uint32_t encounterTypeMask = projectConfig.metatileEncounterTypeMask;
|
||||
uint32_t layerTypeMask = projectConfig.metatileLayerTypeMask;
|
||||
|
||||
// Calculate mask of bits not used by standard behaviors so we can preserve this data.
|
||||
uint32_t unusedMask = ~(behaviorMask | terrainTypeMask | encounterTypeMask | layerTypeMask);
|
||||
|
|
|
@ -80,7 +80,7 @@ QList<Metatile*> MetatileParser::parse(QString filepath, bool *error, bool prima
|
|||
|
||||
// AdvanceMap .bvd files only contain 8 tiles of data per metatile.
|
||||
// If the user has triple-layer metatiles enabled we need to fill the remaining 4 tiles ourselves.
|
||||
if (projectConfig.getTripleLayerMetatilesEnabled()) {
|
||||
if (projectConfig.tripleLayerMetatilesEnabled) {
|
||||
Tile tile = Tile();
|
||||
for (int j = 0; j < 4; j++)
|
||||
tiles.append(tile);
|
||||
|
|
|
@ -9,15 +9,10 @@
|
|||
static const int DefaultWaitTime = 120;
|
||||
|
||||
NetworkAccessManager::NetworkAccessManager(QObject * parent) : QNetworkAccessManager(parent) {
|
||||
// We store rate limit end times in the user's config so that Porymap will still respect them after a restart.
|
||||
// To avoid reading/writing to a local file during network operations, we only read/write the file when the
|
||||
// manager is created/destroyed respectively.
|
||||
this->rateLimitTimes = porymapConfig.getRateLimitTimes();
|
||||
this->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
};
|
||||
|
||||
NetworkAccessManager::~NetworkAccessManager() {
|
||||
porymapConfig.setRateLimitTimes(this->rateLimitTimes);
|
||||
qDeleteAll(this->cache);
|
||||
}
|
||||
|
||||
|
@ -47,8 +42,9 @@ NetworkReplyData * NetworkAccessManager::get(const QUrl &url) {
|
|||
data->m_url = url;
|
||||
|
||||
// If we are rate-limited, don't send a new request.
|
||||
if (this->rateLimitTimes.contains(url)) {
|
||||
auto time = this->rateLimitTimes.value(url);
|
||||
// We store rate limit end times in the user's config so that Porymap will still respect them after a restart.
|
||||
if (porymapConfig.rateLimitTimes.contains(url)) {
|
||||
auto time = porymapConfig.rateLimitTimes.value(url);
|
||||
if (!time.isNull() && time > QDateTime::currentDateTime()) {
|
||||
data->m_retryAfter = time;
|
||||
data->m_error = QString("Rate limit reached. Please try again after %1.").arg(data->m_retryAfter.toString());
|
||||
|
@ -56,7 +52,7 @@ NetworkReplyData * NetworkAccessManager::get(const QUrl &url) {
|
|||
return data;
|
||||
}
|
||||
// Rate limiting expired
|
||||
this->rateLimitTimes.remove(url);
|
||||
porymapConfig.rateLimitTimes.remove(url);
|
||||
}
|
||||
|
||||
QNetworkReply * reply = QNetworkAccessManager::get(this->getRequest(url));
|
||||
|
@ -117,7 +113,7 @@ void NetworkAccessManager::processReply(QNetworkReply * reply, NetworkReplyData
|
|||
data->m_error = "Service busy or unavailable. ";
|
||||
}
|
||||
data->m_error.append(QString("Please try again after %1.").arg(data->m_retryAfter.toString()));
|
||||
this->rateLimitTimes.insert(url, data->m_retryAfter);
|
||||
porymapConfig.rateLimitTimes.insert(url, data->m_retryAfter);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -129,7 +125,7 @@ void NetworkAccessManager::processReply(QNetworkReply * reply, NetworkReplyData
|
|||
data->m_retryAfter = ok ? QDateTime::fromSecsSinceEpoch(limitReset).toLocalTime()
|
||||
: QDateTime::currentDateTime().addSecs(DefaultWaitTime);;
|
||||
data->m_error = QString("Too many requests. Please try again after %1.").arg(data->m_retryAfter.toString());
|
||||
this->rateLimitTimes.insert(url, data->m_retryAfter);
|
||||
porymapConfig.rateLimitTimes.insert(url, data->m_retryAfter);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ bool Tileset::appendToHeaders(QString root, QString friendlyName, bool usingAsm)
|
|||
dataString.append(QString("\t.4byte gTilesetTiles_%1\n").arg(friendlyName));
|
||||
dataString.append(QString("\t.4byte gTilesetPalettes_%1\n").arg(friendlyName));
|
||||
dataString.append(QString("\t.4byte gMetatiles_%1\n").arg(friendlyName));
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
if (projectConfig.baseGameVersion == BaseGameVersion::pokefirered) {
|
||||
dataString.append("\t.4byte NULL @ animation callback\n");
|
||||
dataString.append(QString("\t.4byte gMetatileAttributes_%1\n").arg(friendlyName));
|
||||
} else {
|
||||
|
@ -248,13 +248,13 @@ bool Tileset::appendToHeaders(QString root, QString friendlyName, bool usingAsm)
|
|||
} else {
|
||||
// Append to C file
|
||||
dataString.append(QString("const struct Tileset %1 =\n{\n").arg(this->name));
|
||||
if (projectConfig.getTilesetsHaveIsCompressed()) dataString.append(" .isCompressed = TRUE,\n");
|
||||
if (projectConfig.tilesetsHaveIsCompressed) dataString.append(" .isCompressed = TRUE,\n");
|
||||
dataString.append(QString(" .isSecondary = %1,\n").arg(isSecondaryStr));
|
||||
dataString.append(QString(" .tiles = gTilesetTiles_%1,\n").arg(friendlyName));
|
||||
dataString.append(QString(" .palettes = gTilesetPalettes_%1,\n").arg(friendlyName));
|
||||
dataString.append(QString(" .metatiles = gMetatiles_%1,\n").arg(friendlyName));
|
||||
dataString.append(QString(" .metatileAttributes = gMetatileAttributes_%1,\n").arg(friendlyName));
|
||||
if (projectConfig.getTilesetsHaveCallback()) dataString.append(" .callback = NULL,\n");
|
||||
if (projectConfig.tilesetsHaveCallback) dataString.append(" .callback = NULL,\n");
|
||||
dataString.append("};\n");
|
||||
}
|
||||
file.write(dataString.toUtf8());
|
||||
|
@ -325,7 +325,7 @@ bool Tileset::appendToMetatiles(QString root, QString friendlyName, bool usingAs
|
|||
} else {
|
||||
// Append to C file
|
||||
dataString.append(QString("const u16 gMetatiles_%1[] = INCBIN_U16(\"%2\");\n").arg(friendlyName, metatilesPath));
|
||||
QString numBits = QString::number(projectConfig.getMetatileAttributesSize() * 8);
|
||||
QString numBits = QString::number(projectConfig.metatileAttributesSize * 8);
|
||||
dataString.append(QString("const u%1 gMetatileAttributes_%2[] = INCBIN_U%1(\"%3\");\n").arg(numBits, friendlyName, metatileAttrsPath));
|
||||
}
|
||||
file.write(dataString.toUtf8());
|
||||
|
@ -358,7 +358,7 @@ QHash<int, QString> Tileset::getHeaderMemberMap(bool usingAsm)
|
|||
int paddingOffset = usingAsm ? 1 : 0;
|
||||
|
||||
// The position of metatileAttributes changes between games
|
||||
bool isPokefirered = (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered);
|
||||
bool isPokefirered = (projectConfig.baseGameVersion == BaseGameVersion::pokefirered);
|
||||
int metatileAttrPosition = (isPokefirered ? 6 : 5) + paddingOffset;
|
||||
|
||||
auto map = QHash<int, QString>();
|
||||
|
|
146
src/editor.cpp
146
src/editor.cpp
|
@ -79,10 +79,13 @@ void Editor::saveUiFields() {
|
|||
}
|
||||
|
||||
void Editor::closeProject() {
|
||||
if (this->project) {
|
||||
delete this->project;
|
||||
this->project = nullptr;
|
||||
}
|
||||
if (!this->project)
|
||||
return;
|
||||
this->project->saveConfig();
|
||||
Scripting::cb_ProjectClosed(this->project->root);
|
||||
Scripting::stop();
|
||||
clearMap();
|
||||
delete this->project;
|
||||
}
|
||||
|
||||
void Editor::setEditingMap() {
|
||||
|
@ -181,9 +184,8 @@ void Editor::setEditingConnections() {
|
|||
this->cursorMapTileRect->setActive(false);
|
||||
}
|
||||
|
||||
void Editor::displayWildMonTables() {
|
||||
void Editor::clearWildMonTables() {
|
||||
QStackedWidget *stack = ui->stackedWidget_WildMons;
|
||||
QComboBox *labelCombo = ui->comboBox_EncounterGroupLabel;
|
||||
|
||||
// delete widgets from previous map data if they exist
|
||||
while (stack->count()) {
|
||||
|
@ -192,18 +194,24 @@ void Editor::displayWildMonTables() {
|
|||
delete oldWidget;
|
||||
}
|
||||
|
||||
labelCombo->clear();
|
||||
ui->comboBox_EncounterGroupLabel->clear();
|
||||
}
|
||||
|
||||
void Editor::displayWildMonTables() {
|
||||
clearWildMonTables();
|
||||
|
||||
// Don't try to read encounter data if it doesn't exist on disk for this map.
|
||||
if (!project->wildMonData.contains(map->constantName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QComboBox *labelCombo = ui->comboBox_EncounterGroupLabel;
|
||||
for (auto groupPair : project->wildMonData[map->constantName])
|
||||
labelCombo->addItem(groupPair.first);
|
||||
|
||||
labelCombo->setCurrentText(labelCombo->itemText(0));
|
||||
|
||||
QStackedWidget *stack = ui->stackedWidget_WildMons;
|
||||
int labelIndex = 0;
|
||||
for (auto labelPair : project->wildMonData[map->constantName]) {
|
||||
|
||||
|
@ -1528,6 +1536,35 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm
|
|||
}
|
||||
}
|
||||
|
||||
// On project close we want to leave the editor view empty.
|
||||
// Otherwise a map is normally only cleared when a new one is being displayed.
|
||||
void Editor::clearMap() {
|
||||
clearMetatileSelector();
|
||||
clearMovementPermissionSelector();
|
||||
clearMapMetatiles();
|
||||
clearMapMovementPermissions();
|
||||
clearBorderMetatiles();
|
||||
clearCurrentMetatilesSelection();
|
||||
clearMapEvents();
|
||||
//clearMapConnections();
|
||||
clearMapBorder();
|
||||
clearMapGrid();
|
||||
clearWildMonTables();
|
||||
|
||||
// TODO: Handle connections after redesign PR.
|
||||
selected_connection_item = nullptr;
|
||||
connection_items.clear();
|
||||
connection_mask = nullptr;
|
||||
|
||||
current_view = nullptr;
|
||||
map = nullptr;
|
||||
|
||||
// These are normally preserved between map displays, we only delete them now.
|
||||
delete scene;
|
||||
delete metatile_selector_item;
|
||||
delete movement_permissions_selector_item;
|
||||
}
|
||||
|
||||
bool Editor::displayMap() {
|
||||
if (!scene) {
|
||||
scene = new QGraphicsScene;
|
||||
|
@ -1537,12 +1574,6 @@ bool Editor::displayMap() {
|
|||
scene->installEventFilter(this->map_ruler);
|
||||
}
|
||||
|
||||
if (map_item && scene) {
|
||||
scene->removeItem(map_item);
|
||||
delete map_item;
|
||||
scene->removeItem(this->map_ruler);
|
||||
}
|
||||
|
||||
displayMetatileSelector();
|
||||
displayMovementPermissionSelector();
|
||||
displayMapMetatiles();
|
||||
|
@ -1571,11 +1602,16 @@ bool Editor::displayMap() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Editor::displayMetatileSelector() {
|
||||
void Editor::clearMetatileSelector() {
|
||||
if (metatile_selector_item && metatile_selector_item->scene()) {
|
||||
metatile_selector_item->scene()->removeItem(metatile_selector_item);
|
||||
delete scene_metatiles;
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::displayMetatileSelector() {
|
||||
clearMetatileSelector();
|
||||
|
||||
scene_metatiles = new QGraphicsScene;
|
||||
if (!metatile_selector_item) {
|
||||
metatile_selector_item = new MetatileSelector(8, map);
|
||||
|
@ -1600,7 +1636,17 @@ void Editor::displayMetatileSelector() {
|
|||
scene_metatiles->addItem(metatile_selector_item);
|
||||
}
|
||||
|
||||
void Editor::clearMapMetatiles() {
|
||||
if (map_item && scene) {
|
||||
scene->removeItem(map_item);
|
||||
delete map_item;
|
||||
scene->removeItem(this->map_ruler);
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::displayMapMetatiles() {
|
||||
clearMapMetatiles();
|
||||
|
||||
map_item = new MapPixmapItem(map, this->metatile_selector_item, this->settings);
|
||||
connect(map_item, &MapPixmapItem::mouseEvent, this, &Editor::mouseEvent_map);
|
||||
connect(map_item, &MapPixmapItem::startPaint, this, &Editor::onMapStartPaint);
|
||||
|
@ -1621,11 +1667,16 @@ void Editor::displayMapMetatiles() {
|
|||
);
|
||||
}
|
||||
|
||||
void Editor::displayMapMovementPermissions() {
|
||||
void Editor::clearMapMovementPermissions() {
|
||||
if (collision_item && scene) {
|
||||
scene->removeItem(collision_item);
|
||||
delete collision_item;
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::displayMapMovementPermissions() {
|
||||
clearMapMovementPermissions();
|
||||
|
||||
collision_item = new CollisionPixmapItem(map, ui->spinBox_SelectedCollision, ui->spinBox_SelectedElevation,
|
||||
this->metatile_selector_item, this->settings, &this->collisionOpacity);
|
||||
connect(collision_item, &CollisionPixmapItem::mouseEvent, this, &Editor::mouseEvent_collision);
|
||||
|
@ -1638,11 +1689,16 @@ void Editor::displayMapMovementPermissions() {
|
|||
scene->addItem(collision_item);
|
||||
}
|
||||
|
||||
void Editor::displayBorderMetatiles() {
|
||||
void Editor::clearBorderMetatiles() {
|
||||
if (selected_border_metatiles_item && selected_border_metatiles_item->scene()) {
|
||||
selected_border_metatiles_item->scene()->removeItem(selected_border_metatiles_item);
|
||||
delete selected_border_metatiles_item;
|
||||
delete scene_selected_border_metatiles;
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::displayBorderMetatiles() {
|
||||
clearBorderMetatiles();
|
||||
|
||||
scene_selected_border_metatiles = new QGraphicsScene;
|
||||
selected_border_metatiles_item = new BorderMetatilesPixmapItem(map, this->metatile_selector_item);
|
||||
|
@ -1657,11 +1713,17 @@ void Editor::displayBorderMetatiles() {
|
|||
this, &Editor::onBorderMetatilesChanged);
|
||||
}
|
||||
|
||||
void Editor::displayCurrentMetatilesSelection() {
|
||||
void Editor::clearCurrentMetatilesSelection() {
|
||||
if (current_metatile_selection_item && current_metatile_selection_item->scene()) {
|
||||
current_metatile_selection_item->scene()->removeItem(current_metatile_selection_item);
|
||||
delete current_metatile_selection_item;
|
||||
current_metatile_selection_item = nullptr;
|
||||
delete scene_current_metatile_selection;
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::displayCurrentMetatilesSelection() {
|
||||
clearCurrentMetatilesSelection();
|
||||
|
||||
scene_current_metatile_selection = new QGraphicsScene;
|
||||
current_metatile_selection_item = new CurrentSelectedMetatilesPixmapItem(map, this->metatile_selector_item);
|
||||
|
@ -1677,11 +1739,15 @@ void Editor::redrawCurrentMetatilesSelection() {
|
|||
}
|
||||
}
|
||||
|
||||
void Editor::displayMovementPermissionSelector() {
|
||||
void Editor::clearMovementPermissionSelector() {
|
||||
if (movement_permissions_selector_item && movement_permissions_selector_item->scene()) {
|
||||
movement_permissions_selector_item->scene()->removeItem(movement_permissions_selector_item);
|
||||
delete scene_collision_metatiles;
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::displayMovementPermissionSelector() {
|
||||
clearMovementPermissionSelector();
|
||||
|
||||
scene_collision_metatiles = new QGraphicsScene;
|
||||
if (!movement_permissions_selector_item) {
|
||||
|
@ -1693,13 +1759,13 @@ void Editor::displayMovementPermissionSelector() {
|
|||
connect(movement_permissions_selector_item, &SelectablePixmapItem::selectionChanged, [this](int x, int y, int, int) {
|
||||
this->setCollisionTabSpinBoxes(x, y);
|
||||
});
|
||||
movement_permissions_selector_item->select(projectConfig.getDefaultCollision(), projectConfig.getDefaultElevation());
|
||||
movement_permissions_selector_item->select(projectConfig.defaultCollision, projectConfig.defaultElevation);
|
||||
}
|
||||
|
||||
scene_collision_metatiles->addItem(movement_permissions_selector_item);
|
||||
}
|
||||
|
||||
void Editor::displayMapEvents() {
|
||||
void Editor::clearMapEvents() {
|
||||
if (events_group) {
|
||||
for (QGraphicsItem *child : events_group->childItems()) {
|
||||
events_group->removeFromGroup(child);
|
||||
|
@ -1711,9 +1777,13 @@ void Editor::displayMapEvents() {
|
|||
}
|
||||
|
||||
delete events_group;
|
||||
events_group = nullptr;
|
||||
}
|
||||
|
||||
selected_events->clear();
|
||||
}
|
||||
|
||||
void Editor::displayMapEvents() {
|
||||
clearMapEvents();
|
||||
|
||||
events_group = new QGraphicsItemGroup;
|
||||
scene->addItem(events_group);
|
||||
|
@ -1820,7 +1890,7 @@ void Editor::maskNonVisibleConnectionTiles() {
|
|||
connection_mask = scene->addPath(mask, pen, brush);
|
||||
}
|
||||
|
||||
void Editor::displayMapBorder() {
|
||||
void Editor::clearMapBorder() {
|
||||
for (QGraphicsPixmapItem* item : borderItems) {
|
||||
if (item->scene()) {
|
||||
item->scene()->removeItem(item);
|
||||
|
@ -1828,6 +1898,10 @@ void Editor::displayMapBorder() {
|
|||
delete item;
|
||||
}
|
||||
borderItems.clear();
|
||||
}
|
||||
|
||||
void Editor::displayMapBorder() {
|
||||
clearMapBorder();
|
||||
|
||||
int borderWidth = map->getBorderWidth();
|
||||
int borderHeight = map->getBorderHeight();
|
||||
|
@ -1840,7 +1914,7 @@ void Editor::displayMapBorder() {
|
|||
item->setX(x * 16);
|
||||
item->setY(y * 16);
|
||||
item->setZValue(-3);
|
||||
scene->addItem(item);
|
||||
scene->addItem(item); // TODO: If the scene is taking ownership here is a double-free possible?
|
||||
borderItems.append(item);
|
||||
}
|
||||
}
|
||||
|
@ -1875,16 +1949,20 @@ int Editor::getBorderDrawDistance(int dimension) {
|
|||
}
|
||||
|
||||
void Editor::onToggleGridClicked(bool checked) {
|
||||
porymapConfig.setShowGrid(checked);
|
||||
porymapConfig.showGrid = checked;
|
||||
if (ui->graphicsView_Map->scene())
|
||||
ui->graphicsView_Map->scene()->update();
|
||||
}
|
||||
|
||||
void Editor::displayMapGrid() {
|
||||
void Editor::clearMapGrid() {
|
||||
for (QGraphicsLineItem* item : gridLines) {
|
||||
if (item) delete item;
|
||||
}
|
||||
gridLines.clear();
|
||||
}
|
||||
|
||||
void Editor::displayMapGrid() {
|
||||
clearMapGrid();
|
||||
ui->checkBox_ToggleGrid->disconnect();
|
||||
|
||||
int pixelWidth = map->getWidth() * 16;
|
||||
|
@ -1928,7 +2006,7 @@ void Editor::updateSecondaryTileset(QString tilesetLabel, bool forceLoad)
|
|||
|
||||
void Editor::toggleBorderVisibility(bool visible, bool enableScriptCallback)
|
||||
{
|
||||
porymapConfig.setShowBorder(visible);
|
||||
porymapConfig.showBorder = visible;
|
||||
updateBorderVisibility();
|
||||
if (enableScriptCallback)
|
||||
Scripting::cb_BorderVisibilityToggled(visible);
|
||||
|
@ -1996,7 +2074,7 @@ void Editor::redrawObject(DraggablePixmapItem *item) {
|
|||
|
||||
// Warp events display a warning if they're not positioned on a metatile with a warp behavior.
|
||||
void Editor::updateWarpEventWarning(Event *event) {
|
||||
if (porymapConfig.getWarpBehaviorWarningDisabled())
|
||||
if (porymapConfig.warpBehaviorWarningDisabled)
|
||||
return;
|
||||
if (!project || !map || !event || event->getEventType() != Event::Type::Warp)
|
||||
return;
|
||||
|
@ -2007,7 +2085,7 @@ void Editor::updateWarpEventWarning(Event *event) {
|
|||
metatile = Tileset::getMetatile(block.metatileId(), map->layout->tileset_primary, map->layout->tileset_secondary);
|
||||
}
|
||||
// metatile may be null if the warp is in the map border. Display the warning in this case
|
||||
bool validWarpBehavior = metatile && projectConfig.getWarpBehaviors().contains(metatile->behavior());
|
||||
bool validWarpBehavior = metatile && projectConfig.warpBehaviors.contains(metatile->behavior());
|
||||
warpEvent->setWarningEnabled(!validWarpBehavior);
|
||||
}
|
||||
|
||||
|
@ -2017,7 +2095,7 @@ void Editor::updateWarpEventWarning(Event *event) {
|
|||
// events when the Events tab is opened. This does not cover the case where metatiles are painted while
|
||||
// still on the Events tab, such as by Undo/Redo or the scripting API.
|
||||
void Editor::updateWarpEventWarnings() {
|
||||
if (porymapConfig.getWarpBehaviorWarningDisabled())
|
||||
if (porymapConfig.warpBehaviorWarningDisabled)
|
||||
return;
|
||||
if (selected_events) {
|
||||
for (auto selection : *selected_events)
|
||||
|
@ -2192,7 +2270,7 @@ void Editor::openScript(const QString &scriptLabel) const {
|
|||
}
|
||||
|
||||
void Editor::openInTextEditor(const QString &path, int lineNum) {
|
||||
QString command = porymapConfig.getTextEditorGotoLine();
|
||||
QString command = porymapConfig.textEditorGotoLine;
|
||||
if (command.isEmpty()) {
|
||||
// Open map scripts in the system's default editor.
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||
|
@ -2209,7 +2287,7 @@ void Editor::openInTextEditor(const QString &path, int lineNum) {
|
|||
}
|
||||
|
||||
void Editor::openProjectInTextEditor() const {
|
||||
QString command = porymapConfig.getTextEditorOpenFolder();
|
||||
QString command = porymapConfig.textEditorOpenFolder;
|
||||
if (command.contains("%D"))
|
||||
command.replace("%D", '\"' + project->root + '\"');
|
||||
else
|
||||
|
@ -2282,7 +2360,7 @@ void Editor::setCollisionTabSpinBoxes(uint16_t collision, uint16_t elevation) {
|
|||
|
||||
// Custom collision graphics may be provided by the user.
|
||||
void Editor::setCollisionGraphics() {
|
||||
QString filepath = projectConfig.getCollisionSheetPath();
|
||||
QString filepath = projectConfig.collisionSheetPath;
|
||||
|
||||
QImage imgSheet;
|
||||
if (filepath.isEmpty()) {
|
||||
|
@ -2302,8 +2380,8 @@ void Editor::setCollisionGraphics() {
|
|||
|
||||
// Users are not required to provide an image that gives an icon for every elevation/collision combination.
|
||||
// Instead they tell us how many are provided in their image by specifying the number of columns and rows.
|
||||
const int imgColumns = projectConfig.getCollisionSheetWidth();
|
||||
const int imgRows = projectConfig.getCollisionSheetHeight();
|
||||
const int imgColumns = projectConfig.collisionSheetWidth;
|
||||
const int imgRows = projectConfig.collisionSheetHeight;
|
||||
|
||||
// Create a pixmap for the selector on the Collision tab. If a project was previously opened we'll also need to refresh the selector.
|
||||
this->collisionSheetPixmap = QPixmap::fromImage(imgSheet).scaled(MovementPermissionsSelector::CellWidth * imgColumns,
|
||||
|
|
|
@ -70,20 +70,21 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
logInfo(QString("Launching Porymap v%1").arg(QCoreApplication::applicationVersion()));
|
||||
|
||||
this->initWindow();
|
||||
if (porymapConfig.getReopenOnLaunch() && this->openProject(porymapConfig.getRecentProject(), true))
|
||||
if (porymapConfig.reopenOnLaunch && !porymapConfig.projectManuallyClosed && this->openProject(porymapConfig.getRecentProject(), true))
|
||||
on_toolButton_Paint_clicked();
|
||||
|
||||
// there is a bug affecting macOS users, where the trackpad deilveres a bad touch-release gesture
|
||||
// the warning is a bit annoying, so it is disabled here
|
||||
QLoggingCategory::setFilterRules(QStringLiteral("qt.pointer.dispatch=false"));
|
||||
|
||||
if (porymapConfig.getCheckForUpdates())
|
||||
if (porymapConfig.checkForUpdates)
|
||||
this->checkForUpdates(false);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete label_MapRulerStatus;
|
||||
delete editor;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
@ -291,12 +292,12 @@ void MainWindow::checkForUpdates(bool requestedByUser) {
|
|||
openSubWindow(this->updatePromoter);
|
||||
} else {
|
||||
// This is an automatic update check. Only run if we haven't done one in the last 5 minutes
|
||||
QDateTime lastCheck = porymapConfig.getLastUpdateCheckTime();
|
||||
QDateTime lastCheck = porymapConfig.lastUpdateCheckTime;
|
||||
if (lastCheck.addSecs(5*60) >= QDateTime::currentDateTime())
|
||||
return;
|
||||
}
|
||||
this->updatePromoter->checkForUpdates();
|
||||
porymapConfig.setLastUpdateCheckTime(QDateTime::currentDateTime());
|
||||
porymapConfig.lastUpdateCheckTime = QDateTime::currentDateTime();
|
||||
}
|
||||
#else
|
||||
void MainWindow::checkForUpdates(bool) {}
|
||||
|
@ -428,34 +429,6 @@ void MainWindow::markMapEdited(Map* map) {
|
|||
showWindowTitle();
|
||||
}
|
||||
|
||||
// Update the UI using information we've read from the user's project files.
|
||||
void MainWindow::setProjectSpecificUI()
|
||||
{
|
||||
// Wild Encounters tab
|
||||
ui->mainTabBar->setTabEnabled(MainTab::WildPokemon, editor->project->wildEncountersLoaded);
|
||||
|
||||
bool hasFlags = projectConfig.getMapAllowFlagsEnabled();
|
||||
ui->checkBox_AllowRunning->setVisible(hasFlags);
|
||||
ui->checkBox_AllowBiking->setVisible(hasFlags);
|
||||
ui->checkBox_AllowEscaping->setVisible(hasFlags);
|
||||
ui->label_AllowRunning->setVisible(hasFlags);
|
||||
ui->label_AllowBiking->setVisible(hasFlags);
|
||||
ui->label_AllowEscaping->setVisible(hasFlags);
|
||||
|
||||
ui->newEventToolButton->newWeatherTriggerAction->setVisible(projectConfig.getEventWeatherTriggerEnabled());
|
||||
ui->newEventToolButton->newSecretBaseAction->setVisible(projectConfig.getEventSecretBaseEnabled());
|
||||
ui->newEventToolButton->newCloneObjectAction->setVisible(projectConfig.getEventCloneObjectEnabled());
|
||||
|
||||
bool floorNumEnabled = projectConfig.getFloorNumberEnabled();
|
||||
ui->spinBox_FloorNumber->setVisible(floorNumEnabled);
|
||||
ui->label_FloorNumber->setVisible(floorNumEnabled);
|
||||
|
||||
Event::setIcons();
|
||||
editor->setCollisionGraphics();
|
||||
ui->spinBox_SelectedElevation->setMaximum(Block::getMaxElevation());
|
||||
ui->spinBox_SelectedCollision->setMaximum(Block::getMaxCollision());
|
||||
}
|
||||
|
||||
void MainWindow::mapSortOrder_changed(QAction *action)
|
||||
{
|
||||
QList<QAction*> items = ui->toolButton_MapSortOrder->menu()->actions();
|
||||
|
@ -471,8 +444,7 @@ void MainWindow::mapSortOrder_changed(QAction *action)
|
|||
if (i != mapSortOrder)
|
||||
{
|
||||
ui->toolButton_MapSortOrder->setIcon(action->icon());
|
||||
mapSortOrder = static_cast<MapSortOrder>(i);
|
||||
porymapConfig.setMapSortOrder(mapSortOrder);
|
||||
porymapConfig.mapSortOrder = static_cast<MapSortOrder>(i);
|
||||
if (isProjectOpen())
|
||||
{
|
||||
sortMapList();
|
||||
|
@ -499,26 +471,26 @@ void MainWindow::applyMapListFilter(QString filterText)
|
|||
}
|
||||
|
||||
void MainWindow::loadUserSettings() {
|
||||
ui->actionBetter_Cursors->setChecked(porymapConfig.getPrettyCursors());
|
||||
this->editor->settings->betterCursors = porymapConfig.getPrettyCursors();
|
||||
ui->actionPlayer_View_Rectangle->setChecked(porymapConfig.getShowPlayerView());
|
||||
this->editor->settings->playerViewRectEnabled = porymapConfig.getShowPlayerView();
|
||||
ui->actionCursor_Tile_Outline->setChecked(porymapConfig.getShowCursorTile());
|
||||
this->editor->settings->cursorTileRectEnabled = porymapConfig.getShowCursorTile();
|
||||
ui->checkBox_ToggleBorder->setChecked(porymapConfig.getShowBorder());
|
||||
ui->checkBox_ToggleGrid->setChecked(porymapConfig.getShowGrid());
|
||||
mapSortOrder = porymapConfig.getMapSortOrder();
|
||||
ui->actionBetter_Cursors->setChecked(porymapConfig.prettyCursors);
|
||||
this->editor->settings->betterCursors = porymapConfig.prettyCursors;
|
||||
ui->actionPlayer_View_Rectangle->setChecked(porymapConfig.showPlayerView);
|
||||
this->editor->settings->playerViewRectEnabled = porymapConfig.showPlayerView;
|
||||
ui->actionCursor_Tile_Outline->setChecked(porymapConfig.showCursorTile);
|
||||
this->editor->settings->cursorTileRectEnabled = porymapConfig.showCursorTile;
|
||||
ui->checkBox_ToggleBorder->setChecked(porymapConfig.showBorder);
|
||||
ui->checkBox_ToggleGrid->setChecked(porymapConfig.showGrid);
|
||||
mapSortOrder = porymapConfig.mapSortOrder;
|
||||
ui->horizontalSlider_CollisionTransparency->blockSignals(true);
|
||||
this->editor->collisionOpacity = static_cast<qreal>(porymapConfig.getCollisionOpacity()) / 100;
|
||||
ui->horizontalSlider_CollisionTransparency->setValue(porymapConfig.getCollisionOpacity());
|
||||
this->editor->collisionOpacity = static_cast<qreal>(porymapConfig.collisionOpacity) / 100;
|
||||
ui->horizontalSlider_CollisionTransparency->setValue(porymapConfig.collisionOpacity);
|
||||
ui->horizontalSlider_CollisionTransparency->blockSignals(false);
|
||||
ui->horizontalSlider_MetatileZoom->blockSignals(true);
|
||||
ui->horizontalSlider_MetatileZoom->setValue(porymapConfig.getMetatilesZoom());
|
||||
ui->horizontalSlider_MetatileZoom->setValue(porymapConfig.metatilesZoom);
|
||||
ui->horizontalSlider_MetatileZoom->blockSignals(false);
|
||||
ui->horizontalSlider_CollisionZoom->blockSignals(true);
|
||||
ui->horizontalSlider_CollisionZoom->setValue(porymapConfig.getCollisionZoom());
|
||||
ui->horizontalSlider_CollisionZoom->setValue(porymapConfig.collisionZoom);
|
||||
ui->horizontalSlider_CollisionZoom->blockSignals(false);
|
||||
setTheme(porymapConfig.getTheme());
|
||||
setTheme(porymapConfig.theme);
|
||||
}
|
||||
|
||||
void MainWindow::restoreWindowState() {
|
||||
|
@ -542,17 +514,20 @@ void MainWindow::setTheme(QString theme) {
|
|||
}
|
||||
}
|
||||
|
||||
bool MainWindow::openProject(const QString &dir, bool initial) {
|
||||
bool MainWindow::openProject(QString dir, bool initial) {
|
||||
if (dir.isNull() || dir.length() <= 0) {
|
||||
projectOpenFailure = true;
|
||||
if (!initial) setWindowDisabled(true);
|
||||
// If this happened on startup it's because the user has no recent projects, which is fine.
|
||||
// This shouldn't happen otherwise, but if it does then display an error.
|
||||
if (!initial) {
|
||||
logError("Failed to open project: Directory name cannot be empty");
|
||||
showProjectOpenFailure();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString projectString = QString("%1project '%2'").arg(initial ? "recent " : "").arg(QDir::toNativeSeparators(dir));
|
||||
|
||||
if (!QDir(dir).exists()) {
|
||||
projectOpenFailure = true;
|
||||
const QString errorMsg = QString("Failed to open %1: No such directory").arg(projectString);
|
||||
this->statusBar()->showMessage(errorMsg);
|
||||
if (initial) {
|
||||
|
@ -565,53 +540,59 @@ bool MainWindow::openProject(const QString &dir, bool initial) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// The above checks can fail and the user will be allowed to continue with their currently-opened project (if there is one).
|
||||
// We close the current project below, after which either the new project will open successfully or the window will be disabled.
|
||||
if (!closeProject()) {
|
||||
logInfo("Aborted project open.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString openMessage = QString("Opening %1").arg(projectString);
|
||||
this->statusBar()->showMessage(openMessage);
|
||||
logInfo(openMessage);
|
||||
|
||||
userConfig.setProjectDir(dir);
|
||||
userConfig.projectDir = dir;
|
||||
userConfig.load();
|
||||
projectConfig.setProjectDir(dir);
|
||||
projectConfig.projectDir = dir;
|
||||
projectConfig.load();
|
||||
|
||||
this->closeSupplementaryWindows();
|
||||
this->newMapDefaultsSet = false;
|
||||
|
||||
if (isProjectOpen())
|
||||
Scripting::cb_ProjectClosed(editor->project->root);
|
||||
Scripting::init(this);
|
||||
|
||||
bool already_open = isProjectOpen() && (editor->project->root == dir);
|
||||
if (!already_open) {
|
||||
editor->closeProject();
|
||||
editor->project = new Project(this);
|
||||
QObject::connect(editor->project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered);
|
||||
QObject::connect(editor->project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared);
|
||||
QObject::connect(editor->project, &Project::uncheckMonitorFilesAction, [this]() {
|
||||
porymapConfig.setMonitorFiles(false);
|
||||
if (this->preferenceEditor)
|
||||
this->preferenceEditor->updateFields();
|
||||
});
|
||||
editor->project->set_root(dir);
|
||||
} else {
|
||||
editor->project->fileWatcher.removePaths(editor->project->fileWatcher.files());
|
||||
editor->project->clearMapCache();
|
||||
editor->project->clearTilesetCache();
|
||||
}
|
||||
// Create the project
|
||||
this->editor->project = new Project(this);
|
||||
QObject::connect(this->editor->project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered);
|
||||
QObject::connect(this->editor->project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared);
|
||||
QObject::connect(this->editor->project, &Project::uncheckMonitorFilesAction, [this]() {
|
||||
porymapConfig.monitorFiles = false;
|
||||
if (this->preferenceEditor)
|
||||
this->preferenceEditor->updateFields();
|
||||
});
|
||||
this->editor->project->set_root(dir);
|
||||
|
||||
this->projectOpenFailure = !(loadDataStructures()
|
||||
&& populateMapList()
|
||||
&& setInitialMap());
|
||||
|
||||
if (this->projectOpenFailure) {
|
||||
this->statusBar()->showMessage(QString("Failed to open %1").arg(projectString));
|
||||
showProjectOpenFailure();
|
||||
// Make sure project looks reasonable before attempting to load it
|
||||
if (!checkProjectSanity()) {
|
||||
delete this->editor->project;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the project
|
||||
if (!(loadProjectData() && setProjectUI() && setInitialMap())) {
|
||||
this->statusBar()->showMessage(QString("Failed to open %1").arg(projectString));
|
||||
showProjectOpenFailure();
|
||||
delete this->editor->project;
|
||||
// TODO: Allow changing project settings at this point
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only create the config files once the project has opened successfully in case the user selected an invalid directory
|
||||
this->editor->project->saveConfig();
|
||||
|
||||
showWindowTitle();
|
||||
this->statusBar()->showMessage(QString("Opened %1").arg(projectString));
|
||||
|
||||
porymapConfig.projectManuallyClosed = false;
|
||||
porymapConfig.addRecentProject(dir);
|
||||
refreshRecentProjectsMenu();
|
||||
|
||||
|
@ -625,16 +606,45 @@ bool MainWindow::openProject(const QString &dir, bool initial) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MainWindow::loadProjectData() {
|
||||
bool success = editor->project->load();
|
||||
Scripting::populateGlobalObject(this);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool MainWindow::checkProjectSanity() {
|
||||
if (editor->project->sanityCheck())
|
||||
return true;
|
||||
|
||||
logWarn(QString("The directory '%1' failed the project sanity check.").arg(editor->project->root));
|
||||
|
||||
QMessageBox msgBox;
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setText(QString("The selected directory appears to be invalid."));
|
||||
msgBox.setInformativeText(QString("The directory '%1' is missing key files.\n\n"
|
||||
"Make sure you selected the correct project directory "
|
||||
"(the one used to make your .gba file, e.g. 'pokeemerald').").arg(editor->project->root));
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
auto tryAnyway = msgBox.addButton("Try Anyway", QMessageBox::ActionRole);
|
||||
msgBox.exec();
|
||||
if (msgBox.clickedButton() == tryAnyway) {
|
||||
// The user has chosen to try to load this project anyway.
|
||||
// This will almost certainly fail, but they'll get a more specific error message.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainWindow::showProjectOpenFailure() {
|
||||
QString errorMsg = QString("There was an error opening the project. Please see %1 for full error details.").arg(getLogPath());
|
||||
QMessageBox error(QMessageBox::Critical, "porymap", errorMsg, QMessageBox::Ok, this);
|
||||
error.setDetailedText(getMostRecentError());
|
||||
error.exec();
|
||||
setWindowDisabled(true);
|
||||
}
|
||||
|
||||
bool MainWindow::isProjectOpen() {
|
||||
return !projectOpenFailure && editor && editor->project;
|
||||
return editor && editor->project;
|
||||
}
|
||||
|
||||
bool MainWindow::setInitialMap() {
|
||||
|
@ -643,7 +653,7 @@ bool MainWindow::setInitialMap() {
|
|||
names = editor->project->mapNames;
|
||||
|
||||
// Try to set most recently-opened map, if it's still in the list.
|
||||
QString recentMap = userConfig.getRecentMap();
|
||||
QString recentMap = userConfig.recentMap;
|
||||
if (!recentMap.isEmpty() && names.contains(recentMap) && setMap(recentMap, true))
|
||||
return true;
|
||||
|
||||
|
@ -711,11 +721,7 @@ QString MainWindow::getExistingDirectory(QString dir) {
|
|||
|
||||
void MainWindow::on_action_Open_Project_triggered()
|
||||
{
|
||||
QString recent = ".";
|
||||
if (!userConfig.getRecentMap().isEmpty()) {
|
||||
recent = userConfig.getRecentMap();
|
||||
}
|
||||
QString dir = getExistingDirectory(recent);
|
||||
QString dir = getExistingDirectory(!userConfig.recentMap.isEmpty() ? userConfig.recentMap : ".");
|
||||
if (!dir.isEmpty())
|
||||
openProject(dir);
|
||||
}
|
||||
|
@ -733,6 +739,11 @@ void MainWindow::on_action_Reload_Project_triggered() {
|
|||
openProject(editor->project->root);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Close_Project_triggered() {
|
||||
closeProject();
|
||||
porymapConfig.projectManuallyClosed = true;
|
||||
}
|
||||
|
||||
// setMap, but with a visible error message in case of failure.
|
||||
// Use when the user is specifically requesting a map to open.
|
||||
bool MainWindow::userSetMap(QString map_name, bool scrollTreeView) {
|
||||
|
@ -788,7 +799,7 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) {
|
|||
connect(editor->map, &Map::mapNeedsRedrawing, this, &MainWindow::onMapNeedsRedrawing);
|
||||
connect(editor->map, &Map::modified, [this](){ this->markMapEdited(); });
|
||||
|
||||
setRecentMap(map_name);
|
||||
userConfig.recentMap = map_name;
|
||||
updateMapList();
|
||||
|
||||
Scripting::cb_MapOpened(map_name);
|
||||
|
@ -863,10 +874,6 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::setRecentMap(QString mapName) {
|
||||
userConfig.setRecentMap(mapName);
|
||||
}
|
||||
|
||||
void MainWindow::displayMapProperties() {
|
||||
// Block signals to the comboboxes while they are being modified
|
||||
const QSignalBlocker blocker1(ui->comboBox_Song);
|
||||
|
@ -1012,45 +1019,8 @@ void MainWindow::on_spinBox_FloorNumber_valueChanged(int offset)
|
|||
}
|
||||
}
|
||||
|
||||
bool MainWindow::loadDataStructures() {
|
||||
Project *project = editor->project;
|
||||
bool success = project->readMapLayouts()
|
||||
&& project->readRegionMapSections()
|
||||
&& project->readItemNames()
|
||||
&& project->readFlagNames()
|
||||
&& project->readVarNames()
|
||||
&& project->readMovementTypes()
|
||||
&& project->readInitialFacingDirections()
|
||||
&& project->readMapTypes()
|
||||
&& project->readMapBattleScenes()
|
||||
&& project->readWeatherNames()
|
||||
&& project->readCoordEventWeatherNames()
|
||||
&& project->readSecretBaseIds()
|
||||
&& project->readBgEventFacingDirections()
|
||||
&& project->readTrainerTypes()
|
||||
&& project->readMetatileBehaviors()
|
||||
&& project->readFieldmapProperties()
|
||||
&& project->readFieldmapMasks()
|
||||
&& project->readTilesetLabels()
|
||||
&& project->readTilesetMetatileLabels()
|
||||
&& project->readHealLocations()
|
||||
&& project->readMiscellaneousConstants()
|
||||
&& project->readSpeciesIconPaths()
|
||||
&& project->readWildMonData()
|
||||
&& project->readEventScriptLabels()
|
||||
&& project->readObjEventGfxConstants()
|
||||
&& project->readEventGraphics()
|
||||
&& project->readSongNames();
|
||||
|
||||
project->applyParsedLimits();
|
||||
setProjectSpecificUI();
|
||||
Scripting::populateGlobalObject(this);
|
||||
|
||||
return success && loadProjectCombos();
|
||||
}
|
||||
|
||||
bool MainWindow::loadProjectCombos() {
|
||||
// set up project ui comboboxes
|
||||
// Update the UI using information we've read from the user's project files.
|
||||
bool MainWindow::setProjectUI() {
|
||||
Project *project = editor->project;
|
||||
|
||||
// Block signals to the comboboxes while they are being modified
|
||||
|
@ -1062,6 +1032,7 @@ bool MainWindow::loadProjectCombos() {
|
|||
const QSignalBlocker blocker6(ui->comboBox_BattleScene);
|
||||
const QSignalBlocker blocker7(ui->comboBox_Type);
|
||||
|
||||
// Set up project comboboxes
|
||||
ui->comboBox_Song->clear();
|
||||
ui->comboBox_Song->addItems(project->songNames);
|
||||
ui->comboBox_Location->clear();
|
||||
|
@ -1077,15 +1048,58 @@ bool MainWindow::loadProjectCombos() {
|
|||
ui->comboBox_Type->clear();
|
||||
ui->comboBox_Type->addItems(project->mapTypes);
|
||||
|
||||
sortMapList();
|
||||
|
||||
// Show/hide parts of the UI that are dependent on the user's project settings
|
||||
|
||||
// Wild Encounters tab
|
||||
ui->mainTabBar->setTabEnabled(MainTab::WildPokemon, editor->project->wildEncountersLoaded);
|
||||
|
||||
bool hasFlags = projectConfig.mapAllowFlagsEnabled;
|
||||
ui->checkBox_AllowRunning->setVisible(hasFlags);
|
||||
ui->checkBox_AllowBiking->setVisible(hasFlags);
|
||||
ui->checkBox_AllowEscaping->setVisible(hasFlags);
|
||||
ui->label_AllowRunning->setVisible(hasFlags);
|
||||
ui->label_AllowBiking->setVisible(hasFlags);
|
||||
ui->label_AllowEscaping->setVisible(hasFlags);
|
||||
|
||||
ui->newEventToolButton->newWeatherTriggerAction->setVisible(projectConfig.eventWeatherTriggerEnabled);
|
||||
ui->newEventToolButton->newSecretBaseAction->setVisible(projectConfig.eventSecretBaseEnabled);
|
||||
ui->newEventToolButton->newCloneObjectAction->setVisible(projectConfig.eventCloneObjectEnabled);
|
||||
|
||||
bool floorNumEnabled = projectConfig.floorNumberEnabled;
|
||||
ui->spinBox_FloorNumber->setVisible(floorNumEnabled);
|
||||
ui->label_FloorNumber->setVisible(floorNumEnabled);
|
||||
|
||||
Event::setIcons();
|
||||
editor->setCollisionGraphics();
|
||||
ui->spinBox_SelectedElevation->setMaximum(Block::getMaxElevation());
|
||||
ui->spinBox_SelectedCollision->setMaximum(Block::getMaxCollision());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MainWindow::populateMapList() {
|
||||
bool success = editor->project->readMapGroups();
|
||||
if (success) {
|
||||
sortMapList();
|
||||
}
|
||||
return success;
|
||||
void MainWindow::clearProjectUI() {
|
||||
// Block signals to the comboboxes while they are being modified
|
||||
const QSignalBlocker blocker1(ui->comboBox_Song);
|
||||
const QSignalBlocker blocker2(ui->comboBox_Location);
|
||||
const QSignalBlocker blocker3(ui->comboBox_PrimaryTileset);
|
||||
const QSignalBlocker blocker4(ui->comboBox_SecondaryTileset);
|
||||
const QSignalBlocker blocker5(ui->comboBox_Weather);
|
||||
const QSignalBlocker blocker6(ui->comboBox_BattleScene);
|
||||
const QSignalBlocker blocker7(ui->comboBox_Type);
|
||||
|
||||
ui->comboBox_Song->clear();
|
||||
ui->comboBox_Location->clear();
|
||||
ui->comboBox_PrimaryTileset->clear();
|
||||
ui->comboBox_SecondaryTileset->clear();
|
||||
ui->comboBox_Weather->clear();
|
||||
ui->comboBox_BattleScene->clear();
|
||||
ui->comboBox_Type->clear();
|
||||
|
||||
// Clear map list
|
||||
mapListModel->clear();
|
||||
mapGroupItemsList->clear();
|
||||
}
|
||||
|
||||
void MainWindow::sortMapList() {
|
||||
|
@ -1304,12 +1318,10 @@ void MainWindow::openNewMapPopupWindow() {
|
|||
}
|
||||
if (!this->newMapPrompt) {
|
||||
this->newMapPrompt = new NewMapPopup(this, this->editor->project);
|
||||
connect(this->newMapPrompt, &NewMapPopup::applied, this, &MainWindow::onNewMapCreated);
|
||||
}
|
||||
|
||||
openSubWindow(this->newMapPrompt);
|
||||
|
||||
connect(this->newMapPrompt, &NewMapPopup::applied, this, &MainWindow::onNewMapCreated);
|
||||
this->newMapPrompt->setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_NewMap_triggered() {
|
||||
|
@ -1443,7 +1455,7 @@ void MainWindow::updateTilesetEditor() {
|
|||
}
|
||||
|
||||
double MainWindow::getMetatilesZoomScale() {
|
||||
return pow(3.0, static_cast<double>(porymapConfig.getMetatilesZoom() - 30) / 30.0);
|
||||
return pow(3.0, static_cast<double>(porymapConfig.metatilesZoom - 30) / 30.0);
|
||||
}
|
||||
|
||||
void MainWindow::redrawMetatileSelection() {
|
||||
|
@ -1568,8 +1580,8 @@ void MainWindow::copy() {
|
|||
collisions.clear();
|
||||
for (int i = 0; i < metatiles.length(); i++) {
|
||||
OrderedJson::object collision;
|
||||
collision["collision"] = projectConfig.getDefaultCollision();
|
||||
collision["elevation"] = projectConfig.getDefaultElevation();
|
||||
collision["collision"] = projectConfig.defaultCollision;
|
||||
collision["elevation"] = projectConfig.defaultElevation;
|
||||
collisions.append(collision);
|
||||
}
|
||||
}
|
||||
|
@ -1808,21 +1820,16 @@ void MainWindow::on_mapViewTab_tabBarClicked(int index)
|
|||
editor->setEditingCollision();
|
||||
} else if (index == MapViewTab::Prefabs) {
|
||||
editor->setEditingMap();
|
||||
if (projectConfig.getPrefabFilepath().isEmpty() && !projectConfig.getPrefabImportPrompted()) {
|
||||
if (projectConfig.prefabFilepath.isEmpty() && !projectConfig.prefabImportPrompted) {
|
||||
// User hasn't set up prefabs and hasn't been prompted before.
|
||||
// Ask if they'd like to import the default prefabs file.
|
||||
if (prefab.tryImportDefaultPrefabs(this, projectConfig.getBaseGameVersion()))
|
||||
if (prefab.tryImportDefaultPrefabs(this, projectConfig.baseGameVersion))
|
||||
prefab.updatePrefabUi(this->editor->map);
|
||||
}
|
||||
}
|
||||
editor->setCursorRectVisible(false);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Exit_triggered()
|
||||
{
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
void MainWindow::on_mainTabBar_tabBarClicked(int index)
|
||||
{
|
||||
int oldIndex = ui->mainTabBar->currentIndex();
|
||||
|
@ -1870,14 +1877,14 @@ void MainWindow::on_actionZoom_Out_triggered() {
|
|||
}
|
||||
|
||||
void MainWindow::on_actionBetter_Cursors_triggered() {
|
||||
porymapConfig.setPrettyCursors(ui->actionBetter_Cursors->isChecked());
|
||||
porymapConfig.prettyCursors = ui->actionBetter_Cursors->isChecked();
|
||||
this->editor->settings->betterCursors = ui->actionBetter_Cursors->isChecked();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPlayer_View_Rectangle_triggered()
|
||||
{
|
||||
bool enabled = ui->actionPlayer_View_Rectangle->isChecked();
|
||||
porymapConfig.setShowPlayerView(enabled);
|
||||
porymapConfig.showPlayerView = enabled;
|
||||
this->editor->settings->playerViewRectEnabled = enabled;
|
||||
if ((this->editor->map_item && this->editor->map_item->has_mouse)
|
||||
|| (this->editor->collision_item && this->editor->collision_item->has_mouse)) {
|
||||
|
@ -1889,7 +1896,7 @@ void MainWindow::on_actionPlayer_View_Rectangle_triggered()
|
|||
void MainWindow::on_actionCursor_Tile_Outline_triggered()
|
||||
{
|
||||
bool enabled = ui->actionCursor_Tile_Outline->isChecked();
|
||||
porymapConfig.setShowCursorTile(enabled);
|
||||
porymapConfig.showCursorTile = enabled;
|
||||
this->editor->settings->cursorTileRectEnabled = enabled;
|
||||
if ((this->editor->map_item && this->editor->map_item->has_mouse)
|
||||
|| (this->editor->collision_item && this->editor->collision_item->has_mouse)) {
|
||||
|
@ -2238,7 +2245,7 @@ void MainWindow::eventTabChanged(int index) {
|
|||
|
||||
void MainWindow::on_horizontalSlider_CollisionTransparency_valueChanged(int value) {
|
||||
this->editor->collisionOpacity = static_cast<qreal>(value) / 100;
|
||||
porymapConfig.setCollisionOpacity(value);
|
||||
porymapConfig.collisionOpacity = value;
|
||||
this->editor->collision_item->draw(true);
|
||||
}
|
||||
|
||||
|
@ -2553,11 +2560,12 @@ void MainWindow::importMapFromAdvanceMap1_92()
|
|||
void MainWindow::showExportMapImageWindow(ImageExporterMode mode) {
|
||||
if (!editor->project) return;
|
||||
|
||||
// If the user is requesting this window again we assume it's for a new
|
||||
// window (the map/mode may have changed), so delete the old window.
|
||||
if (this->mapImageExporter)
|
||||
delete this->mapImageExporter;
|
||||
|
||||
this->mapImageExporter = new MapImageExporter(this, this->editor, mode);
|
||||
this->mapImageExporter->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
openSubWindow(this->mapImageExporter);
|
||||
}
|
||||
|
@ -2651,7 +2659,7 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked()
|
|||
heightSpinBox->setValue(editor->map->getHeight());
|
||||
bwidthSpinBox->setValue(editor->map->getBorderWidth());
|
||||
bheightSpinBox->setValue(editor->map->getBorderHeight());
|
||||
if (projectConfig.getUseCustomBorderSize()) {
|
||||
if (projectConfig.useCustomBorderSize) {
|
||||
form.addRow(new QLabel("Map Width"), widthSpinBox);
|
||||
form.addRow(new QLabel("Map Height"), heightSpinBox);
|
||||
form.addRow(new QLabel("Border Width"), bwidthSpinBox);
|
||||
|
@ -2792,7 +2800,7 @@ void MainWindow::on_actionPreferences_triggered() {
|
|||
}
|
||||
|
||||
void MainWindow::togglePreferenceSpecificUi() {
|
||||
if (porymapConfig.getTextEditorOpenFolder().isEmpty())
|
||||
if (porymapConfig.textEditorOpenFolder.isEmpty())
|
||||
ui->actionOpen_Project_in_Text_Editor->setEnabled(false);
|
||||
else
|
||||
ui->actionOpen_Project_in_Text_Editor->setEnabled(true);
|
||||
|
@ -2812,7 +2820,7 @@ void MainWindow::openProjectSettingsEditor(int tab) {
|
|||
}
|
||||
|
||||
void MainWindow::on_actionProject_Settings_triggered() {
|
||||
this->openProjectSettingsEditor(porymapConfig.getProjectSettingsTab());
|
||||
this->openProjectSettingsEditor(porymapConfig.projectSettingsTab);
|
||||
}
|
||||
|
||||
void MainWindow::onWarpBehaviorWarningClicked() {
|
||||
|
@ -2858,7 +2866,7 @@ void MainWindow::reloadScriptEngine() {
|
|||
Scripting::init(this);
|
||||
Scripting::populateGlobalObject(this);
|
||||
// Lying to the scripts here, simulating a project reload
|
||||
Scripting::cb_ProjectOpened(projectConfig.getProjectDir());
|
||||
Scripting::cb_ProjectOpened(projectConfig.projectDir);
|
||||
if (editor && editor->map)
|
||||
Scripting::cb_MapOpened(editor->map->name);
|
||||
}
|
||||
|
@ -2885,7 +2893,7 @@ void MainWindow::on_tableWidget_CustomHeaderFields_cellChanged(int, int)
|
|||
}
|
||||
|
||||
void MainWindow::on_horizontalSlider_MetatileZoom_valueChanged(int value) {
|
||||
porymapConfig.setMetatilesZoom(value);
|
||||
porymapConfig.metatilesZoom = value;
|
||||
double scale = pow(3.0, static_cast<double>(value - 30) / 30.0);
|
||||
|
||||
QTransform transform;
|
||||
|
@ -2910,7 +2918,7 @@ void MainWindow::on_horizontalSlider_MetatileZoom_valueChanged(int value) {
|
|||
}
|
||||
|
||||
void MainWindow::on_horizontalSlider_CollisionZoom_valueChanged(int value) {
|
||||
porymapConfig.setCollisionZoom(value);
|
||||
porymapConfig.collisionZoom = value;
|
||||
double scale = pow(3.0, static_cast<double>(value - 30) / 30.0);
|
||||
|
||||
QTransform transform;
|
||||
|
@ -2993,36 +3001,75 @@ bool MainWindow::askToFixRegionMapEditor() {
|
|||
return false;
|
||||
}
|
||||
|
||||
void MainWindow::closeSupplementaryWindows() {
|
||||
delete this->tilesetEditor;
|
||||
delete this->regionMapEditor;
|
||||
delete this->mapImageExporter;
|
||||
delete this->newMapPrompt;
|
||||
delete this->shortcutsEditor;
|
||||
delete this->customScriptsEditor;
|
||||
// Attempt to close any open sub-windows of the main window, giving each a chance to abort the process.
|
||||
// Each of these windows is a widget with WA_DeleteOnClose set, so manually deleting them isn't necessary.
|
||||
// Because they're tracked with QPointers nullifying them shouldn't be necessary either, but it seems the
|
||||
// delete is happening too late and some of the pointers haven't been cleared by the time we need them to,
|
||||
// so we nullify them all here anyway.
|
||||
bool MainWindow::closeSupplementaryWindows() {
|
||||
if (this->tilesetEditor && !this->tilesetEditor->close())
|
||||
return false;
|
||||
this->tilesetEditor = nullptr;
|
||||
|
||||
if (this->regionMapEditor && !this->regionMapEditor->close())
|
||||
return false;
|
||||
this->regionMapEditor = nullptr;
|
||||
|
||||
if (this->mapImageExporter && !this->mapImageExporter->close())
|
||||
return false;
|
||||
this->mapImageExporter = nullptr;
|
||||
|
||||
if (this->newMapPrompt && !this->newMapPrompt->close())
|
||||
return false;
|
||||
this->newMapPrompt = nullptr;
|
||||
|
||||
if (this->shortcutsEditor && !this->shortcutsEditor->close())
|
||||
return false;
|
||||
this->shortcutsEditor = nullptr;
|
||||
|
||||
if (this->preferenceEditor && !this->preferenceEditor->close())
|
||||
return false;
|
||||
this->preferenceEditor = nullptr;
|
||||
|
||||
if (this->customScriptsEditor && !this->customScriptsEditor->close())
|
||||
return false;
|
||||
this->customScriptsEditor = nullptr;
|
||||
|
||||
if (this->projectSettingsEditor) this->projectSettingsEditor->closeQuietly();
|
||||
this->projectSettingsEditor = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
if (isProjectOpen()) {
|
||||
if (projectHasUnsavedChanges || (editor->map && editor->map->hasUnsavedChanges())) {
|
||||
QMessageBox::StandardButton result = QMessageBox::question(
|
||||
this, "porymap", "The project has been modified, save changes?",
|
||||
QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
|
||||
bool MainWindow::closeProject() {
|
||||
if (!closeSupplementaryWindows())
|
||||
return false;
|
||||
|
||||
if (result == QMessageBox::Yes) {
|
||||
editor->saveProject();
|
||||
} else if (result == QMessageBox::No) {
|
||||
logWarn("Closing porymap with unsaved changes.");
|
||||
} else if (result == QMessageBox::Cancel) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
if (!isProjectOpen())
|
||||
return true;
|
||||
|
||||
if (projectHasUnsavedChanges || (editor->map && editor->map->hasUnsavedChanges())) {
|
||||
QMessageBox::StandardButton result = QMessageBox::question(
|
||||
this, "porymap", "The project has been modified, save changes?",
|
||||
QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
|
||||
|
||||
if (result == QMessageBox::Yes) {
|
||||
editor->saveProject();
|
||||
} else if (result == QMessageBox::No) {
|
||||
logWarn("Closing project with unsaved changes.");
|
||||
} else if (result == QMessageBox::Cancel) {
|
||||
return false;
|
||||
}
|
||||
projectConfig.save();
|
||||
userConfig.save();
|
||||
}
|
||||
clearProjectUI();
|
||||
editor->closeProject();
|
||||
setWindowDisabled(true);
|
||||
setWindowTitle(QCoreApplication::applicationName());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::saveGlobalConfigs() {
|
||||
porymapConfig.setMainGeometry(
|
||||
this->saveGeometry(),
|
||||
this->saveState(),
|
||||
|
@ -3032,6 +3079,24 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
|||
);
|
||||
porymapConfig.save();
|
||||
shortcutsConfig.save();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Exit_triggered() {
|
||||
if (!closeProject())
|
||||
return;
|
||||
|
||||
saveGlobalConfigs();
|
||||
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
if (!closeProject()) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
saveGlobalConfigs();
|
||||
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
|
182
src/project.cpp
182
src/project.cpp
|
@ -49,7 +49,7 @@ Project::~Project()
|
|||
void Project::initSignals() {
|
||||
// detect changes to specific filepaths being monitored
|
||||
QObject::connect(&fileWatcher, &QFileSystemWatcher::fileChanged, [this](QString changed){
|
||||
if (!porymapConfig.getMonitorFiles()) return;
|
||||
if (!porymapConfig.monitorFiles) return;
|
||||
if (modifiedFileTimestamps.contains(changed)) {
|
||||
if (QDateTime::currentMSecsSinceEpoch() < modifiedFileTimestamps[changed]) {
|
||||
return;
|
||||
|
@ -77,7 +77,7 @@ void Project::initSignals() {
|
|||
emit reloadProject();
|
||||
} else if (choice == QMessageBox::No) {
|
||||
if (showAgainCheck.isChecked()) {
|
||||
porymapConfig.setMonitorFiles(false);
|
||||
porymapConfig.monitorFiles = false;
|
||||
emit uncheckMonitorFilesAction();
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +91,60 @@ void Project::set_root(QString dir) {
|
|||
this->parser.set_root(dir);
|
||||
}
|
||||
|
||||
// Before attempting the initial project load we should check for a few notable files.
|
||||
// If all are missing then we can warn the user, they may have accidentally selected the wrong folder.
|
||||
bool Project::sanityCheck() {
|
||||
// The goal with the file selection is to pick files that are important enough that any reasonable project would have
|
||||
// at least 1 in the expected location, but unique enough that they're unlikely to overlap with a completely unrelated
|
||||
// directory (e.g. checking for 'data/maps/' is a bad choice because it's too generic, pokeyellow would pass for instance)
|
||||
static const QSet<ProjectFilePath> pathsToCheck = {
|
||||
ProjectFilePath::json_map_groups,
|
||||
ProjectFilePath::json_layouts,
|
||||
ProjectFilePath::tilesets_headers,
|
||||
ProjectFilePath::global_fieldmap,
|
||||
};
|
||||
for (auto pathId : pathsToCheck) {
|
||||
const QString path = QString("%1/%2").arg(this->root).arg(projectConfig.getFilePath(pathId));
|
||||
QFileInfo fileInfo(path);
|
||||
if (fileInfo.exists() && fileInfo.isFile())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Project::load() {
|
||||
bool success = readMapLayouts()
|
||||
&& readRegionMapSections()
|
||||
&& readItemNames()
|
||||
&& readFlagNames()
|
||||
&& readVarNames()
|
||||
&& readMovementTypes()
|
||||
&& readInitialFacingDirections()
|
||||
&& readMapTypes()
|
||||
&& readMapBattleScenes()
|
||||
&& readWeatherNames()
|
||||
&& readCoordEventWeatherNames()
|
||||
&& readSecretBaseIds()
|
||||
&& readBgEventFacingDirections()
|
||||
&& readTrainerTypes()
|
||||
&& readMetatileBehaviors()
|
||||
&& readFieldmapProperties()
|
||||
&& readFieldmapMasks()
|
||||
&& readTilesetLabels()
|
||||
&& readTilesetMetatileLabels()
|
||||
&& readHealLocations()
|
||||
&& readMiscellaneousConstants()
|
||||
&& readSpeciesIconPaths()
|
||||
&& readWildMonData()
|
||||
&& readEventScriptLabels()
|
||||
&& readObjEventGfxConstants()
|
||||
&& readEventGraphics()
|
||||
&& readSongNames()
|
||||
&& readMapGroups();
|
||||
applyParsedLimits();
|
||||
return success;
|
||||
}
|
||||
|
||||
QString Project::getProjectTitle() {
|
||||
if (!root.isNull()) {
|
||||
return root.section('/', -1);
|
||||
|
@ -165,13 +219,13 @@ const QSet<QString> defaultTopLevelMapFields = {
|
|||
|
||||
QSet<QString> Project::getTopLevelMapFields() {
|
||||
QSet<QString> topLevelMapFields = defaultTopLevelMapFields;
|
||||
if (projectConfig.getMapAllowFlagsEnabled()) {
|
||||
if (projectConfig.mapAllowFlagsEnabled) {
|
||||
topLevelMapFields.insert("allow_cycling");
|
||||
topLevelMapFields.insert("allow_escaping");
|
||||
topLevelMapFields.insert("allow_running");
|
||||
}
|
||||
|
||||
if (projectConfig.getFloorNumberEnabled()) {
|
||||
if (projectConfig.floorNumberEnabled) {
|
||||
topLevelMapFields.insert("floor_number");
|
||||
}
|
||||
return topLevelMapFields;
|
||||
|
@ -200,12 +254,12 @@ bool Project::loadMapData(Map* map) {
|
|||
map->show_location = ParseUtil::jsonToBool(mapObj["show_map_name"]);
|
||||
map->battle_scene = ParseUtil::jsonToQString(mapObj["battle_scene"]);
|
||||
|
||||
if (projectConfig.getMapAllowFlagsEnabled()) {
|
||||
if (projectConfig.mapAllowFlagsEnabled) {
|
||||
map->allowBiking = ParseUtil::jsonToBool(mapObj["allow_cycling"]);
|
||||
map->allowEscaping = ParseUtil::jsonToBool(mapObj["allow_escaping"]);
|
||||
map->allowRunning = ParseUtil::jsonToBool(mapObj["allow_running"]);
|
||||
}
|
||||
if (projectConfig.getFloorNumberEnabled()) {
|
||||
if (projectConfig.floorNumberEnabled) {
|
||||
map->floorNumber = ParseUtil::jsonToInt(mapObj["floor_number"]);
|
||||
}
|
||||
map->sharedEventsMap = ParseUtil::jsonToQString(mapObj["shared_events_map"]);
|
||||
|
@ -214,11 +268,10 @@ bool Project::loadMapData(Map* map) {
|
|||
// Events
|
||||
map->events[Event::Group::Object].clear();
|
||||
QJsonArray objectEventsArr = mapObj["object_events"].toArray();
|
||||
bool hasCloneObjects = projectConfig.getEventCloneObjectEnabled();
|
||||
for (int i = 0; i < objectEventsArr.size(); i++) {
|
||||
QJsonObject event = objectEventsArr[i].toObject();
|
||||
// If clone objects are not enabled then no type field is present
|
||||
QString type = hasCloneObjects ? ParseUtil::jsonToQString(event["type"]) : "object";
|
||||
QString type = projectConfig.eventCloneObjectEnabled ? ParseUtil::jsonToQString(event["type"]) : "object";
|
||||
if (type.isEmpty() || type == "object") {
|
||||
ObjectEvent *object = new ObjectEvent();
|
||||
object->loadFromJson(event, this);
|
||||
|
@ -300,11 +353,11 @@ bool Project::loadMapData(Map* map) {
|
|||
heal->setMap(map);
|
||||
heal->setX(loc.x);
|
||||
heal->setY(loc.y);
|
||||
heal->setElevation(projectConfig.getDefaultElevation());
|
||||
heal->setElevation(projectConfig.defaultElevation);
|
||||
heal->setLocationName(loc.mapName);
|
||||
heal->setIdName(loc.idName);
|
||||
heal->setIndex(loc.index);
|
||||
if (projectConfig.getHealLocationRespawnDataEnabled()) {
|
||||
if (projectConfig.healLocationRespawnDataEnabled) {
|
||||
heal->setRespawnMap(mapConstantsToMapNames.value(QString(mapPrefix + loc.respawnMap)));
|
||||
heal->setRespawnNPC(loc.respawnNPC);
|
||||
}
|
||||
|
@ -441,7 +494,6 @@ bool Project::readMapLayouts() {
|
|||
"border_filepath",
|
||||
"blockdata_filepath",
|
||||
};
|
||||
bool useCustomBorderSize = projectConfig.getUseCustomBorderSize();
|
||||
for (int i = 0; i < layouts.size(); i++) {
|
||||
QJsonObject layoutObj = layouts[i].toObject();
|
||||
if (layoutObj.isEmpty())
|
||||
|
@ -482,7 +534,7 @@ bool Project::readMapLayouts() {
|
|||
return false;
|
||||
}
|
||||
layout->height = lheight;
|
||||
if (useCustomBorderSize) {
|
||||
if (projectConfig.useCustomBorderSize) {
|
||||
int bwidth = ParseUtil::jsonToInt(layoutObj["border_width"]);
|
||||
if (bwidth <= 0) { // 0 is an expected border width/height that should be handled, GF used it for the RS layouts in FRLG
|
||||
logWarn(QString("Invalid 'border_width' value '%1' for %2 in %3. Must be greater than 0. Using default (%4) instead.")
|
||||
|
@ -548,7 +600,6 @@ void Project::saveMapLayouts() {
|
|||
OrderedJson::object layoutsObj;
|
||||
layoutsObj["layouts_table_label"] = layoutsLabel;
|
||||
|
||||
bool useCustomBorderSize = projectConfig.getUseCustomBorderSize();
|
||||
OrderedJson::array layoutsArr;
|
||||
for (QString layoutId : mapLayoutsTableMaster) {
|
||||
MapLayout *layout = mapLayouts.value(layoutId);
|
||||
|
@ -557,7 +608,7 @@ void Project::saveMapLayouts() {
|
|||
layoutObj["name"] = layout->name;
|
||||
layoutObj["width"] = layout->width;
|
||||
layoutObj["height"] = layout->height;
|
||||
if (useCustomBorderSize) {
|
||||
if (projectConfig.useCustomBorderSize) {
|
||||
layoutObj["border_width"] = layout->border_width;
|
||||
layoutObj["border_height"] = layout->border_height;
|
||||
}
|
||||
|
@ -771,7 +822,7 @@ void Project::saveHealLocationsData(Map *map) {
|
|||
}
|
||||
|
||||
// Create the definition text for each data table
|
||||
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||
bool respawnEnabled = projectConfig.healLocationRespawnDataEnabled;
|
||||
const QString qualifiers = QString(healLocationDataQualifiers.isStatic ? "static " : "")
|
||||
+ QString(healLocationDataQualifiers.isConst ? "const " : "");
|
||||
|
||||
|
@ -954,10 +1005,9 @@ void Project::saveTilesetMetatileAttributes(Tileset *tileset) {
|
|||
QFile attrs_file(tileset->metatile_attrs_path);
|
||||
if (attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
QByteArray data;
|
||||
int attrSize = projectConfig.getMetatileAttributesSize();
|
||||
for (Metatile *metatile : tileset->metatiles) {
|
||||
uint32_t attributes = metatile->getAttributes();
|
||||
for (int i = 0; i < attrSize; i++)
|
||||
for (int i = 0; i < projectConfig.metatileAttributesSize; i++)
|
||||
data.append(static_cast<char>(attributes >> (8 * i)));
|
||||
}
|
||||
attrs_file.write(data);
|
||||
|
@ -1093,7 +1143,7 @@ void Project::setNewMapBlockdata(Map *map) {
|
|||
map->layout->blockdata.clear();
|
||||
int width = map->getWidth();
|
||||
int height = map->getHeight();
|
||||
Block block(projectConfig.getDefaultMetatileId(), projectConfig.getDefaultCollision(), projectConfig.getDefaultElevation());
|
||||
Block block(projectConfig.defaultMetatileId, projectConfig.defaultCollision, projectConfig.defaultElevation);
|
||||
for (int i = 0; i < width * height; i++) {
|
||||
map->layout->blockdata.append(block);
|
||||
}
|
||||
|
@ -1122,8 +1172,7 @@ void Project::setNewMapBorder(Map *map) {
|
|||
int width = map->getBorderWidth();
|
||||
int height = map->getBorderHeight();
|
||||
|
||||
const QList<uint16_t> configMetatileIds = projectConfig.getNewMapBorderMetatileIds();
|
||||
if (configMetatileIds.length() != width * height) {
|
||||
if (projectConfig.newMapBorderMetatileIds.length() != width * height) {
|
||||
// Border size doesn't match the number of default border metatiles.
|
||||
// Fill the border with empty metatiles.
|
||||
for (int i = 0; i < width * height; i++) {
|
||||
|
@ -1132,7 +1181,7 @@ void Project::setNewMapBorder(Map *map) {
|
|||
} else {
|
||||
// Fill the border with the default metatiles from the config.
|
||||
for (int i = 0; i < width * height; i++) {
|
||||
map->layout->border.append(configMetatileIds.at(i));
|
||||
map->layout->border.append(projectConfig.newMapBorderMetatileIds.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1175,18 +1224,17 @@ void Project::saveMap(Map *map) {
|
|||
}
|
||||
|
||||
// Create file data/maps/<map_name>/scripts.inc
|
||||
QString text = this->getScriptDefaultString(projectConfig.getUsePoryScript(), map->name);
|
||||
saveTextFile(mapDataDir + "/scripts" + this->getScriptFileExtension(projectConfig.getUsePoryScript()), text);
|
||||
QString text = this->getScriptDefaultString(projectConfig.usePoryScript, map->name);
|
||||
saveTextFile(mapDataDir + "/scripts" + this->getScriptFileExtension(projectConfig.usePoryScript), text);
|
||||
|
||||
bool usesTextFile = projectConfig.getCreateMapTextFileEnabled();
|
||||
if (usesTextFile) {
|
||||
if (projectConfig.createMapTextFileEnabled) {
|
||||
// Create file data/maps/<map_name>/text.inc
|
||||
saveTextFile(mapDataDir + "/text" + this->getScriptFileExtension(projectConfig.getUsePoryScript()), "\n");
|
||||
saveTextFile(mapDataDir + "/text" + this->getScriptFileExtension(projectConfig.usePoryScript), "\n");
|
||||
}
|
||||
|
||||
// Simply append to data/event_scripts.s.
|
||||
text = QString("\n\t.include \"%1%2/scripts.inc\"\n").arg(basePath, map->name);
|
||||
if (usesTextFile) {
|
||||
if (projectConfig.createMapTextFileEnabled) {
|
||||
text += QString("\t.include \"%1%2/text.inc\"\n").arg(basePath, map->name);
|
||||
}
|
||||
appendTextFile(root + "/" + projectConfig.getFilePath(ProjectFilePath::data_event_scripts), text);
|
||||
|
@ -1217,13 +1265,13 @@ void Project::saveMap(Map *map) {
|
|||
mapObj["requires_flash"] = map->requiresFlash;
|
||||
mapObj["weather"] = map->weather;
|
||||
mapObj["map_type"] = map->type;
|
||||
if (projectConfig.getMapAllowFlagsEnabled()) {
|
||||
if (projectConfig.mapAllowFlagsEnabled) {
|
||||
mapObj["allow_cycling"] = map->allowBiking;
|
||||
mapObj["allow_escaping"] = map->allowEscaping;
|
||||
mapObj["allow_running"] = map->allowRunning;
|
||||
}
|
||||
mapObj["show_map_name"] = map->show_location;
|
||||
if (projectConfig.getFloorNumberEnabled()) {
|
||||
if (projectConfig.floorNumberEnabled) {
|
||||
mapObj["floor_number"] = map->floorNumber;
|
||||
}
|
||||
mapObj["battle_scene"] = map->battle_scene;
|
||||
|
@ -1331,6 +1379,12 @@ void Project::saveAllDataStructures() {
|
|||
saveMapGroups();
|
||||
saveMapConstantsHeader();
|
||||
saveWildMonData();
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
void Project::saveConfig() {
|
||||
projectConfig.save();
|
||||
userConfig.save();
|
||||
}
|
||||
|
||||
void Project::loadTilesetAssets(Tileset* tileset) {
|
||||
|
@ -1469,7 +1523,7 @@ void Project::loadTilesetMetatiles(Tileset* tileset) {
|
|||
if (attrs_file.open(QIODevice::ReadOnly)) {
|
||||
QByteArray data = attrs_file.readAll();
|
||||
int num_metatiles = tileset->metatiles.count();
|
||||
int attrSize = projectConfig.getMetatileAttributesSize();
|
||||
int attrSize = projectConfig.metatileAttributesSize;
|
||||
int num_metatileAttrs = data.length() / attrSize;
|
||||
if (num_metatiles != num_metatileAttrs) {
|
||||
logWarn(QString("Metatile count %1 does not match metatile attribute count %2 in %3").arg(num_metatiles).arg(num_metatileAttrs).arg(tileset->name));
|
||||
|
@ -1606,7 +1660,7 @@ bool Project::readWildMonData() {
|
|||
wildMonData.clear();
|
||||
encounterGroupLabels.clear();
|
||||
this->wildEncountersLoaded = false;
|
||||
if (!userConfig.getEncounterJsonActive()) {
|
||||
if (!userConfig.useEncounterJson) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1816,7 +1870,7 @@ Project::DataQualifiers Project::getDataQualifiers(QString text, QString label)
|
|||
}
|
||||
|
||||
QString Project::getDefaultPrimaryTilesetLabel() {
|
||||
QString defaultLabel = projectConfig.getDefaultPrimaryTileset();
|
||||
QString defaultLabel = projectConfig.defaultPrimaryTileset;
|
||||
if (!this->primaryTilesetLabels.contains(defaultLabel)) {
|
||||
QString firstLabel = this->primaryTilesetLabels.first();
|
||||
logWarn(QString("Unable to find default primary tileset '%1', using '%2' instead.").arg(defaultLabel).arg(firstLabel));
|
||||
|
@ -1826,7 +1880,7 @@ QString Project::getDefaultPrimaryTilesetLabel() {
|
|||
}
|
||||
|
||||
QString Project::getDefaultSecondaryTilesetLabel() {
|
||||
QString defaultLabel = projectConfig.getDefaultSecondaryTileset();
|
||||
QString defaultLabel = projectConfig.defaultSecondaryTileset;
|
||||
if (!this->secondaryTilesetLabels.contains(defaultLabel)) {
|
||||
QString firstLabel = this->secondaryTilesetLabels.first();
|
||||
logWarn(QString("Unable to find default secondary tileset '%1', using '%2' instead.").arg(defaultLabel).arg(firstLabel));
|
||||
|
@ -1978,9 +2032,6 @@ bool Project::readFieldmapMasks() {
|
|||
const QStringList defineNames = defines.keys();
|
||||
this->disabledSettingsNames = QSet<QString>(defineNames.constBegin(), defineNames.constEnd());
|
||||
|
||||
// Avoid repeatedly writing the config file
|
||||
projectConfig.setSaveDisabled(true);
|
||||
|
||||
// Read Block masks
|
||||
auto readBlockMask = [defines](const QString name, uint16_t *value) {
|
||||
auto it = defines.find(name);
|
||||
|
@ -1995,21 +2046,22 @@ bool Project::readFieldmapMasks() {
|
|||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
uint16_t blockMask;
|
||||
if (readBlockMask(metatileIdMaskName, &blockMask))
|
||||
projectConfig.setBlockMetatileIdMask(blockMask);
|
||||
projectConfig.blockMetatileIdMask = blockMask;
|
||||
if (readBlockMask(collisionMaskName, &blockMask))
|
||||
projectConfig.setBlockCollisionMask(blockMask);
|
||||
projectConfig.blockCollisionMask = blockMask;
|
||||
if (readBlockMask(elevationMaskName, &blockMask))
|
||||
projectConfig.setBlockElevationMask(blockMask);
|
||||
projectConfig.blockElevationMask = blockMask;
|
||||
|
||||
// Read RSE metatile attribute masks
|
||||
auto it = defines.find(behaviorMaskName);
|
||||
if (it != defines.end())
|
||||
projectConfig.setMetatileBehaviorMask(static_cast<uint32_t>(it.value()));
|
||||
projectConfig.metatileBehaviorMask = static_cast<uint32_t>(it.value());
|
||||
it = defines.find(layerTypeMaskName);
|
||||
if (it != defines.end())
|
||||
projectConfig.setMetatileLayerTypeMask(static_cast<uint32_t>(it.value()));
|
||||
projectConfig.metatileLayerTypeMask = static_cast<uint32_t>(it.value());
|
||||
|
||||
// pokefirered keeps its attribute masks in a separate table, parse this too.
|
||||
const QString attrTableName = projectConfig.getIdentifier(ProjectIdentifier::symbol_attribute_table);
|
||||
|
@ -2026,13 +2078,13 @@ bool Project::readFieldmapMasks() {
|
|||
// Read terrain type mask
|
||||
uint32_t mask = attrTable.value(terrainTypeTableName).toUInt(&ok, 0);
|
||||
if (ok) {
|
||||
projectConfig.setMetatileTerrainTypeMask(mask);
|
||||
projectConfig.metatileTerrainTypeMask = mask;
|
||||
this->disabledSettingsNames.insert(terrainTypeTableName);
|
||||
}
|
||||
// Read encounter type mask
|
||||
mask = attrTable.value(encounterTypeTableName).toUInt(&ok, 0);
|
||||
if (ok) {
|
||||
projectConfig.setMetatileEncounterTypeMask(mask);
|
||||
projectConfig.metatileEncounterTypeMask = mask;
|
||||
this->disabledSettingsNames.insert(encounterTypeTableName);
|
||||
}
|
||||
// If we haven't already parsed behavior and layer type then try those too
|
||||
|
@ -2040,7 +2092,7 @@ bool Project::readFieldmapMasks() {
|
|||
// Read behavior mask
|
||||
mask = attrTable.value(behaviorTableName).toUInt(&ok, 0);
|
||||
if (ok) {
|
||||
projectConfig.setMetatileBehaviorMask(mask);
|
||||
projectConfig.metatileBehaviorMask = mask;
|
||||
this->disabledSettingsNames.insert(behaviorTableName);
|
||||
}
|
||||
}
|
||||
|
@ -2048,12 +2100,11 @@ bool Project::readFieldmapMasks() {
|
|||
// Read layer type mask
|
||||
mask = attrTable.value(layerTypeTableName).toUInt(&ok, 0);
|
||||
if (ok) {
|
||||
projectConfig.setMetatileLayerTypeMask(mask);
|
||||
projectConfig.metatileLayerTypeMask = mask;
|
||||
this->disabledSettingsNames.insert(layerTypeTableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
projectConfig.setSaveDisabled(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2105,7 +2156,7 @@ bool Project::readHealLocations() {
|
|||
static const QRegularExpression re_comments("//.*?(\r\n?|\n)|/\\*.*?\\*/", QRegularExpression::DotMatchesEverythingOption);
|
||||
text.replace(re_comments, "");
|
||||
|
||||
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||
bool respawnEnabled = projectConfig.healLocationRespawnDataEnabled;
|
||||
|
||||
// Search for the name of the main Heal Locations table
|
||||
const QRegularExpression tableNameExpr(QString("%1\\s+(?<name>[A-Za-z0-9_]+)\\[").arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations_type)));
|
||||
|
@ -2263,7 +2314,7 @@ bool Project::readWeatherNames() {
|
|||
}
|
||||
|
||||
bool Project::readCoordEventWeatherNames() {
|
||||
if (!projectConfig.getEventWeatherTriggerEnabled())
|
||||
if (!projectConfig.eventWeatherTriggerEnabled)
|
||||
return true;
|
||||
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_coord_event_weather)};
|
||||
|
@ -2276,7 +2327,7 @@ bool Project::readCoordEventWeatherNames() {
|
|||
}
|
||||
|
||||
bool Project::readSecretBaseIds() {
|
||||
if (!projectConfig.getEventSecretBaseEnabled())
|
||||
if (!projectConfig.eventSecretBaseEnabled)
|
||||
return true;
|
||||
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_secret_bases)};
|
||||
|
@ -2319,7 +2370,7 @@ bool Project::readMetatileBehaviors() {
|
|||
if (defines.isEmpty()) {
|
||||
// Not having any metatile behavior names is ok (their values will be displayed instead).
|
||||
// If the user's metatiles can have nonzero values then warn them, as they likely want names.
|
||||
if (projectConfig.getMetatileBehaviorMask())
|
||||
if (projectConfig.metatileBehaviorMask)
|
||||
logWarn(QString("Failed to read metatile behaviors from %1.").arg(filename));
|
||||
return true;
|
||||
}
|
||||
|
@ -2360,7 +2411,7 @@ bool Project::readObjEventGfxConstants() {
|
|||
|
||||
bool Project::readMiscellaneousConstants() {
|
||||
miscConstants.clear();
|
||||
if (userConfig.getEncounterJsonActive()) {
|
||||
if (userConfig.useEncounterJson) {
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_pokemon);
|
||||
const QString minLevelName = projectConfig.getIdentifier(ProjectIdentifier::define_min_level);
|
||||
const QString maxLevelName = projectConfig.getIdentifier(ProjectIdentifier::define_max_level);
|
||||
|
@ -2439,9 +2490,8 @@ QStringList Project::getEventScriptsFilePaths() const {
|
|||
QStringList filePaths(QDir::cleanPath(root + "/" + projectConfig.getFilePath(ProjectFilePath::data_event_scripts)));
|
||||
const QString scriptsDir = QDir::cleanPath(root + "/" + projectConfig.getFilePath(ProjectFilePath::data_scripts_folders));
|
||||
const QString mapsDir = QDir::cleanPath(root + "/" + projectConfig.getFilePath(ProjectFilePath::data_map_folders));
|
||||
const bool usePoryscript = projectConfig.getUsePoryScript();
|
||||
|
||||
if (usePoryscript) {
|
||||
if (projectConfig.usePoryScript) {
|
||||
QDirIterator it_pory_shared(scriptsDir, {"*.pory"}, QDir::Files);
|
||||
while (it_pory_shared.hasNext())
|
||||
filePaths << it_pory_shared.next();
|
||||
|
@ -2742,7 +2792,7 @@ QString Project::getExistingFilepath(QString filepath) {
|
|||
if (filepath.isEmpty() || QFile::exists(filepath))
|
||||
return filepath;
|
||||
|
||||
filepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
|
||||
filepath = QDir::cleanPath(projectConfig.projectDir + QDir::separator() + filepath);
|
||||
if (QFile::exists(filepath))
|
||||
return filepath;
|
||||
|
||||
|
@ -2755,25 +2805,19 @@ QString Project::getExistingFilepath(QString filepath) {
|
|||
// can be limited by fieldmap defines)
|
||||
// Once we've read data from the project files we can adjust these accordingly.
|
||||
void Project::applyParsedLimits() {
|
||||
// Avoid repeatedly writing the config file
|
||||
projectConfig.setSaveDisabled(true);
|
||||
|
||||
uint32_t maxMask = Metatile::getMaxAttributesMask();
|
||||
projectConfig.setMetatileBehaviorMask(projectConfig.getMetatileBehaviorMask() & maxMask);
|
||||
projectConfig.setMetatileTerrainTypeMask(projectConfig.getMetatileTerrainTypeMask() & maxMask);
|
||||
projectConfig.setMetatileEncounterTypeMask(projectConfig.getMetatileEncounterTypeMask() & maxMask);
|
||||
projectConfig.setMetatileLayerTypeMask(projectConfig.getMetatileLayerTypeMask() & maxMask);
|
||||
projectConfig.metatileBehaviorMask &= maxMask;
|
||||
projectConfig.metatileTerrainTypeMask &= maxMask;
|
||||
projectConfig.metatileEncounterTypeMask &= maxMask;
|
||||
projectConfig.metatileLayerTypeMask &= maxMask;
|
||||
|
||||
Block::setLayout();
|
||||
Metatile::setLayout(this);
|
||||
|
||||
Project::num_metatiles_primary = qMin(Project::num_metatiles_primary, Block::getMaxMetatileId() + 1);
|
||||
projectConfig.setDefaultMetatileId(qMin(projectConfig.getDefaultMetatileId(), Block::getMaxMetatileId()));
|
||||
projectConfig.setDefaultElevation(qMin(projectConfig.getDefaultElevation(), Block::getMaxElevation()));
|
||||
projectConfig.setDefaultCollision(qMin(projectConfig.getDefaultCollision(), Block::getMaxCollision()));
|
||||
projectConfig.setCollisionSheetHeight(qMin(projectConfig.getCollisionSheetHeight(), Block::getMaxElevation() + 1));
|
||||
projectConfig.setCollisionSheetWidth(qMin(projectConfig.getCollisionSheetWidth(), Block::getMaxCollision() + 1));
|
||||
|
||||
projectConfig.setSaveDisabled(false);
|
||||
projectConfig.save();
|
||||
projectConfig.defaultMetatileId = qMin(projectConfig.defaultMetatileId, Block::getMaxMetatileId());
|
||||
projectConfig.defaultElevation = qMin(projectConfig.defaultElevation, Block::getMaxElevation());
|
||||
projectConfig.defaultCollision = qMin(projectConfig.defaultCollision, Block::getMaxCollision());
|
||||
projectConfig.collisionSheetHeight = qMin(projectConfig.collisionSheetHeight, Block::getMaxElevation() + 1);
|
||||
projectConfig.collisionSheetWidth = qMin(projectConfig.collisionSheetWidth, Block::getMaxCollision() + 1);
|
||||
}
|
||||
|
|
|
@ -295,7 +295,7 @@ int MainWindow::getBorderHeight() {
|
|||
}
|
||||
|
||||
void MainWindow::setBorderDimensions(int width, int height) {
|
||||
if (!this->editor || !this->editor->map || !projectConfig.getUseCustomBorderSize())
|
||||
if (!this->editor || !this->editor->map || !projectConfig.useCustomBorderSize)
|
||||
return;
|
||||
if (width < 1 || height < 1 || width > MAX_BORDER_WIDTH || height > MAX_BORDER_HEIGHT)
|
||||
return;
|
||||
|
@ -305,7 +305,7 @@ void MainWindow::setBorderDimensions(int width, int height) {
|
|||
}
|
||||
|
||||
void MainWindow::setBorderWidth(int width) {
|
||||
if (!this->editor || !this->editor->map || !projectConfig.getUseCustomBorderSize())
|
||||
if (!this->editor || !this->editor->map || !projectConfig.useCustomBorderSize)
|
||||
return;
|
||||
if (width < 1 || width > MAX_BORDER_WIDTH)
|
||||
return;
|
||||
|
@ -315,7 +315,7 @@ void MainWindow::setBorderWidth(int width) {
|
|||
}
|
||||
|
||||
void MainWindow::setBorderHeight(int height) {
|
||||
if (!this->editor || !this->editor->map || !projectConfig.getUseCustomBorderSize())
|
||||
if (!this->editor || !this->editor->map || !projectConfig.useCustomBorderSize)
|
||||
return;
|
||||
if (height < 1 || height > MAX_BORDER_HEIGHT)
|
||||
return;
|
||||
|
|
|
@ -21,14 +21,19 @@ QMap<CallbackType, QString> callbackFunctions = {
|
|||
|
||||
Scripting *instance = nullptr;
|
||||
|
||||
void Scripting::stop() {
|
||||
if (!instance) return;
|
||||
instance->engine->setInterrupted(true);
|
||||
instance->scriptUtility->clearActions();
|
||||
qDeleteAll(instance->imageCache);
|
||||
delete instance;
|
||||
instance = nullptr;
|
||||
}
|
||||
|
||||
void Scripting::init(MainWindow *mainWindow) {
|
||||
mainWindow->ui->graphicsView_Map->clearOverlayMap();
|
||||
if (instance) {
|
||||
instance->engine->setInterrupted(true);
|
||||
instance->scriptUtility->clearActions();
|
||||
qDeleteAll(instance->imageCache);
|
||||
delete instance;
|
||||
}
|
||||
if (mainWindow->ui->graphicsView_Map)
|
||||
mainWindow->ui->graphicsView_Map->clearOverlayMap();
|
||||
Scripting::stop();
|
||||
instance = new Scripting(mainWindow);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ void CityMapPixmapItem::init() {
|
|||
if (!binFile.open(QIODevice::ReadOnly)) return;
|
||||
|
||||
data = binFile.readAll();
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby) {
|
||||
if (projectConfig.baseGameVersion == BaseGameVersion::pokeruby) {
|
||||
for (int i = 0; i < data.size(); i++)
|
||||
data[i] = data[i] ^ 0x80;
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ void CityMapPixmapItem::save() {
|
|||
logError(QString("Cannot save city map tilemap to %1.").arg(file));
|
||||
return;
|
||||
}
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby) {
|
||||
if (projectConfig.baseGameVersion == BaseGameVersion::pokeruby) {
|
||||
for (int i = 0; i < data.size(); i++)
|
||||
data[i] = data[i] ^ 0x80;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::CustomScriptsEditor),
|
||||
baseDir(userConfig.getProjectDir() + QDir::separator())
|
||||
baseDir(userConfig.projectDir + QDir::separator())
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
@ -23,7 +23,7 @@ CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) :
|
|||
for (int i = 0; i < paths.length(); i++)
|
||||
this->displayScript(paths.at(i), enabled.at(i));
|
||||
|
||||
this->fileDialogDir = userConfig.getProjectDir();
|
||||
this->fileDialogDir = userConfig.projectDir;
|
||||
|
||||
connect(ui->button_CreateNewScript, &QAbstractButton::clicked, this, &CustomScriptsEditor::createNewScript);
|
||||
connect(ui->button_LoadScript, &QAbstractButton::clicked, this, &CustomScriptsEditor::loadScript);
|
||||
|
|
|
@ -360,7 +360,7 @@ void ObjectFrame::initialize() {
|
|||
|
||||
// script
|
||||
this->combo_script->setCurrentText(this->object->getScript());
|
||||
if (porymapConfig.getTextEditorGotoLine().isEmpty())
|
||||
if (porymapConfig.textEditorGotoLine.isEmpty())
|
||||
this->button_script->hide();
|
||||
|
||||
// flag
|
||||
|
@ -858,16 +858,16 @@ void HiddenItemFrame::initialize() {
|
|||
this->combo_flag->setTextItem(this->hiddenItem->getFlag());
|
||||
|
||||
// quantity
|
||||
if (projectConfig.getHiddenItemQuantityEnabled()) {
|
||||
if (projectConfig.hiddenItemQuantityEnabled) {
|
||||
this->spinner_quantity->setValue(this->hiddenItem->getQuantity());
|
||||
}
|
||||
this->hideable_quantity->setVisible(projectConfig.getHiddenItemQuantityEnabled());
|
||||
this->hideable_quantity->setVisible(projectConfig.hiddenItemQuantityEnabled);
|
||||
|
||||
// underfoot
|
||||
if (projectConfig.getHiddenItemRequiresItemfinderEnabled()) {
|
||||
if (projectConfig.hiddenItemRequiresItemfinderEnabled) {
|
||||
this->check_itemfinder->setChecked(this->hiddenItem->getUnderfoot());
|
||||
}
|
||||
this->hideable_itemfinder->setVisible(projectConfig.getHiddenItemRequiresItemfinderEnabled());
|
||||
this->hideable_itemfinder->setVisible(projectConfig.hiddenItemRequiresItemfinderEnabled);
|
||||
}
|
||||
|
||||
void HiddenItemFrame::populate(Project *project) {
|
||||
|
@ -971,7 +971,7 @@ void HealLocationFrame::connectSignals(MainWindow *window) {
|
|||
|
||||
EventFrame::connectSignals(window);
|
||||
|
||||
if (projectConfig.getHealLocationRespawnDataEnabled()) {
|
||||
if (projectConfig.healLocationRespawnDataEnabled) {
|
||||
this->combo_respawn_map->disconnect();
|
||||
connect(this->combo_respawn_map, &QComboBox::currentTextChanged, [this](const QString &text) {
|
||||
this->healLocation->setRespawnMap(text);
|
||||
|
@ -992,7 +992,7 @@ void HealLocationFrame::initialize() {
|
|||
const QSignalBlocker blocker(this);
|
||||
EventFrame::initialize();
|
||||
|
||||
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||
bool respawnEnabled = projectConfig.healLocationRespawnDataEnabled;
|
||||
if (respawnEnabled) {
|
||||
this->combo_respawn_map->setTextItem(this->healLocation->getRespawnMap());
|
||||
this->spinner_respawn_npc->setValue(this->healLocation->getRespawnNPC());
|
||||
|
@ -1008,6 +1008,6 @@ void HealLocationFrame::populate(Project *project) {
|
|||
const QSignalBlocker blocker(this);
|
||||
EventFrame::populate(project);
|
||||
|
||||
if (projectConfig.getHealLocationRespawnDataEnabled())
|
||||
if (projectConfig.healLocationRespawnDataEnabled)
|
||||
this->combo_respawn_map->addItems(project->mapNames);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ QImage getMetatileImage(
|
|||
QList<QList<QRgb>> palettes = Tileset::getBlockPalettes(primaryTileset, secondaryTileset, useTruePalettes);
|
||||
|
||||
QPainter metatile_painter(&metatile_image);
|
||||
bool isTripleLayerMetatile = projectConfig.getTripleLayerMetatilesEnabled();
|
||||
const int numLayers = 3; // When rendering, metatiles always have 3 layers
|
||||
uint32_t layerType = metatile->layerType();
|
||||
for (int layer = 0; layer < numLayers; layer++)
|
||||
|
@ -60,7 +59,7 @@ QImage getMetatileImage(
|
|||
// Get the tile to render next
|
||||
Tile tile;
|
||||
int tileOffset = (y * 2) + x;
|
||||
if (isTripleLayerMetatile) {
|
||||
if (projectConfig.tripleLayerMetatilesEnabled) {
|
||||
tile = metatile->tiles.value(tileOffset + (l * 4));
|
||||
} else {
|
||||
// "Vanilla" metatiles only have 8 tiles, but render 12.
|
||||
|
|
|
@ -27,6 +27,7 @@ MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExpor
|
|||
QDialog(parent_),
|
||||
ui(new Ui::MapImageExporter)
|
||||
{
|
||||
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
this->map = editor_->map;
|
||||
this->editor = editor_;
|
||||
|
|
|
@ -14,6 +14,7 @@ NewMapPopup::NewMapPopup(QWidget *parent, Project *project) :
|
|||
QMainWindow(parent),
|
||||
ui(new Ui::NewMapPopup)
|
||||
{
|
||||
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
this->project = project;
|
||||
this->existingLayout = false;
|
||||
|
@ -48,7 +49,7 @@ void NewMapPopup::init() {
|
|||
ui->spinBox_NewMap_Floor_Number->setMaximum(127);
|
||||
|
||||
// Hide config specific ui elements
|
||||
bool hasFlags = projectConfig.getMapAllowFlagsEnabled();
|
||||
bool hasFlags = projectConfig.mapAllowFlagsEnabled;
|
||||
ui->checkBox_NewMap_Allow_Running->setVisible(hasFlags);
|
||||
ui->checkBox_NewMap_Allow_Biking->setVisible(hasFlags);
|
||||
ui->checkBox_NewMap_Allow_Escape_Rope->setVisible(hasFlags);
|
||||
|
@ -56,13 +57,13 @@ void NewMapPopup::init() {
|
|||
ui->label_NewMap_Allow_Biking->setVisible(hasFlags);
|
||||
ui->label_NewMap_Allow_Escape_Rope->setVisible(hasFlags);
|
||||
|
||||
bool hasCustomBorders = projectConfig.getUseCustomBorderSize();
|
||||
bool hasCustomBorders = projectConfig.useCustomBorderSize;
|
||||
ui->spinBox_NewMap_BorderWidth->setVisible(hasCustomBorders);
|
||||
ui->spinBox_NewMap_BorderHeight->setVisible(hasCustomBorders);
|
||||
ui->label_NewMap_BorderWidth->setVisible(hasCustomBorders);
|
||||
ui->label_NewMap_BorderHeight->setVisible(hasCustomBorders);
|
||||
|
||||
bool hasFloorNumber = projectConfig.getFloorNumberEnabled();
|
||||
bool hasFloorNumber = projectConfig.floorNumberEnabled;
|
||||
ui->spinBox_NewMap_Floor_Number->setVisible(hasFloorNumber);
|
||||
ui->label_NewMap_Floor_Number->setVisible(hasFloorNumber);
|
||||
|
||||
|
@ -271,7 +272,7 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
|
|||
layout->name = QString("%1_Layout").arg(newMap->name);
|
||||
layout->width = this->ui->spinBox_NewMap_Width->value();
|
||||
layout->height = this->ui->spinBox_NewMap_Height->value();
|
||||
if (projectConfig.getUseCustomBorderSize()) {
|
||||
if (projectConfig.useCustomBorderSize) {
|
||||
layout->border_width = this->ui->spinBox_NewMap_BorderWidth->value();
|
||||
layout->border_height = this->ui->spinBox_NewMap_BorderHeight->value();
|
||||
} else {
|
||||
|
@ -295,12 +296,12 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
|
|||
newMap->needsHealLocation = true;
|
||||
}
|
||||
|
||||
if (projectConfig.getMapAllowFlagsEnabled()) {
|
||||
if (projectConfig.mapAllowFlagsEnabled) {
|
||||
newMap->allowRunning = this->ui->checkBox_NewMap_Allow_Running->isChecked();
|
||||
newMap->allowBiking = this->ui->checkBox_NewMap_Allow_Biking->isChecked();
|
||||
newMap->allowEscaping = this->ui->checkBox_NewMap_Allow_Escape_Rope->isChecked();
|
||||
}
|
||||
if (projectConfig.getFloorNumberEnabled()) {
|
||||
if (projectConfig.floorNumberEnabled) {
|
||||
newMap->floorNumber = this->ui->spinBox_NewMap_Floor_Number->value();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ NewTilesetDialog::NewTilesetDialog(Project* project, QWidget *parent) :
|
|||
QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression);
|
||||
this->ui->nameLineEdit->setValidator(validator);
|
||||
|
||||
bool checkerboard = porymapConfig.getTilesetCheckerboardFill();
|
||||
bool checkerboard = porymapConfig.tilesetCheckerboardFill;
|
||||
this->ui->fillCheckBox->setChecked(checkerboard);
|
||||
this->checkerboardFill = checkerboard;
|
||||
|
||||
|
@ -46,5 +46,5 @@ void NewTilesetDialog::NameOrSecondaryChanged() {
|
|||
|
||||
void NewTilesetDialog::FillChanged() {
|
||||
this->checkerboardFill = this->ui->fillCheckBox->isChecked();
|
||||
porymapConfig.setTilesetCheckerboardFill(this->checkerboardFill);
|
||||
porymapConfig.tilesetCheckerboardFill = this->checkerboardFill;
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset
|
|||
connect(this->pickButtons[i], &QToolButton::clicked, [this, i](){ this->pickColor(i); });
|
||||
}
|
||||
|
||||
int bitDepth = porymapConfig.getPaletteEditorBitDepth();
|
||||
int bitDepth = porymapConfig.paletteEditorBitDepth;
|
||||
if (bitDepth == 15) {
|
||||
this->ui->bit_depth_15->setChecked(true);
|
||||
} else {
|
||||
|
@ -233,7 +233,7 @@ void PaletteEditor::setBitDepth(int bits) {
|
|||
break;
|
||||
}
|
||||
this->bitDepth = bits;
|
||||
porymapConfig.setPaletteEditorBitDepth(bits);
|
||||
porymapConfig.paletteEditorBitDepth = bits;
|
||||
refreshColorUis();
|
||||
setSignalsEnabled(true);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ const QString defaultFilepath = "prefabs.json";
|
|||
|
||||
void Prefab::loadPrefabs() {
|
||||
this->items.clear();
|
||||
QString filepath = projectConfig.getPrefabFilepath();
|
||||
QString filepath = projectConfig.prefabFilepath;
|
||||
if (filepath.isEmpty()) return;
|
||||
|
||||
ParseUtil parser;
|
||||
|
@ -86,15 +86,14 @@ void Prefab::loadPrefabs() {
|
|||
}
|
||||
|
||||
void Prefab::savePrefabs() {
|
||||
QString filepath = projectConfig.getPrefabFilepath();
|
||||
if (filepath.isEmpty()) {
|
||||
filepath = defaultFilepath;
|
||||
projectConfig.setPrefabFilepath(filepath);
|
||||
}
|
||||
if (projectConfig.prefabFilepath.isEmpty())
|
||||
projectConfig.prefabFilepath = defaultFilepath;
|
||||
|
||||
QString filepath = projectConfig.prefabFilepath;
|
||||
|
||||
QFileInfo info(filepath);
|
||||
if (info.isRelative()) {
|
||||
filepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
|
||||
filepath = QDir::cleanPath(projectConfig.projectDir + QDir::separator() + filepath);
|
||||
}
|
||||
QFile prefabsFile(filepath);
|
||||
if (!prefabsFile.open(QIODevice::WriteOnly)) {
|
||||
|
@ -287,7 +286,7 @@ bool Prefab::tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version,
|
|||
if (fileInfo.suffix().isEmpty())
|
||||
filepath += ".json";
|
||||
if (fileInfo.isRelative()) {
|
||||
absFilepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
|
||||
absFilepath = QDir::cleanPath(projectConfig.projectDir + QDir::separator() + filepath);
|
||||
} else {
|
||||
absFilepath = filepath;
|
||||
}
|
||||
|
@ -313,10 +312,10 @@ bool Prefab::tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version,
|
|||
bool acceptedImport = (prompt == QMessageBox::Yes);
|
||||
if (acceptedImport) {
|
||||
// Sets up the default prefabs.json filepath.
|
||||
projectConfig.setPrefabFilepath(filepath);
|
||||
projectConfig.prefabFilepath = filepath;
|
||||
QFile prefabsFile(absFilepath);
|
||||
if (!prefabsFile.open(QIODevice::WriteOnly)) {
|
||||
projectConfig.setPrefabFilepath(QString());
|
||||
projectConfig.prefabFilepath = QString();
|
||||
|
||||
logError(QString("Error: Could not open %1 for writing").arg(absFilepath));
|
||||
QMessageBox messageBox(parent);
|
||||
|
@ -339,6 +338,9 @@ bool Prefab::tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version,
|
|||
case BaseGameVersion::pokeemerald:
|
||||
content = parser.readTextFile(":/text/prefabs_default_emerald.json");
|
||||
break;
|
||||
default:
|
||||
content = QString();
|
||||
break;
|
||||
}
|
||||
|
||||
prefabsFile.write(content.toUtf8());
|
||||
|
@ -346,7 +348,7 @@ bool Prefab::tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version,
|
|||
this->loadPrefabs();
|
||||
}
|
||||
|
||||
projectConfig.setPrefabImportPrompted(true);
|
||||
projectConfig.prefabImportPrompted = true;
|
||||
return acceptedImport;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,28 +44,26 @@ void PreferenceEditor::initFields() {
|
|||
}
|
||||
|
||||
void PreferenceEditor::updateFields() {
|
||||
themeSelector->setCurrentText(porymapConfig.getTheme());
|
||||
ui->lineEdit_TextEditorOpenFolder->setText(porymapConfig.getTextEditorOpenFolder());
|
||||
ui->lineEdit_TextEditorGotoLine->setText(porymapConfig.getTextEditorGotoLine());
|
||||
ui->checkBox_MonitorProjectFiles->setChecked(porymapConfig.getMonitorFiles());
|
||||
ui->checkBox_OpenRecentProject->setChecked(porymapConfig.getReopenOnLaunch());
|
||||
ui->checkBox_CheckForUpdates->setChecked(porymapConfig.getCheckForUpdates());
|
||||
themeSelector->setCurrentText(porymapConfig.theme);
|
||||
ui->lineEdit_TextEditorOpenFolder->setText(porymapConfig.textEditorOpenFolder);
|
||||
ui->lineEdit_TextEditorGotoLine->setText(porymapConfig.textEditorGotoLine);
|
||||
ui->checkBox_MonitorProjectFiles->setChecked(porymapConfig.monitorFiles);
|
||||
ui->checkBox_OpenRecentProject->setChecked(porymapConfig.reopenOnLaunch);
|
||||
ui->checkBox_CheckForUpdates->setChecked(porymapConfig.checkForUpdates);
|
||||
}
|
||||
|
||||
void PreferenceEditor::saveFields() {
|
||||
if (themeSelector->currentText() != porymapConfig.getTheme()) {
|
||||
if (themeSelector->currentText() != porymapConfig.theme) {
|
||||
const auto theme = themeSelector->currentText();
|
||||
porymapConfig.setTheme(theme);
|
||||
porymapConfig.theme = theme;
|
||||
emit themeChanged(theme);
|
||||
}
|
||||
|
||||
porymapConfig.setSaveDisabled(true);
|
||||
porymapConfig.setTextEditorOpenFolder(ui->lineEdit_TextEditorOpenFolder->text());
|
||||
porymapConfig.setTextEditorGotoLine(ui->lineEdit_TextEditorGotoLine->text());
|
||||
porymapConfig.setMonitorFiles(ui->checkBox_MonitorProjectFiles->isChecked());
|
||||
porymapConfig.setReopenOnLaunch(ui->checkBox_OpenRecentProject->isChecked());
|
||||
porymapConfig.setCheckForUpdates(ui->checkBox_CheckForUpdates->isChecked());
|
||||
porymapConfig.setSaveDisabled(false);
|
||||
porymapConfig.textEditorOpenFolder = ui->lineEdit_TextEditorOpenFolder->text();
|
||||
porymapConfig.textEditorGotoLine = ui->lineEdit_TextEditorGotoLine->text();
|
||||
porymapConfig.monitorFiles = ui->checkBox_MonitorProjectFiles->isChecked();
|
||||
porymapConfig.reopenOnLaunch = ui->checkBox_OpenRecentProject->isChecked();
|
||||
porymapConfig.checkForUpdates = ui->checkBox_CheckForUpdates->isChecked();
|
||||
porymapConfig.save();
|
||||
|
||||
emit preferencesSaved();
|
||||
|
|
|
@ -18,7 +18,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(QWidget *parent, Project *project)
|
|||
QMainWindow(parent),
|
||||
ui(new Ui::ProjectSettingsEditor),
|
||||
project(project),
|
||||
baseDir(userConfig.getProjectDir() + QDir::separator())
|
||||
baseDir(projectConfig.projectDir + QDir::separator())
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
@ -109,7 +109,7 @@ void ProjectSettingsEditor::initUi() {
|
|||
static const QRegularExpression expression_HexList(QString("^(%1,)*%1$").arg(regex_Hex)); // Comma-separated list of hex values
|
||||
QRegularExpressionValidator *validator_HexList = new QRegularExpressionValidator(expression_HexList);
|
||||
ui->lineEdit_BorderMetatiles->setValidator(validator_HexList);
|
||||
this->setBorderMetatilesUi(projectConfig.getUseCustomBorderSize());
|
||||
this->setBorderMetatilesUi(projectConfig.useCustomBorderSize);
|
||||
|
||||
// Validate that the text added to the warp behavior list could be a valid define
|
||||
// (we don't care whether it actually is a metatile behavior define)
|
||||
|
@ -184,12 +184,12 @@ void ProjectSettingsEditor::disableParsedSetting(QWidget * widget, const QString
|
|||
|
||||
// Remember the current settings tab for future sessions
|
||||
void ProjectSettingsEditor::on_mainTabs_tabBarClicked(int index) {
|
||||
porymapConfig.setProjectSettingsTab(index);
|
||||
porymapConfig.projectSettingsTab = index;
|
||||
}
|
||||
|
||||
void ProjectSettingsEditor::setTab(int index) {
|
||||
ui->mainTabs->setCurrentIndex(index);
|
||||
porymapConfig.setProjectSettingsTab(index);
|
||||
porymapConfig.projectSettingsTab = index;
|
||||
}
|
||||
|
||||
void ProjectSettingsEditor::setBorderMetatilesUi(bool customSize) {
|
||||
|
@ -424,10 +424,10 @@ void ProjectSettingsEditor::refresh() {
|
|||
this->refreshing = true; // Block signals
|
||||
|
||||
// Set combo box texts
|
||||
ui->comboBox_DefaultPrimaryTileset->setTextItem(projectConfig.getDefaultPrimaryTileset());
|
||||
ui->comboBox_DefaultSecondaryTileset->setTextItem(projectConfig.getDefaultSecondaryTileset());
|
||||
ui->comboBox_DefaultPrimaryTileset->setTextItem(projectConfig.defaultPrimaryTileset);
|
||||
ui->comboBox_DefaultSecondaryTileset->setTextItem(projectConfig.defaultSecondaryTileset);
|
||||
ui->comboBox_BaseGameVersion->setTextItem(projectConfig.getBaseGameVersionString());
|
||||
ui->comboBox_AttributesSize->setTextItem(QString::number(projectConfig.getMetatileAttributesSize()));
|
||||
ui->comboBox_AttributesSize->setTextItem(QString::number(projectConfig.metatileAttributesSize));
|
||||
this->updateAttributeLimits(ui->comboBox_AttributesSize->currentText());
|
||||
|
||||
this->prevIconSpecies = QString();
|
||||
|
@ -435,45 +435,44 @@ void ProjectSettingsEditor::refresh() {
|
|||
this->updatePokemonIconPath(ui->comboBox_IconSpecies->currentText());
|
||||
|
||||
// Set check box states
|
||||
ui->checkBox_UsePoryscript->setChecked(projectConfig.getUsePoryScript());
|
||||
ui->checkBox_ShowWildEncounterTables->setChecked(userConfig.getEncounterJsonActive());
|
||||
ui->checkBox_CreateTextFile->setChecked(projectConfig.getCreateMapTextFileEnabled());
|
||||
ui->checkBox_EnableTripleLayerMetatiles->setChecked(projectConfig.getTripleLayerMetatilesEnabled());
|
||||
ui->checkBox_EnableRequiresItemfinder->setChecked(projectConfig.getHiddenItemRequiresItemfinderEnabled());
|
||||
ui->checkBox_EnableQuantity->setChecked(projectConfig.getHiddenItemQuantityEnabled());
|
||||
ui->checkBox_EnableCloneObjects->setChecked(projectConfig.getEventCloneObjectEnabled());
|
||||
ui->checkBox_EnableWeatherTriggers->setChecked(projectConfig.getEventWeatherTriggerEnabled());
|
||||
ui->checkBox_EnableSecretBases->setChecked(projectConfig.getEventSecretBaseEnabled());
|
||||
ui->checkBox_EnableRespawn->setChecked(projectConfig.getHealLocationRespawnDataEnabled());
|
||||
ui->checkBox_EnableAllowFlags->setChecked(projectConfig.getMapAllowFlagsEnabled());
|
||||
ui->checkBox_EnableFloorNumber->setChecked(projectConfig.getFloorNumberEnabled());
|
||||
ui->checkBox_EnableCustomBorderSize->setChecked(projectConfig.getUseCustomBorderSize());
|
||||
ui->checkBox_OutputCallback->setChecked(projectConfig.getTilesetsHaveCallback());
|
||||
ui->checkBox_OutputIsCompressed->setChecked(projectConfig.getTilesetsHaveIsCompressed());
|
||||
ui->checkBox_DisableWarning->setChecked(porymapConfig.getWarpBehaviorWarningDisabled());
|
||||
ui->checkBox_UsePoryscript->setChecked(projectConfig.usePoryScript);
|
||||
ui->checkBox_ShowWildEncounterTables->setChecked(userConfig.useEncounterJson);
|
||||
ui->checkBox_CreateTextFile->setChecked(projectConfig.createMapTextFileEnabled);
|
||||
ui->checkBox_EnableTripleLayerMetatiles->setChecked(projectConfig.tripleLayerMetatilesEnabled);
|
||||
ui->checkBox_EnableRequiresItemfinder->setChecked(projectConfig.hiddenItemRequiresItemfinderEnabled);
|
||||
ui->checkBox_EnableQuantity->setChecked(projectConfig.hiddenItemQuantityEnabled);
|
||||
ui->checkBox_EnableCloneObjects->setChecked(projectConfig.eventCloneObjectEnabled);
|
||||
ui->checkBox_EnableWeatherTriggers->setChecked(projectConfig.eventWeatherTriggerEnabled);
|
||||
ui->checkBox_EnableSecretBases->setChecked(projectConfig.eventSecretBaseEnabled);
|
||||
ui->checkBox_EnableRespawn->setChecked(projectConfig.healLocationRespawnDataEnabled);
|
||||
ui->checkBox_EnableAllowFlags->setChecked(projectConfig.mapAllowFlagsEnabled);
|
||||
ui->checkBox_EnableFloorNumber->setChecked(projectConfig.floorNumberEnabled);
|
||||
ui->checkBox_EnableCustomBorderSize->setChecked(projectConfig.useCustomBorderSize);
|
||||
ui->checkBox_OutputCallback->setChecked(projectConfig.tilesetsHaveCallback);
|
||||
ui->checkBox_OutputIsCompressed->setChecked(projectConfig.tilesetsHaveIsCompressed);
|
||||
ui->checkBox_DisableWarning->setChecked(porymapConfig.warpBehaviorWarningDisabled);
|
||||
|
||||
// Set spin box values
|
||||
ui->spinBox_Elevation->setValue(projectConfig.getDefaultElevation());
|
||||
ui->spinBox_Collision->setValue(projectConfig.getDefaultCollision());
|
||||
ui->spinBox_FillMetatile->setValue(projectConfig.getDefaultMetatileId());
|
||||
ui->spinBox_MaxElevation->setValue(projectConfig.getCollisionSheetHeight() - 1);
|
||||
ui->spinBox_MaxCollision->setValue(projectConfig.getCollisionSheetWidth() - 1);
|
||||
ui->spinBox_BehaviorMask->setValue(projectConfig.getMetatileBehaviorMask() & ui->spinBox_BehaviorMask->maximum());
|
||||
ui->spinBox_EncounterTypeMask->setValue(projectConfig.getMetatileEncounterTypeMask() & ui->spinBox_EncounterTypeMask->maximum());
|
||||
ui->spinBox_LayerTypeMask->setValue(projectConfig.getMetatileLayerTypeMask() & ui->spinBox_LayerTypeMask->maximum());
|
||||
ui->spinBox_TerrainTypeMask->setValue(projectConfig.getMetatileTerrainTypeMask() & ui->spinBox_TerrainTypeMask->maximum());
|
||||
ui->spinBox_MetatileIdMask->setValue(projectConfig.getBlockMetatileIdMask() & ui->spinBox_MetatileIdMask->maximum());
|
||||
ui->spinBox_CollisionMask->setValue(projectConfig.getBlockCollisionMask() & ui->spinBox_CollisionMask->maximum());
|
||||
ui->spinBox_ElevationMask->setValue(projectConfig.getBlockElevationMask() & ui->spinBox_ElevationMask->maximum());
|
||||
ui->spinBox_Elevation->setValue(projectConfig.defaultElevation);
|
||||
ui->spinBox_Collision->setValue(projectConfig.defaultCollision);
|
||||
ui->spinBox_FillMetatile->setValue(projectConfig.defaultMetatileId);
|
||||
ui->spinBox_MaxElevation->setValue(projectConfig.collisionSheetHeight - 1);
|
||||
ui->spinBox_MaxCollision->setValue(projectConfig.collisionSheetWidth - 1);
|
||||
ui->spinBox_BehaviorMask->setValue(projectConfig.metatileBehaviorMask & ui->spinBox_BehaviorMask->maximum());
|
||||
ui->spinBox_EncounterTypeMask->setValue(projectConfig.metatileEncounterTypeMask & ui->spinBox_EncounterTypeMask->maximum());
|
||||
ui->spinBox_LayerTypeMask->setValue(projectConfig.metatileLayerTypeMask & ui->spinBox_LayerTypeMask->maximum());
|
||||
ui->spinBox_TerrainTypeMask->setValue(projectConfig.metatileTerrainTypeMask & ui->spinBox_TerrainTypeMask->maximum());
|
||||
ui->spinBox_MetatileIdMask->setValue(projectConfig.blockMetatileIdMask & ui->spinBox_MetatileIdMask->maximum());
|
||||
ui->spinBox_CollisionMask->setValue(projectConfig.blockCollisionMask & ui->spinBox_CollisionMask->maximum());
|
||||
ui->spinBox_ElevationMask->setValue(projectConfig.blockElevationMask & ui->spinBox_ElevationMask->maximum());
|
||||
|
||||
// Set (and sync) border metatile IDs
|
||||
auto metatileIds = projectConfig.getNewMapBorderMetatileIds();
|
||||
this->setBorderMetatileIds(false, metatileIds);
|
||||
this->setBorderMetatileIds(true, metatileIds);
|
||||
this->setBorderMetatileIds(false, projectConfig.newMapBorderMetatileIds);
|
||||
this->setBorderMetatileIds(true, projectConfig.newMapBorderMetatileIds);
|
||||
|
||||
// Set line edit texts
|
||||
ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath());
|
||||
ui->lineEdit_CollisionGraphics->setText(projectConfig.getCollisionSheetPath());
|
||||
ui->lineEdit_PrefabsPath->setText(projectConfig.prefabFilepath);
|
||||
ui->lineEdit_CollisionGraphics->setText(projectConfig.collisionSheetPath);
|
||||
ui->lineEdit_ObjectsIcon->setText(projectConfig.getEventIconPath(Event::Group::Object));
|
||||
ui->lineEdit_WarpsIcon->setText(projectConfig.getEventIconPath(Event::Group::Warp));
|
||||
ui->lineEdit_TriggersIcon->setText(projectConfig.getEventIconPath(Event::Group::Coord));
|
||||
|
@ -485,9 +484,8 @@ void ProjectSettingsEditor::refresh() {
|
|||
lineEdit->setText(projectConfig.getCustomIdentifier(lineEdit->objectName()));
|
||||
|
||||
// Set warp behaviors
|
||||
auto behaviorValues = projectConfig.getWarpBehaviors();
|
||||
QStringList behaviorNames;
|
||||
for (auto value : behaviorValues) {
|
||||
for (auto value : projectConfig.warpBehaviors) {
|
||||
if (project->metatileBehaviorMapInverse.contains(value))
|
||||
behaviorNames.append(project->metatileBehaviorMapInverse.value(value));
|
||||
}
|
||||
|
@ -500,50 +498,47 @@ void ProjectSettingsEditor::save() {
|
|||
if (!this->hasUnsavedChanges)
|
||||
return;
|
||||
|
||||
// Prevent a call to save() for each of the config settings
|
||||
projectConfig.setSaveDisabled(true);
|
||||
|
||||
// Save combo box settings
|
||||
projectConfig.setDefaultPrimaryTileset(ui->comboBox_DefaultPrimaryTileset->currentText());
|
||||
projectConfig.setDefaultSecondaryTileset(ui->comboBox_DefaultSecondaryTileset->currentText());
|
||||
projectConfig.setBaseGameVersion(projectConfig.stringToBaseGameVersion(ui->comboBox_BaseGameVersion->currentText()));
|
||||
projectConfig.setMetatileAttributesSize(ui->comboBox_AttributesSize->currentText().toInt());
|
||||
projectConfig.defaultPrimaryTileset = ui->comboBox_DefaultPrimaryTileset->currentText();
|
||||
projectConfig.defaultSecondaryTileset = ui->comboBox_DefaultSecondaryTileset->currentText();
|
||||
projectConfig.baseGameVersion = projectConfig.stringToBaseGameVersion(ui->comboBox_BaseGameVersion->currentText());
|
||||
projectConfig.metatileAttributesSize = ui->comboBox_AttributesSize->currentText().toInt();
|
||||
|
||||
// Save check box settings
|
||||
projectConfig.setUsePoryScript(ui->checkBox_UsePoryscript->isChecked());
|
||||
userConfig.setEncounterJsonActive(ui->checkBox_ShowWildEncounterTables->isChecked());
|
||||
projectConfig.setCreateMapTextFileEnabled(ui->checkBox_CreateTextFile->isChecked());
|
||||
projectConfig.setTripleLayerMetatilesEnabled(ui->checkBox_EnableTripleLayerMetatiles->isChecked());
|
||||
projectConfig.setHiddenItemRequiresItemfinderEnabled(ui->checkBox_EnableRequiresItemfinder->isChecked());
|
||||
projectConfig.setHiddenItemQuantityEnabled(ui->checkBox_EnableQuantity->isChecked());
|
||||
projectConfig.setEventCloneObjectEnabled(ui->checkBox_EnableCloneObjects->isChecked());
|
||||
projectConfig.setEventWeatherTriggerEnabled(ui->checkBox_EnableWeatherTriggers->isChecked());
|
||||
projectConfig.setEventSecretBaseEnabled(ui->checkBox_EnableSecretBases->isChecked());
|
||||
projectConfig.setHealLocationRespawnDataEnabled(ui->checkBox_EnableRespawn->isChecked());
|
||||
projectConfig.setMapAllowFlagsEnabled(ui->checkBox_EnableAllowFlags->isChecked());
|
||||
projectConfig.setFloorNumberEnabled(ui->checkBox_EnableFloorNumber->isChecked());
|
||||
projectConfig.setUseCustomBorderSize(ui->checkBox_EnableCustomBorderSize->isChecked());
|
||||
projectConfig.setTilesetsHaveCallback(ui->checkBox_OutputCallback->isChecked());
|
||||
projectConfig.setTilesetsHaveIsCompressed(ui->checkBox_OutputIsCompressed->isChecked());
|
||||
porymapConfig.setWarpBehaviorWarningDisabled(ui->checkBox_DisableWarning->isChecked());
|
||||
projectConfig.usePoryScript = ui->checkBox_UsePoryscript->isChecked();
|
||||
userConfig.useEncounterJson = ui->checkBox_ShowWildEncounterTables->isChecked();
|
||||
projectConfig.createMapTextFileEnabled = ui->checkBox_CreateTextFile->isChecked();
|
||||
projectConfig.tripleLayerMetatilesEnabled = ui->checkBox_EnableTripleLayerMetatiles->isChecked();
|
||||
projectConfig.hiddenItemRequiresItemfinderEnabled = ui->checkBox_EnableRequiresItemfinder->isChecked();
|
||||
projectConfig.hiddenItemQuantityEnabled = ui->checkBox_EnableQuantity->isChecked();
|
||||
projectConfig.eventCloneObjectEnabled = ui->checkBox_EnableCloneObjects->isChecked();
|
||||
projectConfig.eventWeatherTriggerEnabled = ui->checkBox_EnableWeatherTriggers->isChecked();
|
||||
projectConfig.eventSecretBaseEnabled = ui->checkBox_EnableSecretBases->isChecked();
|
||||
projectConfig.healLocationRespawnDataEnabled = ui->checkBox_EnableRespawn->isChecked();
|
||||
projectConfig.mapAllowFlagsEnabled = ui->checkBox_EnableAllowFlags->isChecked();
|
||||
projectConfig.floorNumberEnabled = ui->checkBox_EnableFloorNumber->isChecked();
|
||||
projectConfig.useCustomBorderSize = ui->checkBox_EnableCustomBorderSize->isChecked();
|
||||
projectConfig.tilesetsHaveCallback = ui->checkBox_OutputCallback->isChecked();
|
||||
projectConfig.tilesetsHaveIsCompressed = ui->checkBox_OutputIsCompressed->isChecked();
|
||||
porymapConfig.warpBehaviorWarningDisabled = ui->checkBox_DisableWarning->isChecked();
|
||||
|
||||
// Save spin box settings
|
||||
projectConfig.setDefaultElevation(ui->spinBox_Elevation->value());
|
||||
projectConfig.setDefaultCollision(ui->spinBox_Collision->value());
|
||||
projectConfig.setDefaultMetatileId(ui->spinBox_FillMetatile->value());
|
||||
projectConfig.setCollisionSheetHeight(ui->spinBox_MaxElevation->value() + 1);
|
||||
projectConfig.setCollisionSheetWidth(ui->spinBox_MaxCollision->value() + 1);
|
||||
projectConfig.setMetatileBehaviorMask(ui->spinBox_BehaviorMask->value());
|
||||
projectConfig.setMetatileTerrainTypeMask(ui->spinBox_TerrainTypeMask->value());
|
||||
projectConfig.setMetatileEncounterTypeMask(ui->spinBox_EncounterTypeMask->value());
|
||||
projectConfig.setMetatileLayerTypeMask(ui->spinBox_LayerTypeMask->value());
|
||||
projectConfig.setBlockMetatileIdMask(ui->spinBox_MetatileIdMask->value());
|
||||
projectConfig.setBlockCollisionMask(ui->spinBox_CollisionMask->value());
|
||||
projectConfig.setBlockElevationMask(ui->spinBox_ElevationMask->value());
|
||||
projectConfig.defaultElevation = ui->spinBox_Elevation->value();
|
||||
projectConfig.defaultCollision = ui->spinBox_Collision->value();
|
||||
projectConfig.defaultMetatileId = ui->spinBox_FillMetatile->value();
|
||||
projectConfig.collisionSheetHeight = ui->spinBox_MaxElevation->value() + 1;
|
||||
projectConfig.collisionSheetWidth = ui->spinBox_MaxCollision->value() + 1;
|
||||
projectConfig.metatileBehaviorMask = ui->spinBox_BehaviorMask->value();
|
||||
projectConfig.metatileTerrainTypeMask = ui->spinBox_TerrainTypeMask->value();
|
||||
projectConfig.metatileEncounterTypeMask = ui->spinBox_EncounterTypeMask->value();
|
||||
projectConfig.metatileLayerTypeMask = ui->spinBox_LayerTypeMask->value();
|
||||
projectConfig.blockMetatileIdMask = ui->spinBox_MetatileIdMask->value();
|
||||
projectConfig.blockCollisionMask = ui->spinBox_CollisionMask->value();
|
||||
projectConfig.blockElevationMask = ui->spinBox_ElevationMask->value();
|
||||
|
||||
// Save line edit settings
|
||||
projectConfig.setPrefabFilepath(ui->lineEdit_PrefabsPath->text());
|
||||
projectConfig.setCollisionSheetPath(ui->lineEdit_CollisionGraphics->text());
|
||||
projectConfig.prefabFilepath = ui->lineEdit_PrefabsPath->text();
|
||||
projectConfig.collisionSheetPath = ui->lineEdit_CollisionGraphics->text();
|
||||
projectConfig.setEventIconPath(Event::Group::Object, ui->lineEdit_ObjectsIcon->text());
|
||||
projectConfig.setEventIconPath(Event::Group::Warp, ui->lineEdit_WarpsIcon->text());
|
||||
projectConfig.setEventIconPath(Event::Group::Coord, ui->lineEdit_TriggersIcon->text());
|
||||
|
@ -555,14 +550,13 @@ void ProjectSettingsEditor::save() {
|
|||
projectConfig.setIdentifier(lineEdit->objectName(), lineEdit->text());
|
||||
|
||||
// Save warp behaviors
|
||||
projectConfig.warpBehaviors.clear();
|
||||
QStringList behaviorNames = this->getWarpBehaviorsList();
|
||||
QSet<uint32_t> behaviorValues;
|
||||
for (auto name : behaviorNames)
|
||||
behaviorValues.insert(project->metatileBehaviorMap.value(name));
|
||||
projectConfig.setWarpBehaviors(behaviorValues);
|
||||
projectConfig.warpBehaviors.insert(project->metatileBehaviorMap.value(name));
|
||||
|
||||
// Save border metatile IDs
|
||||
projectConfig.setNewMapBorderMetatileIds(this->getBorderMetatileIds(ui->checkBox_EnableCustomBorderSize->isChecked()));
|
||||
projectConfig.newMapBorderMetatileIds = this->getBorderMetatileIds(ui->checkBox_EnableCustomBorderSize->isChecked());
|
||||
|
||||
// Save pokemon icon paths
|
||||
const QString species = ui->comboBox_IconSpecies->currentText();
|
||||
|
@ -571,8 +565,10 @@ void ProjectSettingsEditor::save() {
|
|||
for (auto i = this->editedPokemonIconPaths.cbegin(), end = this->editedPokemonIconPaths.cend(); i != end; i++)
|
||||
projectConfig.setPokemonIconPath(i.key(), i.value());
|
||||
|
||||
projectConfig.setSaveDisabled(false);
|
||||
projectConfig.save();
|
||||
userConfig.save();
|
||||
porymapConfig.save();
|
||||
|
||||
this->hasUnsavedChanges = false;
|
||||
|
||||
// Technically, a reload is not required for several of the config settings.
|
||||
|
@ -611,7 +607,7 @@ void ProjectSettingsEditor::importDefaultPrefabsClicked(bool) {
|
|||
// If the prompt is accepted the prefabs file will be created and its filepath will be saved in the config.
|
||||
BaseGameVersion version = projectConfig.stringToBaseGameVersion(ui->comboBox_BaseGameVersion->currentText());
|
||||
if (prefab.tryImportDefaultPrefabs(this, version, ui->lineEdit_PrefabsPath->text())) {
|
||||
ui->lineEdit_PrefabsPath->setText(projectConfig.getPrefabFilepath()); // Refresh with new filepath
|
||||
ui->lineEdit_PrefabsPath->setText(projectConfig.prefabFilepath); // Refresh with new filepath
|
||||
this->hasUnsavedChanges = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ RegionMapEditor::RegionMapEditor(QWidget *parent, Project *project) :
|
|||
QMainWindow(parent),
|
||||
ui(new Ui::RegionMapEditor)
|
||||
{
|
||||
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||
this->ui->setupUi(this);
|
||||
this->project = project;
|
||||
this->configFilepath = QString("%1/%2").arg(this->project->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_porymap_cfg));
|
||||
|
@ -201,18 +202,18 @@ void buildFireredDefaults(poryjson::Json &json) {
|
|||
|
||||
poryjson::Json RegionMapEditor::buildDefaultJson() {
|
||||
poryjson::Json defaultJson;
|
||||
switch (projectConfig.getBaseGameVersion()) {
|
||||
switch (projectConfig.baseGameVersion) {
|
||||
case BaseGameVersion::pokeemerald:
|
||||
buildEmeraldDefaults(defaultJson);
|
||||
break;
|
||||
|
||||
case BaseGameVersion::pokeruby:
|
||||
buildRubyDefaults(defaultJson);
|
||||
break;
|
||||
|
||||
case BaseGameVersion::pokefirered:
|
||||
buildFireredDefaults(defaultJson);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return defaultJson;
|
||||
|
@ -314,7 +315,7 @@ bool RegionMapEditor::buildConfigDialog() {
|
|||
QPushButton *delMapButton = new QPushButton("Delete Selected Region Map");
|
||||
form.addRow(delMapButton);
|
||||
|
||||
connect(delMapButton, &QPushButton::clicked, [this, regionMapList, &updateJsonFromList] {
|
||||
connect(delMapButton, &QPushButton::clicked, [regionMapList, &updateJsonFromList] {
|
||||
QListWidgetItem *item = regionMapList->currentItem();
|
||||
if (item) {
|
||||
regionMapList->removeItemWidget(item);
|
||||
|
@ -343,8 +344,8 @@ bool RegionMapEditor::buildConfigDialog() {
|
|||
|
||||
|
||||
// for sake of convenience, option to just use defaults for each basegame version
|
||||
QPushButton *config_useProjectDefault;
|
||||
switch (projectConfig.getBaseGameVersion()) {
|
||||
QPushButton *config_useProjectDefault = nullptr;
|
||||
switch (projectConfig.baseGameVersion) {
|
||||
case BaseGameVersion::pokefirered:
|
||||
config_useProjectDefault = new QPushButton("\nUse pokefirered defaults\n");
|
||||
break;
|
||||
|
|
|
@ -53,6 +53,7 @@ void ShortcutsEditor::saveShortcuts() {
|
|||
}
|
||||
|
||||
shortcutsConfig.setUserShortcuts(objects_keySequences);
|
||||
shortcutsConfig.save();
|
||||
emit shortcutsSaved();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ TilesetEditor::TilesetEditor(Project *project, Map *map, QWidget *parent) :
|
|||
map(map),
|
||||
hasUnsavedChanges(false)
|
||||
{
|
||||
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||
this->setTilesets(this->map->layout->tileset_primary_label, this->map->layout->tileset_secondary_label);
|
||||
this->initUi();
|
||||
}
|
||||
|
@ -113,7 +114,7 @@ void TilesetEditor::initUi() {
|
|||
|
||||
void TilesetEditor::setAttributesUi() {
|
||||
// Behavior
|
||||
if (projectConfig.getMetatileBehaviorMask()) {
|
||||
if (projectConfig.metatileBehaviorMask) {
|
||||
for (int num : project->metatileBehaviorMapInverse.keys()) {
|
||||
this->ui->comboBox_metatileBehaviors->addItem(project->metatileBehaviorMapInverse[num], num);
|
||||
}
|
||||
|
@ -124,7 +125,7 @@ void TilesetEditor::setAttributesUi() {
|
|||
}
|
||||
|
||||
// Terrain Type
|
||||
if (projectConfig.getMetatileTerrainTypeMask()) {
|
||||
if (projectConfig.metatileTerrainTypeMask) {
|
||||
this->ui->comboBox_terrainType->addItem("Normal", TERRAIN_NONE);
|
||||
this->ui->comboBox_terrainType->addItem("Grass", TERRAIN_GRASS);
|
||||
this->ui->comboBox_terrainType->addItem("Water", TERRAIN_WATER);
|
||||
|
@ -137,7 +138,7 @@ void TilesetEditor::setAttributesUi() {
|
|||
}
|
||||
|
||||
// Encounter Type
|
||||
if (projectConfig.getMetatileEncounterTypeMask()) {
|
||||
if (projectConfig.metatileEncounterTypeMask) {
|
||||
this->ui->comboBox_encounterType->addItem("None", ENCOUNTER_NONE);
|
||||
this->ui->comboBox_encounterType->addItem("Land", ENCOUNTER_LAND);
|
||||
this->ui->comboBox_encounterType->addItem("Water", ENCOUNTER_WATER);
|
||||
|
@ -149,13 +150,13 @@ void TilesetEditor::setAttributesUi() {
|
|||
}
|
||||
|
||||
// Layer Type
|
||||
if (!projectConfig.getTripleLayerMetatilesEnabled()) {
|
||||
if (!projectConfig.tripleLayerMetatilesEnabled) {
|
||||
this->ui->comboBox_layerType->addItem("Normal - Middle/Top", METATILE_LAYER_MIDDLE_TOP);
|
||||
this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", METATILE_LAYER_BOTTOM_MIDDLE);
|
||||
this->ui->comboBox_layerType->addItem("Split - Bottom/Top", METATILE_LAYER_BOTTOM_TOP);
|
||||
this->ui->comboBox_layerType->setEditable(false);
|
||||
this->ui->comboBox_layerType->setMinimumContentsLength(0);
|
||||
if (!projectConfig.getMetatileLayerTypeMask()) {
|
||||
if (!projectConfig.metatileLayerTypeMask) {
|
||||
// User doesn't have triple layer metatiles, but has no layer type attribute.
|
||||
// Porymap is still using the layer type value to render metatiles, and with
|
||||
// no mask set every metatile will be "Middle/Top", so just display the combo
|
||||
|
@ -187,7 +188,7 @@ void TilesetEditor::initMetatileSelector()
|
|||
connect(this->metatileSelector, &TilesetEditorMetatileSelector::selectedMetatileChanged,
|
||||
this, &TilesetEditor::onSelectedMetatileChanged);
|
||||
|
||||
bool showGrid = porymapConfig.getShowTilesetEditorMetatileGrid();
|
||||
bool showGrid = porymapConfig.showTilesetEditorMetatileGrid;
|
||||
this->ui->actionMetatile_Grid->setChecked(showGrid);
|
||||
this->metatileSelector->showGrid = showGrid;
|
||||
|
||||
|
@ -197,7 +198,7 @@ void TilesetEditor::initMetatileSelector()
|
|||
|
||||
this->ui->graphicsView_Metatiles->setScene(this->metatilesScene);
|
||||
this->ui->graphicsView_Metatiles->setResizeAnchor(QGraphicsView::AnchorViewCenter);
|
||||
this->ui->horizontalSlider_MetatilesZoom->setValue(porymapConfig.getTilesetEditorMetatilesZoom());
|
||||
this->ui->horizontalSlider_MetatilesZoom->setValue(porymapConfig.tilesetEditorMetatilesZoom);
|
||||
}
|
||||
|
||||
void TilesetEditor::initMetatileLayersItem() {
|
||||
|
@ -212,7 +213,7 @@ void TilesetEditor::initMetatileLayersItem() {
|
|||
connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileCleared,
|
||||
this, &TilesetEditor::onHoveredTileCleared);
|
||||
|
||||
bool showGrid = porymapConfig.getShowTilesetEditorLayerGrid();
|
||||
bool showGrid = porymapConfig.showTilesetEditorLayerGrid;
|
||||
this->ui->actionLayer_Grid->setChecked(showGrid);
|
||||
this->metatileLayersItem->showGrid = showGrid;
|
||||
|
||||
|
@ -238,7 +239,7 @@ void TilesetEditor::initTileSelector()
|
|||
|
||||
this->ui->graphicsView_Tiles->setScene(this->tilesScene);
|
||||
this->ui->graphicsView_Tiles->setResizeAnchor(QGraphicsView::AnchorViewCenter);
|
||||
this->ui->horizontalSlider_TilesZoom->setValue(porymapConfig.getTilesetEditorTilesZoom());
|
||||
this->ui->horizontalSlider_TilesZoom->setValue(porymapConfig.tilesetEditorTilesZoom);
|
||||
}
|
||||
|
||||
void TilesetEditor::initSelectedTileItem() {
|
||||
|
@ -1069,13 +1070,13 @@ void TilesetEditor::on_actionShow_UnusedTiles_toggled(bool checked) {
|
|||
void TilesetEditor::on_actionMetatile_Grid_triggered(bool checked) {
|
||||
this->metatileSelector->showGrid = checked;
|
||||
this->metatileSelector->draw();
|
||||
porymapConfig.setShowTilesetEditorMetatileGrid(checked);
|
||||
porymapConfig.showTilesetEditorMetatileGrid = checked;
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionLayer_Grid_triggered(bool checked) {
|
||||
this->metatileLayersItem->showGrid = checked;
|
||||
this->metatileLayersItem->draw();
|
||||
porymapConfig.setShowTilesetEditorLayerGrid(checked);
|
||||
porymapConfig.showTilesetEditorLayerGrid = checked;
|
||||
}
|
||||
|
||||
void TilesetEditor::countMetatileUsage() {
|
||||
|
@ -1187,7 +1188,7 @@ void TilesetEditor::on_copyButton_metatileLabel_clicked() {
|
|||
}
|
||||
|
||||
void TilesetEditor::on_horizontalSlider_MetatilesZoom_valueChanged(int value) {
|
||||
porymapConfig.setTilesetEditorMetatilesZoom(value);
|
||||
porymapConfig.tilesetEditorMetatilesZoom = value;
|
||||
this->redrawMetatileSelector();
|
||||
}
|
||||
|
||||
|
@ -1195,7 +1196,7 @@ void TilesetEditor::redrawMetatileSelector() {
|
|||
QSize size(this->metatileSelector->pixmap().width(), this->metatileSelector->pixmap().height());
|
||||
this->ui->graphicsView_Metatiles->setSceneRect(0, 0, size.width(), size.height());
|
||||
|
||||
double scale = pow(3.0, static_cast<double>(porymapConfig.getTilesetEditorMetatilesZoom() - 30) / 30.0);
|
||||
double scale = pow(3.0, static_cast<double>(porymapConfig.tilesetEditorMetatilesZoom - 30) / 30.0);
|
||||
QTransform transform;
|
||||
transform.scale(scale, scale);
|
||||
size *= scale;
|
||||
|
@ -1212,7 +1213,7 @@ void TilesetEditor::redrawMetatileSelector() {
|
|||
}
|
||||
|
||||
void TilesetEditor::on_horizontalSlider_TilesZoom_valueChanged(int value) {
|
||||
porymapConfig.setTilesetEditorTilesZoom(value);
|
||||
porymapConfig.tilesetEditorTilesZoom = value;
|
||||
this->redrawTileSelector();
|
||||
}
|
||||
|
||||
|
@ -1220,7 +1221,7 @@ void TilesetEditor::redrawTileSelector() {
|
|||
QSize size(this->tileSelector->pixmap().width(), this->tileSelector->pixmap().height());
|
||||
this->ui->graphicsView_Tiles->setSceneRect(0, 0, size.width(), size.height());
|
||||
|
||||
double scale = pow(3.0, static_cast<double>(porymapConfig.getTilesetEditorTilesZoom() - 30) / 30.0);
|
||||
double scale = pow(3.0, static_cast<double>(porymapConfig.tilesetEditorTilesZoom - 30) / 30.0);
|
||||
QTransform transform;
|
||||
transform.scale(scale, scale);
|
||||
size *= scale;
|
||||
|
|
|
@ -20,8 +20,7 @@ UpdatePromoter::UpdatePromoter(QWidget *parent, NetworkAccessManager *manager)
|
|||
this->updatePreferences();
|
||||
ui->checkBox_StopAlerts->setVisible(false);
|
||||
connect(ui->checkBox_StopAlerts, &QCheckBox::stateChanged, [this](int state) {
|
||||
bool enable = (state != Qt::Checked);
|
||||
porymapConfig.setCheckForUpdates(enable);
|
||||
porymapConfig.checkForUpdates = (state != Qt::Checked);
|
||||
emit this->changedPreferences();
|
||||
});
|
||||
|
||||
|
@ -141,11 +140,11 @@ void UpdatePromoter::processWebpage(const QJsonDocument &data, const QUrl &nextU
|
|||
// Alert the user about the new version if the dialog wasn't already open.
|
||||
// Show the window, but also show the option to turn off automatic alerts in the future.
|
||||
// We only show this alert once for a given release.
|
||||
if (!this->isVisible() && this->newVersion > porymapConfig.getLastUpdateCheckVersion()) {
|
||||
if (!this->isVisible() && this->newVersion > porymapConfig.lastUpdateCheckVersion) {
|
||||
ui->checkBox_StopAlerts->setVisible(true);
|
||||
this->show();
|
||||
}
|
||||
porymapConfig.setLastUpdateCheckVersion(this->newVersion);
|
||||
porymapConfig.lastUpdateCheckVersion = this->newVersion;
|
||||
} else {
|
||||
ui->label_Status->setText("Your version of Porymap is up to date!");
|
||||
ui->label_Warning->setVisible(false);
|
||||
|
@ -173,7 +172,7 @@ void UpdatePromoter::error(const QString &err, const QDateTime retryAfter) {
|
|||
|
||||
void UpdatePromoter::updatePreferences() {
|
||||
const QSignalBlocker blocker(ui->checkBox_StopAlerts);
|
||||
ui->checkBox_StopAlerts->setChecked(!porymapConfig.getCheckForUpdates());
|
||||
ui->checkBox_StopAlerts->setChecked(!porymapConfig.checkForUpdates);
|
||||
}
|
||||
|
||||
void UpdatePromoter::dialogButtonClicked(QAbstractButton *button) {
|
||||
|
|
Loading…
Reference in a new issue