Merge pull request #543 from GriffinRichards/options

Add Project Settings Editor
This commit is contained in:
GriffinR
2023-09-25 10:45:16 -04:00
committed by GitHub
49 changed files with 3034 additions and 442 deletions

View File

@@ -10,8 +10,8 @@
#include <QMultiMap>
// In both versions the default new map border is a generic tree
#define DEFAULT_BORDER_RSE (QList<int>{468, 469, 476, 477})
#define DEFAULT_BORDER_FRLG (QList<int>{20, 21, 28, 29})
#define DEFAULT_BORDER_RSE (QList<uint16_t>{0x1D4, 0x1D5, 0x1DC, 0x1DD})
#define DEFAULT_BORDER_FRLG (QList<uint16_t>{0x14, 0x15, 0x1C, 0x1D})
#define CONFIG_BACKWARDS_COMPATABILITY
@@ -26,6 +26,7 @@ class KeyValueConfigBase
public:
void save();
void load();
void setSaveDisabled(bool disabled);
virtual ~KeyValueConfigBase();
virtual void reset() = 0;
protected:
@@ -37,6 +38,8 @@ protected:
bool getConfigBool(QString key, QString value);
int getConfigInteger(QString key, QString value, int min, int max, int defaultValue);
uint32_t getConfigUint32(QString key, QString value, uint32_t min, uint32_t max, uint32_t defaultValue);
private:
bool saveDisabled = false;
};
class PorymapConfig: public KeyValueConfigBase
@@ -70,6 +73,8 @@ public:
void setTilesetEditorGeometry(QByteArray, QByteArray);
void setPaletteEditorGeometry(QByteArray, QByteArray);
void setRegionMapEditorGeometry(QByteArray, QByteArray);
void setProjectSettingsEditorGeometry(QByteArray, QByteArray);
void setCustomScriptsEditorGeometry(QByteArray, QByteArray);
void setCollisionOpacity(int opacity);
void setMetatilesZoom(int zoom);
void setShowPlayerView(bool enabled);
@@ -90,6 +95,8 @@ public:
QMap<QString, QByteArray> getTilesetEditorGeometry();
QMap<QString, QByteArray> getPaletteEditorGeometry();
QMap<QString, QByteArray> getRegionMapEditorGeometry();
QMap<QString, QByteArray> getProjectSettingsEditorGeometry();
QMap<QString, QByteArray> getCustomScriptsEditorGeometry();
int getCollisionOpacity();
int getMetatilesZoom();
bool getShowPlayerView();
@@ -126,6 +133,10 @@ private:
QByteArray paletteEditorState;
QByteArray regionMapEditorGeometry;
QByteArray regionMapEditorState;
QByteArray projectSettingsEditorGeometry;
QByteArray projectSettingsEditorState;
QByteArray customScriptsEditorGeometry;
QByteArray customScriptsEditorState;
int collisionOpacity;
int metatilesZoom;
bool showPlayerView;
@@ -203,20 +214,11 @@ public:
}
virtual void reset() override {
this->baseGameVersion = BaseGameVersion::pokeemerald;
this->useCustomBorderSize = false;
this->enableEventWeatherTrigger = true;
this->enableEventSecretBase = true;
this->enableHiddenItemQuantity = false;
this->enableHiddenItemRequiresItemfinder = false;
this->enableHealLocationRespawnData = false;
this->enableEventCloneObject = false;
this->enableFloorNumber = false;
this->createMapTextFile = false;
// Reset non-version-specific settings
this->usePoryScript = false;
this->enableTripleLayerMetatiles = false;
this->newMapMetatileId = 1;
this->newMapElevation = 3;
this->newMapBorderMetatileIds = DEFAULT_BORDER_RSE;
this->defaultPrimaryTileset = "gTileset_General";
this->prefabFilepath = QString();
this->prefabImportPrompted = false;
@@ -225,9 +227,14 @@ public:
this->filePaths.clear();
this->readKeys.clear();
}
static const QMap<ProjectFilePath, std::pair<QString, QString>> defaultPaths;
static const QStringList versionStrings;
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);
@@ -254,18 +261,22 @@ public:
bool getTripleLayerMetatilesEnabled();
int getNumLayersInMetatile();
int getNumTilesInMetatile();
void setNewMapMetatileId(int metatileId);
int getNewMapMetatileId();
void setNewMapMetatileId(uint16_t metatileId);
uint16_t getNewMapMetatileId();
void setNewMapElevation(int elevation);
int getNewMapElevation();
void setNewMapBorderMetatileIds(QList<int> metatileIds);
QList<int> getNewMapBorderMetatileIds();
void setNewMapBorderMetatileIds(QList<uint16_t> metatileIds);
QList<uint16_t> getNewMapBorderMetatileIds();
QString getDefaultPrimaryTileset();
QString getDefaultSecondaryTileset();
void setDefaultPrimaryTileset(QString tilesetName);
void setDefaultSecondaryTileset(QString tilesetName);
void setFilePath(QString pathId, QString path);
void setFilePath(ProjectFilePath pathId, QString path);
QString getFilePath(ProjectFilePath pathId);
QString getFilePath(QString defaultPath, bool customOnly = false);
QString getFilePath(ProjectFilePath pathId, bool customOnly = false);
void setPrefabFilepath(QString filepath);
QString getPrefabFilepath(bool setIfEmpty);
QString getPrefabFilepath();
void setPrefabImportPrompted(bool prompted);
bool getPrefabImportPrompted();
void setTilesetsHaveCallback(bool has);
@@ -273,11 +284,17 @@ public:
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);
bool getMapAllowFlagsEnabled();
void setMapAllowFlagsEnabled(bool enabled);
protected:
virtual QString getConfigFilepath() override;
virtual void parseConfigKeyValue(QString key, QString value) override;
@@ -299,9 +316,9 @@ private:
bool enableFloorNumber;
bool createMapTextFile;
bool enableTripleLayerMetatiles;
int newMapMetatileId;
uint16_t newMapMetatileId;
int newMapElevation;
QList<int> newMapBorderMetatileIds;
QList<uint16_t> newMapBorderMetatileIds;
QString defaultPrimaryTileset;
QString defaultSecondaryTileset;
QStringList readKeys;
@@ -337,8 +354,11 @@ public:
bool getEncounterJsonActive();
void setProjectDir(QString projectDir);
QString getProjectDir();
void setCustomScripts(QList<QString> scripts);
QList<QString> getCustomScripts();
void setCustomScripts(QStringList scripts, QList<bool> enabled);
QStringList getCustomScriptPaths();
QList<bool> getCustomScriptsEnabled();
void parseCustomScripts(QString input);
QString outputCustomScripts();
protected:
virtual QString getConfigFilepath() override;
virtual void parseConfigKeyValue(QString key, QString value) override;
@@ -352,7 +372,7 @@ private:
QString projectDir;
QString recentMap;
bool useEncounterJson;
QList<QString> customScripts;
QMap<QString, bool> customScripts;
QStringList readKeys;
};

View File

@@ -93,6 +93,15 @@ public:
static QPoint coordFromPixmapCoord(const QPointF &pixelCoord);
static int getDefaultAttributesSize(BaseGameVersion version);
static void setCustomLayout(Project*);
static QString getMetatileIdString(uint16_t metatileId) {
return "0x" + QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper();
};
static QString getMetatileIdStringList(const QList<uint16_t> metatileIds) {
QStringList metatiles;
for (auto metatileId : metatileIds)
metatiles << Metatile::getMetatileIdString(metatileId);
return metatiles.join(",");
};
private:
// Stores how each attribute should be laid out for all metatiles, according to the user's config

View File

@@ -149,7 +149,7 @@ public:
void shouldReselectEvents();
void scaleMapView(int);
void openInTextEditor(const QString &path, int lineNum = 0) const;
static void openInTextEditor(const QString &path, int lineNum = 0);
bool eventLimitReached(Event::Type type);
public slots:
@@ -179,9 +179,9 @@ private:
void updateEncounterFields(EncounterFields newFields);
QString getMovementPermissionText(uint16_t collision, uint16_t elevation);
QString getMetatileDisplayMessage(uint16_t metatileId);
bool startDetachedProcess(const QString &command,
const QString &workingDirectory = QString(),
qint64 *pid = nullptr) const;
static bool startDetachedProcess(const QString &command,
const QString &workingDirectory = QString(),
qint64 *pid = nullptr);
private slots:
void onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);

View File

@@ -25,6 +25,8 @@
#include "newtilesetdialog.h"
#include "shortcutseditor.h"
#include "preferenceeditor.h"
#include "projectsettingseditor.h"
#include "customscriptseditor.h"
@@ -197,11 +199,7 @@ private slots:
void on_checkBox_AllowBiking_stateChanged(int selected);
void on_checkBox_AllowEscaping_stateChanged(int selected);
void on_spinBox_FloorNumber_valueChanged(int offset);
void on_actionUse_Encounter_Json_triggered(bool checked);
void on_actionMonitor_Project_Files_triggered(bool checked);
void on_actionUse_Poryscript_triggered(bool checked);
void on_actionOpen_Recent_Project_On_Launch_triggered(bool checked);
void on_actionEdit_Shortcuts_triggered();
void on_actionShortcuts_triggered();
void on_actionZoom_In_triggered();
void on_actionZoom_Out_triggered();
@@ -284,8 +282,11 @@ private slots:
void on_pushButton_CreatePrefab_clicked();
void on_actionRegion_Map_Editor_triggered();
void on_actionEdit_Preferences_triggered();
void on_actionPreferences_triggered();
void togglePreferenceSpecificUi();
void on_actionProject_Settings_triggered();
void on_actionCustom_Scripts_triggered();
void reloadScriptEngine();
public:
Ui::MainWindow *ui;
@@ -299,6 +300,8 @@ private:
QPointer<MapImageExporter> mapImageExporter = nullptr;
QPointer<NewMapPopup> newMapPrompt = nullptr;
QPointer<PreferenceEditor> preferenceEditor = nullptr;
QPointer<ProjectSettingsEditor> projectSettingsEditor = nullptr;
QPointer<CustomScriptsEditor> customScriptsEditor = nullptr;
FilterChildrenProxyModel *mapListProxyModel;
QStandardItemModel *mapListModel;
QList<QStandardItem*> *mapGroupItemsList;
@@ -342,6 +345,7 @@ private:
bool loadProjectCombos();
bool populateMapList();
void sortMapList();
void openSubWindow(QWidget * window);
QString getExistingDirectory(QString);
bool openProject(QString dir);
QString getDefaultMap();
@@ -381,6 +385,7 @@ private:
void initTilesetEditor();
bool initRegionMapEditor(bool silent = false);
void initShortcutsEditor();
void initCustomScriptsEditor();
void connectSubEditorsToShortcutsEditor();
bool isProjectOpen();

View File

@@ -0,0 +1,61 @@
#ifndef CUSTOMSCRIPTSEDITOR_H
#define CUSTOMSCRIPTSEDITOR_H
#include <QMainWindow>
#include <QListWidget>
#include <QAbstractButton>
#include <QMessageBox>
#include "customscriptslistitem.h"
namespace Ui {
class CustomScriptsEditor;
}
class CustomScriptsEditor : public QMainWindow
{
Q_OBJECT
public:
explicit CustomScriptsEditor(QWidget *parent = nullptr);
~CustomScriptsEditor();
signals:
void reloadScriptEngine();
public slots:
void applyUserShortcuts();
private:
Ui::CustomScriptsEditor *ui;
bool hasUnsavedChanges = false;
QString importDir;
const QString baseDir;
void displayScript(const QString &filepath, bool enabled);
QString chooseScript(QString dir);
void removeScript(QListWidgetItem * item);
void replaceScript(QListWidgetItem * item);
void openScript(QListWidgetItem * item);
QString getScriptFilepath(QListWidgetItem * item, bool absolutePath = true) const;
void setScriptFilepath(QListWidgetItem * item, QString filepath) const;
bool getScriptEnabled(QListWidgetItem * item) const;
void markEdited();
int prompt(const QString &text, QMessageBox::StandardButton defaultButton);
void save();
void closeEvent(QCloseEvent*);
void restoreWindowState();
void initShortcuts();
QObjectList shortcutableObjects() const;
private slots:
void dialogButtonClicked(QAbstractButton *button);
void addNewScript();
void reloadScripts();
void removeSelectedScripts();
void openSelectedScripts();
};
#endif // CUSTOMSCRIPTSEDITOR_H

View File

@@ -0,0 +1,22 @@
#ifndef CUSTOMSCRIPTSLISTITEM_H
#define CUSTOMSCRIPTSLISTITEM_H
#include <QFrame>
namespace Ui {
class CustomScriptsListItem;
}
class CustomScriptsListItem : public QFrame
{
Q_OBJECT
public:
explicit CustomScriptsListItem(QWidget *parent = nullptr);
~CustomScriptsListItem();
public:
Ui::CustomScriptsListItem *ui;
};
#endif // CUSTOMSCRIPTSLISTITEM_H

View File

@@ -11,8 +11,10 @@ public:
explicit NoScrollComboBox(QWidget *parent = nullptr);
void wheelEvent(QWheelEvent *event);
void setTextItem(const QString &text);
void setNumberItem(int value);
private:
void setItem(int index, const QString &text);
};
#endif // NOSCROLLCOMBOBOX_H

View File

@@ -23,7 +23,7 @@ public:
void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map);
void addPrefab(MetatileSelection selection, Map *map, QString name);
void updatePrefabUi(Map *map);
void tryImportDefaultPrefabs(Map *map);
bool tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version, QString filepath = "");
private:
MetatileSelector *selector;

View File

@@ -18,6 +18,7 @@ class PreferenceEditor : public QMainWindow
public:
explicit PreferenceEditor(QWidget *parent = nullptr);
~PreferenceEditor();
void updateFields();
signals:
void preferencesSaved();
@@ -27,9 +28,10 @@ private:
Ui::PreferenceEditor *ui;
NoScrollComboBox *themeSelector;
void populateFields();
void initFields();
void saveFields();
private slots:
void dialogButtonClicked(QAbstractButton *button);
};

View File

@@ -0,0 +1,60 @@
#ifndef PROJECTSETTINGSEDITOR_H
#define PROJECTSETTINGSEDITOR_H
#include <QMainWindow>
#include "project.h"
class NoScrollComboBox;
class QAbstractButton;
namespace Ui {
class ProjectSettingsEditor;
}
class ProjectSettingsEditor : public QMainWindow
{
Q_OBJECT
public:
explicit ProjectSettingsEditor(QWidget *parent = nullptr, Project *project = nullptr);
~ProjectSettingsEditor();
signals:
void reloadProject();
private:
Ui::ProjectSettingsEditor *ui;
Project *project;
bool hasUnsavedChanges = false;
bool projectNeedsReload = false;
bool refreshing = false;
const QString baseDir;
void initUi();
void connectSignals();
void restoreWindowState();
void save();
void refresh();
void closeEvent(QCloseEvent*);
int prompt(const QString &, QMessageBox::StandardButton = QMessageBox::Yes);
bool promptSaveChanges();
bool promptRestoreDefaults();
void setBorderMetatilesUi(bool customSize);
void setBorderMetatileIds(bool customSize, QList<uint16_t> metatileIds);
QList<uint16_t> getBorderMetatileIds(bool customSize);
void createProjectPathsTable();
QString chooseProjectFile(const QString &defaultFilepath);
private slots:
void dialogButtonClicked(QAbstractButton *button);
void choosePrefabsFileClicked(bool);
void importDefaultPrefabsClicked(bool);
void updateAttributeLimits(const QString &attrSize);
void markEdited();
};
#endif // PROJECTSETTINGSEDITOR_H

View File

@@ -138,7 +138,6 @@ private:
void copyMetatile(bool cut);
void pasteMetatile(const Metatile * toPaste, QString label);
bool replaceMetatile(uint16_t metatileId, const Metatile * src, QString label);
void setComboValue(QComboBox * combo, int value);
void commitMetatileChange(Metatile * prevMetatile);
void commitMetatileAndLabelChange(Metatile * prevMetatile, QString prevLabel);

67
include/ui/uintspinbox.h Normal file
View File

@@ -0,0 +1,67 @@
#ifndef UINTSPINBOX_H
#define UINTSPINBOX_H
#include <QAbstractSpinBox>
#include <QLineEdit>
/*
QSpinBox stores minimum/maximum/value as ints. This class is a version of QAbstractSpinBox for values above 0x7FFFFFFF.
It minimally implements some QSpinBox-specific features like prefixes to simplify support for hex value input.
It also implements the scroll focus requirements of NoScrollSpinBox.
*/
class UIntSpinBox : public QAbstractSpinBox
{
Q_OBJECT
public:
explicit UIntSpinBox(QWidget *parent = nullptr);
~UIntSpinBox() {};
uint32_t value() const { return m_value; }
uint32_t minimum() const { return m_minimum; }
uint32_t maximum() const { return m_maximum; }
QString prefix() const { return m_prefix; }
int displayIntegerBase() const { return m_displayIntegerBase; }
bool hasPadding() const { return m_hasPadding; }
void setMinimum(uint32_t min);
void setMaximum(uint32_t max);
void setRange(uint32_t min, uint32_t max);
void setPrefix(const QString &prefix);
void setDisplayIntegerBase(int base);
void setHasPadding(bool enabled);
private:
uint32_t m_minimum;
uint32_t m_maximum;
uint32_t m_value;
QString m_prefix;
int m_displayIntegerBase;
bool m_hasPadding;
int m_numChars;
void updateEdit();
QString stripped(QString input) const;
virtual void stepBy(int steps) override;
virtual void wheelEvent(QWheelEvent *event) override;
virtual void focusOutEvent(QFocusEvent *event) override;
protected:
virtual uint32_t valueFromText(const QString &text) const;
virtual QString textFromValue(uint32_t val) const;
virtual QValidator::State validate(QString &input, int &pos) const override;
virtual QAbstractSpinBox::StepEnabled stepEnabled() const override;
public slots:
void setValue(uint32_t val);
void onEditFinished();
signals:
void valueChanged(uint32_t val);
void textChanged(const QString &text);
};
#endif // UINTSPINBOX_H