diff --git a/include/config.h b/include/config.h index 7f10ce91..6fc02c31 100644 --- a/include/config.h +++ b/include/config.h @@ -9,6 +9,8 @@ #include #include +#include "events.h" + // In both versions the default new map border is a generic tree #define DEFAULT_BORDER_RSE (QList{0x1D4, 0x1D5, 0x1DC, 0x1DD}) #define DEFAULT_BORDER_FRLG (QList{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 eventIconPaths; + QString collisionMapPath; }; extern ProjectConfig projectConfig; diff --git a/include/core/events.h b/include/core/events.h index 566f0687..4ab30231 100644 --- a/include/core/events.h +++ b/include/core/events.h @@ -111,6 +111,7 @@ public: } } + static QMap icons; // standard public methods public: @@ -155,7 +156,7 @@ public: const QMap getCustomValues() { return this->customValues; } void setCustomValues(const QMap 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 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 getExpectedFields() override = 0; - virtual void loadPixmap(Project *) override; + static const QPixmap * defaultIcon; }; @@ -473,7 +477,7 @@ public: virtual QSet getExpectedFields() override = 0; - virtual void loadPixmap(Project *project) override; + static const QPixmap * defaultIcon; }; @@ -614,8 +618,6 @@ public: virtual QSet getExpectedFields() override { return QSet(); } - 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; diff --git a/include/project.h b/include/project.h index 05029df3..34a8c918 100644 --- a/include/project.h +++ b/include/project.h @@ -86,8 +86,6 @@ public: bool usingAsmTilesets; QString importExportPath; - const QPixmap entitiesPixmap = QPixmap(":/images/Entities_16x16.png"); - void set_root(QString); void initSignals(); diff --git a/include/ui/movementpermissionsselector.h b/include/ui/movementpermissionsselector.h index a962f01a..f2a993fd 100644 --- a/include/ui/movementpermissionsselector.h +++ b/include/ui/movementpermissionsselector.h @@ -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); diff --git a/src/config.cpp b/src/config.cpp index 681dc3f9..df90213b 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -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 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; diff --git a/src/core/events.cpp b/src/core/events.cpp index 331eb69f..ad5a3055 100644 --- a/src/core/events.cpp +++ b/src/core/events.cpp @@ -4,7 +4,7 @@ #include "project.h" #include "config.h" - +QMap 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(Event::Group::None)); + for (int i = 0; i < numIcons; i++) { + Event::Group group = static_cast(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 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 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); -} diff --git a/src/editor.cpp b/src/editor.cpp index 4dc12885..31ead704 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -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, diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ed6b9432..7f9d1f82 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -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) { diff --git a/src/ui/imageproviders.cpp b/src/ui/imageproviders.cpp index 891cfbba..3935b196 100644 --- a/src/ui/imageproviders.cpp +++ b/src/ui/imageproviders.cpp @@ -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; diff --git a/src/ui/movementpermissionsselector.cpp b/src/ui/movementpermissionsselector.cpp index 9bad2a0f..30dfde10 100644 --- a/src/ui/movementpermissionsselector.cpp +++ b/src/ui/movementpermissionsselector.cpp @@ -2,8 +2,7 @@ #include void MovementPermissionsSelector::draw() { - QPixmap pixmap(":/images/collisions.png"); - this->setPixmap(pixmap.scaled(64, 512)); + this->setPixmap(this->basePixmap); this->drawSelection(); }