Support custom event icons

This commit is contained in:
GriffinR 2023-12-05 02:01:44 -05:00
parent b88d62ecc1
commit 1b9b980121
10 changed files with 103 additions and 37 deletions

View file

@ -9,6 +9,8 @@
#include <QKeySequence>
#include <QMultiMap>
#include "events.h"
// 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})
@ -295,6 +297,11 @@ public:
void setMetatileLayerTypeMask(uint32_t mask);
bool getMapAllowFlagsEnabled();
void setMapAllowFlagsEnabled(bool enabled);
void setEventIconPath(Event::Group group, const QString &path);
QString getEventIconPath(Event::Group group);
void setCollisionMapPath(const QString &path);
QString getCollisionMapPath();
protected:
virtual QString getConfigFilepath() override;
virtual void parseConfigKeyValue(QString key, QString value) override;
@ -332,6 +339,8 @@ private:
uint32_t metatileEncounterTypeMask;
uint32_t metatileLayerTypeMask;
bool enableMapAllowFlags;
QMap<Event::Group, QString> eventIconPaths;
QString collisionMapPath;
};
extern ProjectConfig projectConfig;

View file

@ -111,6 +111,7 @@ public:
}
}
static QMap<Event::Group, const QPixmap*> icons;
// standard public methods
public:
@ -155,7 +156,7 @@ public:
const QMap<QString, QJsonValue> getCustomValues() { return this->customValues; }
void setCustomValues(const QMap<QString, QJsonValue> newCustomValues) { this->customValues = newCustomValues; }
virtual void loadPixmap(Project *project) = 0;
virtual void loadPixmap(Project *project);
void setPixmap(QPixmap newPixmap) { this->pixmap = newPixmap; }
QPixmap getPixmap() { return this->pixmap; }
@ -177,6 +178,7 @@ public:
static QString eventGroupToString(Event::Group group);
static QString eventTypeToString(Event::Type type);
static Event::Type eventTypeFromString(QString type);
static void initIcons();
// protected attributes
protected:
@ -258,6 +260,8 @@ public:
void setFrameFromMovement(QString movement);
void setPixmapFromSpritesheet(QImage, int, int, bool);
static const QPixmap * defaultIcon;
protected:
QString gfx;
@ -337,14 +341,14 @@ public:
virtual QSet<QString> getExpectedFields() override;
virtual void loadPixmap(Project *) override;
void setDestinationMap(QString newDestinationMap) { this->destinationMap = newDestinationMap; }
QString getDestinationMap() { return this->destinationMap; }
void setDestinationWarpID(QString newDestinationWarpID) { this->destinationWarpID = newDestinationWarpID; }
QString getDestinationWarpID() { return this->destinationWarpID; }
static const QPixmap * defaultIcon;
private:
QString destinationMap;
QString destinationWarpID;
@ -372,7 +376,7 @@ public:
virtual QSet<QString> getExpectedFields() override = 0;
virtual void loadPixmap(Project *) override;
static const QPixmap * defaultIcon;
};
@ -473,7 +477,7 @@ public:
virtual QSet<QString> getExpectedFields() override = 0;
virtual void loadPixmap(Project *project) override;
static const QPixmap * defaultIcon;
};
@ -614,8 +618,6 @@ public:
virtual QSet<QString> getExpectedFields() override { return QSet<QString>(); }
virtual void loadPixmap(Project *project) override;
void setIndex(int newIndex) { this->index = newIndex; }
int getIndex() { return this->index; }
@ -631,6 +633,8 @@ public:
void setRespawnNPC(uint8_t newRespawnNPC) { this->respawnNPC = newRespawnNPC; }
uint8_t getRespawnNPC() { return this->respawnNPC; }
static const QPixmap * defaultIcon;
private:
int index = -1;
QString locationName;

View file

@ -86,8 +86,6 @@ public:
bool usingAsmTilesets;
QString importExportPath;
const QPixmap entitiesPixmap = QPixmap(":/images/Entities_16x16.png");
void set_root(QString);
void initSignals();

View file

@ -6,7 +6,9 @@
class MovementPermissionsSelector: public SelectablePixmapItem {
Q_OBJECT
public:
MovementPermissionsSelector(): SelectablePixmapItem(32, 32, 1, 1) {
MovementPermissionsSelector(QPixmap basePixmap) :
SelectablePixmapItem(32, 32, 1, 1),
basePixmap(basePixmap) {
setAcceptHoverEvents(true);
}
void draw();
@ -20,6 +22,7 @@ protected:
private:
void setSelectedMovementPermissions(QPointF);
const QPixmap basePixmap;
signals:
void hoveredMovementPermissionChanged(uint16_t, uint16_t);

View file

@ -684,6 +684,16 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
this->tilesetsHaveCallback = getConfigBool(key, value);
} else if (key == "tilesets_have_is_compressed") {
this->tilesetsHaveIsCompressed = getConfigBool(key, value);
} else if (key == "event_icon_path_object") {
this->eventIconPaths[Event::Group::Object] = value;
} else if (key == "event_icon_path_warp") {
this->eventIconPaths[Event::Group::Warp] = value;
} else if (key == "event_icon_path_coord") {
this->eventIconPaths[Event::Group::Coord] = value;
} else if (key == "event_icon_path_bg") {
this->eventIconPaths[Event::Group::Bg] = value;
} else if (key == "event_icon_path_heal") {
this->eventIconPaths[Event::Group::Heal] = value;
} else {
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
}
@ -751,6 +761,11 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
map.insert("metatile_encounter_type_mask", "0x" + QString::number(this->metatileEncounterTypeMask, 16).toUpper());
map.insert("metatile_layer_type_mask", "0x" + QString::number(this->metatileLayerTypeMask, 16).toUpper());
map.insert("enable_map_allow_flags", QString::number(this->enableMapAllowFlags));
map.insert("event_icon_path_object", this->eventIconPaths[Event::Group::Object]);
map.insert("event_icon_path_warp", this->eventIconPaths[Event::Group::Warp]);
map.insert("event_icon_path_coord", this->eventIconPaths[Event::Group::Coord]);
map.insert("event_icon_path_bg", this->eventIconPaths[Event::Group::Bg]);
map.insert("event_icon_path_heal", this->eventIconPaths[Event::Group::Heal]);
return map;
}
@ -1091,6 +1106,24 @@ void ProjectConfig::setMapAllowFlagsEnabled(bool enabled) {
this->save();
}
// TODO: Expose to project settings editor
void ProjectConfig::setEventIconPath(Event::Group group, const QString &path) {
this->eventIconPaths[group] = path;
this->save();
}
QString ProjectConfig::getEventIconPath(Event::Group group) {
return this->eventIconPaths.value(group);
}
void ProjectConfig::setCollisionMapPath(const QString &path) {
this->collisionMapPath = path;
this->save();
}
QString ProjectConfig::getCollisionMapPath() {
return this->collisionMapPath;
}
UserConfig userConfig;

View file

@ -4,7 +4,7 @@
#include "project.h"
#include "config.h"
QMap<Event::Group, const QPixmap*> Event::icons;
Event::~Event() {
if (this->eventFrame)
@ -126,6 +126,45 @@ Event::Type Event::eventTypeFromString(QString type) {
}
}
void Event::loadPixmap(Project *) {
const QPixmap * pixmap = Event::icons.value(this->getEventGroup());
this->pixmap = pixmap ? *pixmap : QPixmap();
}
void Event::initIcons() {
qDeleteAll(icons);
icons.clear();
const int w = 16;
const int h = 16;
static const QPixmap defaultIcons = QPixmap(":/images/Entities_16x16.png");
// Custom event icons may be provided by the user.
const int numIcons = qMin(defaultIcons.width() / w, static_cast<int>(Event::Group::None));
for (int i = 0; i < numIcons; i++) {
Event::Group group = static_cast<Event::Group>(i);
QString customIconPath = projectConfig.getEventIconPath(group);
if (customIconPath.isEmpty()) {
// No custom icon specified, use the default icon.
icons[group] = new QPixmap(defaultIcons.copy(i * w, 0, w, h));
continue;
}
// Try to load custom icon
QFileInfo info(customIconPath);
if (info.isRelative()) {
customIconPath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + customIconPath);
}
const QPixmap customIcon = QPixmap(customIconPath);
if (customIcon.isNull()) {
// Custom icon failed to load, use the default icon.
icons[group] = new QPixmap(defaultIcons.copy(i * w, 0, w, h));
logError(QString("Failed to load custom event icon '%1', using default icon.").arg(customIconPath));
} else {
icons[group] = new QPixmap(customIcon);
}
}
}
Event *ObjectEvent::duplicate() {
@ -243,7 +282,7 @@ void ObjectEvent::loadPixmap(Project *project) {
if (!eventGfx || eventGfx->spritesheet.isNull()) {
// No sprite associated with this gfx constant.
// Use default sprite instead.
this->pixmap = project->entitiesPixmap.copy(0, 0, 16, 16);
Event::loadPixmap(project);
this->spriteWidth = 16;
this->spriteHeight = 16;
this->usingSprite = false;
@ -389,7 +428,7 @@ void CloneObjectEvent::loadPixmap(Project *project) {
if (!eventGfx || eventGfx->spritesheet.isNull()) {
// No sprite associated with this gfx constant.
// Use default sprite instead.
this->pixmap = project->entitiesPixmap.copy(0, 0, 16, 16);
Event::loadPixmap(project);
this->spriteWidth = 16;
this->spriteHeight = 16;
this->usingSprite = false;
@ -478,17 +517,6 @@ QSet<QString> WarpEvent::getExpectedFields() {
return expectedFields;
}
void WarpEvent::loadPixmap(Project *project) {
this->pixmap = project->entitiesPixmap.copy(16, 0, 16, 16);
}
void CoordEvent::loadPixmap(Project *project) {
this->pixmap = project->entitiesPixmap.copy(32, 0, 16, 16);
}
Event *TriggerEvent::duplicate() {
TriggerEvent *copy = new TriggerEvent();
@ -632,12 +660,6 @@ QSet<QString> WeatherTriggerEvent::getExpectedFields() {
void BGEvent::loadPixmap(Project *project) {
this->pixmap = project->entitiesPixmap.copy(48, 0, 16, 16);
}
Event *SignEvent::duplicate() {
SignEvent *copy = new SignEvent();
@ -897,7 +919,3 @@ void HealLocationEvent::setDefaultValues(Project *) {
this->setRespawnNPC(1);
}
}
void HealLocationEvent::loadPixmap(Project *project) {
this->pixmap = project->entitiesPixmap.copy(64, 0, 16, 16);
}

View file

@ -1484,7 +1484,7 @@ void Editor::displayMovementPermissionSelector() {
scene_collision_metatiles = new QGraphicsScene;
if (!movement_permissions_selector_item) {
movement_permissions_selector_item = new MovementPermissionsSelector();
movement_permissions_selector_item = new MovementPermissionsSelector(QPixmap(":/images/collisions.png").scaled(32 * 2, 32 * 16)); // TODO: Don't assume default
connect(movement_permissions_selector_item, &MovementPermissionsSelector::hoveredMovementPermissionChanged,
this, &Editor::onHoveredMovementPermissionChanged);
connect(movement_permissions_selector_item, &MovementPermissionsSelector::hoveredMovementPermissionCleared,

View file

@ -514,6 +514,7 @@ bool MainWindow::openProject(QString dir) {
this->setProjectSpecificUIVisibility();
this->newMapDefaultsSet = false;
Event::initIcons();
Scripting::init(this);
bool already_open = isProjectOpen() && (editor->project->root == dir);
if (!already_open) {

View file

@ -7,6 +7,7 @@ QImage getCollisionMetatileImage(Block block) {
return getCollisionMetatileImage(block.collision, block.elevation);
}
// TODO:
QImage getCollisionMetatileImage(int collision, int elevation) {
static const QImage collisionImage(":/images/collisions.png");
int x = (collision != 0) * 16;

View file

@ -2,8 +2,7 @@
#include <QPainter>
void MovementPermissionsSelector::draw() {
QPixmap pixmap(":/images/collisions.png");
this->setPixmap(pixmap.scaled(64, 512));
this->setPixmap(this->basePixmap);
this->drawSelection();
}