Merge branch 'master' of https://github.com/huderlem/porymap into slam
This commit is contained in:
commit
c0f32c6a17
15 changed files with 209 additions and 126 deletions
|
@ -12,11 +12,14 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
|||
- Add `metatile_behaviors`, `num_primary_palettes`, and `num_secondary_palettes` to `constants` in the API.
|
||||
|
||||
### Changed
|
||||
- The API functions `addImage` and `createImage` now support project-relative paths.
|
||||
- Metatile ID strings are now padded to their current max, not the overall max.
|
||||
- The name of the Heal Locations table is no longer enforced.
|
||||
- The API functions `addImage` and `createImage` now support project-relative paths.
|
||||
|
||||
### Fixed
|
||||
- Fix the metatile selector rectangle jumping when selecting up or left of the origin.
|
||||
- Fix the event group tabs sometimes showing an event from the wrong group
|
||||
- Fix the clear buttons in the Shortcuts Editor not actually removing shortcuts.
|
||||
- Fix API error reporting
|
||||
|
||||
## [5.2.0] - 2024-01-02
|
||||
|
|
|
@ -86,10 +86,11 @@ In addition to these files, there are some specific symbol and macro names that
|
|||
``symbol_obj_event_gfx_pointers``, ``gObjectEventGraphicsInfoPointers``, to map Object Event graphics IDs to graphics data
|
||||
``symbol_pokemon_icon_table``, ``gMonIconTable``, to map species constants to icon images
|
||||
``symbol_wild_encounters``, ``gWildMonHeaders``, output as the ``label`` property for the top-level wild ecounters JSON object
|
||||
``symbol_heal_locations``, ``sHealLocations``, only if ``Respawn Map/NPC`` is disabled
|
||||
``symbol_spawn_points``, ``sSpawnPoints``, only if ``Respawn Map/NPC`` is enabled
|
||||
``symbol_spawn_maps``, ``sWhiteoutRespawnHealCenterMapIdxs``, values for Heal Locations ``Respawn Map`` field
|
||||
``symbol_spawn_npcs``, ``sWhiteoutRespawnHealerNpcIds``, values for Heal Locations ``Respawn NPC`` field
|
||||
``symbol_heal_locations_type``, ``struct HealLocation``, the type for the Heal Locations table
|
||||
``symbol_heal_locations``, ``sHealLocations``, the default Heal Locations table name when ``Respawn Map/NPC`` is disabled
|
||||
``symbol_spawn_points``, ``sSpawnPoints``, the default Heal Locations table name when ``Respawn Map/NPC`` is enabled
|
||||
``symbol_spawn_maps``, ``u16 sWhiteoutRespawnHealCenterMapIdxs``, the type and table name for Heal Location ``Respawn Map`` values
|
||||
``symbol_spawn_npcs``, ``u8 sWhiteoutRespawnHealerNpcIds``, the type and table name for Heal Location ``Respawn NPC`` values
|
||||
``symbol_attribute_table``, ``sMetatileAttrMasks``, optionally read to get settings on ``Tilesets`` tab
|
||||
``symbol_tilesets_prefix``, ``gTileset_``, for new tileset names and to extract base tileset names
|
||||
``define_obj_event_count``, ``OBJECT_EVENT_TEMPLATES_COUNT``, to limit total Object Events
|
||||
|
|
|
@ -189,6 +189,7 @@ enum ProjectIdentifier {
|
|||
symbol_obj_event_gfx_pointers,
|
||||
symbol_pokemon_icon_table,
|
||||
symbol_wild_encounters,
|
||||
symbol_heal_locations_type,
|
||||
symbol_heal_locations,
|
||||
symbol_spawn_points,
|
||||
symbol_spawn_maps,
|
||||
|
|
|
@ -373,7 +373,8 @@ private:
|
|||
void openSubWindow(QWidget * window);
|
||||
void scrollTreeView(QString itemName);
|
||||
QString getExistingDirectory(QString);
|
||||
bool openProject(QString dir);
|
||||
bool openProject(const QString &dir, bool initial = false);
|
||||
void showProjectOpenFailure();
|
||||
QString getDefaultMap();
|
||||
QString getDefaultLayout();
|
||||
void setRecentMapConfig(QString map_name);
|
||||
|
@ -406,7 +407,6 @@ private:
|
|||
void applyMapListFilter(QString filterText);
|
||||
void restoreWindowState();
|
||||
void setTheme(QString);
|
||||
bool openRecentProject();
|
||||
void updateTilesetEditor();
|
||||
Event::Group getEventGroupFromTabWidget(QWidget *tab);
|
||||
void closeSupplementaryWindows();
|
||||
|
|
|
@ -95,6 +95,7 @@ public:
|
|||
};
|
||||
DataQualifiers getDataQualifiers(QString, QString);
|
||||
DataQualifiers healLocationDataQualifiers;
|
||||
QString healLocationsTableName;
|
||||
|
||||
QMap<QString, Map*> mapCache;
|
||||
Map* loadMap(QString);
|
||||
|
@ -243,7 +244,6 @@ private:
|
|||
|
||||
void saveHealLocationsData(Map *map);
|
||||
void saveHealLocationsConstants();
|
||||
QString getHealLocationsTableName();
|
||||
|
||||
void ignoreWatchedFileTemporarily(QString filepath);
|
||||
|
||||
|
|
|
@ -14,25 +14,33 @@ public:
|
|||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->clearLastModifiedCoords();
|
||||
this->clearLastHoveredCoords();
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
void draw();
|
||||
void setTilesets(Tileset*, Tileset*);
|
||||
void setMetatile(Metatile*);
|
||||
void clearLastModifiedCoords();
|
||||
void clearLastHoveredCoords();
|
||||
bool showGrid;
|
||||
private:
|
||||
Metatile* metatile;
|
||||
Tileset *primaryTileset;
|
||||
Tileset *secondaryTileset;
|
||||
QPoint prevChangedTile;
|
||||
void getBoundedCoords(QPointF, int*, int*);
|
||||
QPoint prevChangedPos;
|
||||
QPoint prevHoveredPos;
|
||||
QPoint getBoundedPos(const QPointF &);
|
||||
signals:
|
||||
void tileChanged(int, int);
|
||||
void selectedTilesChanged(QPoint, int, int);
|
||||
void hoveredTileChanged(uint16_t);
|
||||
void hoveredTileCleared();
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
};
|
||||
|
||||
#endif // METATILELAYERSITEM_H
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
this->primaryTileset = layout->tileset_primary;
|
||||
this->secondaryTileset = layout->tileset_secondary;
|
||||
this->selection = MetatileSelection{};
|
||||
this->cellPos = QPoint(-1, -1);
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
QPoint getSelectionDimensions();
|
||||
|
@ -68,13 +69,15 @@ private:
|
|||
int externalSelectionHeight;
|
||||
QList<uint16_t> externalSelectedMetatiles;
|
||||
MetatileSelection selection;
|
||||
QPoint cellPos;
|
||||
|
||||
void updateSelectedMetatiles();
|
||||
void updateExternalSelectedMetatiles();
|
||||
uint16_t getMetatileId(int x, int y);
|
||||
uint16_t getMetatileId(int x, int y) const;
|
||||
QPoint getMetatileIdCoords(uint16_t);
|
||||
bool shouldAcceptEvent(QGraphicsSceneMouseEvent*);
|
||||
bool positionIsValid(const QPoint &pos) const;
|
||||
bool selectionIsValid();
|
||||
void hoverChanged();
|
||||
|
||||
signals:
|
||||
void hoveredMetatileSelectionChanged(uint16_t);
|
||||
|
|
|
@ -74,10 +74,11 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
|
|||
{ProjectIdentifier::symbol_obj_event_gfx_pointers, {"symbol_obj_event_gfx_pointers", "gObjectEventGraphicsInfoPointers"}},
|
||||
{ProjectIdentifier::symbol_pokemon_icon_table, {"symbol_pokemon_icon_table", "gMonIconTable"}},
|
||||
{ProjectIdentifier::symbol_wild_encounters, {"symbol_wild_encounters", "gWildMonHeaders"}},
|
||||
{ProjectIdentifier::symbol_heal_locations_type, {"symbol_heal_locations_type", "struct HealLocation"}},
|
||||
{ProjectIdentifier::symbol_heal_locations, {"symbol_heal_locations", "sHealLocations"}},
|
||||
{ProjectIdentifier::symbol_spawn_points, {"symbol_spawn_points", "sSpawnPoints"}},
|
||||
{ProjectIdentifier::symbol_spawn_maps, {"symbol_spawn_maps", "sWhiteoutRespawnHealCenterMapIdxs"}},
|
||||
{ProjectIdentifier::symbol_spawn_npcs, {"symbol_spawn_npcs", "sWhiteoutRespawnHealerNpcIds"}},
|
||||
{ProjectIdentifier::symbol_spawn_maps, {"symbol_spawn_maps", "u16 sWhiteoutRespawnHealCenterMapIdxs"}},
|
||||
{ProjectIdentifier::symbol_spawn_npcs, {"symbol_spawn_npcs", "u8 sWhiteoutRespawnHealerNpcIds"}},
|
||||
{ProjectIdentifier::symbol_attribute_table, {"symbol_attribute_table", "sMetatileAttrMasks"}},
|
||||
{ProjectIdentifier::symbol_tilesets_prefix, {"symbol_tilesets_prefix", "gTileset_"}},
|
||||
// Defines
|
||||
|
|
|
@ -62,7 +62,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
cleanupLargeLog();
|
||||
|
||||
this->initWindow();
|
||||
if (this->openRecentProject())
|
||||
if (porymapConfig.getReopenOnLaunch() && this->openProject(porymapConfig.getRecentProject(), true))
|
||||
on_toolButton_Paint_clicked();
|
||||
|
||||
// there is a bug affecting macOS users, where the trackpad deilveres a bad touch-release gesture
|
||||
|
@ -492,35 +492,29 @@ void MainWindow::setTheme(QString theme) {
|
|||
}
|
||||
}
|
||||
|
||||
bool MainWindow::openRecentProject() {
|
||||
if (!porymapConfig.getReopenOnLaunch())
|
||||
return false;
|
||||
|
||||
QString default_dir = porymapConfig.getRecentProject();
|
||||
if (default_dir.isNull() || default_dir.length() <= 0)
|
||||
return false;
|
||||
|
||||
if (!QDir(default_dir).exists()) {
|
||||
QString message = QString("Recent project directory '%1' doesn't exist.").arg(QDir::toNativeSeparators(default_dir));
|
||||
logWarn(message);
|
||||
this->statusBar()->showMessage(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
logInfo(QString("Opening recent project: '%1'").arg(default_dir));
|
||||
return openProject(default_dir);
|
||||
}
|
||||
|
||||
bool MainWindow::openProject(QString dir) {
|
||||
if (dir.isNull()) {
|
||||
bool MainWindow::openProject(const QString &dir, bool initial) {
|
||||
if (dir.isNull() || dir.length() <= 0) {
|
||||
projectOpenFailure = true;
|
||||
setWindowDisabled(true);
|
||||
if (!initial) setWindowDisabled(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
QString nativeDir = QDir::toNativeSeparators(dir);
|
||||
const QString projectString = QString("%1project '%2'").arg(initial ? "recent " : "").arg(QDir::toNativeSeparators(dir));
|
||||
|
||||
this->statusBar()->showMessage(QString("Opening project %1").arg(nativeDir));
|
||||
if (!QDir(dir).exists()) {
|
||||
projectOpenFailure = true;
|
||||
const QString errorMsg = QString("Failed to open %1: No such directory").arg(projectString);
|
||||
this->statusBar()->showMessage(errorMsg);
|
||||
if (initial) {
|
||||
// Graceful startup if recent project directory is missing
|
||||
logWarn(errorMsg);
|
||||
} else {
|
||||
logError(errorMsg);
|
||||
showProjectOpenFailure();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
this->statusBar()->showMessage(QString("Opening %1").arg(projectString));
|
||||
|
||||
userConfig.setProjectDir(dir);
|
||||
userConfig.load();
|
||||
|
@ -530,7 +524,10 @@ bool MainWindow::openProject(QString dir) {
|
|||
this->closeSupplementaryWindows();
|
||||
this->newMapDefaultsSet = false;
|
||||
|
||||
if (isProjectOpen())
|
||||
Scripting::cb_ProjectClosed(editor->project->root);
|
||||
Scripting::init(this);
|
||||
|
||||
bool already_open = isProjectOpen() && (editor->project->root == dir);
|
||||
if (!already_open) {
|
||||
editor->closeProject();
|
||||
|
@ -555,19 +552,16 @@ bool MainWindow::openProject(QString dir) {
|
|||
&& setInitialMap());
|
||||
|
||||
if (this->projectOpenFailure) {
|
||||
this->statusBar()->showMessage(QString("Failed to open project %1").arg(nativeDir));
|
||||
QMessageBox msgBox(this);
|
||||
QString errorMsg = QString("There was an error opening the project %1. Please see %2 for full error details.\n\n%3")
|
||||
.arg(dir)
|
||||
.arg(getLogPath())
|
||||
.arg(getMostRecentError());
|
||||
msgBox.critical(nullptr, "Error Opening Project", errorMsg);
|
||||
setWindowDisabled(true);
|
||||
this->statusBar()->showMessage(QString("Failed to open %1").arg(projectString));
|
||||
showProjectOpenFailure();
|
||||
return false;
|
||||
}
|
||||
|
||||
showWindowTitle();
|
||||
this->statusBar()->showMessage(QString("Opened project %1").arg(nativeDir));
|
||||
|
||||
const QString successMessage = QString("Opened %1").arg(projectString);
|
||||
this->statusBar()->showMessage(successMessage);
|
||||
logInfo(successMessage);
|
||||
|
||||
porymapConfig.addRecentProject(dir);
|
||||
refreshRecentProjectsMenu();
|
||||
|
@ -582,6 +576,14 @@ bool MainWindow::openProject(QString dir) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::showProjectOpenFailure() {
|
||||
QString errorMsg = QString("There was an error opening the project. Please see %1 for full error details.").arg(getLogPath());
|
||||
QMessageBox error(QMessageBox::Critical, "porymap", errorMsg, QMessageBox::Ok, this);
|
||||
error.setDetailedText(getMostRecentError());
|
||||
error.exec();
|
||||
setWindowDisabled(true);
|
||||
}
|
||||
|
||||
bool MainWindow::isProjectOpen() {
|
||||
return !projectOpenFailure && editor && editor->project;
|
||||
}
|
||||
|
@ -662,17 +664,22 @@ void MainWindow::refreshRecentProjectsMenu() {
|
|||
recentProjects.removeOne(this->editor->project->root);
|
||||
}
|
||||
|
||||
// Add project paths to menu. Arbitrary limit of 10 items.
|
||||
const int numItems = qMin(10, recentProjects.length());
|
||||
for (int i = 0; i < numItems; i++) {
|
||||
// Add project paths to menu. Skip any paths to folders that don't exist
|
||||
for (int i = 0; i < recentProjects.length(); i++) {
|
||||
const QString path = recentProjects.at(i);
|
||||
ui->menuOpen_Recent_Project->addAction(path, [this, path](){
|
||||
this->openProject(path);
|
||||
});
|
||||
if (QDir(path).exists()) {
|
||||
ui->menuOpen_Recent_Project->addAction(path, [this, path](){
|
||||
this->openProject(path);
|
||||
});
|
||||
}
|
||||
// Arbitrary limit of 10 items.
|
||||
if (ui->menuOpen_Recent_Project->actions().length() >= 10)
|
||||
break;
|
||||
}
|
||||
|
||||
// Add action to clear list of paths
|
||||
if (!recentProjects.isEmpty()) ui->menuOpen_Recent_Project->addSeparator();
|
||||
if (!ui->menuOpen_Recent_Project->actions().isEmpty())
|
||||
ui->menuOpen_Recent_Project->addSeparator();
|
||||
QAction *clearAction = ui->menuOpen_Recent_Project->addAction("Clear Items", [this](){
|
||||
QStringList paths = QStringList();
|
||||
if (isProjectOpen())
|
||||
|
@ -719,13 +726,8 @@ void MainWindow::on_action_Open_Project_triggered()
|
|||
recent = userConfig.getRecentMap();
|
||||
}
|
||||
QString dir = getExistingDirectory(recent);
|
||||
if (!dir.isEmpty()) {
|
||||
if (this->editor && this->editor->project) {
|
||||
Scripting::cb_ProjectClosed(this->editor->project->root);
|
||||
this->ui->graphicsView_Map->clearOverlayMap();
|
||||
}
|
||||
if (!dir.isEmpty())
|
||||
openProject(dir);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Reload_Project_triggered() {
|
||||
|
@ -2349,6 +2351,7 @@ void MainWindow::on_toolButton_Paint_clicked()
|
|||
ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
QScroller::ungrabGesture(ui->graphicsView_Map);
|
||||
ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate);
|
||||
ui->graphicsView_Map->setFocus();
|
||||
|
||||
checkToolButtons();
|
||||
}
|
||||
|
@ -2367,6 +2370,7 @@ void MainWindow::on_toolButton_Select_clicked()
|
|||
ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
QScroller::ungrabGesture(ui->graphicsView_Map);
|
||||
ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate);
|
||||
ui->graphicsView_Map->setFocus();
|
||||
|
||||
checkToolButtons();
|
||||
}
|
||||
|
@ -2385,6 +2389,7 @@ void MainWindow::on_toolButton_Fill_clicked()
|
|||
ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
QScroller::ungrabGesture(ui->graphicsView_Map);
|
||||
ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate);
|
||||
ui->graphicsView_Map->setFocus();
|
||||
|
||||
checkToolButtons();
|
||||
}
|
||||
|
@ -2403,6 +2408,7 @@ void MainWindow::on_toolButton_Dropper_clicked()
|
|||
ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
QScroller::ungrabGesture(ui->graphicsView_Map);
|
||||
ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate);
|
||||
ui->graphicsView_Map->setFocus();
|
||||
|
||||
checkToolButtons();
|
||||
}
|
||||
|
@ -2421,6 +2427,7 @@ void MainWindow::on_toolButton_Move_clicked()
|
|||
ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
QScroller::grabGesture(ui->graphicsView_Map, QScroller::LeftMouseButtonGesture);
|
||||
ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::FullViewportUpdate);
|
||||
ui->graphicsView_Map->setFocus();
|
||||
|
||||
checkToolButtons();
|
||||
}
|
||||
|
@ -2439,6 +2446,7 @@ void MainWindow::on_toolButton_Shift_clicked()
|
|||
ui->graphicsView_Map->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
QScroller::ungrabGesture(ui->graphicsView_Map);
|
||||
ui->graphicsView_Map->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate);
|
||||
ui->graphicsView_Map->setFocus();
|
||||
|
||||
checkToolButtons();
|
||||
}
|
||||
|
@ -2942,7 +2950,6 @@ void MainWindow::initCustomScriptsEditor() {
|
|||
|
||||
void MainWindow::reloadScriptEngine() {
|
||||
Scripting::init(this);
|
||||
this->ui->graphicsView_Map->clearOverlayMap();
|
||||
Scripting::populateGlobalObject(this);
|
||||
// Lying to the scripts here, simulating a project reload
|
||||
Scripting::cb_ProjectOpened(projectConfig.getProjectDir());
|
||||
|
|
|
@ -781,12 +781,6 @@ void Project::saveHealLocations(Map *map) {
|
|||
this->saveHealLocationsConstants();
|
||||
}
|
||||
|
||||
QString Project::getHealLocationsTableName() {
|
||||
if (projectConfig.getHealLocationRespawnDataEnabled())
|
||||
return projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_points);
|
||||
return projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations);
|
||||
}
|
||||
|
||||
// Saves heal location maps/coords/respawn data in root + /src/data/heal_locations.h
|
||||
void Project::saveHealLocationsData(Map *map) {
|
||||
// Update heal locations from map
|
||||
|
@ -813,11 +807,13 @@ void Project::saveHealLocationsData(Map *map) {
|
|||
const QString qualifiers = QString(healLocationDataQualifiers.isStatic ? "static " : "")
|
||||
+ QString(healLocationDataQualifiers.isConst ? "const " : "");
|
||||
|
||||
QString locationTableText = QString("%1struct HealLocation %2[] =\n{\n").arg(qualifiers).arg(this->getHealLocationsTableName());
|
||||
QString locationTableText = QString("%1%2 %3[] =\n{\n").arg(qualifiers)
|
||||
.arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations_type))
|
||||
.arg(this->healLocationsTableName);
|
||||
QString respawnMapTableText, respawnNPCTableText;
|
||||
if (respawnEnabled) {
|
||||
respawnMapTableText = QString("\n%1u16 %2[][2] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_maps));
|
||||
respawnNPCTableText = QString("\n%1u8 %2[] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_npcs));
|
||||
respawnMapTableText = QString("\n%1%2[][2] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_maps));
|
||||
respawnNPCTableText = QString("\n%1%2[] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_npcs));
|
||||
}
|
||||
|
||||
// Populate the data tables with the heal location data
|
||||
|
@ -2129,7 +2125,6 @@ bool Project::readHealLocationConstants() {
|
|||
|
||||
// TODO: Simplify using the new C struct parsing functions (and indexed array parsing functions)
|
||||
bool Project::readHealLocations() {
|
||||
this->healLocationDataQualifiers = {};
|
||||
this->healLocations.clear();
|
||||
|
||||
if (!this->readHealLocationConstants())
|
||||
|
@ -2145,8 +2140,19 @@ bool Project::readHealLocations() {
|
|||
|
||||
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||
|
||||
// Get data qualifiers for the location data table
|
||||
this->healLocationDataQualifiers = this->getDataQualifiers(text, this->getHealLocationsTableName());
|
||||
// Search for the name of the main Heal Locations table
|
||||
const QRegularExpression tableNameExpr(QString("%1\\s+(?<name>[A-Za-z0-9_]+)\\[").arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations_type)));
|
||||
const QRegularExpressionMatch tableNameMatch = tableNameExpr.match(text);
|
||||
if (tableNameMatch.hasMatch()) {
|
||||
// Found table name, record it and its qualifiers for output when saving.
|
||||
this->healLocationsTableName = tableNameMatch.captured("name");
|
||||
this->healLocationDataQualifiers = this->getDataQualifiers(text, this->healLocationsTableName);
|
||||
} else {
|
||||
// No table name found, initialize default name for output when saving.
|
||||
this->healLocationsTableName = respawnEnabled ? projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_points)
|
||||
: projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations);
|
||||
this->healLocationDataQualifiers = { .isStatic = true, .isConst = true };
|
||||
}
|
||||
|
||||
// Create regex pattern for the constants (ex: "SPAWN_PALLET_TOWN" or "HEAL_LOCATION_PETALBURG_CITY")
|
||||
const QString spawnPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_spawn_prefix);
|
||||
|
|
|
@ -23,6 +23,7 @@ QMap<CallbackType, QString> callbackFunctions = {
|
|||
Scripting *instance = nullptr;
|
||||
|
||||
void Scripting::init(MainWindow *mainWindow) {
|
||||
mainWindow->ui->graphicsView_Map->clearOverlayMap();
|
||||
if (instance) {
|
||||
instance->engine->setInterrupted(true);
|
||||
instance->scriptUtility->clearActions();
|
||||
|
|
|
@ -3,22 +3,22 @@
|
|||
#include "imageproviders.h"
|
||||
#include <QPainter>
|
||||
|
||||
void MetatileLayersItem::draw() {
|
||||
static const QList<QPoint> tileCoords = QList<QPoint>{
|
||||
QPoint(0, 0),
|
||||
QPoint(16, 0),
|
||||
QPoint(0, 16),
|
||||
QPoint(16, 16),
|
||||
QPoint(32, 0),
|
||||
QPoint(48, 0),
|
||||
QPoint(32, 16),
|
||||
QPoint(48, 16),
|
||||
QPoint(64, 0),
|
||||
QPoint(80, 0),
|
||||
QPoint(64, 16),
|
||||
QPoint(80, 16),
|
||||
};
|
||||
static const QList<QPoint> tilePositions = {
|
||||
QPoint(0, 0),
|
||||
QPoint(1, 0),
|
||||
QPoint(0, 1),
|
||||
QPoint(1, 1),
|
||||
QPoint(2, 0),
|
||||
QPoint(3, 0),
|
||||
QPoint(2, 1),
|
||||
QPoint(3, 1),
|
||||
QPoint(4, 0),
|
||||
QPoint(5, 0),
|
||||
QPoint(4, 1),
|
||||
QPoint(5, 1),
|
||||
};
|
||||
|
||||
void MetatileLayersItem::draw() {
|
||||
const int numLayers = projectConfig.getNumLayersInMetatile();
|
||||
QPixmap pixmap(numLayers * 32, 32);
|
||||
QPainter painter(&pixmap);
|
||||
|
@ -30,7 +30,7 @@ void MetatileLayersItem::draw() {
|
|||
QImage tileImage = getPalettedTileImage(tile.tileId, this->primaryTileset, this->secondaryTileset, tile.palette, true)
|
||||
.mirrored(tile.xflip, tile.yflip)
|
||||
.scaled(16, 16);
|
||||
painter.drawImage(tileCoords.at(i), tileImage);
|
||||
painter.drawImage(tilePositions.at(i) * 16, tileImage);
|
||||
}
|
||||
if (this->showGrid) {
|
||||
// Draw grid
|
||||
|
@ -47,6 +47,7 @@ void MetatileLayersItem::draw() {
|
|||
void MetatileLayersItem::setMetatile(Metatile *metatile) {
|
||||
this->metatile = metatile;
|
||||
this->clearLastModifiedCoords();
|
||||
this->clearLastHoveredCoords();
|
||||
}
|
||||
|
||||
void MetatileLayersItem::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
|
@ -54,6 +55,7 @@ void MetatileLayersItem::setTilesets(Tileset *primaryTileset, Tileset *secondary
|
|||
this->secondaryTileset = secondaryTileset;
|
||||
this->draw();
|
||||
this->clearLastModifiedCoords();
|
||||
this->clearLastHoveredCoords();
|
||||
}
|
||||
|
||||
void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
|
@ -64,11 +66,10 @@ void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
|||
emit this->selectedTilesChanged(selectionOrigin, dimensions.x(), dimensions.y());
|
||||
this->drawSelection();
|
||||
} else {
|
||||
int x, y;
|
||||
this->getBoundedCoords(event->pos(), &x, &y);
|
||||
this->prevChangedTile.setX(x);
|
||||
this->prevChangedTile.setY(y);
|
||||
emit this->tileChanged(x, y);
|
||||
const QPoint pos = this->getBoundedPos(event->pos());
|
||||
this->prevChangedPos = pos;
|
||||
this->clearLastHoveredCoords();
|
||||
emit this->tileChanged(pos.x(), pos.y());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,12 +81,11 @@ void MetatileLayersItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
|||
emit this->selectedTilesChanged(selectionOrigin, dimensions.x(), dimensions.y());
|
||||
this->drawSelection();
|
||||
} else {
|
||||
int x, y;
|
||||
this->getBoundedCoords(event->pos(), &x, &y);
|
||||
if (prevChangedTile.x() != x || prevChangedTile.y() != y) {
|
||||
this->prevChangedTile.setX(x);
|
||||
this->prevChangedTile.setY(y);
|
||||
emit this->tileChanged(x, y);
|
||||
const QPoint pos = this->getBoundedPos(event->pos());
|
||||
if (prevChangedPos != pos) {
|
||||
this->prevChangedPos = pos;
|
||||
this->clearLastHoveredCoords();
|
||||
emit this->tileChanged(pos.x(), pos.y());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,17 +101,40 @@ void MetatileLayersItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
|||
this->draw();
|
||||
}
|
||||
|
||||
void MetatileLayersItem::clearLastModifiedCoords() {
|
||||
this->prevChangedTile.setX(-1);
|
||||
this->prevChangedTile.setY(-1);
|
||||
void MetatileLayersItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) {
|
||||
const QPoint pos = this->getBoundedPos(event->pos());
|
||||
if (pos == this->prevHoveredPos)
|
||||
return;
|
||||
this->prevHoveredPos = pos;
|
||||
|
||||
int tileIndex = tilePositions.indexOf(pos);
|
||||
if (tileIndex < 0 || tileIndex >= this->metatile->tiles.length())
|
||||
return;
|
||||
|
||||
emit this->hoveredTileChanged(this->metatile->tiles.at(tileIndex).tileId);
|
||||
}
|
||||
|
||||
void MetatileLayersItem::getBoundedCoords(QPointF pos, int *x, int *y) {
|
||||
int maxX = (projectConfig.getNumLayersInMetatile() * 2) - 1;
|
||||
*x = static_cast<int>(pos.x()) / 16;
|
||||
*y = static_cast<int>(pos.y()) / 16;
|
||||
if (*x < 0) *x = 0;
|
||||
if (*y < 0) *y = 0;
|
||||
if (*x > maxX) *x = maxX;
|
||||
if (*y > 1) *y = 1;
|
||||
void MetatileLayersItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
|
||||
this->clearLastHoveredCoords();
|
||||
emit this->hoveredTileCleared();
|
||||
}
|
||||
|
||||
void MetatileLayersItem::clearLastModifiedCoords() {
|
||||
this->prevChangedPos = QPoint(-1, -1);
|
||||
}
|
||||
|
||||
void MetatileLayersItem::clearLastHoveredCoords() {
|
||||
this->prevHoveredPos = QPoint(-1, -1);
|
||||
}
|
||||
|
||||
QPoint MetatileLayersItem::getBoundedPos(const QPointF &pos) {
|
||||
int x, y;
|
||||
int maxX = (projectConfig.getNumLayersInMetatile() * 2) - 1;
|
||||
x = static_cast<int>(pos.x()) / 16;
|
||||
y = static_cast<int>(pos.y()) / 16;
|
||||
if (x < 0) x = 0;
|
||||
if (y < 0) y = 0;
|
||||
if (x > maxX) x = maxX;
|
||||
if (y > 1) y = 1;
|
||||
return QPoint(x, y);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
#include <QPainter>
|
||||
|
||||
QPoint MetatileSelector::getSelectionDimensions() {
|
||||
return selection.dimensions;
|
||||
if (this->prefabSelection || this->externalSelection)
|
||||
return selection.dimensions;
|
||||
return SelectablePixmapItem::getSelectionDimensions();
|
||||
}
|
||||
|
||||
void MetatileSelector::draw() {
|
||||
|
@ -112,41 +114,55 @@ void MetatileSelector::setPrefabSelection(MetatileSelection selection) {
|
|||
emit selectedMetatilesChanged();
|
||||
}
|
||||
|
||||
bool MetatileSelector::shouldAcceptEvent(QGraphicsSceneMouseEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
bool MetatileSelector::positionIsValid(const QPoint &pos) const {
|
||||
return Tileset::metatileIsValid(getMetatileId(pos.x(), pos.y()), this->primaryTileset, this->secondaryTileset);
|
||||
}
|
||||
|
||||
void MetatileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
if (!shouldAcceptEvent(event)) return;
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
if (!positionIsValid(pos))
|
||||
return;
|
||||
|
||||
this->cellPos = pos;
|
||||
SelectablePixmapItem::mousePressEvent(event);
|
||||
this->updateSelectedMetatiles();
|
||||
}
|
||||
|
||||
void MetatileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
if (!shouldAcceptEvent(event)) return;
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
if (!positionIsValid(pos) || this->cellPos == pos)
|
||||
return;
|
||||
|
||||
this->cellPos = pos;
|
||||
SelectablePixmapItem::mouseMoveEvent(event);
|
||||
this->updateSelectedMetatiles();
|
||||
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
uint16_t metatileId = this->getMetatileId(pos.x(), pos.y());
|
||||
emit this->hoveredMetatileSelectionChanged(metatileId);
|
||||
this->hoverChanged();
|
||||
}
|
||||
|
||||
void MetatileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||
if (!shouldAcceptEvent(event)) return;
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
if (!positionIsValid(pos))
|
||||
return;
|
||||
SelectablePixmapItem::mouseReleaseEvent(event);
|
||||
this->updateSelectedMetatiles();
|
||||
}
|
||||
|
||||
void MetatileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
uint16_t metatileId = this->getMetatileId(pos.x(), pos.y());
|
||||
if (!positionIsValid(pos) || this->cellPos == pos)
|
||||
return;
|
||||
|
||||
this->cellPos = pos;
|
||||
this->hoverChanged();
|
||||
}
|
||||
|
||||
void MetatileSelector::hoverChanged() {
|
||||
uint16_t metatileId = this->getMetatileId(this->cellPos.x(), this->cellPos.y());
|
||||
emit this->hoveredMetatileSelectionChanged(metatileId);
|
||||
}
|
||||
|
||||
void MetatileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
|
||||
emit this->hoveredMetatileSelectionCleared();
|
||||
this->cellPos = QPoint(-1, -1);
|
||||
}
|
||||
|
||||
void MetatileSelector::updateSelectedMetatiles() {
|
||||
|
@ -155,7 +171,7 @@ void MetatileSelector::updateSelectedMetatiles() {
|
|||
this->selection.metatileItems.clear();
|
||||
this->selection.collisionItems.clear();
|
||||
this->selection.hasCollision = false;
|
||||
this->selection.dimensions = SelectablePixmapItem::getSelectionDimensions();
|
||||
this->selection.dimensions = this->getSelectionDimensions();
|
||||
QPoint origin = this->getSelectionStart();
|
||||
for (int j = 0; j < this->selection.dimensions.y(); j++) {
|
||||
for (int i = 0; i < this->selection.dimensions.x(); i++) {
|
||||
|
@ -180,7 +196,7 @@ void MetatileSelector::updateExternalSelectedMetatiles() {
|
|||
emit selectedMetatilesChanged();
|
||||
}
|
||||
|
||||
uint16_t MetatileSelector::getMetatileId(int x, int y) {
|
||||
uint16_t MetatileSelector::getMetatileId(int x, int y) const {
|
||||
int index = y * this->numMetatilesWide + x;
|
||||
if (index < this->primaryTileset->metatiles.length()) {
|
||||
return static_cast<uint16_t>(index);
|
||||
|
|
|
@ -140,6 +140,14 @@ void MultiKeyEdit::addNewKeySequenceEdit() {
|
|||
connect(lineEdit, &QLineEdit::customContextMenuRequested,
|
||||
this, &MultiKeyEdit::customContextMenuRequested);
|
||||
|
||||
// Gross way to connect the line edit's clear button.
|
||||
auto actions = lineEdit->findChildren<QAction*>();
|
||||
if (!actions.isEmpty()) {
|
||||
connect(actions.first(), &QAction::triggered, this, [this, keySequenceEdit]() {
|
||||
removeOne(keySequenceEdit->keySequence());
|
||||
});
|
||||
}
|
||||
|
||||
layout()->addWidget(keySequenceEdit);
|
||||
keySequenceEdit_vec.append(keySequenceEdit);
|
||||
}
|
||||
|
|
|
@ -206,6 +206,10 @@ void TilesetEditor::initMetatileLayersItem() {
|
|||
this, &TilesetEditor::onMetatileLayerTileChanged);
|
||||
connect(this->metatileLayersItem, &MetatileLayersItem::selectedTilesChanged,
|
||||
this, &TilesetEditor::onMetatileLayerSelectionChanged);
|
||||
connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileChanged,
|
||||
this, &TilesetEditor::onHoveredTileChanged);
|
||||
connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileCleared,
|
||||
this, &TilesetEditor::onHoveredTileCleared);
|
||||
|
||||
bool showGrid = porymapConfig.getShowTilesetEditorLayerGrid();
|
||||
this->ui->actionLayer_Grid->setChecked(showGrid);
|
||||
|
@ -861,6 +865,7 @@ bool TilesetEditor::replaceMetatile(uint16_t metatileId, const Metatile * src, Q
|
|||
this->metatileSelector->draw();
|
||||
this->metatileLayersItem->draw();
|
||||
this->metatileLayersItem->clearLastModifiedCoords();
|
||||
this->metatileLayersItem->clearLastHoveredCoords();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue