Add setMetatile functions to API (layerType, encounterType, terrainType, Behavior, Tile)
This commit is contained in:
parent
26f0042ff4
commit
ce12a1e017
6 changed files with 150 additions and 45 deletions
|
@ -7,6 +7,28 @@
|
|||
#include <QPoint>
|
||||
#include <QString>
|
||||
|
||||
enum {
|
||||
METATILE_LAYER_MIDDLE_TOP,
|
||||
METATILE_LAYER_BOTTOM_MIDDLE,
|
||||
METATILE_LAYER_BOTTOM_TOP,
|
||||
NUM_METATILE_LAYER_TYPES
|
||||
};
|
||||
|
||||
enum {
|
||||
ENCOUNTER_NONE,
|
||||
ENCOUNTER_LAND,
|
||||
ENCOUNTER_WATER,
|
||||
NUM_METATILE_ENCOUNTER_TYPES
|
||||
};
|
||||
|
||||
enum {
|
||||
TERRAIN_NONE,
|
||||
TERRAIN_GRASS,
|
||||
TERRAIN_WATER,
|
||||
TERRAIN_WATERFALL,
|
||||
NUM_METATILE_TERRAIN_TYPES
|
||||
};
|
||||
|
||||
class Metatile
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -112,6 +112,8 @@ public:
|
|||
Q_INVOKABLE void setMetatileLayerOrder(QList<int> order);
|
||||
Q_INVOKABLE QList<float> getMetatileLayerOpacity();
|
||||
Q_INVOKABLE void setMetatileLayerOpacity(QList<float> order);
|
||||
void saveMetatilesByMetatileId(int metatileId);
|
||||
void saveMetatileAttributesByMetatileId(int metatileId);
|
||||
Metatile * getMetatile(int metatileId);
|
||||
Q_INVOKABLE QString getMetatileLabel(int metatileId);
|
||||
Q_INVOKABLE void setMetatileLabel(int metatileId, QString label);
|
||||
|
@ -124,7 +126,8 @@ public:
|
|||
Q_INVOKABLE int getMetatileBehavior(int metatileId);
|
||||
Q_INVOKABLE void setMetatileBehavior(int metatileId, int behavior);
|
||||
Q_INVOKABLE QJSValue getMetatileTile(int metatileId, int tileIndex);
|
||||
Q_INVOKABLE void setMetatileTile(int metatileId, int tileIndex, int tile, bool xflip, bool yflip, int palette);
|
||||
Q_INVOKABLE void setMetatileTile(int metatileId, int tileIndex, int tileId, bool xflip, bool yflip, int palette, bool forceRedraw = true);
|
||||
Q_INVOKABLE void setMetatileTile(int metatileId, int tileIndex, QJSValue obj, bool forceRedraw = true);
|
||||
|
||||
|
||||
private slots:
|
||||
|
@ -304,6 +307,8 @@ private:
|
|||
|
||||
MapSortOrder mapSortOrder;
|
||||
|
||||
bool needsFullRedraw = false;
|
||||
|
||||
bool setMap(QString, bool scrollTreeView = false);
|
||||
void redrawMapScene();
|
||||
void refreshMapScene();
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
Scripting(MainWindow *mainWindow);
|
||||
static QJSValue fromBlock(Block block);
|
||||
static QJSValue fromTile(Tile tile);
|
||||
static Tile toTile(QJSValue obj);
|
||||
static QJSValue dimensions(int width, int height);
|
||||
static QJSEngine *getEngine();
|
||||
static void init(MainWindow *mainWindow);
|
||||
|
|
|
@ -15,7 +15,15 @@ QJSValue MainWindow::getBlock(int x, int y) {
|
|||
}
|
||||
|
||||
void MainWindow::tryRedrawMapArea(bool forceRedraw) {
|
||||
if (forceRedraw) {
|
||||
if (!forceRedraw) return;
|
||||
|
||||
if (this->needsFullRedraw) {
|
||||
this->editor->map_item->draw(true);
|
||||
this->editor->collision_item->draw(true);
|
||||
this->editor->updateMapBorder();
|
||||
this->editor->updateMapConnections();
|
||||
this->needsFullRedraw = false;
|
||||
} else {
|
||||
this->editor->map_item->draw();
|
||||
this->editor->collision_item->draw();
|
||||
}
|
||||
|
@ -541,6 +549,32 @@ void MainWindow::setMetatileLayerOpacity(QList<float> order) {
|
|||
this->refreshAfterPalettePreviewChange();
|
||||
}
|
||||
|
||||
void MainWindow::saveMetatilesByMetatileId(int metatileId) {
|
||||
Tileset * tileset = Tileset::getBlockTileset(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
|
||||
if (this->editor->project)
|
||||
this->editor->project->saveTilesetMetatiles(tileset);
|
||||
|
||||
// Refresh anything that can display metatiles (except the actual map view)
|
||||
if (this->tilesetEditor)
|
||||
this->tilesetEditor->updateTilesets(this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label);
|
||||
if (this->editor->metatile_selector_item)
|
||||
this->editor->metatile_selector_item->draw();
|
||||
if (this->editor->selected_border_metatiles_item)
|
||||
this->editor->selected_border_metatiles_item->draw();
|
||||
if (this->editor->current_metatile_selection_item)
|
||||
this->editor->current_metatile_selection_item->draw();
|
||||
}
|
||||
|
||||
void MainWindow::saveMetatileAttributesByMetatileId(int metatileId) {
|
||||
Tileset * tileset = Tileset::getBlockTileset(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
|
||||
if (this->editor->project)
|
||||
this->editor->project->saveTilesetMetatileAttributes(tileset);
|
||||
|
||||
// If the Tileset Editor is currently displaying the updated metatile, refresh it
|
||||
if (this->tilesetEditor && this->tilesetEditor->getSelectedMetatile() == metatileId)
|
||||
this->tilesetEditor->updateTilesets(this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label);
|
||||
}
|
||||
|
||||
Metatile * MainWindow::getMetatile(int metatileId) {
|
||||
if (!this->editor || !this->editor->map || !this->editor->map->layout)
|
||||
return nullptr;
|
||||
|
@ -548,101 +582,129 @@ Metatile * MainWindow::getMetatile(int metatileId) {
|
|||
}
|
||||
|
||||
QString MainWindow::getMetatileLabel(int metatileId) {
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
if (!metatile || metatile->label.size() == 0)
|
||||
return QString();
|
||||
return metatile->label;
|
||||
}
|
||||
|
||||
// TODO: Validate label
|
||||
void MainWindow::setMetatileLabel(int metatileId, QString label) {
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
if (!metatile)
|
||||
return;
|
||||
|
||||
// TODO: Verify input
|
||||
//label.remove(QRegularExpression("?![_A-Za-z0-9]*$"));
|
||||
|
||||
if (this->tilesetEditor && this->tilesetEditor->getSelectedMetatile() == metatileId) {
|
||||
this->tilesetEditor->setMetatileLabel(label);
|
||||
} else if (metatile->label != label) {
|
||||
metatile->label = label;
|
||||
|
||||
// TODO: Writing to file immediately.
|
||||
// Perhaps update tilesets to carry a "hasUnsavedChanges" field,
|
||||
// and on saving the project save all tilesets with unsaved changes.
|
||||
// saveTilesetMetatileLabels can be trivially updated to handle a single tileset at a time.
|
||||
if (this->editor->project)
|
||||
this->editor->project->saveTilesetMetatileLabels(this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
|
||||
}
|
||||
}
|
||||
|
||||
int MainWindow::getMetatileLayerType(int metatileId) {
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
if (!metatile)
|
||||
return -1;
|
||||
return metatile->layerType;
|
||||
}
|
||||
|
||||
void MainWindow::setMetatileLayerType(int metatileId, int layerType) {
|
||||
// TODO
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
if (!metatile)
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
uint8_t u_layerType = static_cast<uint8_t>(layerType);
|
||||
if (!metatile || metatile->layerType == u_layerType || u_layerType >= NUM_METATILE_LAYER_TYPES)
|
||||
return;
|
||||
metatile->layerType = u_layerType;
|
||||
this->saveMetatileAttributesByMetatileId(metatileId);
|
||||
}
|
||||
|
||||
int MainWindow::getMetatileEncounterType(int metatileId) {
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
if (!metatile)
|
||||
return -1;
|
||||
return metatile->encounterType;
|
||||
}
|
||||
|
||||
void MainWindow::setMetatileEncounterType(int metatileId, int encounterType) {
|
||||
// TODO
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
if (!metatile)
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
uint8_t u_encounterType = static_cast<uint8_t>(encounterType);
|
||||
if (!metatile || metatile->encounterType == u_encounterType || u_encounterType >= NUM_METATILE_ENCOUNTER_TYPES)
|
||||
return;
|
||||
metatile->encounterType = u_encounterType;
|
||||
this->saveMetatileAttributesByMetatileId(metatileId);
|
||||
}
|
||||
|
||||
int MainWindow::getMetatileTerrainType(int metatileId) {
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
if (!metatile)
|
||||
return -1;
|
||||
return metatile->terrainType;
|
||||
}
|
||||
|
||||
void MainWindow::setMetatileTerrainType(int metatileId, int terrainType) {
|
||||
// TODO
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
if (!metatile)
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
uint8_t u_terrainType = static_cast<uint8_t>(terrainType);
|
||||
if (!metatile || metatile->terrainType == u_terrainType || u_terrainType >= NUM_METATILE_TERRAIN_TYPES)
|
||||
return;
|
||||
metatile->terrainType = u_terrainType;
|
||||
this->saveMetatileAttributesByMetatileId(metatileId);
|
||||
}
|
||||
|
||||
int MainWindow::getMetatileBehavior(int metatileId) {
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
if (!metatile)
|
||||
return -1;
|
||||
return metatile->behavior;
|
||||
}
|
||||
|
||||
void MainWindow::setMetatileBehavior(int metatileId, int behavior) {
|
||||
// TODO
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
if (!metatile)
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
uint16_t u_behavior = static_cast<uint16_t>(behavior);
|
||||
if (!metatile || metatile->behavior == u_behavior)
|
||||
return;
|
||||
metatile->behavior = u_behavior;
|
||||
this->saveMetatileAttributesByMetatileId(metatileId);
|
||||
}
|
||||
|
||||
QJSValue MainWindow::getMetatileTile(int metatileId, int tileIndex) {
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
int maxTileIndex = projectConfig.getTripleLayerMetatilesEnabled() ? 12 : 8;
|
||||
if (!metatile || tileIndex >= maxTileIndex)
|
||||
if (!metatile || tileIndex >= maxTileIndex || tileIndex < 0)
|
||||
return QJSValue();
|
||||
return Scripting::fromTile(metatile->tiles[tileIndex]);
|
||||
}
|
||||
|
||||
void MainWindow::setMetatileTile(int metatileId, int tileIndex, int tile, bool xflip, bool yflip, int palette) {
|
||||
// TODO
|
||||
Metatile * metatile = getMetatile(metatileId);
|
||||
if (!metatile)
|
||||
void MainWindow::setMetatileTile(int metatileId, int tileIndex, int tileId, bool xflip, bool yflip, int palette, bool forceRedraw) {
|
||||
Metatile * metatile = this->getMetatile(metatileId);
|
||||
int maxTileIndex = projectConfig.getTripleLayerMetatilesEnabled() ? 12 : 8;
|
||||
if (!metatile || tileIndex >= maxTileIndex || tileIndex < 0)
|
||||
return;
|
||||
Tile * tile = &metatile->tiles[tileIndex];
|
||||
if (!tile) return;
|
||||
if (tile->tile == tileId
|
||||
&& tile->xflip == xflip
|
||||
&& tile->yflip == yflip
|
||||
&& tile->palette == palette)
|
||||
return;
|
||||
|
||||
tile->tile = tileId;
|
||||
tile->xflip = xflip;
|
||||
tile->yflip = yflip;
|
||||
tile->palette = palette;
|
||||
this->saveMetatilesByMetatileId(metatileId);
|
||||
|
||||
// TODO: Making tryRedrawMapArea do a full draw is unnecessarily expensive.
|
||||
// The map metatiles that need to be updated are not changed by the above
|
||||
// operation, so they will not be redrawn if the cache isn't ignored.
|
||||
// Ideally setMetatileTile would properly set each of the map spaces that
|
||||
// use this metatile so that the cache could be used, though this would
|
||||
// likely still require a full read of the map and its border/connections.
|
||||
this->needsFullRedraw = true;
|
||||
this->tryRedrawMapArea(forceRedraw);
|
||||
}
|
||||
|
||||
void MainWindow::setMetatileTile(int metatileId, int tileIndex, QJSValue obj, bool forceRedraw) {
|
||||
Tile tile = Scripting::toTile(obj);
|
||||
this->setMetatileTile(metatileId, tileIndex, tile.tile, tile.xflip, tile.yflip, tile.palette, forceRedraw);
|
||||
}
|
||||
|
|
|
@ -156,6 +156,21 @@ QJSValue Scripting::dimensions(int width, int height) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
Tile Scripting::toTile(QJSValue obj) {
|
||||
if (!obj.hasProperty("tile")
|
||||
|| !obj.hasProperty("xflip")
|
||||
|| !obj.hasProperty("yflip")
|
||||
|| !obj.hasProperty("palette")) {
|
||||
return Tile();
|
||||
}
|
||||
Tile tile = Tile();
|
||||
tile.tile = obj.property("tile").toInt();
|
||||
tile.xflip = obj.property("xflip").toBool();
|
||||
tile.yflip = obj.property("yflip").toBool();
|
||||
tile.palette = obj.property("palette").toInt();
|
||||
return tile;
|
||||
}
|
||||
|
||||
QJSValue Scripting::fromTile(Tile tile) {
|
||||
QJSValue obj = instance->engine->newObject();
|
||||
obj.setProperty("tile", tile.tile);
|
||||
|
|
|
@ -120,9 +120,9 @@ void TilesetEditor::setMetatileBehaviors() {
|
|||
|
||||
void TilesetEditor::setMetatileLayersUi() {
|
||||
if (!projectConfig.getTripleLayerMetatilesEnabled()) {
|
||||
this->ui->comboBox_layerType->addItem("Normal - Middle/Top", 0);
|
||||
this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", 1);
|
||||
this->ui->comboBox_layerType->addItem("Split - Bottom/Top", 2);
|
||||
this->ui->comboBox_layerType->addItem("Normal - Middle/Top", METATILE_LAYER_MIDDLE_TOP);
|
||||
this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", METATILE_LAYER_BOTTOM_MIDDLE);
|
||||
this->ui->comboBox_layerType->addItem("Split - Bottom/Top", METATILE_LAYER_BOTTOM_TOP);
|
||||
} else {
|
||||
this->ui->comboBox_layerType->setVisible(false);
|
||||
this->ui->label_layerType->setVisible(false);
|
||||
|
@ -134,15 +134,15 @@ void TilesetEditor::setVersionSpecificUi() {
|
|||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
this->ui->comboBox_encounterType->setVisible(true);
|
||||
this->ui->label_encounterType->setVisible(true);
|
||||
this->ui->comboBox_encounterType->addItem("None", 0);
|
||||
this->ui->comboBox_encounterType->addItem("Land", 1);
|
||||
this->ui->comboBox_encounterType->addItem("Water", 2);
|
||||
this->ui->comboBox_encounterType->addItem("None", ENCOUNTER_NONE);
|
||||
this->ui->comboBox_encounterType->addItem("Land", ENCOUNTER_LAND);
|
||||
this->ui->comboBox_encounterType->addItem("Water", ENCOUNTER_WATER);
|
||||
this->ui->comboBox_terrainType->setVisible(true);
|
||||
this->ui->label_terrainType->setVisible(true);
|
||||
this->ui->comboBox_terrainType->addItem("Normal", 0);
|
||||
this->ui->comboBox_terrainType->addItem("Grass", 1);
|
||||
this->ui->comboBox_terrainType->addItem("Water", 2);
|
||||
this->ui->comboBox_terrainType->addItem("Waterfall", 3);
|
||||
this->ui->comboBox_terrainType->addItem("Normal", TERRAIN_NONE);
|
||||
this->ui->comboBox_terrainType->addItem("Grass", TERRAIN_GRASS);
|
||||
this->ui->comboBox_terrainType->addItem("Water", TERRAIN_WATER);
|
||||
this->ui->comboBox_terrainType->addItem("Waterfall", TERRAIN_WATERFALL);
|
||||
} else {
|
||||
this->ui->comboBox_encounterType->setVisible(false);
|
||||
this->ui->label_encounterType->setVisible(false);
|
||||
|
@ -485,7 +485,7 @@ void TilesetEditor::on_comboBox_metatileBehaviors_textActivated(const QString &m
|
|||
{
|
||||
if (this->metatile) {
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
this->metatile->behavior = static_cast<uint8_t>(project->metatileBehaviorMap[metatileBehavior]);
|
||||
this->metatile->behavior = static_cast<uint16_t>(project->metatileBehaviorMap[metatileBehavior]);
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatile(),
|
||||
prevMetatile, new Metatile(*this->metatile));
|
||||
metatileHistory.push(commit);
|
||||
|
|
Loading…
Reference in a new issue