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);
void setImportExportPath(QString filename);
static QString getExistingFilepath(QString filepath);
void applyParsedLimits();
static int getNumTilesPrimary();

View file

@ -55,7 +55,7 @@ public:
static QJSValue version(QList<int> versionNums);
static QJSValue dimensions(int width, int height);
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);
private:

View file

@ -151,10 +151,8 @@ void Event::setIcons() {
}
// Try to load custom icon
QFileInfo info(customIconPath);
if (info.isRelative()) {
customIconPath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + customIconPath);
}
QString validPath = Project::getExistingFilepath(customIconPath);
if (!validPath.isEmpty()) customIconPath = validPath; // Otherwise allow it to fail with the original path
const QPixmap customIcon = QPixmap(customIconPath);
if (customIcon.isNull()) {
// 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.
void Editor::setCollisionGraphics() {
QString customPath = projectConfig.getCollisionSheetPath();
QString filepath = projectConfig.getCollisionSheetPath();
QImage imgSheet;
if (customPath.isEmpty()) {
if (filepath.isEmpty()) {
// No custom collision image specified, use the default.
imgSheet = this->defaultCollisionImgSheet;
} else {
// Try to load custom collision image
QFileInfo info(customPath);
if (info.isRelative()) {
customPath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + customPath);
}
imgSheet = QImage(customPath);
QString validPath = Project::getExistingFilepath(filepath);
if (!validPath.isEmpty()) filepath = validPath; // Otherwise allow it to fail with the original path
imgSheet = QImage(filepath);
if (imgSheet.isNull()) {
// 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;
}
}

View file

@ -2747,6 +2747,20 @@ void Project::setImportExportPath(QString filename)
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
// (for example, metatile attributes size limits the metatile attribute masks).
// 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) {
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);
if (module.isError()) {
QString relativePath = QDir::cleanPath(userConfig.getProjectDir() + QDir::separator() + filepath);
module = this->engine->importModule(relativePath);
if (tryErrorJS(module)) {
QMessageBox messageBox(this->mainWindow);
messageBox.setText("Failed to load script");
@ -62,8 +62,6 @@ void Scripting::loadModules(QStringList moduleFiles) {
messageBox.exec();
continue;
}
}
logInfo(QString("Successfully loaded custom script file '%1'").arg(filepath));
this->modules.append(module);
}
@ -377,11 +375,22 @@ QJSEngine *Scripting::getEngine() {
return instance->engine;
}
QImage Scripting::getImage(QString filepath) {
const QImage * image = instance->imageCache.value(filepath, nullptr);
if (!image) {
const QImage * Scripting::getImage(const QString &inputFilepath, bool useCache) {
if (inputFilepath.isEmpty())
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);
instance->imageCache.insert(filepath, image);
}
return QImage(*image);
instance->imageCache.insert(inputFilepath, image);
return image;
}

View file

@ -21,9 +21,7 @@ void SpeciesComboDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
if (path.isEmpty()) {
path = this->project->speciesToIconPath.value(species);
} else {
QFileInfo info(path);
if (info.isRelative())
path = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + path);
path = Project::getExistingFilepath(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) {
QImage image = useCache ? Scripting::getImage(filepath) : QImage(filepath);
if (image.isNull()) {
const QImage * baseImage = Scripting::getImage(filepath, useCache);
if (!baseImage || baseImage->isNull()) {
logError(QString("Failed to load image '%1'").arg(filepath));
return false;
}
QImage image = *baseImage;
int fullWidth = image.width();
int fullHeight = image.height();

View file

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