Merge branch 'master' of https://github.com/huderlem/porymap into slam

This commit is contained in:
garak
2024-02-22 16:20:23 -05:00
50 changed files with 2647 additions and 1554 deletions

View File

@@ -8,9 +8,14 @@
#include <QSize>
#include <QKeySequence>
#include <QMultiMap>
#include <QDateTime>
#include <QUrl>
#include <QVersionNumber>
#include "events.h"
static const QVersionNumber porymapVersion = QVersionNumber::fromString(PORYMAP_VERSION);
// In both versions the default new map border is a generic tree
#define DEFAULT_BORDER_RSE (QList<uint16_t>{0x1D4, 0x1D5, 0x1DC, 0x1DD})
#define DEFAULT_BORDER_FRLG (QList<uint16_t>{0x14, 0x15, 0x1C, 0x1D})
@@ -74,14 +79,18 @@ public:
this->paletteEditorBitDepth = 24;
this->projectSettingsTab = 0;
this->warpBehaviorWarningDisabled = false;
this->checkForUpdates = true;
this->lastUpdateCheckTime = QDateTime();
this->lastUpdateCheckVersion = porymapVersion;
this->rateLimitTimes.clear();
}
void addRecentProject(QString project);
void setRecentProjects(QStringList projects);
void setReopenOnLaunch(bool enabled);
void setMapSortOrder(MapSortOrder order);
void setPrettyCursors(bool enabled);
void setMainGeometry(QByteArray, QByteArray, QByteArray, QByteArray);
void setTilesetEditorGeometry(QByteArray, QByteArray);
void setMainGeometry(QByteArray, QByteArray, QByteArray, QByteArray, QByteArray);
void setTilesetEditorGeometry(QByteArray, QByteArray, QByteArray);
void setPaletteEditorGeometry(QByteArray, QByteArray);
void setRegionMapEditorGeometry(QByteArray, QByteArray);
void setProjectSettingsEditorGeometry(QByteArray, QByteArray);
@@ -105,6 +114,10 @@ public:
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();
@@ -135,6 +148,10 @@ public:
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;
@@ -151,10 +168,11 @@ private:
QByteArray mainWindowGeometry;
QByteArray mainWindowState;
QByteArray mapSplitterState;
QByteArray eventsSlpitterState;
QByteArray mainSplitterState;
QByteArray metatilesSplitterState;
QByteArray tilesetEditorGeometry;
QByteArray tilesetEditorState;
QByteArray tilesetEditorSplitterState;
QByteArray paletteEditorGeometry;
QByteArray paletteEditorState;
QByteArray regionMapEditorGeometry;
@@ -182,6 +200,10 @@ private:
int paletteEditorBitDepth;
int projectSettingsTab;
bool warpBehaviorWarningDisabled;
bool checkForUpdates;
QDateTime lastUpdateCheckTime;
QVersionNumber lastUpdateCheckVersion;
QMap<QUrl, QDateTime> rateLimitTimes;
};
extern PorymapConfig porymapConfig;

View File

@@ -67,6 +67,7 @@ public:
bool needsLayoutDir = true;
bool needsHealLocation = false;
bool scriptsLoaded = false;
QMap<Event::Group, QList<Event *>> events;
QList<Event *> ownedEvents; // for memory management
@@ -85,7 +86,7 @@ public:
int getBorderHeight();
QList<Event *> getAllEvents() const;
QStringList getScriptLabels(Event::Group group = Event::Group::None) const;
QStringList getScriptLabels(Event::Group group = Event::Group::None);
QString getScriptsFilePath() const;
void openScript(QString label);
void removeEvent(Event *);

87
include/core/network.h Normal file
View File

@@ -0,0 +1,87 @@
#ifndef NETWORK_H
#define NETWORK_H
/*
The two classes defined here provide a simplified interface for Qt's network classes QNetworkAccessManager and QNetworkReply.
With the Qt classes, the workflow for a GET is roughly: generate a QNetworkRequest, give this request to QNetworkAccessManager::get,
connect the returned object to QNetworkReply::finished, and in the slot of that connection handle the various HTTP headers and attributes,
then manage errors or process the webpage's body.
These classes handle generating the QNetworkRequest with a given URL and manage the HTTP headers in the reply. They will automatically
respect rate limits and return cached data if the webpage hasn't changed since previous requests. Instead of interacting with a QNetworkReply,
callers interact with a simplified NetworkReplyData.
Example that logs Porymap's description on GitHub:
NetworkAccessManager * manager = new NetworkAccessManager(this);
NetworkReplyData * reply = manager->get("https://api.github.com/repos/huderlem/porymap");
connect(reply, &NetworkReplyData::finished, [reply] () {
if (!reply->errorString().isEmpty()) {
logError(QString("Failed to read description: %1").arg(reply->errorString()));
} else {
auto webpage = QJsonDocument::fromJson(reply->body());
logInfo(QString("Porymap: %1").arg(webpage["description"].toString()));
}
reply->deleteLater();
});
*/
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDateTime>
class NetworkReplyData : public QObject
{
Q_OBJECT
public:
QUrl url() const { return m_url; }
QUrl nextUrl() const { return m_nextUrl; }
QByteArray body() const { return m_body; }
QString errorString() const { return m_error; }
QDateTime retryAfter() const { return m_retryAfter; }
bool isFinished() const { return m_finished; }
friend class NetworkAccessManager;
private:
QUrl m_url;
QUrl m_nextUrl;
QByteArray m_body;
QString m_error;
QDateTime m_retryAfter;
bool m_finished;
void finish() {
m_finished = true;
emit finished();
};
signals:
void finished();
};
class NetworkAccessManager : public QNetworkAccessManager
{
Q_OBJECT
public:
NetworkAccessManager(QObject * parent = nullptr);
~NetworkAccessManager();
NetworkReplyData * get(const QString &url);
NetworkReplyData * get(const QUrl &url);
private:
// For a more complex cache we could implement a QAbstractCache for the manager
struct CacheEntry {
QString eTag;
QByteArray data;
};
QMap<QUrl, CacheEntry*> cache;
QMap<QUrl, QDateTime> rateLimitTimes;
void processReply(QNetworkReply * reply, NetworkReplyData * data);
const QNetworkRequest getRequest(const QUrl &url);
};
#endif // NETWORK_H

View File

@@ -28,6 +28,7 @@
#include "preferenceeditor.h"
#include "projectsettingseditor.h"
#include "customscriptseditor.h"
#include "updatepromoter.h"
@@ -306,6 +307,7 @@ private slots:
void on_spinBox_SelectedCollision_valueChanged(int collision);
void on_actionRegion_Map_Editor_triggered();
void on_actionPreferences_triggered();
void on_actionCheck_for_Updates_triggered();
void togglePreferenceSpecificUi();
void on_actionProject_Settings_triggered();
void on_actionCustom_Scripts_triggered();
@@ -335,7 +337,8 @@ private:
FilterChildrenProxyModel *layoutListProxyModel;
LayoutTreeModel *layoutTreeModel;
QPointer<UpdatePromoter> updatePromoter = nullptr;
QPointer<NetworkAccessManager> networkAccessManager = nullptr;
QAction *undoAction = nullptr;
QAction *redoAction = nullptr;
@@ -414,7 +417,6 @@ private:
void initShortcuts();
void initExtraShortcuts();
void setProjectSpecificUI();
void setWildEncountersUIEnabled(bool enabled);
void loadUserSettings();
void applyMapListFilter(QString filterText);
void restoreWindowState();
@@ -432,11 +434,15 @@ private:
void openProjectSettingsEditor(int tab);
bool isProjectOpen();
void showExportMapImageWindow(ImageExporterMode mode);
double getMetatilesZoomScale();
void redrawMetatileSelection();
void scrollMetatileSelectorToSelection();
QObjectList shortcutableObjects() const;
void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false);
int insertTilesetLabel(QStringList * list, QString label);
void checkForUpdates(bool requestedByUser);
};
#endif // MAINWINDOW_H

View File

@@ -55,6 +55,7 @@ public:
QMap<int, QString> mapSectionValueToName;
QMap<QString, EventGraphics*> eventGraphicsMap;
QMap<QString, int> gfxDefines;
QString defaultSong;
QStringList songNames;
QStringList itemNames;
QStringList flagNames;
@@ -79,6 +80,7 @@ public:
bool usingAsmTilesets;
QString importExportPath;
QSet<QString> disabledSettingsNames;
bool wildEncountersLoaded;
// For files that are read and could contain extra text
QMap<QString, QString> extraFileText;
@@ -174,8 +176,6 @@ public:
void saveTilesetMetatiles(Tileset*);
void saveTilesetTilesImage(Tileset*);
void saveTilesetPalettes(Tileset*);
QString defaultSong;
void appendTilesetLabel(QString label, QString isSecondaryStr);
bool readTilesetLabels();
bool readTilesetMetatileLabels();
@@ -264,7 +264,6 @@ private:
signals:
void reloadProject();
void uncheckMonitorFilesAction();
void disableWildEncountersUI();
};
#endif // PROJECT_H

View File

@@ -52,7 +52,6 @@ public:
static QJSValue fromBlock(Block block);
static QJSValue fromTile(Tile tile);
static Tile toTile(QJSValue obj);
static QJSValue version(QList<int> versionNums);
static QJSValue dimensions(int width, int height);
static QJSValue position(int x, int y);
static const QImage * getImage(const QString &filepath, bool useCache);

View File

@@ -14,7 +14,6 @@ class AboutPorymap : public QMainWindow
public:
explicit AboutPorymap(QWidget *parent = nullptr);
~AboutPorymap();
QList<int> getVersionNumbers();
private:
Ui::AboutPorymap *ui;
};

View File

@@ -4,12 +4,23 @@
#include <QGraphicsView>
#include <QMouseEvent>
class ClickableGraphicsView : public QGraphicsView
class NoScrollGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
ClickableGraphicsView() : QGraphicsView() {}
ClickableGraphicsView(QWidget *parent) : QGraphicsView(parent) {}
NoScrollGraphicsView(QWidget *parent = nullptr) : QGraphicsView(parent) {}
protected:
void wheelEvent(QWheelEvent *event) {
event->ignore();
}
};
class ClickableGraphicsView : public NoScrollGraphicsView
{
Q_OBJECT
public:
ClickableGraphicsView(QWidget *parent = nullptr) : NoScrollGraphicsView(parent) {}
public:
void mouseReleaseEvent(QMouseEvent *event) override {

View File

@@ -45,13 +45,14 @@ public:
QPoint getSelectionDimensions();
void draw();
bool select(uint16_t metatile);
bool selectFromMap(uint16_t metatileId, uint16_t collision, uint16_t elevation);
void selectFromMap(uint16_t metatileId, uint16_t collision, uint16_t elevation);
void setTilesets(Tileset*, Tileset*);
MetatileSelection getMetatileSelection();
void setPrefabSelection(MetatileSelection selection);
void setExternalSelection(int, int, QList<uint16_t>, QList<QPair<uint16_t, uint16_t>>);
QPoint getMetatileIdCoordsOnWidget(uint16_t);
void setLayout(Layout *layout);
bool isInternalSelection() const { return (!this->externalSelection && !this->prefabSelection); }
Tileset *primaryTileset;
Tileset *secondaryTileset;
protected:

View File

@@ -134,6 +134,8 @@ private:
void setTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel);
void reset();
void drawSelectedTiles();
void redrawTileSelector();
void redrawMetatileSelector();
void importTilesetTiles(Tileset*, bool);
void importTilesetMetatiles(Tileset*, bool);
void refresh();

View File

@@ -0,0 +1,50 @@
#ifndef UPDATEPROMOTER_H
#define UPDATEPROMOTER_H
#include "network.h"
#include <QDialog>
#include <QPushButton>
#include <QVersionNumber>
namespace Ui {
class UpdatePromoter;
}
class UpdatePromoter : public QDialog
{
Q_OBJECT
public:
explicit UpdatePromoter(QWidget *parent, NetworkAccessManager *manager);
~UpdatePromoter() {};
void checkForUpdates();
void updatePreferences();
private:
Ui::UpdatePromoter *ui;
NetworkAccessManager *const manager;
QPushButton * button_Downloads;
QPushButton * button_Retry;
QString changelog;
QUrl downloadUrl;
QVersionNumber newVersion;
bool foundReleases;
QSet<QUrl> visitedUrls; // Prevent infinite redirection
void resetDialog();
void get(const QUrl &url);
void processWebpage(const QJsonDocument &data, const QUrl &nextUrl);
void error(const QString &err, const QDateTime time = QDateTime());
private slots:
void dialogButtonClicked(QAbstractButton *button);
signals:
void changedPreferences();
};
#endif // UPDATEPROMOTER_H