Support relative paths in image API functions, combine projectDir calls

This commit is contained in:
GriffinR 2024-01-03 12:13:53 -05:00
parent d1c25a8eca
commit 2c61df578a
9 changed files with 62 additions and 44 deletions

View file

@ -210,6 +210,7 @@ public:
QString findMetatileLabelsTileset(QString label); QString findMetatileLabelsTileset(QString label);
void setImportExportPath(QString filename); void setImportExportPath(QString filename);
static QString getExistingFilepath(QString filepath);
void applyParsedLimits(); void applyParsedLimits();
static int getNumTilesPrimary(); static int getNumTilesPrimary();

View file

@ -55,7 +55,7 @@ public:
static QJSValue version(QList<int> versionNums); static QJSValue version(QList<int> versionNums);
static QJSValue dimensions(int width, int height); static QJSValue dimensions(int width, int height);
static QJSValue position(int x, int y); static QJSValue position(int x, int y);
static QImage getImage(QString filepath); static const QImage * getImage(const QString &filepath, bool useCache);
static QJSValue dialogInput(QJSValue input, bool selectedOk); static QJSValue dialogInput(QJSValue input, bool selectedOk);
private: private:

View file

@ -151,10 +151,8 @@ void Event::setIcons() {
} }
// Try to load custom icon // Try to load custom icon
QFileInfo info(customIconPath); QString validPath = Project::getExistingFilepath(customIconPath);
if (info.isRelative()) { if (!validPath.isEmpty()) customIconPath = validPath; // Otherwise allow it to fail with the original path
customIconPath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + customIconPath);
}
const QPixmap customIcon = QPixmap(customIconPath); const QPixmap customIcon = QPixmap(customIconPath);
if (customIcon.isNull()) { if (customIcon.isNull()) {
// Custom icon failed to load, use the default icon. // Custom icon failed to load, use the default icon.

View file

@ -2278,22 +2278,20 @@ void Editor::setCollisionTabSpinBoxes(uint16_t collision, uint16_t elevation) {
// Custom collision graphics may be provided by the user. // Custom collision graphics may be provided by the user.
void Editor::setCollisionGraphics() { void Editor::setCollisionGraphics() {
QString customPath = projectConfig.getCollisionSheetPath(); QString filepath = projectConfig.getCollisionSheetPath();
QImage imgSheet; QImage imgSheet;
if (customPath.isEmpty()) { if (filepath.isEmpty()) {
// No custom collision image specified, use the default. // No custom collision image specified, use the default.
imgSheet = this->defaultCollisionImgSheet; imgSheet = this->defaultCollisionImgSheet;
} else { } else {
// Try to load custom collision image // Try to load custom collision image
QFileInfo info(customPath); QString validPath = Project::getExistingFilepath(filepath);
if (info.isRelative()) { if (!validPath.isEmpty()) filepath = validPath; // Otherwise allow it to fail with the original path
customPath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + customPath); imgSheet = QImage(filepath);
}
imgSheet = QImage(customPath);
if (imgSheet.isNull()) { if (imgSheet.isNull()) {
// Custom collision image failed to load, use default // Custom collision image failed to load, use default
logWarn(QString("Failed to load custom collision image '%1', using default.").arg(customPath)); logWarn(QString("Failed to load custom collision image '%1', using default.").arg(filepath));
imgSheet = this->defaultCollisionImgSheet; imgSheet = this->defaultCollisionImgSheet;
} }
} }

View file

@ -2747,6 +2747,20 @@ void Project::setImportExportPath(QString filename)
this->importExportPath = QFileInfo(filename).absolutePath(); this->importExportPath = QFileInfo(filename).absolutePath();
} }
// If the provided filepath is an absolute path to an existing file, return filepath.
// If not, and the provided filepath is a relative path from the project dir to an existing file, return the relative path.
// Otherwise return empty string.
QString Project::getExistingFilepath(QString filepath) {
if (filepath.isEmpty() || QFile::exists(filepath))
return filepath;
filepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
if (QFile::exists(filepath))
return filepath;
return QString();
}
// The values of some config fields can limit the values of other config fields // The values of some config fields can limit the values of other config fields
// (for example, metatile attributes size limits the metatile attribute masks). // (for example, metatile attributes size limits the metatile attribute masks).
// Others depend on information in the project (for example the default metatile ID // Others depend on information in the project (for example the default metatile ID

View file

@ -48,10 +48,10 @@ Scripting::Scripting(MainWindow *mainWindow) {
void Scripting::loadModules(QStringList moduleFiles) { void Scripting::loadModules(QStringList moduleFiles) {
for (QString filepath : moduleFiles) { for (QString filepath : moduleFiles) {
QString validPath = Project::getExistingFilepath(filepath);
if (!validPath.isEmpty()) filepath = validPath; // Otherwise allow it to fail with the original path
QJSValue module = this->engine->importModule(filepath); QJSValue module = this->engine->importModule(filepath);
if (module.isError()) {
QString relativePath = QDir::cleanPath(userConfig.getProjectDir() + QDir::separator() + filepath);
module = this->engine->importModule(relativePath);
if (tryErrorJS(module)) { if (tryErrorJS(module)) {
QMessageBox messageBox(this->mainWindow); QMessageBox messageBox(this->mainWindow);
messageBox.setText("Failed to load script"); messageBox.setText("Failed to load script");
@ -62,8 +62,6 @@ void Scripting::loadModules(QStringList moduleFiles) {
messageBox.exec(); messageBox.exec();
continue; continue;
} }
}
logInfo(QString("Successfully loaded custom script file '%1'").arg(filepath)); logInfo(QString("Successfully loaded custom script file '%1'").arg(filepath));
this->modules.append(module); this->modules.append(module);
} }
@ -377,11 +375,22 @@ QJSEngine *Scripting::getEngine() {
return instance->engine; return instance->engine;
} }
QImage Scripting::getImage(QString filepath) { const QImage * Scripting::getImage(const QString &inputFilepath, bool useCache) {
const QImage * image = instance->imageCache.value(filepath, nullptr); if (inputFilepath.isEmpty())
if (!image) { return nullptr;
const QImage * image;
if (useCache) {
// Try to retrieve image from the cache
image = instance->imageCache.value(inputFilepath, nullptr);
if (image) return image;
}
const QString filepath = Project::getExistingFilepath(inputFilepath);
if (filepath.isEmpty())
return nullptr;
image = new QImage(filepath); image = new QImage(filepath);
instance->imageCache.insert(filepath, image); instance->imageCache.insert(inputFilepath, image);
} return image;
return QImage(*image);
} }

View file

@ -21,9 +21,7 @@ void SpeciesComboDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
if (path.isEmpty()) { if (path.isEmpty()) {
path = this->project->speciesToIconPath.value(species); path = this->project->speciesToIconPath.value(species);
} else { } else {
QFileInfo info(path); path = Project::getExistingFilepath(path);
if (info.isRelative())
path = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + path);
} }
QImage img(path); QImage img(path);

View file

@ -202,11 +202,12 @@ bool Overlay::addPath(QList<int> xCoords, QList<int> yCoords, QString borderColo
} }
bool Overlay::addImage(int x, int y, QString filepath, bool useCache, int width, int height, int xOffset, int yOffset, qreal hScale, qreal vScale, QList<QRgb> palette, bool setTransparency) { bool Overlay::addImage(int x, int y, QString filepath, bool useCache, int width, int height, int xOffset, int yOffset, qreal hScale, qreal vScale, QList<QRgb> palette, bool setTransparency) {
QImage image = useCache ? Scripting::getImage(filepath) : QImage(filepath); const QImage * baseImage = Scripting::getImage(filepath, useCache);
if (image.isNull()) { if (!baseImage || baseImage->isNull()) {
logError(QString("Failed to load image '%1'").arg(filepath)); logError(QString("Failed to load image '%1'").arg(filepath));
return false; return false;
} }
QImage image = *baseImage;
int fullWidth = image.width(); int fullWidth = image.width();
int fullHeight = image.height(); int fullHeight = image.height();

View file

@ -28,14 +28,13 @@ void Prefab::loadPrefabs() {
ParseUtil parser; ParseUtil parser;
QJsonDocument prefabDoc; QJsonDocument prefabDoc;
QFileInfo info(filepath);
if (info.isRelative()) { QString validPath = Project::getExistingFilepath(filepath);
filepath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath); if (validPath.isEmpty() || !parser.tryParseJsonFile(&prefabDoc, validPath)) {
}
if (!QFile::exists(filepath) || !parser.tryParseJsonFile(&prefabDoc, filepath)) {
logError(QString("Failed to read prefab data from %1").arg(filepath)); logError(QString("Failed to read prefab data from %1").arg(filepath));
return; return;
} }
filepath = validPath;
QJsonArray prefabs = prefabDoc.array(); QJsonArray prefabs = prefabDoc.array();
if (prefabs.size() == 0) { if (prefabs.size() == 0) {