From b25dbb849edaa75f8bcb877ffe5ce1750798cfdf Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 4 Sep 2022 20:24:11 -0400 Subject: [PATCH 1/7] Reorganize API files --- porymap.pro | 6 +- .../api_map.cpp} | 574 ++---------------- src/script_api/api_overlay.cpp | 224 +++++++ src/script_api/api_util.cpp | 261 ++++++++ src/{ => script_api}/scripting.cpp | 0 5 files changed, 549 insertions(+), 516 deletions(-) rename src/{mainwindow_scriptapi.cpp => script_api/api_map.cpp} (67%) create mode 100644 src/script_api/api_overlay.cpp create mode 100644 src/script_api/api_util.cpp rename src/{ => script_api}/scripting.cpp (100%) diff --git a/porymap.pro b/porymap.pro index 21417d3e..0f1ef60f 100644 --- a/porymap.pro +++ b/porymap.pro @@ -37,7 +37,10 @@ SOURCES += src/core/block.cpp \ src/lib/fex/parser_util.cpp \ src/lib/orderedjson.cpp \ src/core/regionmapeditcommands.cpp \ - src/mainwindow_scriptapi.cpp \ + src/script_api/api_map.cpp \ + src/script_api/api_overlay.cpp \ + src/script_api/api_util.cpp \ + src/script_api/scripting.cpp \ src/ui/aboutporymap.cpp \ src/ui/draggablepixmapitem.cpp \ src/ui/bordermetatilespixmapitem.cpp \ @@ -88,7 +91,6 @@ SOURCES += src/core/block.cpp \ src/main.cpp \ src/mainwindow.cpp \ src/project.cpp \ - src/scripting.cpp \ src/settings.cpp \ src/log.cpp diff --git a/src/mainwindow_scriptapi.cpp b/src/script_api/api_map.cpp similarity index 67% rename from src/mainwindow_scriptapi.cpp rename to src/script_api/api_map.cpp index a28d7d9c..e813f24e 100644 --- a/src/mainwindow_scriptapi.cpp +++ b/src/script_api/api_map.cpp @@ -4,17 +4,6 @@ #include "editcommands.h" #include "config.h" #include "imageproviders.h" -#include "aboutporymap.h" - -QJSValue MainWindow::getBlock(int x, int y) { - if (!this->editor || !this->editor->map) - return QJSValue(); - Block block; - if (!this->editor->map->getBlock(x, y, &block)) { - return Scripting::fromBlock(Block()); - } - return Scripting::fromBlock(block); -} // TODO: "needsFullRedraw" is used when redrawing the map after // changing a metatile's tiles via script. It is unnecessarily @@ -56,6 +45,20 @@ void MainWindow::tryCommitMapChanges(bool commitChanges) { } } +//===================== +// Editing map blocks +//===================== + +QJSValue MainWindow::getBlock(int x, int y) { + if (!this->editor || !this->editor->map) + return QJSValue(); + Block block; + if (!this->editor->map->getBlock(x, y, &block)) { + return Scripting::fromBlock(Block()); + } + return Scripting::fromBlock(block); +} + void MainWindow::setBlock(int x, int y, int metatileId, int collision, int elevation, bool forceRedraw, bool commitChanges) { if (!this->editor || !this->editor->map) return; @@ -102,24 +105,6 @@ void MainWindow::setMetatileId(int x, int y, int metatileId, bool forceRedraw, b this->tryRedrawMapArea(forceRedraw); } -int MainWindow::getBorderMetatileId(int x, int y) { - if (!this->editor || !this->editor->map) - return 0; - if (!this->editor->map->isWithinBorderBounds(x, y)) - return 0; - return this->editor->map->getBorderMetatileId(x, y); -} - -void MainWindow::setBorderMetatileId(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) { - if (!this->editor || !this->editor->map) - return; - if (!this->editor->map->isWithinBorderBounds(x, y)) - return; - this->editor->map->setBorderMetatileId(x, y, metatileId); - this->tryCommitMapChanges(commitChanges); - this->tryRedrawMapArea(forceRedraw); -} - int MainWindow::getCollision(int x, int y) { if (!this->editor || !this->editor->map) return 0; @@ -230,24 +215,6 @@ int MainWindow::getHeight() { return this->editor->map->getHeight(); } -QJSValue MainWindow::getBorderDimensions() { - if (!this->editor || !this->editor->map) - return QJSValue(); - return Scripting::dimensions(this->editor->map->getBorderWidth(), this->editor->map->getBorderHeight()); -} - -int MainWindow::getBorderWidth() { - if (!this->editor || !this->editor->map) - return 0; - return this->editor->map->getBorderWidth(); -} - -int MainWindow::getBorderHeight() { - if (!this->editor || !this->editor->map) - return 0; - return this->editor->map->getBorderHeight(); -} - void MainWindow::setDimensions(int width, int height) { if (!this->editor || !this->editor->map) return; @@ -278,6 +245,46 @@ void MainWindow::setHeight(int height) { this->onMapNeedsRedrawing(); } +//===================== +// Editing map border +//===================== + +int MainWindow::getBorderMetatileId(int x, int y) { + if (!this->editor || !this->editor->map) + return 0; + if (!this->editor->map->isWithinBorderBounds(x, y)) + return 0; + return this->editor->map->getBorderMetatileId(x, y); +} + +void MainWindow::setBorderMetatileId(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) { + if (!this->editor || !this->editor->map) + return; + if (!this->editor->map->isWithinBorderBounds(x, y)) + return; + this->editor->map->setBorderMetatileId(x, y, metatileId); + this->tryCommitMapChanges(commitChanges); + this->tryRedrawMapArea(forceRedraw); +} + +QJSValue MainWindow::getBorderDimensions() { + if (!this->editor || !this->editor->map) + return QJSValue(); + return Scripting::dimensions(this->editor->map->getBorderWidth(), this->editor->map->getBorderHeight()); +} + +int MainWindow::getBorderWidth() { + if (!this->editor || !this->editor->map) + return 0; + return this->editor->map->getBorderWidth(); +} + +int MainWindow::getBorderHeight() { + if (!this->editor || !this->editor->map) + return 0; + return this->editor->map->getBorderHeight(); +} + void MainWindow::setBorderDimensions(int width, int height) { if (!this->editor || !this->editor->map || !projectConfig.getUseCustomBorderSize()) return; @@ -308,224 +315,9 @@ void MainWindow::setBorderHeight(int height) { this->onMapNeedsRedrawing(); } -void MainWindow::clearOverlay(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->clearItems(); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::clearOverlays() { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->clearOverlays(); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::hideOverlay(int layer) { - this->setOverlayVisibility(false, layer); -} - -void MainWindow::hideOverlays() { - this->setOverlaysVisibility(false); -} - -void MainWindow::showOverlay(int layer) { - this->setOverlayVisibility(true, layer); -} - -void MainWindow::showOverlays() { - this->setOverlaysVisibility(true); -} - -bool MainWindow::getOverlayVisibility(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return false; - return !(this->ui->graphicsView_Map->getOverlay(layer)->getHidden()); -} - -void MainWindow::setOverlayVisibility(bool visible, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->setHidden(!visible); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::setOverlaysVisibility(bool visible) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->setOverlaysHidden(!visible); - this->ui->graphicsView_Map->scene()->update(); -} - -int MainWindow::getOverlayX(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return 0; - return this->ui->graphicsView_Map->getOverlay(layer)->getX(); -} - -int MainWindow::getOverlayY(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return 0; - return this->ui->graphicsView_Map->getOverlay(layer)->getY(); -} - -void MainWindow::setOverlayX(int x, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->setX(x); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::setOverlayY(int y, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->setY(y); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::setOverlaysX(int x) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->setOverlaysX(x); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::setOverlaysY(int y) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->setOverlaysY(y); - this->ui->graphicsView_Map->scene()->update(); -} - -QJSValue MainWindow::getOverlayPosition(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return QJSValue(); - Overlay * overlay = this->ui->graphicsView_Map->getOverlay(layer); - return Scripting::position(overlay->getX(), overlay->getY()); -} - -void MainWindow::setOverlayPosition(int x, int y, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->setPosition(x, y); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::setOverlaysPosition(int x, int y) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->setOverlaysPosition(x, y); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::moveOverlay(int deltaX, int deltaY, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->move(deltaX, deltaY); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::moveOverlays(int deltaX, int deltaY) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->moveOverlays(deltaX, deltaY); - this->ui->graphicsView_Map->scene()->update(); -} - -int MainWindow::getOverlayOpacity(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return 0; - return this->ui->graphicsView_Map->getOverlay(layer)->getOpacity(); -} - -void MainWindow::setOverlayOpacity(int opacity, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->setOpacity(opacity); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::setOverlaysOpacity(int opacity) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->setOverlaysOpacity(opacity); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::addText(QString text, int x, int y, QString color, int fontSize, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->addText(text, x, y, color, fontSize); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::addRect(int x, int y, int width, int height, QString color, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->addRect(x, y, width, height, color, false); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::addFilledRect(int x, int y, int width, int height, QString color, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->addRect(x, y, width, height, color, true); - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::addImage(int x, int y, QString filepath, int layer, bool useCache) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, filepath, useCache)) - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::createImage(int x, int y, QString filepath, int width, int height, unsigned offset, qreal hScale, qreal vScale, int paletteId, bool setTransparency, int layer, bool useCache) { - if (!this->ui || !this->ui->graphicsView_Map || !this->editor || !this->editor->map || !this->editor->map->layout - || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) - return; - QList palette; - if (paletteId != -1) - palette = Tileset::getPalette(paletteId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); - if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, filepath, useCache, width, height, offset, hScale, vScale, palette, setTransparency)) - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::addTileImage(int x, int y, int tileId, bool xflip, bool yflip, int paletteId, bool setTransparency, int layer) { - if (!this->ui || !this->ui->graphicsView_Map || !this->editor || !this->editor->map || !this->editor->map->layout - || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) - return; - QImage image = getPalettedTileImage(tileId, - this->editor->map->layout->tileset_primary, - this->editor->map->layout->tileset_secondary, - paletteId) - .mirrored(xflip, yflip); - if (setTransparency) - image.setColor(0, qRgba(0, 0, 0, 0)); - if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, image)) - this->ui->graphicsView_Map->scene()->update(); -} - -void MainWindow::addTileImage(int x, int y, QJSValue tileObj, bool setTransparency, int layer) { - Tile tile = Scripting::toTile(tileObj); - this->addTileImage(x, y, tile.tileId, tile.xflip, tile.yflip, tile.palette, setTransparency, layer); -} - -void MainWindow::addMetatileImage(int x, int y, int metatileId, bool setTransparency, int layer) { - if (!this->ui || !this->ui->graphicsView_Map || !this->editor || !this->editor->map || !this->editor->map->layout - || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) - return; - QImage image = getMetatileImage(static_cast(metatileId), - this->editor->map->layout->tileset_primary, - this->editor->map->layout->tileset_secondary, - this->editor->map->metatileLayerOrder, - this->editor->map->metatileLayerOpacity); - if (setTransparency) - image.setColor(0, qRgba(0, 0, 0, 0)); - if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, image)) - this->ui->graphicsView_Map->scene()->update(); -} +//====================== +// Editing map tilesets +//====================== void MainWindow::refreshAfterPaletteChange(Tileset *tileset) { if (this->tilesetEditor) { @@ -719,61 +511,24 @@ int MainWindow::getNumPrimaryTilesetMetatiles() { return this->editor->map->layout->tileset_primary->metatiles.length(); } -int MainWindow::getMaxPrimaryTilesetMetatiles() { - if (!this->editor || !this->editor->project) - return 0; - return this->editor->project->getNumMetatilesPrimary(); -} - int MainWindow::getNumSecondaryTilesetMetatiles() { if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) return 0; return this->editor->map->layout->tileset_secondary->metatiles.length(); } -int MainWindow::getMaxSecondaryTilesetMetatiles() { - if (!this->editor || !this->editor->project) - return 0; - return this->editor->project->getNumMetatilesTotal() - this->editor->project->getNumMetatilesPrimary(); -} - - int MainWindow::getNumPrimaryTilesetTiles() { if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) return 0; return this->editor->map->layout->tileset_primary->tiles.length(); } -int MainWindow::getMaxPrimaryTilesetTiles() { - if (!this->editor || !this->editor->project) - return 0; - return this->editor->project->getNumTilesPrimary(); -} - int MainWindow::getNumSecondaryTilesetTiles() { if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary) return 0; return this->editor->map->layout->tileset_secondary->tiles.length(); } -int MainWindow::getMaxSecondaryTilesetTiles() { - if (!this->editor || !this->editor->project) - return 0; - return this->editor->project->getNumTilesTotal() - this->editor->project->getNumTilesPrimary(); -} - -bool MainWindow::isPrimaryTileset(QString tilesetName) { - if (!this->editor || !this->editor->project) - return false; - return this->editor->project->tilesetLabels["primary"].contains(tilesetName); -} - -bool MainWindow::isSecondaryTileset(QString tilesetName) { - if (!this->editor || !this->editor->project) - return false; - return this->editor->project->tilesetLabels["secondary"].contains(tilesetName); -} - QString MainWindow::getPrimaryTileset() { if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary) return QString(); @@ -794,169 +549,6 @@ void MainWindow::setSecondaryTileset(QString tileset) { this->on_comboBox_SecondaryTileset_currentTextChanged(tileset); } -void MainWindow::setGridVisibility(bool visible) { - this->ui->checkBox_ToggleGrid->setChecked(visible); -} - -bool MainWindow::getGridVisibility() { - return this->ui->checkBox_ToggleGrid->isChecked(); -} - -void MainWindow::setBorderVisibility(bool visible) { - this->editor->toggleBorderVisibility(visible, false); -} - -bool MainWindow::getBorderVisibility() { - return this->ui->checkBox_ToggleBorder->isChecked(); -} - -void MainWindow::setSmartPathsEnabled(bool visible) { - this->ui->checkBox_smartPaths->setChecked(visible); -} - -bool MainWindow::getSmartPathsEnabled() { - return this->ui->checkBox_smartPaths->isChecked(); -} - -void MainWindow::registerAction(QString functionName, QString actionName, QString shortcut) { - if (!this->ui || !this->ui->menuTools) - return; - - Scripting::registerAction(functionName, actionName); - if (Scripting::numRegisteredActions() == 1) { - QAction *section = this->ui->menuTools->addSection("Custom Actions"); - this->registeredActions.append(section); - } - QAction *action = this->ui->menuTools->addAction(actionName, [actionName](){ - Scripting::invokeAction(actionName); - }); - if (!shortcut.isEmpty()) { - action->setShortcut(QKeySequence(shortcut)); - } - this->registeredActions.append(action); -} - -void MainWindow::setTimeout(QJSValue callback, int milliseconds) { - if (!callback.isCallable() || milliseconds < 0) - return; - - QTimer *timer = new QTimer(0); - connect(timer, &QTimer::timeout, [=](){ - this->invokeCallback(callback); - }); - connect(timer, &QTimer::timeout, timer, &QTimer::deleteLater); - timer->setSingleShot(true); - timer->start(milliseconds); -} - -void MainWindow::invokeCallback(QJSValue callback) { - Scripting::tryErrorJS(callback.call()); -} - -void MainWindow::log(QString message) { - logInfo(message); -} - -void MainWindow::warn(QString message) { - logWarn(message); -} - -void MainWindow::error(QString message) { - logError(message); -} - -void MainWindow::runMessageBox(QString text, QString informativeText, QString detailedText, QMessageBox::Icon icon) { - QMessageBox messageBox(this); - messageBox.setText(text); - messageBox.setInformativeText(informativeText); - messageBox.setDetailedText(detailedText); - messageBox.setIcon(icon); - messageBox.exec(); -} - -void MainWindow::showMessage(QString text, QString informativeText, QString detailedText) { - this->runMessageBox(text, informativeText, detailedText, QMessageBox::Information); -} - -void MainWindow::showWarning(QString text, QString informativeText, QString detailedText) { - this->runMessageBox(text, informativeText, detailedText, QMessageBox::Warning); -} - -void MainWindow::showError(QString text, QString informativeText, QString detailedText) { - this->runMessageBox(text, informativeText, detailedText, QMessageBox::Critical); -} - -bool MainWindow::showQuestion(QString text, QString informativeText, QString detailedText) { - QMessageBox messageBox(this); - messageBox.setText(text); - messageBox.setInformativeText(informativeText); - messageBox.setDetailedText(detailedText); - messageBox.setIcon(QMessageBox::Question); - messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - return messageBox.exec() == QMessageBox::Yes; -} - -QJSValue MainWindow::getInputText(QString title, QString label, QString defaultValue) { - bool ok; - QString input = QInputDialog::getText(this, title, label, QLineEdit::Normal, defaultValue, &ok); - return Scripting::dialogInput(input, ok); -} - -QJSValue MainWindow::getInputNumber(QString title, QString label, double defaultValue, double min, double max, int decimals, double step) { - bool ok; - double input = QInputDialog::getDouble(this, title, label, defaultValue, min, max, decimals, &ok, Qt::WindowFlags(), step); - return Scripting::dialogInput(input, ok); -} - -QJSValue MainWindow::getInputItem(QString title, QString label, QStringList items, int defaultValue, bool editable) { - bool ok; - QString input = QInputDialog::getItem(this, title, label, items, defaultValue, editable, &ok); - return Scripting::dialogInput(input, ok); -} - -QList MainWindow::getMetatileLayerOrder() { - if (!this->editor || !this->editor->map) - return QList(); - return this->editor->map->metatileLayerOrder; -} - -void MainWindow::setMetatileLayerOrder(QList order) { - if (!this->editor || !this->editor->map) - return; - - const int numLayers = 3; - int size = order.size(); - if (size < numLayers) { - logError(QString("Metatile layer order has insufficient elements (%1), needs at least %2.").arg(size).arg(numLayers)); - return; - } - bool invalid = false; - for (int i = 0; i < numLayers; i++) { - int layer = order.at(i); - if (layer < 0 || layer >= numLayers) { - logError(QString("'%1' is not a valid metatile layer order value, must be in range 0-%2.").arg(layer).arg(numLayers - 1)); - invalid = true; - } - } - if (invalid) return; - - this->editor->map->metatileLayerOrder = order; - this->refreshAfterPalettePreviewChange(); -} - -QList MainWindow::getMetatileLayerOpacity() { - if (!this->editor || !this->editor->map) - return QList(); - return this->editor->map->metatileLayerOpacity; -} - -void MainWindow::setMetatileLayerOpacity(QList order) { - if (!this->editor || !this->editor->map) - return; - this->editor->map->metatileLayerOpacity = order; - this->refreshAfterPalettePreviewChange(); -} - void MainWindow::saveMetatilesByMetatileId(int metatileId) { Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); if (this->editor->project && tileset) @@ -1184,55 +776,9 @@ QJSValue MainWindow::getTilePixels(int tileId) { return pixelArray; } -int MainWindow::getNumTilesInMetatile() { - return projectConfig.getTripleLayerMetatilesEnabled() ? 12 : 8; -} - -int MainWindow::getNumMetatileLayers() { - return projectConfig.getTripleLayerMetatilesEnabled() ? 3 : 2; -} - -QString MainWindow::getBaseGameVersion() { - return projectConfig.getBaseGameVersionString(); -} - -QJSValue MainWindow::getPorymapVersion() { - AboutPorymap *window = new AboutPorymap(this); - QJSValue version = Scripting::version(window->getVersionNumbers()); - delete window; - return version; -} - -QList MainWindow::getCustomScripts() { - return projectConfig.getCustomScripts(); -} - -int MainWindow::getMainTab() { - if (!this->ui || !this->ui->mainTabBar) - return -1; - return this->ui->mainTabBar->currentIndex(); -} - -void MainWindow::setMainTab(int index) { - if (!this->ui || !this->ui->mainTabBar || index < 0 || index >= this->ui->mainTabBar->count()) - return; - // Can't select Wild Encounters tab if it's disabled - if (index == 4 && !projectConfig.getEncounterJsonActive()) - return; - this->on_mainTabBar_tabBarClicked(index); -} - -int MainWindow::getMapViewTab() { - if (!this->ui || !this->ui->mapViewTab) - return -1; - return this->ui->mapViewTab->currentIndex(); -} - -void MainWindow::setMapViewTab(int index) { - if (this->getMainTab() != 0 || !this->ui->mapViewTab || index < 0 || index >= this->ui->mapViewTab->count()) - return; - this->on_mapViewTab_tabBarClicked(index); -} +//===================== +// Editing map header +//===================== bool MainWindow::gameStringToBool(QString s) { return (s.toInt() > 0 || s == "TRUE"); diff --git a/src/script_api/api_overlay.cpp b/src/script_api/api_overlay.cpp new file mode 100644 index 00000000..187bee2e --- /dev/null +++ b/src/script_api/api_overlay.cpp @@ -0,0 +1,224 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "scripting.h" +#include "config.h" +#include "imageproviders.h" + +void MainWindow::clearOverlay(int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->getOverlay(layer)->clearItems(); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::clearOverlays() { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->clearOverlays(); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::hideOverlay(int layer) { + this->setOverlayVisibility(false, layer); +} + +void MainWindow::hideOverlays() { + this->setOverlaysVisibility(false); +} + +void MainWindow::showOverlay(int layer) { + this->setOverlayVisibility(true, layer); +} + +void MainWindow::showOverlays() { + this->setOverlaysVisibility(true); +} + +bool MainWindow::getOverlayVisibility(int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return false; + return !(this->ui->graphicsView_Map->getOverlay(layer)->getHidden()); +} + +void MainWindow::setOverlayVisibility(bool visible, int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->getOverlay(layer)->setHidden(!visible); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::setOverlaysVisibility(bool visible) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->setOverlaysHidden(!visible); + this->ui->graphicsView_Map->scene()->update(); +} + +int MainWindow::getOverlayX(int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return 0; + return this->ui->graphicsView_Map->getOverlay(layer)->getX(); +} + +int MainWindow::getOverlayY(int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return 0; + return this->ui->graphicsView_Map->getOverlay(layer)->getY(); +} + +void MainWindow::setOverlayX(int x, int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->getOverlay(layer)->setX(x); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::setOverlayY(int y, int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->getOverlay(layer)->setY(y); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::setOverlaysX(int x) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->setOverlaysX(x); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::setOverlaysY(int y) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->setOverlaysY(y); + this->ui->graphicsView_Map->scene()->update(); +} + +QJSValue MainWindow::getOverlayPosition(int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return QJSValue(); + Overlay * overlay = this->ui->graphicsView_Map->getOverlay(layer); + return Scripting::position(overlay->getX(), overlay->getY()); +} + +void MainWindow::setOverlayPosition(int x, int y, int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->getOverlay(layer)->setPosition(x, y); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::setOverlaysPosition(int x, int y) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->setOverlaysPosition(x, y); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::moveOverlay(int deltaX, int deltaY, int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->getOverlay(layer)->move(deltaX, deltaY); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::moveOverlays(int deltaX, int deltaY) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->moveOverlays(deltaX, deltaY); + this->ui->graphicsView_Map->scene()->update(); +} + +int MainWindow::getOverlayOpacity(int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return 0; + return this->ui->graphicsView_Map->getOverlay(layer)->getOpacity(); +} + +void MainWindow::setOverlayOpacity(int opacity, int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->getOverlay(layer)->setOpacity(opacity); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::setOverlaysOpacity(int opacity) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->setOverlaysOpacity(opacity); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::addText(QString text, int x, int y, QString color, int fontSize, int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->getOverlay(layer)->addText(text, x, y, color, fontSize); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::addRect(int x, int y, int width, int height, QString color, int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->getOverlay(layer)->addRect(x, y, width, height, color, false); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::addFilledRect(int x, int y, int width, int height, QString color, int layer) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + this->ui->graphicsView_Map->getOverlay(layer)->addRect(x, y, width, height, color, true); + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::addImage(int x, int y, QString filepath, int layer, bool useCache) { + if (!this->ui || !this->ui->graphicsView_Map) + return; + if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, filepath, useCache)) + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::createImage(int x, int y, QString filepath, int width, int height, unsigned offset, qreal hScale, qreal vScale, int paletteId, bool setTransparency, int layer, bool useCache) { + if (!this->ui || !this->ui->graphicsView_Map || !this->editor || !this->editor->map || !this->editor->map->layout + || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) + return; + QList palette; + if (paletteId != -1) + palette = Tileset::getPalette(paletteId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); + if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, filepath, useCache, width, height, offset, hScale, vScale, palette, setTransparency)) + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::addTileImage(int x, int y, int tileId, bool xflip, bool yflip, int paletteId, bool setTransparency, int layer) { + if (!this->ui || !this->ui->graphicsView_Map || !this->editor || !this->editor->map || !this->editor->map->layout + || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) + return; + QImage image = getPalettedTileImage(tileId, + this->editor->map->layout->tileset_primary, + this->editor->map->layout->tileset_secondary, + paletteId) + .mirrored(xflip, yflip); + if (setTransparency) + image.setColor(0, qRgba(0, 0, 0, 0)); + if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, image)) + this->ui->graphicsView_Map->scene()->update(); +} + +void MainWindow::addTileImage(int x, int y, QJSValue tileObj, bool setTransparency, int layer) { + Tile tile = Scripting::toTile(tileObj); + this->addTileImage(x, y, tile.tileId, tile.xflip, tile.yflip, tile.palette, setTransparency, layer); +} + +void MainWindow::addMetatileImage(int x, int y, int metatileId, bool setTransparency, int layer) { + if (!this->ui || !this->ui->graphicsView_Map || !this->editor || !this->editor->map || !this->editor->map->layout + || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) + return; + QImage image = getMetatileImage(static_cast(metatileId), + this->editor->map->layout->tileset_primary, + this->editor->map->layout->tileset_secondary, + this->editor->map->metatileLayerOrder, + this->editor->map->metatileLayerOpacity); + if (setTransparency) + image.setColor(0, qRgba(0, 0, 0, 0)); + if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, image)) + this->ui->graphicsView_Map->scene()->update(); +} diff --git a/src/script_api/api_util.cpp b/src/script_api/api_util.cpp new file mode 100644 index 00000000..3fe69bf2 --- /dev/null +++ b/src/script_api/api_util.cpp @@ -0,0 +1,261 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "scripting.h" +#include "config.h" +#include "aboutporymap.h" + +void MainWindow::registerAction(QString functionName, QString actionName, QString shortcut) { + if (!this->ui || !this->ui->menuTools) + return; + + Scripting::registerAction(functionName, actionName); + if (Scripting::numRegisteredActions() == 1) { + QAction *section = this->ui->menuTools->addSection("Custom Actions"); + this->registeredActions.append(section); + } + QAction *action = this->ui->menuTools->addAction(actionName, [actionName](){ + Scripting::invokeAction(actionName); + }); + if (!shortcut.isEmpty()) { + action->setShortcut(QKeySequence(shortcut)); + } + this->registeredActions.append(action); +} + +void MainWindow::setTimeout(QJSValue callback, int milliseconds) { + if (!callback.isCallable() || milliseconds < 0) + return; + + QTimer *timer = new QTimer(0); + connect(timer, &QTimer::timeout, [=](){ + this->invokeCallback(callback); + }); + connect(timer, &QTimer::timeout, timer, &QTimer::deleteLater); + timer->setSingleShot(true); + timer->start(milliseconds); +} + +void MainWindow::invokeCallback(QJSValue callback) { + Scripting::tryErrorJS(callback.call()); +} + +void MainWindow::log(QString message) { + logInfo(message); +} + +void MainWindow::warn(QString message) { + logWarn(message); +} + +void MainWindow::error(QString message) { + logError(message); +} + +void MainWindow::runMessageBox(QString text, QString informativeText, QString detailedText, QMessageBox::Icon icon) { + QMessageBox messageBox(this); + messageBox.setText(text); + messageBox.setInformativeText(informativeText); + messageBox.setDetailedText(detailedText); + messageBox.setIcon(icon); + messageBox.exec(); +} + +void MainWindow::showMessage(QString text, QString informativeText, QString detailedText) { + this->runMessageBox(text, informativeText, detailedText, QMessageBox::Information); +} + +void MainWindow::showWarning(QString text, QString informativeText, QString detailedText) { + this->runMessageBox(text, informativeText, detailedText, QMessageBox::Warning); +} + +void MainWindow::showError(QString text, QString informativeText, QString detailedText) { + this->runMessageBox(text, informativeText, detailedText, QMessageBox::Critical); +} + +bool MainWindow::showQuestion(QString text, QString informativeText, QString detailedText) { + QMessageBox messageBox(this); + messageBox.setText(text); + messageBox.setInformativeText(informativeText); + messageBox.setDetailedText(detailedText); + messageBox.setIcon(QMessageBox::Question); + messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + return messageBox.exec() == QMessageBox::Yes; +} + +QJSValue MainWindow::getInputText(QString title, QString label, QString defaultValue) { + bool ok; + QString input = QInputDialog::getText(this, title, label, QLineEdit::Normal, defaultValue, &ok); + return Scripting::dialogInput(input, ok); +} + +QJSValue MainWindow::getInputNumber(QString title, QString label, double defaultValue, double min, double max, int decimals, double step) { + bool ok; + double input = QInputDialog::getDouble(this, title, label, defaultValue, min, max, decimals, &ok, Qt::WindowFlags(), step); + return Scripting::dialogInput(input, ok); +} + +QJSValue MainWindow::getInputItem(QString title, QString label, QStringList items, int defaultValue, bool editable) { + bool ok; + QString input = QInputDialog::getItem(this, title, label, items, defaultValue, editable, &ok); + return Scripting::dialogInput(input, ok); +} + +int MainWindow::getMainTab() { + if (!this->ui || !this->ui->mainTabBar) + return -1; + return this->ui->mainTabBar->currentIndex(); +} + +void MainWindow::setMainTab(int index) { + if (!this->ui || !this->ui->mainTabBar || index < 0 || index >= this->ui->mainTabBar->count()) + return; + // Can't select Wild Encounters tab if it's disabled + if (index == 4 && !projectConfig.getEncounterJsonActive()) + return; + this->on_mainTabBar_tabBarClicked(index); +} + +int MainWindow::getMapViewTab() { + if (!this->ui || !this->ui->mapViewTab) + return -1; + return this->ui->mapViewTab->currentIndex(); +} + +void MainWindow::setMapViewTab(int index) { + if (this->getMainTab() != 0 || !this->ui->mapViewTab || index < 0 || index >= this->ui->mapViewTab->count()) + return; + this->on_mapViewTab_tabBarClicked(index); +} + +void MainWindow::setGridVisibility(bool visible) { + this->ui->checkBox_ToggleGrid->setChecked(visible); +} + +bool MainWindow::getGridVisibility() { + return this->ui->checkBox_ToggleGrid->isChecked(); +} + +void MainWindow::setBorderVisibility(bool visible) { + this->editor->toggleBorderVisibility(visible, false); +} + +bool MainWindow::getBorderVisibility() { + return this->ui->checkBox_ToggleBorder->isChecked(); +} + +void MainWindow::setSmartPathsEnabled(bool visible) { + this->ui->checkBox_smartPaths->setChecked(visible); +} + +bool MainWindow::getSmartPathsEnabled() { + return this->ui->checkBox_smartPaths->isChecked(); +} + +QList MainWindow::getMetatileLayerOrder() { + if (!this->editor || !this->editor->map) + return QList(); + return this->editor->map->metatileLayerOrder; +} + +void MainWindow::setMetatileLayerOrder(QList order) { + if (!this->editor || !this->editor->map) + return; + + const int numLayers = 3; + int size = order.size(); + if (size < numLayers) { + logError(QString("Metatile layer order has insufficient elements (%1), needs at least %2.").arg(size).arg(numLayers)); + return; + } + bool invalid = false; + for (int i = 0; i < numLayers; i++) { + int layer = order.at(i); + if (layer < 0 || layer >= numLayers) { + logError(QString("'%1' is not a valid metatile layer order value, must be in range 0-%2.").arg(layer).arg(numLayers - 1)); + invalid = true; + } + } + if (invalid) return; + + this->editor->map->metatileLayerOrder = order; + this->refreshAfterPalettePreviewChange(); +} + +QList MainWindow::getMetatileLayerOpacity() { + if (!this->editor || !this->editor->map) + return QList(); + return this->editor->map->metatileLayerOpacity; +} + +void MainWindow::setMetatileLayerOpacity(QList order) { + if (!this->editor || !this->editor->map) + return; + this->editor->map->metatileLayerOpacity = order; + this->refreshAfterPalettePreviewChange(); +} + +bool MainWindow::isPrimaryTileset(QString tilesetName) { + if (!this->editor || !this->editor->project) + return false; + return this->editor->project->tilesetLabels["primary"].contains(tilesetName); +} + +bool MainWindow::isSecondaryTileset(QString tilesetName) { + if (!this->editor || !this->editor->project) + return false; + return this->editor->project->tilesetLabels["secondary"].contains(tilesetName); +} + + +//================================= +// Here below should be constants +//================================= + + +int MainWindow::getMaxPrimaryTilesetMetatiles() { + if (!this->editor || !this->editor->project) + return 0; + return this->editor->project->getNumMetatilesPrimary(); +} + +int MainWindow::getMaxSecondaryTilesetMetatiles() { + if (!this->editor || !this->editor->project) + return 0; + return this->editor->project->getNumMetatilesTotal() - this->editor->project->getNumMetatilesPrimary(); +} + +int MainWindow::getMaxPrimaryTilesetTiles() { + if (!this->editor || !this->editor->project) + return 0; + return this->editor->project->getNumTilesPrimary(); +} + +int MainWindow::getMaxSecondaryTilesetTiles() { + if (!this->editor || !this->editor->project) + return 0; + return this->editor->project->getNumTilesTotal() - this->editor->project->getNumTilesPrimary(); +} + +int MainWindow::getNumTilesInMetatile() { + return projectConfig.getTripleLayerMetatilesEnabled() ? 12 : 8; +} + +int MainWindow::getNumMetatileLayers() { + return projectConfig.getTripleLayerMetatilesEnabled() ? 3 : 2; +} + +QString MainWindow::getBaseGameVersion() { + return projectConfig.getBaseGameVersionString(); +} + +QJSValue MainWindow::getPorymapVersion() { + AboutPorymap *window = new AboutPorymap(this); + QJSValue version = Scripting::version(window->getVersionNumbers()); + delete window; + return version; +} + +QList MainWindow::getCustomScripts() { + return projectConfig.getCustomScripts(); +} + diff --git a/src/scripting.cpp b/src/script_api/scripting.cpp similarity index 100% rename from src/scripting.cpp rename to src/script_api/scripting.cpp From a3dadadd5b56132b8bb559f1060de9f8849bf68e Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 4 Sep 2022 21:17:50 -0400 Subject: [PATCH 2/7] Reorganize overlay functions under MapView --- include/mainwindow.h | 37 +----- include/ui/mapview.h | 52 ++++++-- porymap.pro | 1 + src/mainwindow.cpp | 6 +- src/script_api/api_overlay.cpp | 235 ++++++++++++++------------------- src/script_api/scripting.cpp | 1 + src/ui/graphicsview.cpp | 38 +----- 7 files changed, 157 insertions(+), 213 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 703d6b95..0ee96c69 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -42,6 +42,8 @@ public: MainWindow(const MainWindow &) = delete; MainWindow & operator = (const MainWindow &) = delete; + MapView *getMapView(); + // Scripting API Q_INVOKABLE QJSValue getBlock(int x, int y); void tryRedrawMapArea(bool forceRedraw); @@ -76,40 +78,6 @@ public: Q_INVOKABLE void setBorderDimensions(int width, int height); Q_INVOKABLE void setBorderWidth(int width); Q_INVOKABLE void setBorderHeight(int height); - Q_INVOKABLE void clearOverlay(int layer = 0); - Q_INVOKABLE void clearOverlays(); - Q_INVOKABLE void hideOverlay(int layer = 0); - Q_INVOKABLE void hideOverlays(); - Q_INVOKABLE void showOverlay(int layer = 0); - Q_INVOKABLE void showOverlays(); - Q_INVOKABLE bool getOverlayVisibility(int layer = 0); - Q_INVOKABLE void setOverlayVisibility(bool visible, int layer = 0); - Q_INVOKABLE void setOverlaysVisibility(bool visible); - Q_INVOKABLE int getOverlayX(int layer = 0); - Q_INVOKABLE int getOverlayY(int layer = 0); - Q_INVOKABLE void setOverlayX(int x, int layer = 0); - Q_INVOKABLE void setOverlayY(int y, int layer = 0); - Q_INVOKABLE void setOverlaysX(int x); - Q_INVOKABLE void setOverlaysY(int y); - Q_INVOKABLE QJSValue getOverlayPosition(int layer = 0); - Q_INVOKABLE void setOverlayPosition(int x, int y, int layer = 0); - Q_INVOKABLE void setOverlaysPosition(int x, int y); - Q_INVOKABLE void moveOverlay(int deltaX, int deltaY, int layer = 0); - Q_INVOKABLE void moveOverlays(int deltaX, int deltaY); - Q_INVOKABLE int getOverlayOpacity(int layer); - Q_INVOKABLE void setOverlayOpacity(int opacity, int layer = 0); - Q_INVOKABLE void setOverlaysOpacity(int opacity); - Q_INVOKABLE void addText(QString text, int x, int y, QString color = "#000000", int fontSize = 12, int layer = 0); - Q_INVOKABLE void addRect(int x, int y, int width, int height, QString color = "#000000", int layer = 0); - Q_INVOKABLE void addFilledRect(int x, int y, int width, int height, QString color = "#000000", int layer = 0); - Q_INVOKABLE void addImage(int x, int y, QString filepath, int layer = 0, bool useCache = true); - Q_INVOKABLE void createImage(int x, int y, QString filepath, - int width = -1, int height = -1, unsigned offset = 0, - qreal hScale = 1, qreal vScale = 1, int paletteId = -1, bool setTransparency = false, - int layer = 0, bool useCache = true); - Q_INVOKABLE void addTileImage(int x, int y, int tileId, bool xflip, bool yflip, int paletteId, bool setTransparency = false, int layer = 0); - Q_INVOKABLE void addTileImage(int x, int y, QJSValue tileObj, bool setTransparency = false, int layer = 0); - Q_INVOKABLE void addMetatileImage(int x, int y, int metatileId, bool setTransparency = false, int layer = 0); void refreshAfterPaletteChange(Tileset *tileset); void setTilesetPalette(Tileset *tileset, int paletteIndex, QList> colors); Q_INVOKABLE void setPrimaryTilesetPalette(int paletteIndex, QList> colors); @@ -226,7 +194,6 @@ public: Q_INVOKABLE int getFloorNumber(); Q_INVOKABLE void setFloorNumber(int floorNumber); - private slots: void on_action_Open_Project_triggered(); void on_action_Reload_Project_triggered(); diff --git a/include/ui/mapview.h b/include/ui/mapview.h index 54b1760f..5954f710 100644 --- a/include/ui/mapview.h +++ b/include/ui/mapview.h @@ -1,24 +1,58 @@ #ifndef MAPVIEW_H #define MAPVIEW_H +#include #include "graphicsview.h" #include "overlay.h" class MapView : public GraphicsView { + Q_OBJECT + public: MapView() : GraphicsView() {} MapView(QWidget *parent) : GraphicsView(parent) {} - Overlay * getOverlay(int layer); - void clearOverlays(); - void setOverlaysHidden(bool hidden); - void setOverlaysX(int x); - void setOverlaysY(int y); - void setOverlaysPosition(int x, int y); - void moveOverlays(int deltaX, int deltaY); - void setOverlaysOpacity(int opacity); -public: + Overlay * getOverlay(int layer); + void clearOverlayMap(); + + // Overlay scripting API + Q_INVOKABLE void clear(int layer); + Q_INVOKABLE void clear(); + Q_INVOKABLE void hide(int layer); + Q_INVOKABLE void hide(); + Q_INVOKABLE void show(int layer); + Q_INVOKABLE void show(); + Q_INVOKABLE bool getVisibility(int layer = 0); + Q_INVOKABLE void setVisibility(bool visible, int layer); + Q_INVOKABLE void setVisibility(bool visible); + Q_INVOKABLE int getX(int layer = 0); + Q_INVOKABLE int getY(int layer = 0); + Q_INVOKABLE void setX(int x, int layer); + Q_INVOKABLE void setX(int x); + Q_INVOKABLE void setY(int y, int layer); + Q_INVOKABLE void setY(int y); + Q_INVOKABLE QJSValue getPosition(int layer = 0); + Q_INVOKABLE void setPosition(int x, int y, int layer); + Q_INVOKABLE void setPosition(int x, int y); + Q_INVOKABLE void move(int deltaX, int deltaY, int layer); + Q_INVOKABLE void move(int deltaX, int deltaY); + Q_INVOKABLE int getOpacity(int layer = 0); + Q_INVOKABLE void setOpacity(int opacity, int layer); + Q_INVOKABLE void setOpacity(int opacity); + Q_INVOKABLE void addText(QString text, int x, int y, QString color = "#000000", int fontSize = 12, int layer = 0); + Q_INVOKABLE void addRect(int x, int y, int width, int height, QString color = "#000000", int layer = 0); + Q_INVOKABLE void addFilledRect(int x, int y, int width, int height, QString color = "#000000", int layer = 0); + Q_INVOKABLE void addImage(int x, int y, QString filepath, int layer = 0, bool useCache = true); + Q_INVOKABLE void createImage(int x, int y, QString filepath, + int width = -1, int height = -1, unsigned offset = 0, + qreal hScale = 1, qreal vScale = 1, int paletteId = -1, bool setTransparency = false, + int layer = 0, bool useCache = true); + Q_INVOKABLE void addTileImage(int x, int y, int tileId, bool xflip, bool yflip, int paletteId, bool setTransparency = false, int layer = 0); + Q_INVOKABLE void addTileImage(int x, int y, QJSValue tileObj, bool setTransparency = false, int layer = 0); + Q_INVOKABLE void addMetatileImage(int x, int y, int metatileId, bool setTransparency = false, int layer = 0); + +private: QMap overlayMap; protected: void drawForeground(QPainter *painter, const QRectF &rect); diff --git a/porymap.pro b/porymap.pro index 0f1ef60f..c0ab808c 100644 --- a/porymap.pro +++ b/porymap.pro @@ -137,6 +137,7 @@ HEADERS += include/core/block.h \ include/ui/graphicsview.h \ include/ui/imageproviders.h \ include/ui/mappixmapitem.h \ + include/ui/mapview.h \ include/ui/regionmappixmapitem.h \ include/ui/citymappixmapitem.h \ include/ui/mapsceneeventfilter.h \ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ce8e55be..474c2315 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -604,7 +604,7 @@ void MainWindow::on_action_Open_Project_triggered() if (!dir.isEmpty()) { if (this->editor && this->editor->project) { Scripting::cb_ProjectClosed(this->editor->project->root); - this->ui->graphicsView_Map->clearOverlays(); + this->ui->graphicsView_Map->clearOverlayMap(); } porymapConfig.setRecentProject(dir); setWindowDisabled(!openProject(dir)); @@ -3236,3 +3236,7 @@ void MainWindow::closeEvent(QCloseEvent *event) { QMainWindow::closeEvent(event); } + +MapView *MainWindow::getMapView() { + return this->ui->graphicsView_Map; +} diff --git a/src/script_api/api_overlay.cpp b/src/script_api/api_overlay.cpp index 187bee2e..3ce3e145 100644 --- a/src/script_api/api_overlay.cpp +++ b/src/script_api/api_overlay.cpp @@ -1,195 +1,162 @@ -#include "mainwindow.h" -#include "ui_mainwindow.h" +#include "mapview.h" #include "scripting.h" -#include "config.h" #include "imageproviders.h" -void MainWindow::clearOverlay(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->clearItems(); - this->ui->graphicsView_Map->scene()->update(); +void MapView::clear(int layer) { + this->getOverlay(layer)->clearItems(); + this->scene()->update(); } -void MainWindow::clearOverlays() { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->clearOverlays(); - this->ui->graphicsView_Map->scene()->update(); +// Overload. No layer provided, clear all layers +void MapView::clear() { + this->clearOverlayMap(); + this->scene()->update(); } -void MainWindow::hideOverlay(int layer) { - this->setOverlayVisibility(false, layer); +void MapView::hide(int layer) { + this->setVisibility(false, layer); } -void MainWindow::hideOverlays() { - this->setOverlaysVisibility(false); +// Overload. No layer provided, hide all layers +void MapView::hide() { + this->setVisibility(false); } -void MainWindow::showOverlay(int layer) { - this->setOverlayVisibility(true, layer); +void MapView::show(int layer) { + this->setVisibility(true, layer); } -void MainWindow::showOverlays() { - this->setOverlaysVisibility(true); +// Overload. No layer provided, show all layers +void MapView::show() { + this->setVisibility(true); } -bool MainWindow::getOverlayVisibility(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return false; - return !(this->ui->graphicsView_Map->getOverlay(layer)->getHidden()); +bool MapView::getVisibility(int layer) { + return !(this->getOverlay(layer)->getHidden()); } -void MainWindow::setOverlayVisibility(bool visible, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->setHidden(!visible); - this->ui->graphicsView_Map->scene()->update(); +void MapView::setVisibility(bool visible, int layer) { + this->getOverlay(layer)->setHidden(!visible); + this->scene()->update(); } -void MainWindow::setOverlaysVisibility(bool visible) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->setOverlaysHidden(!visible); - this->ui->graphicsView_Map->scene()->update(); +// Overload. No layer provided, set visibility of all layers +void MapView::setVisibility(bool visible) { + foreach (Overlay * layer, this->overlayMap) + layer->setHidden(!visible); + this->scene()->update(); } -int MainWindow::getOverlayX(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return 0; - return this->ui->graphicsView_Map->getOverlay(layer)->getX(); +int MapView::getX(int layer) { + return this->getOverlay(layer)->getX(); } -int MainWindow::getOverlayY(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return 0; - return this->ui->graphicsView_Map->getOverlay(layer)->getY(); +int MapView::getY(int layer) { + return this->getOverlay(layer)->getY(); } -void MainWindow::setOverlayX(int x, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->setX(x); - this->ui->graphicsView_Map->scene()->update(); +void MapView::setX(int x, int layer) { + this->getOverlay(layer)->setX(x); + this->scene()->update(); } -void MainWindow::setOverlayY(int y, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->setY(y); - this->ui->graphicsView_Map->scene()->update(); +// Overload. No layer provided, set x of all layers +void MapView::setX(int x) { + foreach (Overlay * layer, this->overlayMap) + layer->setX(x); + this->scene()->update(); } -void MainWindow::setOverlaysX(int x) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->setOverlaysX(x); - this->ui->graphicsView_Map->scene()->update(); +void MapView::setY(int y, int layer) { + this->getOverlay(layer)->setY(y); + this->scene()->update(); } -void MainWindow::setOverlaysY(int y) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->setOverlaysY(y); - this->ui->graphicsView_Map->scene()->update(); +// Overload. No layer provided, set y of all layers +void MapView::setY(int y) { + foreach (Overlay * layer, this->overlayMap) + layer->setY(y); + this->scene()->update(); } -QJSValue MainWindow::getOverlayPosition(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return QJSValue(); - Overlay * overlay = this->ui->graphicsView_Map->getOverlay(layer); +QJSValue MapView::getPosition(int layer) { + Overlay * overlay = this->getOverlay(layer); return Scripting::position(overlay->getX(), overlay->getY()); } -void MainWindow::setOverlayPosition(int x, int y, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->setPosition(x, y); - this->ui->graphicsView_Map->scene()->update(); +void MapView::setPosition(int x, int y, int layer) { + this->getOverlay(layer)->setPosition(x, y); + this->scene()->update(); } -void MainWindow::setOverlaysPosition(int x, int y) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->setOverlaysPosition(x, y); - this->ui->graphicsView_Map->scene()->update(); +// Overload. No layer provided, set position of all layers +void MapView::setPosition(int x, int y) { + foreach (Overlay * layer, this->overlayMap) + layer->setPosition(x, y); + this->scene()->update(); } -void MainWindow::moveOverlay(int deltaX, int deltaY, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->move(deltaX, deltaY); - this->ui->graphicsView_Map->scene()->update(); +void MapView::move(int deltaX, int deltaY, int layer) { + this->getOverlay(layer)->move(deltaX, deltaY); + this->scene()->update(); } -void MainWindow::moveOverlays(int deltaX, int deltaY) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->moveOverlays(deltaX, deltaY); - this->ui->graphicsView_Map->scene()->update(); +// Overload. No layer provided, move all layers +void MapView::move(int deltaX, int deltaY) { + foreach (Overlay * layer, this->overlayMap) + layer->move(deltaX, deltaY); + this->scene()->update(); } -int MainWindow::getOverlayOpacity(int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return 0; - return this->ui->graphicsView_Map->getOverlay(layer)->getOpacity(); +int MapView::getOpacity(int layer) { + return this->getOverlay(layer)->getOpacity(); } -void MainWindow::setOverlayOpacity(int opacity, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->setOpacity(opacity); - this->ui->graphicsView_Map->scene()->update(); +void MapView::setOpacity(int opacity, int layer) { + this->getOverlay(layer)->setOpacity(opacity); + this->scene()->update(); } -void MainWindow::setOverlaysOpacity(int opacity) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->setOverlaysOpacity(opacity); - this->ui->graphicsView_Map->scene()->update(); +// Overload. No layer provided, set opacity of all layers +void MapView::setOpacity(int opacity) { + foreach (Overlay * layer, this->overlayMap) + layer->setOpacity(opacity); + this->scene()->update(); } -void MainWindow::addText(QString text, int x, int y, QString color, int fontSize, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->addText(text, x, y, color, fontSize); - this->ui->graphicsView_Map->scene()->update(); +void MapView::addText(QString text, int x, int y, QString color, int fontSize, int layer) { + this->getOverlay(layer)->addText(text, x, y, color, fontSize); + this->scene()->update(); } -void MainWindow::addRect(int x, int y, int width, int height, QString color, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->addRect(x, y, width, height, color, false); - this->ui->graphicsView_Map->scene()->update(); +void MapView::addRect(int x, int y, int width, int height, QString color, int layer) { + this->getOverlay(layer)->addRect(x, y, width, height, color, false); + this->scene()->update(); } -void MainWindow::addFilledRect(int x, int y, int width, int height, QString color, int layer) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - this->ui->graphicsView_Map->getOverlay(layer)->addRect(x, y, width, height, color, true); - this->ui->graphicsView_Map->scene()->update(); +void MapView::addFilledRect(int x, int y, int width, int height, QString color, int layer) { + this->getOverlay(layer)->addRect(x, y, width, height, color, true); + this->scene()->update(); } -void MainWindow::addImage(int x, int y, QString filepath, int layer, bool useCache) { - if (!this->ui || !this->ui->graphicsView_Map) - return; - if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, filepath, useCache)) - this->ui->graphicsView_Map->scene()->update(); +void MapView::addImage(int x, int y, QString filepath, int layer, bool useCache) { + if (this->getOverlay(layer)->addImage(x, y, filepath, useCache)) + this->scene()->update(); } -void MainWindow::createImage(int x, int y, QString filepath, int width, int height, unsigned offset, qreal hScale, qreal vScale, int paletteId, bool setTransparency, int layer, bool useCache) { - if (!this->ui || !this->ui->graphicsView_Map || !this->editor || !this->editor->map || !this->editor->map->layout +void MapView::createImage(int x, int y, QString filepath, int width, int height, unsigned offset, qreal hScale, qreal vScale, int paletteId, bool setTransparency, int layer, bool useCache) { + if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) return; QList palette; if (paletteId != -1) palette = Tileset::getPalette(paletteId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary); - if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, filepath, useCache, width, height, offset, hScale, vScale, palette, setTransparency)) - this->ui->graphicsView_Map->scene()->update(); + if (this->getOverlay(layer)->addImage(x, y, filepath, useCache, width, height, offset, hScale, vScale, palette, setTransparency)) + this->scene()->update(); } -void MainWindow::addTileImage(int x, int y, int tileId, bool xflip, bool yflip, int paletteId, bool setTransparency, int layer) { - if (!this->ui || !this->ui->graphicsView_Map || !this->editor || !this->editor->map || !this->editor->map->layout +void MapView::addTileImage(int x, int y, int tileId, bool xflip, bool yflip, int paletteId, bool setTransparency, int layer) { + if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) return; QImage image = getPalettedTileImage(tileId, @@ -199,17 +166,17 @@ void MainWindow::addTileImage(int x, int y, int tileId, bool xflip, bool yflip, .mirrored(xflip, yflip); if (setTransparency) image.setColor(0, qRgba(0, 0, 0, 0)); - if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, image)) - this->ui->graphicsView_Map->scene()->update(); + if (this->getOverlay(layer)->addImage(x, y, image)) + this->scene()->update(); } -void MainWindow::addTileImage(int x, int y, QJSValue tileObj, bool setTransparency, int layer) { +void MapView::addTileImage(int x, int y, QJSValue tileObj, bool setTransparency, int layer) { Tile tile = Scripting::toTile(tileObj); this->addTileImage(x, y, tile.tileId, tile.xflip, tile.yflip, tile.palette, setTransparency, layer); } -void MainWindow::addMetatileImage(int x, int y, int metatileId, bool setTransparency, int layer) { - if (!this->ui || !this->ui->graphicsView_Map || !this->editor || !this->editor->map || !this->editor->map->layout +void MapView::addMetatileImage(int x, int y, int metatileId, bool setTransparency, int layer) { + if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary) return; QImage image = getMetatileImage(static_cast(metatileId), @@ -219,6 +186,6 @@ void MainWindow::addMetatileImage(int x, int y, int metatileId, bool setTranspar this->editor->map->metatileLayerOpacity); if (setTransparency) image.setColor(0, qRgba(0, 0, 0, 0)); - if (this->ui->graphicsView_Map->getOverlay(layer)->addImage(x, y, image)) - this->ui->graphicsView_Map->scene()->update(); + if (this->getOverlay(layer)->addImage(x, y, image)) + this->scene()->update(); } diff --git a/src/script_api/scripting.cpp b/src/script_api/scripting.cpp index 0d4e5817..c32aac71 100644 --- a/src/script_api/scripting.cpp +++ b/src/script_api/scripting.cpp @@ -33,6 +33,7 @@ Scripting::Scripting(MainWindow *mainWindow) { this->engine = new QJSEngine(mainWindow); this->engine->installExtensions(QJSEngine::ConsoleExtension); this->engine->globalObject().setProperty("map", this->engine->newQObject(mainWindow)); + this->engine->globalObject().setProperty("overlay", this->engine->newQObject(mainWindow->getMapView())); for (QString script : projectConfig.getCustomScripts()) { this->filepaths.append(script); } diff --git a/src/ui/graphicsview.cpp b/src/ui/graphicsview.cpp index 556b3eeb..cc270849 100644 --- a/src/ui/graphicsview.cpp +++ b/src/ui/graphicsview.cpp @@ -41,44 +41,14 @@ void MapView::drawForeground(QPainter *painter, const QRectF&) { editor->cursorMapTileRect->paint(painter, &option, this); } -void MapView::clearOverlays() { - foreach (Overlay * overlay, this->overlayMap) { - overlay->clearItems(); - delete overlay; +void MapView::clearOverlayMap() { + foreach (Overlay * layer, this->overlayMap) { + layer->clearItems(); + delete layer; } this->overlayMap.clear(); } -void MapView::setOverlaysHidden(bool hidden) { - foreach (Overlay * overlay, this->overlayMap) - overlay->setHidden(hidden); -} - -void MapView::setOverlaysX(int x) { - foreach (Overlay * overlay, this->overlayMap) - overlay->setX(x); -} - -void MapView::setOverlaysY(int y) { - foreach (Overlay * overlay, this->overlayMap) - overlay->setY(y); -} - -void MapView::setOverlaysPosition(int x, int y) { - foreach (Overlay * overlay, this->overlayMap) - overlay->setPosition(x, y); -} - -void MapView::setOverlaysOpacity(int opacity) { - foreach (Overlay * overlay, this->overlayMap) - overlay->setOpacity(opacity); -} - -void MapView::moveOverlays(int deltaX, int deltaY) { - foreach (Overlay * overlay, this->overlayMap) - overlay->move(deltaX, deltaY); -} - Overlay * MapView::getOverlay(int layer) { Overlay * overlay = this->overlayMap.value(layer, nullptr); if (!overlay) { From 31b22bfcc17810e16677ed3a7ecff88e46f703e7 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 4 Sep 2022 23:41:42 -0400 Subject: [PATCH 3/7] Add constants object to API --- include/mainwindow.h | 8 ------ include/scripting.h | 19 +++++++------- src/mainwindow.cpp | 2 ++ src/script_api/api_map.cpp | 2 +- src/script_api/api_util.cpp | 50 ------------------------------------ src/script_api/scripting.cpp | 45 ++++++++++++++++++++++++++++++-- src/ui/aboutporymap.cpp | 5 +++- 7 files changed, 60 insertions(+), 71 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 0ee96c69..131250e4 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -101,13 +101,9 @@ public: Q_INVOKABLE QJSValue getSecondaryTilesetPalettePreview(int paletteIndex); Q_INVOKABLE QJSValue getSecondaryTilesetPalettesPreview(); Q_INVOKABLE int getNumPrimaryTilesetMetatiles(); - Q_INVOKABLE int getMaxPrimaryTilesetMetatiles(); Q_INVOKABLE int getNumSecondaryTilesetMetatiles(); - Q_INVOKABLE int getMaxSecondaryTilesetMetatiles(); Q_INVOKABLE int getNumPrimaryTilesetTiles(); - Q_INVOKABLE int getMaxPrimaryTilesetTiles(); Q_INVOKABLE int getNumSecondaryTilesetTiles(); - Q_INVOKABLE int getMaxSecondaryTilesetTiles(); Q_INVOKABLE bool isPrimaryTileset(QString tilesetName); Q_INVOKABLE bool isSecondaryTileset(QString tilesetName); Q_INVOKABLE QString getPrimaryTileset(); @@ -161,10 +157,6 @@ public: Q_INVOKABLE void setMetatileTiles(int metatileId, QJSValue tilesObj, int tileStart = 0, int tileEnd = -1, bool forceRedraw = true); Q_INVOKABLE void setMetatileTiles(int metatileId, int tileId, bool xflip, bool yflip, int palette, int tileStart = 0, int tileEnd = -1, bool forceRedraw = true); Q_INVOKABLE QJSValue getTilePixels(int tileId); - Q_INVOKABLE int getNumTilesInMetatile(); - Q_INVOKABLE int getNumMetatileLayers(); - Q_INVOKABLE QString getBaseGameVersion(); - Q_INVOKABLE QJSValue getPorymapVersion(); Q_INVOKABLE QList getCustomScripts(); Q_INVOKABLE int getMainTab(); Q_INVOKABLE void setMainTab(int index); diff --git a/include/scripting.h b/include/scripting.h index 9b15f018..4558f0e0 100644 --- a/include/scripting.h +++ b/include/scripting.h @@ -29,16 +29,9 @@ class Scripting { public: Scripting(MainWindow *mainWindow); - static QJSValue fromBlock(Block block); - static QJSValue fromTile(Tile tile); - static Tile toTile(QJSValue obj); - static QJSValue version(QList versionNums); - static QJSValue dimensions(int width, int height); - static QJSValue position(int x, int y); - static QJSEngine *getEngine(); - static QImage getImage(QString filepath); - static QJSValue dialogInput(QJSValue input, bool selectedOk); static void init(MainWindow *mainWindow); + static void populateGlobalObject(MainWindow *mainWindow); + static QJSEngine *getEngine(); static void registerAction(QString functionName, QString actionName); static int numRegisteredActions(); static void invokeAction(QString actionName); @@ -57,6 +50,14 @@ public: static void cb_MapViewTabChanged(int oldTab, int newTab); static void cb_BorderVisibilityToggled(bool visible); static bool tryErrorJS(QJSValue js); + static QJSValue fromBlock(Block block); + static QJSValue fromTile(Tile tile); + static Tile toTile(QJSValue obj); + static QJSValue version(QList versionNums); + static QJSValue dimensions(int width, int height); + static QJSValue position(int x, int y); + static QImage getImage(QString filepath); + static QJSValue dialogInput(QJSValue input, bool selectedOk); private: QJSEngine *engine; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 474c2315..16a51e9b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -946,6 +946,8 @@ bool MainWindow::loadDataStructures() { && project->readEventGraphics() && project->readSongNames(); + Scripting::populateGlobalObject(this); + return success && loadProjectCombos(); } diff --git a/src/script_api/api_map.cpp b/src/script_api/api_map.cpp index e813f24e..602be5a4 100644 --- a/src/script_api/api_map.cpp +++ b/src/script_api/api_map.cpp @@ -691,7 +691,7 @@ void MainWindow::setMetatileAttributes(int metatileId, int attributes) { } int MainWindow::calculateTileBounds(int * tileStart, int * tileEnd) { - int maxNumTiles = this->getNumTilesInMetatile(); + int maxNumTiles = projectConfig.getTripleLayerMetatilesEnabled() ? 12 : 8; if (*tileEnd >= maxNumTiles || *tileEnd < 0) *tileEnd = maxNumTiles - 1; if (*tileStart >= maxNumTiles || *tileStart < 0) diff --git a/src/script_api/api_util.cpp b/src/script_api/api_util.cpp index 3fe69bf2..6f52434f 100644 --- a/src/script_api/api_util.cpp +++ b/src/script_api/api_util.cpp @@ -2,7 +2,6 @@ #include "ui_mainwindow.h" #include "scripting.h" #include "config.h" -#include "aboutporymap.h" void MainWindow::registerAction(QString functionName, QString actionName, QString shortcut) { if (!this->ui || !this->ui->menuTools) @@ -206,55 +205,6 @@ bool MainWindow::isSecondaryTileset(QString tilesetName) { return this->editor->project->tilesetLabels["secondary"].contains(tilesetName); } - -//================================= -// Here below should be constants -//================================= - - -int MainWindow::getMaxPrimaryTilesetMetatiles() { - if (!this->editor || !this->editor->project) - return 0; - return this->editor->project->getNumMetatilesPrimary(); -} - -int MainWindow::getMaxSecondaryTilesetMetatiles() { - if (!this->editor || !this->editor->project) - return 0; - return this->editor->project->getNumMetatilesTotal() - this->editor->project->getNumMetatilesPrimary(); -} - -int MainWindow::getMaxPrimaryTilesetTiles() { - if (!this->editor || !this->editor->project) - return 0; - return this->editor->project->getNumTilesPrimary(); -} - -int MainWindow::getMaxSecondaryTilesetTiles() { - if (!this->editor || !this->editor->project) - return 0; - return this->editor->project->getNumTilesTotal() - this->editor->project->getNumTilesPrimary(); -} - -int MainWindow::getNumTilesInMetatile() { - return projectConfig.getTripleLayerMetatilesEnabled() ? 12 : 8; -} - -int MainWindow::getNumMetatileLayers() { - return projectConfig.getTripleLayerMetatilesEnabled() ? 3 : 2; -} - -QString MainWindow::getBaseGameVersion() { - return projectConfig.getBaseGameVersionString(); -} - -QJSValue MainWindow::getPorymapVersion() { - AboutPorymap *window = new AboutPorymap(this); - QJSValue version = Scripting::version(window->getVersionNumbers()); - delete window; - return version; -} - QList MainWindow::getCustomScripts() { return projectConfig.getCustomScripts(); } diff --git a/src/script_api/scripting.cpp b/src/script_api/scripting.cpp index c32aac71..5a3fd097 100644 --- a/src/script_api/scripting.cpp +++ b/src/script_api/scripting.cpp @@ -1,5 +1,7 @@ #include "scripting.h" #include "log.h" +#include "config.h" +#include "aboutporymap.h" QMap callbackFunctions = { {OnProjectOpened, "onProjectOpened"}, @@ -32,8 +34,6 @@ void Scripting::init(MainWindow *mainWindow) { Scripting::Scripting(MainWindow *mainWindow) { this->engine = new QJSEngine(mainWindow); this->engine->installExtensions(QJSEngine::ConsoleExtension); - this->engine->globalObject().setProperty("map", this->engine->newQObject(mainWindow)); - this->engine->globalObject().setProperty("overlay", this->engine->newQObject(mainWindow->getMapView())); for (QString script : projectConfig.getCustomScripts()) { this->filepaths.append(script); } @@ -54,6 +54,47 @@ void Scripting::loadModules(QStringList moduleFiles) { } } +void Scripting::populateGlobalObject(MainWindow *mainWindow) { + if (!instance || !instance->engine) return; + + instance->engine->globalObject().setProperty("map", instance->engine->newQObject(mainWindow)); + instance->engine->globalObject().setProperty("overlay", instance->engine->newQObject(mainWindow->getMapView())); + + QJSValue constants = instance->engine->newObject(); + + // Get basic tile/metatile information + int numTilesPrimary = Project::getNumTilesPrimary(); + int numTilesTotal = Project::getNumTilesTotal(); + int numMetatilesPrimary = Project::getNumMetatilesPrimary(); + int numMetatilesTotal = Project::getNumMetatilesTotal(); + bool tripleLayerEnabled = projectConfig.getTripleLayerMetatilesEnabled(); + + // Invisibly create an "About" window to read Porymap version + AboutPorymap *about = new AboutPorymap(mainWindow); + if (about) { + QJSValue version = Scripting::version(about->getVersionNumbers()); + constants.setProperty("version", version); + delete about; + } else { + logError("Failed to read Porymap version for API"); + } + constants.setProperty("max_primary_tiles", numTilesPrimary); + constants.setProperty("max_secondary_tiles", numTilesTotal - numTilesPrimary); + constants.setProperty("max_primary_metatiles", numMetatilesPrimary); + constants.setProperty("max_secondary_metatiles", numMetatilesTotal - numMetatilesPrimary); + constants.setProperty("layers_per_metatile", tripleLayerEnabled ? 3 : 2); + constants.setProperty("tiles_per_metatile", tripleLayerEnabled ? 12 : 8); + constants.setProperty("base_game_version", projectConfig.getBaseGameVersionString()); + + instance->engine->globalObject().setProperty("constants", constants); + + // Prevent changes to the object properties of the global object + instance->engine->evaluate("Object.freeze(map);"); + instance->engine->evaluate("Object.freeze(overlay);"); + instance->engine->evaluate("Object.freeze(constants.version);"); + instance->engine->evaluate("Object.freeze(constants);"); +} + bool Scripting::tryErrorJS(QJSValue js) { if (!js.isError()) return false; diff --git a/src/ui/aboutporymap.cpp b/src/ui/aboutporymap.cpp index 4a47aca8..98e07ec0 100644 --- a/src/ui/aboutporymap.cpp +++ b/src/ui/aboutporymap.cpp @@ -1,5 +1,6 @@ #include "aboutporymap.h" #include "ui_aboutporymap.h" +#include "log.h" AboutPorymap::AboutPorymap(QWidget *parent) : QMainWindow(parent), @@ -19,7 +20,9 @@ QList AboutPorymap::getVersionNumbers() // Get the version string "#.#.#" QRegularExpression regex("Version (\\d+)\\.(\\d+)\\.(\\d+)"); QRegularExpressionMatch match = regex.match(ui->label_Version->text()); - if (!match.hasMatch()) + if (!match.hasMatch()) { + logError("Failed to locate Porymap version text"); return QList({0, 0, 0}); + } return QList({match.captured(1).toInt(), match.captured(2).toInt(), match.captured(3).toInt()}); } From bd5446a40be7acea956a789c1011079b2f88391d Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 5 Sep 2022 11:53:30 -0400 Subject: [PATCH 4/7] Move script utility functions to own object --- include/api_util.h | 54 ++++++++++++ include/mainwindow.h | 47 ++-------- include/scripting.h | 3 +- porymap.pro | 1 + src/mainwindow.cpp | 13 +-- src/script_api/api_util.cpp | 161 +++++++++++++++++++---------------- src/script_api/scripting.cpp | 22 ++--- src/ui/graphicsview.cpp | 6 +- 8 files changed, 164 insertions(+), 143 deletions(-) create mode 100644 include/api_util.h diff --git a/include/api_util.h b/include/api_util.h new file mode 100644 index 00000000..85ad3f1b --- /dev/null +++ b/include/api_util.h @@ -0,0 +1,54 @@ +#pragma once +#ifndef APIUTIL_H +#define APIUTIL_H + +#include "mainwindow.h" + +class ScriptUtility : public QObject +{ + Q_OBJECT + +public: + ScriptUtility(MainWindow *mainWindow); + void clearActions(); + QString getActionFunctionName(QString actionName); + Q_INVOKABLE void registerAction(QString functionName, QString actionName, QString shortcut = ""); + Q_INVOKABLE void setTimeout(QJSValue callback, int milliseconds); + Q_INVOKABLE void log(QString message); + Q_INVOKABLE void warn(QString message); + Q_INVOKABLE void error(QString message); + Q_INVOKABLE void showMessage(QString text, QString informativeText = "", QString detailedText = ""); + Q_INVOKABLE void showWarning(QString text, QString informativeText = "", QString detailedText = ""); + Q_INVOKABLE void showError(QString text, QString informativeText = "", QString detailedText = ""); + Q_INVOKABLE bool showQuestion(QString text, QString informativeText = "", QString detailedText = ""); + Q_INVOKABLE QJSValue getInputText(QString title, QString label, QString defaultValue = ""); + Q_INVOKABLE QJSValue getInputNumber(QString title, QString label, double defaultValue = 0, double min = INT_MIN, double max = INT_MAX, int decimals = 0, double step = 1); + Q_INVOKABLE QJSValue getInputItem(QString title, QString label, QStringList items, int defaultValue = 0, bool editable = false); + Q_INVOKABLE int getMainTab(); + Q_INVOKABLE void setMainTab(int index); + Q_INVOKABLE int getMapViewTab(); + Q_INVOKABLE void setMapViewTab(int index); + Q_INVOKABLE void setGridVisibility(bool visible); + Q_INVOKABLE bool getGridVisibility(); + Q_INVOKABLE void setBorderVisibility(bool visible); + Q_INVOKABLE bool getBorderVisibility(); + Q_INVOKABLE void setSmartPathsEnabled(bool visible); + Q_INVOKABLE bool getSmartPathsEnabled(); + Q_INVOKABLE QList getCustomScripts(); + Q_INVOKABLE QList getMetatileLayerOrder(); + Q_INVOKABLE void setMetatileLayerOrder(QList order); + Q_INVOKABLE QList getMetatileLayerOpacity(); + Q_INVOKABLE void setMetatileLayerOpacity(QList order); + Q_INVOKABLE bool isPrimaryTileset(QString tilesetName); + Q_INVOKABLE bool isSecondaryTileset(QString tilesetName); + +private: + void callTimeoutFunction(QJSValue callback); + void runMessageBox(QString text, QString informativeText, QString detailedText, QMessageBox::Icon icon); + + MainWindow *window; + QList registeredActions; + QMap actionMap; +}; + +#endif // APIUTIL_H diff --git a/include/mainwindow.h b/include/mainwindow.h index 131250e4..d317764e 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -42,8 +42,6 @@ public: MainWindow(const MainWindow &) = delete; MainWindow & operator = (const MainWindow &) = delete; - MapView *getMapView(); - // Scripting API Q_INVOKABLE QJSValue getBlock(int x, int y); void tryRedrawMapArea(bool forceRedraw); @@ -104,36 +102,10 @@ public: Q_INVOKABLE int getNumSecondaryTilesetMetatiles(); Q_INVOKABLE int getNumPrimaryTilesetTiles(); Q_INVOKABLE int getNumSecondaryTilesetTiles(); - Q_INVOKABLE bool isPrimaryTileset(QString tilesetName); - Q_INVOKABLE bool isSecondaryTileset(QString tilesetName); Q_INVOKABLE QString getPrimaryTileset(); Q_INVOKABLE QString getSecondaryTileset(); Q_INVOKABLE void setPrimaryTileset(QString tileset); Q_INVOKABLE void setSecondaryTileset(QString tileset); - Q_INVOKABLE void setGridVisibility(bool visible); - Q_INVOKABLE bool getGridVisibility(); - Q_INVOKABLE void setBorderVisibility(bool visible); - Q_INVOKABLE bool getBorderVisibility(); - Q_INVOKABLE void setSmartPathsEnabled(bool visible); - Q_INVOKABLE bool getSmartPathsEnabled(); - Q_INVOKABLE void registerAction(QString functionName, QString actionName, QString shortcut = ""); - Q_INVOKABLE void setTimeout(QJSValue callback, int milliseconds); - void invokeCallback(QJSValue callback); - Q_INVOKABLE void log(QString message); - Q_INVOKABLE void warn(QString message); - Q_INVOKABLE void error(QString message); - void runMessageBox(QString text, QString informativeText, QString detailedText, QMessageBox::Icon icon); - Q_INVOKABLE void showMessage(QString text, QString informativeText = "", QString detailedText = ""); - Q_INVOKABLE void showWarning(QString text, QString informativeText = "", QString detailedText = ""); - Q_INVOKABLE void showError(QString text, QString informativeText = "", QString detailedText = ""); - Q_INVOKABLE bool showQuestion(QString text, QString informativeText = "", QString detailedText = ""); - Q_INVOKABLE QJSValue getInputText(QString title, QString label, QString defaultValue = ""); - Q_INVOKABLE QJSValue getInputNumber(QString title, QString label, double defaultValue = 0, double min = INT_MIN, double max = INT_MAX, int decimals = 0, double step = 1); - Q_INVOKABLE QJSValue getInputItem(QString title, QString label, QStringList items, int defaultValue = 0, bool editable = false); - Q_INVOKABLE QList getMetatileLayerOrder(); - Q_INVOKABLE void setMetatileLayerOrder(QList order); - Q_INVOKABLE QList getMetatileLayerOpacity(); - Q_INVOKABLE void setMetatileLayerOpacity(QList order); void saveMetatilesByMetatileId(int metatileId); void saveMetatileAttributesByMetatileId(int metatileId); Metatile * getMetatile(int metatileId); @@ -157,11 +129,6 @@ public: Q_INVOKABLE void setMetatileTiles(int metatileId, QJSValue tilesObj, int tileStart = 0, int tileEnd = -1, bool forceRedraw = true); Q_INVOKABLE void setMetatileTiles(int metatileId, int tileId, bool xflip, bool yflip, int palette, int tileStart = 0, int tileEnd = -1, bool forceRedraw = true); Q_INVOKABLE QJSValue getTilePixels(int tileId); - Q_INVOKABLE QList getCustomScripts(); - Q_INVOKABLE int getMainTab(); - Q_INVOKABLE void setMainTab(int index); - Q_INVOKABLE int getMapViewTab(); - Q_INVOKABLE void setMapViewTab(int index); bool gameStringToBool(QString s); Q_INVOKABLE QString getSong(); Q_INVOKABLE void setSong(QString song); @@ -186,6 +153,10 @@ public: Q_INVOKABLE int getFloorNumber(); Q_INVOKABLE void setFloorNumber(int floorNumber); +public slots: + void on_mainTabBar_tabBarClicked(int index); + void on_mapViewTab_tabBarClicked(int index); + private slots: void on_action_Open_Project_triggered(); void on_action_Reload_Project_triggered(); @@ -232,9 +203,6 @@ private slots: void on_actionOpen_Recent_Project_On_Launch_triggered(bool checked); void on_actionEdit_Shortcuts_triggered(); - void on_mainTabBar_tabBarClicked(int index); - void on_mapViewTab_tabBarClicked(int index); - void on_actionZoom_In_triggered(); void on_actionZoom_Out_triggered(); void on_actionBetter_Cursors_triggered(); @@ -318,8 +286,11 @@ private slots: void on_actionEdit_Preferences_triggered(); void togglePreferenceSpecificUi(); -private: +public: Ui::MainWindow *ui; + Editor *editor = nullptr; + +private: QLabel *label_MapRulerStatus = nullptr; QPointer tilesetEditor = nullptr; QPointer regionMapEditor = nullptr; @@ -331,7 +302,6 @@ private: QStandardItemModel *mapListModel; QList *mapGroupItemsList; QMap mapListIndexes; - Editor *editor = nullptr; QIcon* mapIcon; QIcon* mapEditedIcon; QIcon* mapOpenedIcon; @@ -355,7 +325,6 @@ private: DraggablePixmapItem *selectedBG; DraggablePixmapItem *selectedHealspot; - QList registeredActions; QVector openScriptButtons; bool isProgrammaticEventTabChange; diff --git a/include/scripting.h b/include/scripting.h index 4558f0e0..98982e44 100644 --- a/include/scripting.h +++ b/include/scripting.h @@ -4,6 +4,7 @@ #include "mainwindow.h" #include "block.h" +#include "api_util.h" #include #include @@ -63,8 +64,8 @@ private: QJSEngine *engine; QStringList filepaths; QList modules; - QMap registeredActions; QMap imageCache; + ScriptUtility *scriptUtility; void loadModules(QStringList moduleFiles); void invokeCallback(CallbackType type, QJSValueList args); diff --git a/porymap.pro b/porymap.pro index c0ab808c..e1edf4e0 100644 --- a/porymap.pro +++ b/porymap.pro @@ -169,6 +169,7 @@ HEADERS += include/core/block.h \ include/ui/preferenceeditor.h \ include/ui/regionmappropertiesdialog.h \ include/ui/colorpicker.h \ + include/api_util.h \ include/config.h \ include/editor.h \ include/mainwindow.h \ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 16a51e9b..11ba6e3a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -540,6 +540,7 @@ bool MainWindow::openProject(QString dir) { if (success) { showWindowTitle(); this->statusBar()->showMessage(QString("Opened project %1").arg(nativeDir)); + Scripting::cb_ProjectOpened(dir); } else { this->statusBar()->showMessage(QString("Failed to open project %1").arg(nativeDir)); QMessageBox msgBox(this); @@ -550,14 +551,6 @@ bool MainWindow::openProject(QString dir) { msgBox.critical(nullptr, "Error Opening Project", errorMsg); } - - if (success) { - for (auto action : this->registeredActions) { - this->ui->menuTools->removeAction(action); - } - Scripting::cb_ProjectOpened(dir); - } - projectOpenFailure = !success; return success; } @@ -3238,7 +3231,3 @@ void MainWindow::closeEvent(QCloseEvent *event) { QMainWindow::closeEvent(event); } - -MapView *MainWindow::getMapView() { - return this->ui->graphicsView_Map; -} diff --git a/src/script_api/api_util.cpp b/src/script_api/api_util.cpp index 6f52434f..8bf25a17 100644 --- a/src/script_api/api_util.cpp +++ b/src/script_api/api_util.cpp @@ -3,16 +3,20 @@ #include "scripting.h" #include "config.h" -void MainWindow::registerAction(QString functionName, QString actionName, QString shortcut) { - if (!this->ui || !this->ui->menuTools) +ScriptUtility::ScriptUtility(MainWindow *mainWindow) { + this->window = mainWindow; +} + +void ScriptUtility::registerAction(QString functionName, QString actionName, QString shortcut) { + if (!window || !window->ui || !window->ui->menuTools) return; - Scripting::registerAction(functionName, actionName); - if (Scripting::numRegisteredActions() == 1) { - QAction *section = this->ui->menuTools->addSection("Custom Actions"); + this->actionMap.insert(actionName, functionName); + if (this->actionMap.size() == 1) { + QAction *section = window->ui->menuTools->addSection("Custom Actions"); this->registeredActions.append(section); } - QAction *action = this->ui->menuTools->addAction(actionName, [actionName](){ + QAction *action = window->ui->menuTools->addAction(actionName, [actionName](){ Scripting::invokeAction(actionName); }); if (!shortcut.isEmpty()) { @@ -21,37 +25,47 @@ void MainWindow::registerAction(QString functionName, QString actionName, QStrin this->registeredActions.append(action); } -void MainWindow::setTimeout(QJSValue callback, int milliseconds) { +void ScriptUtility::clearActions() { + for (auto action : this->registeredActions) { + window->ui->menuTools->removeAction(action); + } +} + +QString ScriptUtility::getActionFunctionName(QString actionName) { + return this->actionMap.value(actionName); +} + +void ScriptUtility::setTimeout(QJSValue callback, int milliseconds) { if (!callback.isCallable() || milliseconds < 0) return; QTimer *timer = new QTimer(0); connect(timer, &QTimer::timeout, [=](){ - this->invokeCallback(callback); + this->callTimeoutFunction(callback); }); connect(timer, &QTimer::timeout, timer, &QTimer::deleteLater); timer->setSingleShot(true); timer->start(milliseconds); } -void MainWindow::invokeCallback(QJSValue callback) { +void ScriptUtility::callTimeoutFunction(QJSValue callback) { Scripting::tryErrorJS(callback.call()); } -void MainWindow::log(QString message) { +void ScriptUtility::log(QString message) { logInfo(message); } -void MainWindow::warn(QString message) { +void ScriptUtility::warn(QString message) { logWarn(message); } -void MainWindow::error(QString message) { +void ScriptUtility::error(QString message) { logError(message); } -void MainWindow::runMessageBox(QString text, QString informativeText, QString detailedText, QMessageBox::Icon icon) { - QMessageBox messageBox(this); +void ScriptUtility::runMessageBox(QString text, QString informativeText, QString detailedText, QMessageBox::Icon icon) { + QMessageBox messageBox(window); messageBox.setText(text); messageBox.setInformativeText(informativeText); messageBox.setDetailedText(detailedText); @@ -59,20 +73,20 @@ void MainWindow::runMessageBox(QString text, QString informativeText, QString de messageBox.exec(); } -void MainWindow::showMessage(QString text, QString informativeText, QString detailedText) { +void ScriptUtility::showMessage(QString text, QString informativeText, QString detailedText) { this->runMessageBox(text, informativeText, detailedText, QMessageBox::Information); } -void MainWindow::showWarning(QString text, QString informativeText, QString detailedText) { +void ScriptUtility::showWarning(QString text, QString informativeText, QString detailedText) { this->runMessageBox(text, informativeText, detailedText, QMessageBox::Warning); } -void MainWindow::showError(QString text, QString informativeText, QString detailedText) { +void ScriptUtility::showError(QString text, QString informativeText, QString detailedText) { this->runMessageBox(text, informativeText, detailedText, QMessageBox::Critical); } -bool MainWindow::showQuestion(QString text, QString informativeText, QString detailedText) { - QMessageBox messageBox(this); +bool ScriptUtility::showQuestion(QString text, QString informativeText, QString detailedText) { + QMessageBox messageBox(window); messageBox.setText(text); messageBox.setInformativeText(informativeText); messageBox.setDetailedText(detailedText); @@ -81,83 +95,87 @@ bool MainWindow::showQuestion(QString text, QString informativeText, QString det return messageBox.exec() == QMessageBox::Yes; } -QJSValue MainWindow::getInputText(QString title, QString label, QString defaultValue) { +QJSValue ScriptUtility::getInputText(QString title, QString label, QString defaultValue) { bool ok; - QString input = QInputDialog::getText(this, title, label, QLineEdit::Normal, defaultValue, &ok); + QString input = QInputDialog::getText(window, title, label, QLineEdit::Normal, defaultValue, &ok); return Scripting::dialogInput(input, ok); } -QJSValue MainWindow::getInputNumber(QString title, QString label, double defaultValue, double min, double max, int decimals, double step) { +QJSValue ScriptUtility::getInputNumber(QString title, QString label, double defaultValue, double min, double max, int decimals, double step) { bool ok; - double input = QInputDialog::getDouble(this, title, label, defaultValue, min, max, decimals, &ok, Qt::WindowFlags(), step); + double input = QInputDialog::getDouble(window, title, label, defaultValue, min, max, decimals, &ok, Qt::WindowFlags(), step); return Scripting::dialogInput(input, ok); } -QJSValue MainWindow::getInputItem(QString title, QString label, QStringList items, int defaultValue, bool editable) { +QJSValue ScriptUtility::getInputItem(QString title, QString label, QStringList items, int defaultValue, bool editable) { bool ok; - QString input = QInputDialog::getItem(this, title, label, items, defaultValue, editable, &ok); + QString input = QInputDialog::getItem(window, title, label, items, defaultValue, editable, &ok); return Scripting::dialogInput(input, ok); } -int MainWindow::getMainTab() { - if (!this->ui || !this->ui->mainTabBar) +int ScriptUtility::getMainTab() { + if (!window || !window->ui || !window->ui->mainTabBar) return -1; - return this->ui->mainTabBar->currentIndex(); + return window->ui->mainTabBar->currentIndex(); } -void MainWindow::setMainTab(int index) { - if (!this->ui || !this->ui->mainTabBar || index < 0 || index >= this->ui->mainTabBar->count()) +void ScriptUtility::setMainTab(int index) { + if (!window || !window->ui || !window->ui->mainTabBar || index < 0 || index >= window->ui->mainTabBar->count()) return; // Can't select Wild Encounters tab if it's disabled if (index == 4 && !projectConfig.getEncounterJsonActive()) return; - this->on_mainTabBar_tabBarClicked(index); + window->on_mainTabBar_tabBarClicked(index); } -int MainWindow::getMapViewTab() { - if (!this->ui || !this->ui->mapViewTab) +int ScriptUtility::getMapViewTab() { + if (!window || !window->ui || !window->ui->mapViewTab) return -1; - return this->ui->mapViewTab->currentIndex(); + return window->ui->mapViewTab->currentIndex(); } -void MainWindow::setMapViewTab(int index) { - if (this->getMainTab() != 0 || !this->ui->mapViewTab || index < 0 || index >= this->ui->mapViewTab->count()) +void ScriptUtility::setMapViewTab(int index) { + if (this->getMainTab() != 0 || !window->ui->mapViewTab || index < 0 || index >= window->ui->mapViewTab->count()) return; - this->on_mapViewTab_tabBarClicked(index); + window->on_mapViewTab_tabBarClicked(index); } -void MainWindow::setGridVisibility(bool visible) { - this->ui->checkBox_ToggleGrid->setChecked(visible); +void ScriptUtility::setGridVisibility(bool visible) { + window->ui->checkBox_ToggleGrid->setChecked(visible); } -bool MainWindow::getGridVisibility() { - return this->ui->checkBox_ToggleGrid->isChecked(); +bool ScriptUtility::getGridVisibility() { + return window->ui->checkBox_ToggleGrid->isChecked(); } -void MainWindow::setBorderVisibility(bool visible) { - this->editor->toggleBorderVisibility(visible, false); +void ScriptUtility::setBorderVisibility(bool visible) { + window->editor->toggleBorderVisibility(visible, false); } -bool MainWindow::getBorderVisibility() { - return this->ui->checkBox_ToggleBorder->isChecked(); +bool ScriptUtility::getBorderVisibility() { + return window->ui->checkBox_ToggleBorder->isChecked(); } -void MainWindow::setSmartPathsEnabled(bool visible) { - this->ui->checkBox_smartPaths->setChecked(visible); +void ScriptUtility::setSmartPathsEnabled(bool visible) { + window->ui->checkBox_smartPaths->setChecked(visible); } -bool MainWindow::getSmartPathsEnabled() { - return this->ui->checkBox_smartPaths->isChecked(); +bool ScriptUtility::getSmartPathsEnabled() { + return window->ui->checkBox_smartPaths->isChecked(); } -QList MainWindow::getMetatileLayerOrder() { - if (!this->editor || !this->editor->map) +QList ScriptUtility::getCustomScripts() { + return projectConfig.getCustomScripts(); +} + +QList ScriptUtility::getMetatileLayerOrder() { + if (!window || !window->editor || !window->editor->map) return QList(); - return this->editor->map->metatileLayerOrder; + return window->editor->map->metatileLayerOrder; } -void MainWindow::setMetatileLayerOrder(QList order) { - if (!this->editor || !this->editor->map) +void ScriptUtility::setMetatileLayerOrder(QList order) { + if (!window || !window->editor || !window->editor->map) return; const int numLayers = 3; @@ -176,36 +194,31 @@ void MainWindow::setMetatileLayerOrder(QList order) { } if (invalid) return; - this->editor->map->metatileLayerOrder = order; - this->refreshAfterPalettePreviewChange(); + window->editor->map->metatileLayerOrder = order; + window->refreshAfterPalettePreviewChange(); } -QList MainWindow::getMetatileLayerOpacity() { - if (!this->editor || !this->editor->map) +QList ScriptUtility::getMetatileLayerOpacity() { + if (!window || !window->editor || !window->editor->map) return QList(); - return this->editor->map->metatileLayerOpacity; + return window->editor->map->metatileLayerOpacity; } -void MainWindow::setMetatileLayerOpacity(QList order) { - if (!this->editor || !this->editor->map) +void ScriptUtility::setMetatileLayerOpacity(QList order) { + if (!window || !window->editor || !window->editor->map) return; - this->editor->map->metatileLayerOpacity = order; - this->refreshAfterPalettePreviewChange(); + window->editor->map->metatileLayerOpacity = order; + window->refreshAfterPalettePreviewChange(); } -bool MainWindow::isPrimaryTileset(QString tilesetName) { - if (!this->editor || !this->editor->project) +bool ScriptUtility::isPrimaryTileset(QString tilesetName) { + if (!window || !window->editor || !window->editor->project) return false; - return this->editor->project->tilesetLabels["primary"].contains(tilesetName); + return window->editor->project->tilesetLabels["primary"].contains(tilesetName); } -bool MainWindow::isSecondaryTileset(QString tilesetName) { - if (!this->editor || !this->editor->project) +bool ScriptUtility::isSecondaryTileset(QString tilesetName) { + if (!window || !window->editor || !window->editor->project) return false; - return this->editor->project->tilesetLabels["secondary"].contains(tilesetName); + return window->editor->project->tilesetLabels["secondary"].contains(tilesetName); } - -QList MainWindow::getCustomScripts() { - return projectConfig.getCustomScripts(); -} - diff --git a/src/script_api/scripting.cpp b/src/script_api/scripting.cpp index 5a3fd097..6541acb2 100644 --- a/src/script_api/scripting.cpp +++ b/src/script_api/scripting.cpp @@ -25,6 +25,7 @@ Scripting *instance = nullptr; void Scripting::init(MainWindow *mainWindow) { if (instance) { instance->engine->setInterrupted(true); + instance->scriptUtility->clearActions(); qDeleteAll(instance->imageCache); delete instance; } @@ -38,6 +39,7 @@ Scripting::Scripting(MainWindow *mainWindow) { this->filepaths.append(script); } this->loadModules(this->filepaths); + this->scriptUtility = new ScriptUtility(mainWindow); } void Scripting::loadModules(QStringList moduleFiles) { @@ -58,7 +60,8 @@ void Scripting::populateGlobalObject(MainWindow *mainWindow) { if (!instance || !instance->engine) return; instance->engine->globalObject().setProperty("map", instance->engine->newQObject(mainWindow)); - instance->engine->globalObject().setProperty("overlay", instance->engine->newQObject(mainWindow->getMapView())); + instance->engine->globalObject().setProperty("overlay", instance->engine->newQObject(mainWindow->ui->graphicsView_Map)); + instance->engine->globalObject().setProperty("utility", instance->engine->newQObject(instance->scriptUtility)); QJSValue constants = instance->engine->newObject(); @@ -91,6 +94,7 @@ void Scripting::populateGlobalObject(MainWindow *mainWindow) { // Prevent changes to the object properties of the global object instance->engine->evaluate("Object.freeze(map);"); instance->engine->evaluate("Object.freeze(overlay);"); + instance->engine->evaluate("Object.freeze(utility);"); instance->engine->evaluate("Object.freeze(constants.version);"); instance->engine->evaluate("Object.freeze(constants);"); } @@ -125,22 +129,12 @@ void Scripting::invokeCallback(CallbackType type, QJSValueList args) { } } -void Scripting::registerAction(QString functionName, QString actionName) { - if (!instance) return; - instance->registeredActions.insert(actionName, functionName); -} - -int Scripting::numRegisteredActions() { - if (!instance) return 0; - return instance->registeredActions.size(); -} - void Scripting::invokeAction(QString actionName) { - if (!instance) return; - if (!instance->registeredActions.contains(actionName)) return; + if (!instance || !instance->scriptUtility) return; + QString functionName = instance->scriptUtility->getActionFunctionName(actionName); + if (functionName.isEmpty()) return; bool foundFunction = false; - QString functionName = instance->registeredActions.value(actionName); for (QJSValue module : instance->modules) { QJSValue callbackFunction = module.property(functionName); if (callbackFunction.isUndefined() || !callbackFunction.isCallable()) diff --git a/src/ui/graphicsview.cpp b/src/ui/graphicsview.cpp index cc270849..1c86e004 100644 --- a/src/ui/graphicsview.cpp +++ b/src/ui/graphicsview.cpp @@ -42,9 +42,9 @@ void MapView::drawForeground(QPainter *painter, const QRectF&) { } void MapView::clearOverlayMap() { - foreach (Overlay * layer, this->overlayMap) { - layer->clearItems(); - delete layer; + foreach (Overlay * overlay, this->overlayMap) { + overlay->clearItems(); + delete overlay; } this->overlayMap.clear(); } From 6757d8afdb66b9f9333f697521c4f8f2f4da585e Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 5 Sep 2022 12:17:27 -0400 Subject: [PATCH 5/7] Standardize API file names --- include/scripting.h | 2 +- include/{api_util.h => scriptutility.h} | 6 +++--- porymap.pro | 10 +++++----- src/{script_api/api_map.cpp => scriptapi/apimap.cpp} | 0 .../api_overlay.cpp => scriptapi/apioverlay.cpp} | 0 .../api_util.cpp => scriptapi/apiutility.cpp} | 0 src/{script_api => scriptapi}/scripting.cpp | 0 7 files changed, 9 insertions(+), 9 deletions(-) rename include/{api_util.h => scriptutility.h} (97%) rename src/{script_api/api_map.cpp => scriptapi/apimap.cpp} (100%) rename src/{script_api/api_overlay.cpp => scriptapi/apioverlay.cpp} (100%) rename src/{script_api/api_util.cpp => scriptapi/apiutility.cpp} (100%) rename src/{script_api => scriptapi}/scripting.cpp (100%) diff --git a/include/scripting.h b/include/scripting.h index 98982e44..873e24c2 100644 --- a/include/scripting.h +++ b/include/scripting.h @@ -4,7 +4,7 @@ #include "mainwindow.h" #include "block.h" -#include "api_util.h" +#include "scriptutility.h" #include #include diff --git a/include/api_util.h b/include/scriptutility.h similarity index 97% rename from include/api_util.h rename to include/scriptutility.h index 85ad3f1b..e7cbc0cf 100644 --- a/include/api_util.h +++ b/include/scriptutility.h @@ -1,6 +1,6 @@ #pragma once -#ifndef APIUTIL_H -#define APIUTIL_H +#ifndef SCRIPTUTILITY_H +#define SCRIPTUTILITY_H #include "mainwindow.h" @@ -51,4 +51,4 @@ private: QMap actionMap; }; -#endif // APIUTIL_H +#endif // SCRIPTUTILITY_H diff --git a/porymap.pro b/porymap.pro index e1edf4e0..4e3b4614 100644 --- a/porymap.pro +++ b/porymap.pro @@ -37,10 +37,10 @@ SOURCES += src/core/block.cpp \ src/lib/fex/parser_util.cpp \ src/lib/orderedjson.cpp \ src/core/regionmapeditcommands.cpp \ - src/script_api/api_map.cpp \ - src/script_api/api_overlay.cpp \ - src/script_api/api_util.cpp \ - src/script_api/scripting.cpp \ + src/scriptapi/apimap.cpp \ + src/scriptapi/apioverlay.cpp \ + src/scriptapi/apiutility.cpp \ + src/scriptapi/scripting.cpp \ src/ui/aboutporymap.cpp \ src/ui/draggablepixmapitem.cpp \ src/ui/bordermetatilespixmapitem.cpp \ @@ -169,12 +169,12 @@ HEADERS += include/core/block.h \ include/ui/preferenceeditor.h \ include/ui/regionmappropertiesdialog.h \ include/ui/colorpicker.h \ - include/api_util.h \ include/config.h \ include/editor.h \ include/mainwindow.h \ include/project.h \ include/scripting.h \ + include/scriptutility.h \ include/settings.h \ include/log.h diff --git a/src/script_api/api_map.cpp b/src/scriptapi/apimap.cpp similarity index 100% rename from src/script_api/api_map.cpp rename to src/scriptapi/apimap.cpp diff --git a/src/script_api/api_overlay.cpp b/src/scriptapi/apioverlay.cpp similarity index 100% rename from src/script_api/api_overlay.cpp rename to src/scriptapi/apioverlay.cpp diff --git a/src/script_api/api_util.cpp b/src/scriptapi/apiutility.cpp similarity index 100% rename from src/script_api/api_util.cpp rename to src/scriptapi/apiutility.cpp diff --git a/src/script_api/scripting.cpp b/src/scriptapi/scripting.cpp similarity index 100% rename from src/script_api/scripting.cpp rename to src/scriptapi/scripting.cpp From 60a665642fed8701a9e301037659d916cfaf1c3c Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 6 Sep 2022 12:22:22 -0400 Subject: [PATCH 6/7] Drop useless object freezes --- src/scriptapi/scripting.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/scriptapi/scripting.cpp b/src/scriptapi/scripting.cpp index 6541acb2..52bbe872 100644 --- a/src/scriptapi/scripting.cpp +++ b/src/scriptapi/scripting.cpp @@ -91,10 +91,7 @@ void Scripting::populateGlobalObject(MainWindow *mainWindow) { instance->engine->globalObject().setProperty("constants", constants); - // Prevent changes to the object properties of the global object - instance->engine->evaluate("Object.freeze(map);"); - instance->engine->evaluate("Object.freeze(overlay);"); - instance->engine->evaluate("Object.freeze(utility);"); + // Prevent changes to the constants object instance->engine->evaluate("Object.freeze(constants.version);"); instance->engine->evaluate("Object.freeze(constants);"); } From 4afd18bd34ce0eb2f79a89df0f6a0f5056cd6d30 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 13 Sep 2022 23:01:34 -0400 Subject: [PATCH 7/7] Update manual and changelog for API redesign --- CHANGELOG.md | 6 +- docsrc/manual/scripting-capabilities.rst | 773 ++++++++++++----------- 2 files changed, 395 insertions(+), 384 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d0a3a43..f07b883b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,16 +4,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project somewhat adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). The MAJOR version number is bumped when there are breaking changes in the pret projects. -The **"Breaking Changes"** listed below are changes that have been made in the decompilation projects (e.g. pokeemerald), which porymap requires in order to work properly. If porymap is used on a project that is not up-to-date with the breaking changes, then porymap will likely break or behave improperly. +The **"Breaking Changes"** listed below are changes that have been made in the decompilation projects (e.g. pokeemerald), which porymap requires in order to work properly. It also includes changes to the scripting API that may change the behavior of existing porymap scripts. If porymap is used with a project or API script that is not up-to-date with the breaking changes, then porymap will likely break or behave improperly. ## [Unreleased] ### Breaking Changes - Proper support for pokefirered's clone objects was added, which requires the changes made in [pokefirered/#484](https://github.com/pret/pokefirered/pull/484). +- Many API functions which were previously accessible via the `map` object are now accessible via one of the new objects `overlay`, `utility`, or `constants`. Some functions were renamed accordingly. See [porymap/#460](https://github.com/huderlem/porymap/pull/460) for a full list of API function name changes. +- The boolean arguments `xflip` and `yflip` in the API function `createImage` have been replaced with arguments for horizontal and vertical scale. ### Added - Add prefab support - Add Copy/Paste for metatiles in the Tileset Editor. -- Add new features to the scripting API, including the ability to display message boxes and user input windows, set overlay opacity, get/set map header properties, read tile pixel data, and set blocks or metatile attributes using a raw value. +- Add new features to the scripting API, including the ability to display message boxes and user input windows, set overlay opacity, get/set map header properties, read/write the map border, read tile pixel data, and set blocks or metatile attributes using a raw value. - Add button to copy the full metatile label to the clipboard in the Tileset Editor. - Add option to not open the most recent project on launch. - Add color picker to palette editor for taking colors from the screen. diff --git a/docsrc/manual/scripting-capabilities.rst b/docsrc/manual/scripting-capabilities.rst index 133cdaeb..b64dce07 100644 --- a/docsrc/manual/scripting-capabilities.rst +++ b/docsrc/manual/scripting-capabilities.rst @@ -78,7 +78,7 @@ The grass-randomizer script above happens implicitly when the user paints on the // Porymap callback when project is opened. export function onProjectOpened(projectPath) { - map.registerAction("applyNightTint", "View Night Tint", "T") + utility.registerAction("applyNightTint", "View Night Tint", "T") } Then, to trigger the ``applyNightTint()`` function, we could either click ``Tools -> View Night Tint`` or use the ``T`` keyboard shortcut. @@ -192,13 +192,13 @@ Callbacks Functions ~~~~~~~~~ -All scripting functions are callable via the global ``map`` object. - Map Editing Functions ^^^^^^^^^^^^^^^^^^^^^ The following functions are related to editing the map's blocks or retrieving information about them. +All map editing functions are callable via the global ``map`` object. + .. js:function:: map.getBlock(x, y) Gets a block in the currently-opened map. @@ -444,6 +444,8 @@ Map Header Editing Functions The following functions are related to reading/writing the map's header properties. +All map header functions are callable via the global ``map`` object. + .. js:function:: map.getSong() Gets the name of the background song for the currently-opened map. @@ -576,257 +578,61 @@ The following functions are related to reading/writing the map's header properti :param number floorNumber: the floor number -Map Overlay Functions -^^^^^^^^^^^^^^^^^^^^^ - -The following functions are related to an overlay that is drawn on top of the map area. Text, images, and shapes can be drawn using these functions. Items can be drawn and manipulated on separate layers by specifiying a layer id. Items on higher layer ids will be drawn above those on lower layers. If no layer is specified they will be added to the default layer ``0``. The visibility and position of each layer can be changed; by default all layers are visible, and their position is ``0,0``. - -.. js:function:: map.clearOverlay(layer = 0) - - Clears and erases all overlay items on the specified layer that were previously-added to the map. - - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.clearOverlays() - - Clears and erases all overlay items that were previously-added to the map. - -.. js:function:: map.hideOverlay(layer = 0) - - Hides all overlay items on the specified layer. - - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.hideOverlays() - - Hides all overlay items on all active layers. - -.. js:function:: map.showOverlay(layer = 0) - - Shows all overlay items on the specified layer. - - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.showOverlays() - - Shows all overlay items on all active layers. - -.. js:function:: map.getOverlayVisibility(layer = 0) - - Gets whether the specified overlay layer is currently showing or not. - - :param number layer: the layer id. Defaults to ``0`` - :returns boolean: whether the layer is showing - -.. js:function:: map.setOverlayVisibility(visible, layer = 0) - - Sets the visibility of the specified overlay layer. - - :param boolean visible: whether the layer should be showing - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.setOverlaysVisibility(visible) - - Sets the visibility of all active overlay layers. - - :param boolean visible: whether the layers should be showing - -.. js:function:: map.getOverlayOpacity(layer = 0) - - Gets the opacity of the specified overlay layer. Opacity ranges from 0 (invisible) to 100 (completely opaque). - - :param number layer: the layer id. Defaults to ``0`` - :returns number: the opacity - -.. js:function:: map.setOverlayOpacity(opacity, layer = 0) - - Sets the opacity of the specified overlay layer. Opacity ranges from 0 (invisible) to 100 (completely opaque). - - :param number opacity: the opacity - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.setOverlaysOpacity(opacity) - - Sets the opacity of all active overlay layers. Opacity ranges from 0 (invisible) to 100 (completely opaque). - - :param number opacity: the opacity - -.. js:function:: map.getOverlayX(layer = 0) - - Gets the x position of the specified overlay layer. - - :param number layer: the layer id. Defaults to ``0`` - :returns number: the pixel x coordinate - -.. js:function:: map.getOverlayY(layer = 0) - - Gets the y position of the specified overlay layer. - - :param number layer: the layer id. Defaults to ``0`` - :returns number: the pixel y coordinate - -.. js:function:: map.setOverlayX(x, layer = 0) - - Sets the x position of the specified overlay layer. - - :param number x: the pixel x coordinate - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.setOverlayY(y, layer = 0) - - Sets the y position of the specified overlay layer. - - :param number y: the pixel y coordinate - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.setOverlaysX(x) - - Sets the x position of all active overlay layers. - - :param number x: the pixel x coordinate - -.. js:function:: map.setOverlaysY(y) - - Sets the y position of all active overlay layers. - - :param number y: the pixel y coordinate - -.. js:function:: map.getOverlayPosition(layer = 0) - - Gets the position of the specified overlay layer. - - :param number layer: the layer id. Defaults to ``0`` - :returns {x, y}: the layer's pixel coordinates - -.. js:function:: map.setOverlayPosition(x, y, layer = 0) - - Sets the position of the specified overlay layer. - - :param number x: the pixel x coordinate - :param number y: the pixel y coordinate - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.setOverlaysPosition(x, y) - - Sets the position of all active overlay layers. - - :param number x: the pixel x coordinate - :param number y: the pixel y coordinate - -.. js:function:: map.moveOverlay(deltaX, deltaY, layer = 0) - - Moves the specified overlay layer. - - :param number deltaX: the number of pixels to move horizontally - :param number deltaY: the number of pixels to move vertically - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.moveOverlays(deltaX, deltaY) - - Moves all active overlay layers. - - :param number deltaX: the number of pixels to move horizontally - :param number deltaY: the number of pixels to move vertically - -.. js:function:: map.addText(text, x, y, color = "#000000", size = 12, layer = 0) - - Adds a text item to the specified overlay layer. - - :param string text: the text to display - :param number x: the x pixel coordinate of the text (relative to the layer's position) - :param number y: the y pixel coordinate of the text (relative to the layer's position) - :param string color: the color of the text. Can be specified as "#RRGGBB" or "#AARRGGBB". Defaults to black. - :param number size: the font size of the text. Defaults to 12. - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.addRect(x, y, width, height, color = "#000000", layer = 0) - - Adds a rectangle outline item to the specified overlay layer. - - :param number x: the x pixel coordinate of the rectangle's top-left corner (relative to the layer's position) - :param number y: the y pixel coordinate of the rectangle's top-left corner (relative to the layer's position) - :param number width: the pixel width of the rectangle - :param number height: the pixel height of the rectangle - :param string color: the color of the rectangle. Can be specified as "#RRGGBB" or "#AARRGGBB". Defaults to black. - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.addFilledRect(x, y, width, height, color = "#000000", layer = 0) - - Adds a filled rectangle item to the specified overlay layer. - - :param number x: the x pixel coordinate of the rectangle's top-left corner (relative to the layer's position) - :param number y: the y pixel coordinate of the rectangle's top-left corner (relative to the layer's position) - :param number width: the pixel width of the rectangle - :param number height: the pixel height of the rectangle - :param string color: the color of the rectangle. Can be specified as "#RRGGBB" or "#AARRGGBB". Defaults to black. - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.addImage(x, y, filepath, layer = 0, useCache = true) - - Adds an image item to the specified overlay layer. - - :param number x: the x pixel coordinate of the image's top-left corner (relative to the layer's position) - :param number y: the y pixel coordinate of the image's top-left corner (relative to the layer's position) - :param string filepath: the image's filepath - :param number layer: the layer id. Defaults to ``0`` - :param boolean useCache: whether the image should be saved/loaded using the cache. Defaults to ``true``. Reading images from a file is slow. Setting ``useCache`` to ``true`` will save the image to memory so that the next time the filepath is encountered the image can be loaded from memory rather than the file. - -.. js:function:: map.createImage(x, y, filepath, width = -1, height = -1, offset = 0, hScale = 1, vScale = 1, paletteId = -1, setTransparency = false, layer = 0, useCache = true) - - Creates an image item on the specified overlay layer. This differs from ``map.addImage`` by allowing the new image to be a transformation of the image file. - - :param number x: the x pixel coordinate of the image's top-left corner (relative to the layer's position) - :param number y: the y pixel coordinate of the image's top-left corner (relative to the layer's position) - :param string filepath: the image's filepath - :param number width: the width in pixels of the area to read in the image. If ``-1``, use the full width of the original image. Defaults to ``-1`` - :param number height: the height in pixels of the area to read in the image. If ``-1``, use the full height of the original image. Defaults to ``-1`` - :param number offset: the pixel offset into the original image where data should be read from. Defaults to ``0`` - :param number hScale: the horizontal scale for the image. Negative values will be a horizontal flip of the original image. Defaults to ``1`` - :param number vScale: the vertical scale for the image. Negative values will be a vertical flip of the original image. Defaults to ``1`` - :param number paletteId: the id of which currently loaded tileset palette to use for the image. If ``-1``, use the original image's palette. Defaults to ``-1`` - :param boolean setTransparency: whether the color at index 0 should be overwritten with transparent pixels. Defaults to ``false`` - :param number layer: the layer id. Defaults to ``0`` - :param boolean useCache: whether the image should be saved/loaded using the cache. Defaults to ``true``. Reading images from a file is slow. Setting ``useCache`` to ``true`` will save the image to memory so that the next time the filepath is encountered the image can be loaded from memory rather than the file. - -.. js:function:: map.addTileImage(x, y, tileId, xflip, yflip, palette, setTransparency = false, layer = 0) - - Creates an image of a tile on the specified overlay layer. - - :param number x: the x pixel coordinate of the image's top-left corner (relative to the layer's position) - :param number y: the y pixel coordinate of the image's top-left corner (relative to the layer's position) - :param number tileId: tile value for the image - :param boolean xflip: whether the tile image is flipped horizontally - :param boolean yflip: whether the tile image is flipped vertically - :param number palette: palette number for the tile image - :param boolean setTransparency: whether the color at index 0 should be overwritten with transparent pixels. Defaults to ``false`` - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.addTileImage(x, y, tile, setTransparency = false, layer = 0) - - Creates an image of a tile on the specified overlay layer. This is an overloaded function that takes a single tile as a JavaScript object instead of each of the tile's properties individually. - - :param number x: the x pixel coordinate of the image's top-left corner (relative to the layer's position) - :param number y: the y pixel coordinate of the image's top-left corner (relative to the layer's position) - :param {tileId,xflip,yflip,palette} tile: the tile to create an image of - :param boolean setTransparency: whether the color at index 0 should be overwritten with transparent pixels. Defaults to ``false`` - :param number layer: the layer id. Defaults to ``0`` - -.. js:function:: map.addMetatileImage(x, y, metatileId, setTransparency = false, layer = 0) - - Creates an image of a metatile on the specified overlay layer. - - :param number x: the x pixel coordinate of the image's top-left corner (relative to the layer's position) - :param number y: the y pixel coordinate of the image's top-left corner (relative to the layer's position) - :param number metatileId: id of the metatile to create an image of - :param boolean setTransparency: whether the color at index 0 should be overwritten with transparent pixels. Defaults to ``false`` - :param number layer: the layer id. Defaults to ``0`` - - Tileset Functions ^^^^^^^^^^^^^^^^^ The following functions are related to tilesets and how they are rendered. The functions with "preview" in their name operate on a "fake" version of the palette colors. This means that changing these "preview" colors won't affect the actual tileset colors in the project. A good use of the "preview" palettes would be Day/Night tints, for example. +All tileset functions are callable via the global ``map`` object. + +.. js:function:: map.getPrimaryTileset() + + Gets the name of the primary tileset for the currently-opened map. + + :returns string: primary tileset name + +.. js:function:: map.setPrimaryTileset(tileset) + + Sets the primary tileset for the currently-opened map. + + :param string tileset: the tileset name + +.. js:function:: map.getSecondaryTileset() + + Gets the name of the secondary tileset for the currently-opened map. + + :returns string: secondary tileset name + +.. js:function:: map.setSecondaryTileset(tileset) + + Sets the secondary tileset for the currently-opened map. + + :param string tileset: the tileset name + +.. js:function:: map.getNumPrimaryTilesetTiles() + + Gets the number of tiles in the primary tileset for the currently-opened map. + + :returns number: number of tiles + +.. js:function:: map.getNumSecondaryTilesetTiles() + + Gets the number of tiles in the secondary tileset for the currently-opened map. + + :returns number: number of tiles + +.. js:function:: map.getNumPrimaryTilesetMetatiles() + + Gets the number of metatiles in the primary tileset for the currently-opened map. + + :returns number: number of metatiles + +.. js:function:: map.getNumSecondaryTilesetMetatiles() + + Gets the number of metatiles in the secondary tileset for the currently-opened map. + + :returns number: number of metatiles + .. js:function:: map.getPrimaryTilesetPalettePreview(paletteIndex) Gets a palette from the primary tileset of the currently-opened map. @@ -931,104 +737,6 @@ The following functions are related to tilesets and how they are rendered. The f :param array palettes: array of arrays of colors. Each color is a 3-element RGB array -.. js:function:: map.isPrimaryTileset(tilesetName) - - Gets whether the specified tileset is a primary tileset. - - :param string tilesetName: the tileset name - :returns boolean: is a primary tileset - -.. js:function:: map.isSecondaryTileset(tilesetName) - - Gets whether the specified tileset is a secondary tileset. - - :param string tilesetName: the tileset name - :returns boolean: is a secondary tileset - -.. js:function:: map.getPrimaryTileset() - - Gets the name of the primary tileset for the currently-opened map. - - :returns string: primary tileset name - -.. js:function:: map.setPrimaryTileset(tileset) - - Sets the primary tileset for the currently-opened map. - - :param string tileset: the tileset name - -.. js:function:: map.getSecondaryTileset() - - Gets the name of the secondary tileset for the currently-opened map. - - :returns string: secondary tileset name - -.. js:function:: map.setSecondaryTileset(tileset) - - Sets the secondary tileset for the currently-opened map. - - :param string tileset: the tileset name - -.. js:function:: map.getNumPrimaryTilesetMetatiles() - - Gets the number of metatiles in the primary tileset for the currently-opened map. - - :returns number: number of metatiles - -.. js:function:: map.getMaxPrimaryTilesetMetatiles() - - Gets the maximum number of metatiles allowed in a primary tileset. - - :returns number: maximum number of metatiles - -.. js:function:: map.getNumSecondaryTilesetMetatiles() - - Gets the number of metatiles in the secondary tileset for the currently-opened map. - - :returns number: number of metatiles - -.. js:function:: map.getMaxSecondaryTilesetMetatiles() - - Gets the maximum number of metatiles allowed in a secondary tileset. - - :returns number: maximum number of metatiles - -.. js:function:: map.getNumPrimaryTilesetTiles() - - Gets the number of tiles in the primary tileset for the currently-opened map. - - :returns number: number of tiles - -.. js:function:: map.getMaxPrimaryTilesetTiles() - - Gets the maximum number of tiles allowed in a primary tileset. - - :returns number: maximum number of tiles - -.. js:function:: map.getNumSecondaryTilesetTiles() - - Gets the number of tiles in the secondary tileset for the currently-opened map. - - :returns number: number of tiles - -.. js:function:: map.getMaxSecondaryTilesetTiles() - - Gets the maximum number of tiles allowed in a secondary tileset. - - :returns number: maximum number of tiles - -.. js:function:: map.getNumTilesInMetatile() - - Gets the number of tiles in a metatile. Will be either ``8`` or ``12`` depending on ``enable_triple_layer_metatiles``. - - :returns number: number of tiles in a metatile - -.. js:function:: map.getNumMetatileLayers() - - Gets the number of layers in a metatiles. Will be either ``2`` or ``3`` depending on ``enable_triple_layer_metatiles``. - - :returns number: number of layers in a metatile - .. js:function:: map.getMetatileLayerOrder() Gets the order that metatile layers are rendered. @@ -1225,84 +933,322 @@ The following functions are related to tilesets and how they are rendered. The f :returns array: the pixel data +Overlay Functions +^^^^^^^^^^^^^^^^^ + +The following functions are related to an overlay that is drawn on top of the map area. Text, images, and shapes can be drawn using these functions. Items can be drawn and manipulated on separate layers by specifiying a layer id. Items on higher layer ids will be drawn above those on lower layers. The visibility, position, and opacity of each layer can be changed; by default all layers are visible, at position ``0,0``, and have an opacity of ``100``. + +All overlay functions are callable via the global ``overlay`` object. + +.. js:function:: overlay.clear(layer) + + Clears and erases all previously-added overlay items on the specified layer. + + :param number layer: the layer id + +.. js:function:: overlay.clear() + + This is an overloaded function. Clears and erases all previously-added overlay items on every layer. + +.. js:function:: overlay.hide(layer) + + Hides all overlay items on the specified layer. + + :param number layer: the layer id + +.. js:function:: overlay.hide() + + This is an overloaded function. Hides all overlay items on all active layers. Layers that have not been used yet will not be hidden. + +.. js:function:: overlay.show(layer) + + Shows all overlay items on the specified layer. + + :param number layer: the layer id + +.. js:function:: overlay.show() + + This is an overloaded function. Shows all overlay items on all active layers. + +.. js:function:: overlay.getVisibility(layer = 0) + + Gets whether the specified overlay layer is currently showing or not. + + :param number layer: the layer id. Defaults to ``0`` + :returns boolean: whether the layer is showing + +.. js:function:: overlay.setVisibility(visible, layer) + + Sets the visibility of the specified overlay layer. + + :param boolean visible: whether the layer should be showing + :param number layer: the layer id + +.. js:function:: overlay.setVisibility(visible) + + This is an overloaded function. Sets the visibility of all active overlay layers. + + :param boolean visible: whether the layers should be showing + +.. js:function:: overlay.getOpacity(layer = 0) + + Gets the opacity of the specified overlay layer. Opacity ranges from ``0`` (invisible) to ``100`` (completely opaque). + + :param number layer: the layer id. Defaults to ``0`` + :returns number: the opacity + +.. js:function:: overlay.setOpacity(opacity, layer) + + Sets the opacity of the specified overlay layer. Opacity ranges from ``0`` (invisible) to ``100`` (completely opaque). + + :param number opacity: the opacity + :param number layer: the layer id + +.. js:function:: overlay.setOpacity(opacity) + + This is an overloaded function. Sets the opacity of all active overlay layers. Layers that have not been used yet will not have their opacity changed. Opacity ranges from ``0`` (invisible) to ``100`` (completely opaque). + + :param number opacity: the opacity + +.. js:function:: overlay.getX(layer = 0) + + Gets the x position of the specified overlay layer. + + :param number layer: the layer id. Defaults to ``0`` + :returns number: the pixel x coordinate + +.. js:function:: overlay.getY(layer = 0) + + Gets the y position of the specified overlay layer. + + :param number layer: the layer id. Defaults to ``0`` + :returns number: the pixel y coordinate + +.. js:function:: overlay.setX(x, layer) + + Sets the x position of the specified overlay layer. + + :param number x: the pixel x coordinate + :param number layer: the layer id + +.. js:function:: overlay.setX(x) + + This is an overloaded function. Sets the x position of all active overlay layers. Layers that have not been used yet will not have their position changed. + + :param number x: the pixel x coordinate + +.. js:function:: overlay.setY(y, layer) + + Sets the y position of the specified overlay layer. + + :param number y: the pixel y coordinate + :param number layer: the layer id + +.. js:function:: overlay.setY(y) + + This is an overloaded function. Sets the y position of all active overlay layers. Layers that have not been used yet will not have their position changed. + + :param number y: the pixel y coordinate + +.. js:function:: overlay.getPosition(layer = 0) + + Gets the position of the specified overlay layer. + + :param number layer: the layer id. Defaults to ``0`` + :returns {x, y}: the layer's pixel coordinates + +.. js:function:: overlay.setPosition(x, y, layer) + + Sets the position of the specified overlay layer. + + :param number x: the pixel x coordinate + :param number y: the pixel y coordinate + :param number layer: the layer id + +.. js:function:: overlay.setPosition(x, y) + + This is an overloaded function. Sets the position of all active overlay layers. Layers that have not been used yet will not have their position changed. + + :param number x: the pixel x coordinate + :param number y: the pixel y coordinate + +.. js:function:: overlay.move(deltaX, deltaY, layer) + + Moves the specified overlay layer. + + :param number deltaX: the number of pixels to move horizontally + :param number deltaY: the number of pixels to move vertically + :param number layer: the layer id + +.. js:function:: overlay.move(deltaX, deltaY) + + This is an overloaded function. Moves all active overlay layers. Layers that have not been used yet will not have their position changed. + + :param number deltaX: the number of pixels to move horizontally + :param number deltaY: the number of pixels to move vertically + +.. js:function:: overlay.addText(text, x, y, color = "#000000", size = 12, layer = 0) + + Adds a text item to the specified overlay layer. + + :param string text: the text to display + :param number x: the x pixel coordinate of the text (relative to the layer's position) + :param number y: the y pixel coordinate of the text (relative to the layer's position) + :param string color: the color of the text. Can be specified as "#RRGGBB" or "#AARRGGBB". Defaults to black. + :param number size: the font size of the text. Defaults to 12. + :param number layer: the layer id. Defaults to ``0`` + +.. js:function:: overlay.addRect(x, y, width, height, color = "#000000", layer = 0) + + Adds a rectangle outline item to the specified overlay layer. + + :param number x: the x pixel coordinate of the rectangle's top-left corner (relative to the layer's position) + :param number y: the y pixel coordinate of the rectangle's top-left corner (relative to the layer's position) + :param number width: the pixel width of the rectangle + :param number height: the pixel height of the rectangle + :param string color: the color of the rectangle. Can be specified as "#RRGGBB" or "#AARRGGBB". Defaults to black. + :param number layer: the layer id. Defaults to ``0`` + +.. js:function:: overlay.addFilledRect(x, y, width, height, color = "#000000", layer = 0) + + Adds a filled rectangle item to the specified overlay layer. + + :param number x: the x pixel coordinate of the rectangle's top-left corner (relative to the layer's position) + :param number y: the y pixel coordinate of the rectangle's top-left corner (relative to the layer's position) + :param number width: the pixel width of the rectangle + :param number height: the pixel height of the rectangle + :param string color: the color of the rectangle. Can be specified as "#RRGGBB" or "#AARRGGBB". Defaults to black. + :param number layer: the layer id. Defaults to ``0`` + +.. js:function:: overlay.addImage(x, y, filepath, layer = 0, useCache = true) + + Adds an image item to the specified overlay layer. + + :param number x: the x pixel coordinate of the image's top-left corner (relative to the layer's position) + :param number y: the y pixel coordinate of the image's top-left corner (relative to the layer's position) + :param string filepath: the image's filepath + :param number layer: the layer id. Defaults to ``0`` + :param boolean useCache: whether the image should be saved/loaded using the cache. Defaults to ``true``. Reading images from a file is slow. Setting ``useCache`` to ``true`` will save the image to memory so that the next time the filepath is encountered the image can be loaded from memory rather than the file. + +.. js:function:: overlay.createImage(x, y, filepath, width = -1, height = -1, offset = 0, hScale = 1, vScale = 1, paletteId = -1, setTransparency = false, layer = 0, useCache = true) + + Creates an image item on the specified overlay layer. This differs from ``overlay.addImage`` by allowing the new image to be a transformation of the image file. + + :param number x: the x pixel coordinate of the image's top-left corner (relative to the layer's position) + :param number y: the y pixel coordinate of the image's top-left corner (relative to the layer's position) + :param string filepath: the image's filepath + :param number width: the width in pixels of the area to read in the image. If ``-1``, use the full width of the original image. Defaults to ``-1`` + :param number height: the height in pixels of the area to read in the image. If ``-1``, use the full height of the original image. Defaults to ``-1`` + :param number offset: the pixel offset into the original image where data should be read from. Defaults to ``0`` + :param number hScale: the horizontal scale for the image. Negative values will be a horizontal flip of the original image. Defaults to ``1`` + :param number vScale: the vertical scale for the image. Negative values will be a vertical flip of the original image. Defaults to ``1`` + :param number paletteId: the id of which currently loaded tileset palette to use for the image. If ``-1``, use the original image's palette. Defaults to ``-1`` + :param boolean setTransparency: whether the color at index 0 should be overwritten with transparent pixels. Defaults to ``false`` + :param number layer: the layer id. Defaults to ``0`` + :param boolean useCache: whether the image should be saved/loaded using the cache. Defaults to ``true``. Reading images from a file is slow. Setting ``useCache`` to ``true`` will save the image to memory so that the next time the filepath is encountered the image can be loaded from memory rather than the file. + +.. js:function:: overlay.addTileImage(x, y, tileId, xflip, yflip, palette, setTransparency = false, layer = 0) + + Creates an image of a tile on the specified overlay layer. + + :param number x: the x pixel coordinate of the image's top-left corner (relative to the layer's position) + :param number y: the y pixel coordinate of the image's top-left corner (relative to the layer's position) + :param number tileId: tile value for the image + :param boolean xflip: whether the tile image is flipped horizontally + :param boolean yflip: whether the tile image is flipped vertically + :param number palette: palette number for the tile image + :param boolean setTransparency: whether the color at index 0 should be overwritten with transparent pixels. Defaults to ``false`` + :param number layer: the layer id. Defaults to ``0`` + +.. js:function:: overlay.addTileImage(x, y, tile, setTransparency = false, layer = 0) + + Creates an image of a tile on the specified overlay layer. This is an overloaded function that takes a single tile as a JavaScript object instead of each of the tile's properties individually. + + :param number x: the x pixel coordinate of the image's top-left corner (relative to the layer's position) + :param number y: the y pixel coordinate of the image's top-left corner (relative to the layer's position) + :param {tileId,xflip,yflip,palette} tile: the tile to create an image of + :param boolean setTransparency: whether the color at index 0 should be overwritten with transparent pixels. Defaults to ``false`` + :param number layer: the layer id. Defaults to ``0`` + +.. js:function:: overlay.addMetatileImage(x, y, metatileId, setTransparency = false, layer = 0) + + Creates an image of a metatile on the specified overlay layer. + + :param number x: the x pixel coordinate of the image's top-left corner (relative to the layer's position) + :param number y: the y pixel coordinate of the image's top-left corner (relative to the layer's position) + :param number metatileId: id of the metatile to create an image of + :param boolean setTransparency: whether the color at index 0 should be overwritten with transparent pixels. Defaults to ``false`` + :param number layer: the layer id. Defaults to ``0`` + + Settings Functions ^^^^^^^^^^^^^^^^^^ The following functions are related to settings. -.. js:function:: map.getGridVisibility() +All settings functions are callable via the global ``utility`` object. + +.. js:function:: utility.getGridVisibility() Gets the visibility of the map grid overlay. :returns boolean: grid visibility -.. js:function:: map.setGridVisibility(visible) +.. js:function:: utility.setGridVisibility(visible) Sets the visibility of the map grid overlay. :param boolean visible: grid visibility -.. js:function:: map.getBorderVisibility() +.. js:function:: utility.getBorderVisibility() Gets the visibility of the map's border. :returns boolean: border visibility -.. js:function:: map.setBorderVisibility(visible) +.. js:function:: utility.setBorderVisibility(visible) Sets the visibility of the map's border. :param boolean visible: border visibility -.. js:function:: map.getSmartPathsEnabled() +.. js:function:: utility.getSmartPathsEnabled() Gets the toggle state of smart paths. :returns boolean: smart paths enabled -.. js:function:: map.setSmartPathsEnabled(enabled) +.. js:function:: utility.setSmartPathsEnabled(enabled) Sets the toggle state of smart paths. :param boolean enabled: smart paths enabled -.. js:function:: map.getBaseGameVersion() - - Gets the project's base game version. - - :returns string: ``"pokeruby"``, ``"pokefirered"``, or ``"pokeemerald"`` - -.. js:function:: map.getPorymapVersion() - - Gets the current version of Porymap (``MAJOR.MINOR.PATCH``). - - :returns {major, minor, patch}: the version object - -.. js:function:: map.getCustomScripts() +.. js:function:: utility.getCustomScripts() Gets the list of paths to custom scripts. :returns array: string array of custom scripts paths -.. js:function:: map.getMainTab() +.. js:function:: utility.getMainTab() Gets the index of the currently selected main tab. Tabs are indexed from left to right, starting at 0 (``0``: Map, ``1``: Events, ``2``: Header, ``3``: Connections, ``4``: Wild Pokemon). :returns number: current main tab index -.. js:function:: map.setMainTab(tab) +.. js:function:: utility.setMainTab(tab) Sets the currently selected main tab. Tabs are indexed from left to right, starting at 0 (``0``: Map, ``1``: Events, ``2``: Header, ``3``: Connections, ``4``: Wild Pokemon). :param number tab: index of the tab to select -.. js:function:: map.getMapViewTab() +.. js:function:: utility.getMapViewTab() Gets the index of the currently selected map view tab. Tabs are indexed from left to right, starting at 0 (``0``: Metatiles, ``1``: Collision). :returns number: current map view tab index -.. js:function:: map.setMapViewTab(tab) +.. js:function:: utility.setMapViewTab(tab) Sets the currently selected map view tab. Tabs are indexed from left to right, starting at 0 (``0``: Metatiles, ``1``: Collision). @@ -1313,7 +1259,9 @@ Utility Functions These are some miscellaneous functions that can be very useful when building custom scripts. -.. js:function:: map.registerAction(functionName, actionName, shortcut = "") +All utility functions are callable via the global ``utility`` object. + +.. js:function:: utility.registerAction(functionName, actionName, shortcut = "") Registers a JavaScript function to an action that can be manually triggered in Porymap's ``Tools`` menu. Optionally, a keyboard shortcut (e.g. ``"Ctrl+P"``) can also be specified, assuming it doesn't collide with any existing shortcuts used by Porymap. The function specified by ``functionName`` must have the ``export`` keyword. @@ -1321,32 +1269,32 @@ These are some miscellaneous functions that can be very useful when building cus :param string actionName: name of the action that will be displayed in the ``Tools`` menu :param string shortcut: optional keyboard shortcut -.. js:function:: map.setTimeout(func, delayMs) +.. js:function:: utility.setTimeout(func, delayMs) This behaves essentially the same as JavaScript's ``setTimeout()`` that is used in web browsers or NodeJS. The ``func`` argument is a JavaScript function (NOT the name of a function) which will be executed after a delay. This is useful for creating animations or refreshing the overlay at constant intervals. :param function func: a JavaScript function that will be executed later :param number delayMs: the number of milliseconds to wait before executing ``func`` -.. js:function:: map.log(message) +.. js:function:: utility.log(message) Logs a message to the Porymap log file with the prefix ``[INFO]``. This is useful for debugging custom scripts. :param string message: the message to log -.. js:function:: map.warn(message) +.. js:function:: utility.warn(message) Logs a message to the Porymap log file with the prefix ``[WARN]``. :param string message: the message to log -.. js:function:: map.error(message) +.. js:function:: utility.error(message) Logs a message to the Porymap log file with the prefix ``[ERROR]``. :param string message: the message to log -.. js:function:: map.showMessage(text, informativeText, detailedText) +.. js:function:: utility.showMessage(text, informativeText, detailedText) Displays a message box with an "Information" icon and an ``OK`` button. Execution stops while the window is open. @@ -1354,7 +1302,7 @@ These are some miscellaneous functions that can be very useful when building cus :param string informativeText: smaller text below the main message. Defaults to ``""`` :param string detailedText: text hidden behind a "Show Details" box. Defaults to ``""`` -.. js:function:: map.showWarning(text, informativeText, detailedText) +.. js:function:: utility.showWarning(text, informativeText, detailedText) Displays a message box with a "Warning" icon and an ``OK`` button. Execution stops while the window is open. @@ -1362,7 +1310,7 @@ These are some miscellaneous functions that can be very useful when building cus :param string informativeText: smaller text below the main message. Defaults to ``""`` :param string detailedText: text hidden behind a "Show Details" box. Defaults to ``""`` -.. js:function:: map.showError(text, informativeText, detailedText) +.. js:function:: utility.showError(text, informativeText, detailedText) Displays a message box with a "Critical" icon and an ``OK`` button. Execution stops while the window is open. @@ -1370,7 +1318,7 @@ These are some miscellaneous functions that can be very useful when building cus :param string informativeText: smaller text below the main message. Defaults to ``""`` :param string detailedText: text hidden behind a "Show Details" box. Defaults to ``""`` -.. js:function:: map.showQuestion(text, informativeText, detailedText) +.. js:function:: utility.showQuestion(text, informativeText, detailedText) Displays a message box with a "Question" icon and a ``Yes`` and a ``No`` button. Execution stops while the window is open. @@ -1379,7 +1327,7 @@ These are some miscellaneous functions that can be very useful when building cus :param string detailedText: text hidden behind a "Show Details" box. Defaults to ``""`` :returns boolean: ``true`` if ``Yes`` was selected, ``false`` if ``No`` was selected or if the window was closed without selection -.. js:function:: map.getInputText(title, label, default) +.. js:function:: utility.getInputText(title, label, default) Displays a text input dialog with an ``OK`` and a ``Cancel`` button. Execution stops while the window is open. @@ -1388,7 +1336,7 @@ These are some miscellaneous functions that can be very useful when building cus :param string default: the text in the input entry area when the window is opened. Defaults to ``""`` :returns {input, ok}: ``input`` will be the input text and ``ok`` will be ``true`` if ``OK`` was selected. ``input`` will be ``""`` and ``ok`` will be ``false`` if ``Cancel`` was selected or if the window was closed without selection. -.. js:function:: map.getInputNumber(title, label, default, min, max, decimals, step) +.. js:function:: utility.getInputNumber(title, label, default, min, max, decimals, step) Displays a number input dialog with an ``OK`` and a ``Cancel`` button. Execution stops while the window is open. @@ -1401,7 +1349,7 @@ These are some miscellaneous functions that can be very useful when building cus :param number step: the increment by which the input number will change when the spinner is used. Defaults to ``1`` :returns {input, ok}: ``input`` will be the input number and ``ok`` will be ``true`` if ``OK`` was selected. ``input`` will be ``default`` and ``ok`` will be ``false`` if ``Cancel`` was selected or if the window was closed without selection. -.. js:function:: map.getInputItem(title, label, items, default, editable) +.. js:function:: utility.getInputItem(title, label, items, default, editable) Displays a text input dialog with an items dropdown and an ``OK`` and a ``Cancel`` button. Execution stops while the window is open. @@ -1411,3 +1359,64 @@ These are some miscellaneous functions that can be very useful when building cus :param number default: the index of the item to select by default. Defaults to ``0`` :param boolean editable: whether the user is allowed to enter their own text instead. Defaults to ``false`` :returns {input, ok}: ``input`` will be the input text and ``ok`` will be ``true`` if ``OK`` was selected. ``input`` will be the text of the item at ``default`` and ``ok`` will be ``false`` if ``Cancel`` was selected or if the window was closed without selection. + +.. js:function:: utility.isPrimaryTileset(tilesetName) + + Gets whether the specified tileset is a primary tileset. + + :param string tilesetName: the tileset name + :returns boolean: is a primary tileset + +.. js:function:: utility.isSecondaryTileset(tilesetName) + + Gets whether the specified tileset is a secondary tileset. + + :param string tilesetName: the tileset name + :returns boolean: is a secondary tileset + +Constants +~~~~~~~~~ + +Some constant values are provided for convenience. These are read-only properties guaranteed not to change unless a new project is opened or the current one is reloaded. + +All constants are accessible via the global ``constants`` object. + +.. js:attribute:: constants.max_primary_tiles + + The maximum number of tiles in a primary tileset. + +.. js:attribute:: constants.max_secondary_tiles + + The maximum number of tiles in a secondary tileset. + +.. js:attribute:: constants.max_primary_metatiles + + The maximum number of metatiles in a primary tileset. + +.. js:attribute:: constants.max_secondary_metatiles + + The maximum number of metatiles in a secondary tileset. + +.. js:attribute:: constants.layers_per_metatile + + The number of tile layers used in each metatile. This will either be ``2`` or ``3``, depending on the config setting ``enable_triple_layer_metatiles``. + +.. js:attribute:: constants.tiles_per_metatile + + The number of tiles in each metatile. This will either be ``8`` or ``12``, depending on the config setting ``enable_triple_layer_metatiles``. + +.. js:attribute:: constants.base_game_version + + The string value of the config setting ``base_game_version``. This will either be ``pokeruby``, ``pokefirered``, or ``pokeemerald``. + +.. js:attribute:: constants.version.major + + Porymap's major version number. For example, for Porymap version ``5.0.1`` this will be ``5``. + +.. js:attribute:: constants.version.minor + + Porymap's minor version number. For example, for Porymap version ``5.0.1`` this will be ``0``. + +.. js:attribute:: constants.version.patch + + Porymap's patch version number. For example, for Porymap version ``5.0.1`` this will be ``1``.