address feedback, fix oversights

This commit is contained in:
garak 2022-05-05 21:40:13 -04:00 committed by garakmon
parent 15b29ff065
commit 813845e0da
14 changed files with 192 additions and 29 deletions

View file

@ -1101,6 +1101,7 @@
<addaction name="action_Swap"/>
<addaction name="action_RegionMap_ClearImage"/>
<addaction name="action_RegionMap_ClearLayout"/>
<addaction name="action_RegionMap_ClearEntries"/>
</widget>
<widget class="QMenu" name="menuTools">
<property name="title">
@ -1163,6 +1164,11 @@
<string>Save All</string>
</property>
</action>
<action name="action_RegionMap_ClearEntries">
<property name="text">
<string>Clear Map Entries</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View file

@ -55,6 +55,8 @@ public:
bool loadEntries();
void setEntries(tsl::ordered_map<QString, MapSectionEntry> *entries) { this->region_map_entries = entries; }
void setEntries(tsl::ordered_map<QString, MapSectionEntry> entries) { *(this->region_map_entries) = entries; }
void clearEntries() { this->region_map_entries->clear(); }
MapSectionEntry getEntry(QString section);
void setEntry(QString section, MapSectionEntry entry);
void removeEntry(QString section);

View file

@ -17,6 +17,7 @@ enum RMCommandId {
ID_RemoveEntry,
ID_AddEntry,
ID_ResizeTilemap,
ID_ClearEntries,
};
@ -149,4 +150,20 @@ private:
};
/// ClearEntries
class ClearEntries : public QUndoCommand {
public:
ClearEntries(RegionMap *map, tsl::ordered_map<QString, MapSectionEntry>, QUndoCommand *parent = nullptr);
void undo() override;
void redo() override;
bool mergeWith(const QUndoCommand *command) override { return false; }
int id() const override { return RMCommandId::ID_ClearEntries; }
private:
RegionMap *map;
tsl::ordered_map<QString, MapSectionEntry> entries;
};
#endif // REGIONMAPEDITCOMMANDS_H

View file

@ -119,6 +119,7 @@ private slots:
void on_action_RegionMap_Resize_triggered();
void on_action_RegionMap_ClearImage_triggered();
void on_action_RegionMap_ClearLayout_triggered();
void on_action_RegionMap_ClearEntries_triggered();
void on_action_Swap_triggered();
void on_tabWidget_Region_Map_currentChanged(int);
void on_pushButton_RM_Options_delete_clicked();

View file

@ -21,8 +21,10 @@ public:
TilemapTileSelector *tile_selector;
virtual void paint(QGraphicsSceneMouseEvent *);
virtual void fill(QGraphicsSceneMouseEvent *);
virtual void select(QGraphicsSceneMouseEvent *);
virtual void draw();
void floodFill(int x, int y, std::shared_ptr<TilemapTile> oldTile, std::shared_ptr<TilemapTile> newTile);
signals:
void mouseEvent(QGraphicsSceneMouseEvent *, RegionMapPixmapItem *);

View file

@ -60,6 +60,10 @@ public:
virtual void setVFlip(bool vFlip) { this->vFlip_ = vFlip; }
virtual void setPalette(int palette) { this->palette_ = palette; }
bool operator==(const TilemapTile& other) {
return (this->raw() == other.raw());
}
virtual QString info() const {
return QString("Tile: 0x") + QString("%1 ").arg(this->id(), 4, 16, QChar('0')).toUpper();
}
@ -132,7 +136,7 @@ public:
setAcceptHoverEvents(true);
}
void draw();
void setPalette();
QImage setPalette(int index);
int pixelWidth;
int pixelHeight;
@ -146,7 +150,10 @@ public:
void selectHFlip(bool vFlip) { this->tile_vFlip = vFlip; }
bool tile_vFlip = false;
void selectPalette(int palette) { this->tile_palette = palette; }
void selectPalette(int palette) {
this->tile_palette = palette;
this->draw();
}
int tile_palette = 0;
QImage tileset;

View file

@ -549,6 +549,8 @@ void RegionMap::setLayoutDimensions(int width, int height, bool update) {
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++) {
LayoutSquare newSquare;
newSquare.x = x;
newSquare.y = y;
if (x < this->layout_width && y < this->layout_height) {
// within old layout
int oldIndex = this->get_layout_index(x, y);

View file

@ -258,4 +258,29 @@ void ResizeTilemap::undo() {
QUndoCommand::undo();
}
///
ClearEntries::ClearEntries(RegionMap *map, tsl::ordered_map<QString, MapSectionEntry> entries, QUndoCommand *parent) {
setText("Clear Entries");
this->map = map;
this->entries = entries;
}
void ClearEntries::redo() {
QUndoCommand::redo();
if (!map) return;
map->clearEntries();
}
void ClearEntries::undo() {
if (!map) return;
map->setEntries(entries);
QUndoCommand::undo();
}

View file

@ -3147,6 +3147,11 @@ void MainWindow::on_actionRegion_Map_Editor_triggered() {
bool MainWindow::initRegionMapEditor() {
this->regionMapEditor = new RegionMapEditor(this, this->editor->project);
this->regionMapEditor->setAttribute(Qt::WA_DeleteOnClose);
connect(this->regionMapEditor, &QObject::destroyed, [this](){
this->regionMapEditor = nullptr;
});
bool success = this->regionMapEditor->load();
if (!success) {
delete this->regionMapEditor;

View file

@ -482,10 +482,9 @@ void RegionMapEditor::setRegionMap(RegionMap *map) {
} else {
this->ui->tabWidget_Region_Map->setTabEnabled(1, false);
this->ui->tabWidget_Region_Map->setTabEnabled(2, false);
this->ui->tabWidget_Region_Map->setCurrentIndex(0);
}
this->ui->tabWidget_Region_Map->setCurrentIndex(0);
displayRegionMap();
}
@ -685,27 +684,27 @@ void RegionMapEditor::displayRegionMapEntriesImage() {
void RegionMapEditor::displayRegionMapEntryOptions() {
if (!this->region_map->layoutEnabled()) return;
this->ui->comboBox_RM_Entry_MapSection->clear();
this->ui->comboBox_RM_Entry_MapSection->addItems(this->project->mapSectionValueToName.values());
int width = this->region_map->tilemapWidth() - this->region_map->padLeft() - this->region_map->padRight();
int height = this->region_map->tilemapHeight() - this->region_map->padTop() - this->region_map->padBottom();
this->ui->spinBox_RM_Entry_x->setMaximum(width - 1);
this->ui->spinBox_RM_Entry_y->setMaximum(height - 1);
this->ui->spinBox_RM_Entry_x->setMaximum(128);
this->ui->spinBox_RM_Entry_y->setMaximum(128);
this->ui->spinBox_RM_Entry_width->setMinimum(1);
this->ui->spinBox_RM_Entry_height->setMinimum(1);
this->ui->spinBox_RM_Entry_width->setMaximum(width);
this->ui->spinBox_RM_Entry_height->setMaximum(height);
this->ui->spinBox_RM_Entry_width->setMaximum(128);
this->ui->spinBox_RM_Entry_height->setMaximum(128);
}
void RegionMapEditor::updateRegionMapEntryOptions(QString section) {
if (!this->region_map->layoutEnabled()) return;
bool enabled = (section != "MAPSEC_NONE") && (this->region_map_entries.contains(section));
bool enabled = ((section != "MAPSEC_NONE") && (section != "MAPSEC_COUNT")) && (this->region_map_entries.contains(section));
this->ui->lineEdit_RM_MapName->setEnabled(enabled);
this->ui->spinBox_RM_Entry_x->setEnabled(enabled);
this->ui->spinBox_RM_Entry_y->setEnabled(enabled);
this->ui->spinBox_RM_Entry_width->setEnabled(enabled);
this->ui->spinBox_RM_Entry_height->setEnabled(enabled);
this->ui->pushButton_entryActivate->setEnabled(section != "MAPSEC_NONE" && section != "MAPSEC_COUNT");
this->ui->pushButton_entryActivate->setText(enabled ? "Remove" : "Add");
this->ui->lineEdit_RM_MapName->blockSignals(true);
@ -862,7 +861,22 @@ void RegionMapEditor::mouseEvent_region_map(QGraphicsSceneMouseEvent *event, Reg
if (event->buttons() & Qt::RightButton) {
item->select(event);
//} else if (event->buttons() & Qt::MiddleButton) {// TODO
// set palette and flips
auto tile = this->region_map->getTile(x, y);
this->ui->spinBox_tilePalette->setValue(tile->palette());
this->ui->checkBox_tileHFlip->setChecked(tile->hFlip());
this->ui->checkBox_tileVFlip->setChecked(tile->vFlip());
} else if (event->modifiers() & Qt::ControlModifier) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++;
} else {
QByteArray oldTilemap = this->region_map->getTilemap();
item->fill(event);
QByteArray newTilemap = this->region_map->getTilemap();
EditTilemap *command = new EditTilemap(this->region_map, oldTilemap, newTilemap, actionId_);
command->setText("Fill Tilemap");
this->region_map->commit(command);
}
} else {
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++;
@ -872,7 +886,6 @@ void RegionMapEditor::mouseEvent_region_map(QGraphicsSceneMouseEvent *event, Reg
QByteArray newTilemap = this->region_map->getTilemap();
EditTilemap *command = new EditTilemap(this->region_map, oldTilemap, newTilemap, actionId_);
this->region_map->commit(command);
//this->region_map_layout_item->draw();
}
}
}
@ -942,7 +955,6 @@ void RegionMapEditor::on_spinBox_RM_Entry_x_valueChanged(int x) {
this->region_map_entries[activeEntry].y + this->region_map->padTop());
this->region_map_entries_item->select(idx);
this->region_map_entries_item->draw();
this->ui->spinBox_RM_Entry_width->setMaximum(this->region_map->tilemapWidth() - this->region_map->padLeft() - this->region_map->padRight() - x);
}
void RegionMapEditor::on_spinBox_RM_Entry_y_valueChanged(int y) {
@ -956,7 +968,6 @@ void RegionMapEditor::on_spinBox_RM_Entry_y_valueChanged(int y) {
this->region_map_entries[activeEntry].y + this->region_map->padTop());
this->region_map_entries_item->select(idx);
this->region_map_entries_item->draw();
this->ui->spinBox_RM_Entry_height->setMaximum(this->region_map->tilemapHeight() - this->region_map->padTop() - this->region_map->padBottom() - y);
}
void RegionMapEditor::on_spinBox_RM_Entry_width_valueChanged(int width) {
@ -1166,6 +1177,24 @@ void RegionMapEditor::on_action_RegionMap_ClearLayout_triggered() {
}
}
void RegionMapEditor::on_action_RegionMap_ClearEntries_triggered() {
QMessageBox::StandardButton result = QMessageBox::question(
this,
"WARNING",
"This action will remove the entire mapsection entries list, continue?",
QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Yes
);
if (result == QMessageBox::Yes) {
ClearEntries *commit = new ClearEntries(this->region_map, this->region_map_entries);
this->region_map->editHistory.push(commit);
displayRegionMapLayout();
} else {
return;
}
}
bool RegionMapEditor::modified() {
return !this->history.isClean();
}

View file

@ -54,7 +54,8 @@ void RegionMapEntriesPixmapItem::draw() {
this->selectionOffsetY = entry_h - 1;
this->setPixmap(QPixmap::fromImage(image));
this->drawSelection();
if (selectingEntry) this->drawSelection();
}
void RegionMapEntriesPixmapItem::select(int x, int y) {
@ -81,7 +82,6 @@ void RegionMapEntriesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event
int x = pos.x() - this->region_map->padLeft();
int y = pos.y() - this->region_map->padTop();
//RegionMapEntry entry = this->region_map->mapSecToMapEntry.value(currentSection);
MapSectionEntry entry = this->region_map->getEntry(currentSection);
pressedX = x - entry.x;
pressedY = y - entry.y;

View file

@ -62,9 +62,7 @@ void RegionMapLayoutPixmapItem::highlight(int x, int y, int red) {
void RegionMapLayoutPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
QPoint pos = this->getCellPos(event->pos());
int index = this->region_map->getMapSquareIndex(pos.x(), pos.y());
if (this->region_map->squareX(index) >= 0
&& this->region_map->squareY(index) >= 0) {
if (this->region_map->squareInLayout(pos.x(), pos.y())) {
SelectablePixmapItem::mousePressEvent(event);
this->updateSelectedTile();
emit selectedTileChanged(this->selectedTile);

View file

@ -35,6 +35,70 @@ void RegionMapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
}
}
void RegionMapPixmapItem::floodFill(int x, int y, std::shared_ptr<TilemapTile> oldTile, std::shared_ptr<TilemapTile> newTile) {
// out of bounds
if (x < 0
|| y < 0
|| x >= this->region_map->tilemapWidth()
|| y >= this->region_map->tilemapHeight()) {
return;
}
auto tile = this->region_map->getTile(x, y);
if (!tile->operator==(*oldTile) || tile->operator==(*newTile)) {
return;
}
int index = x + y * this->region_map->tilemapWidth();
this->region_map->setTileData(index,
newTile->id(),
newTile->hFlip(),
newTile->vFlip(),
newTile->palette()
);
floodFill(x + 1, y, oldTile, newTile);
floodFill(x - 1, y, oldTile, newTile);
floodFill(x, y + 1, oldTile, newTile);
floodFill(x, y - 1, oldTile, newTile);
}
void RegionMapPixmapItem::fill(QGraphicsSceneMouseEvent *event) {
if (region_map) {
QPointF pos = event->pos();
int x = static_cast<int>(pos.x()) / 8;
int y = static_cast<int>(pos.y()) / 8;
int index = x + y * this->region_map->tilemapWidth();
std::shared_ptr<TilemapTile> currentTile, newTile, oldTile;
currentTile = this->region_map->getTile(index);
switch(this->tile_selector->format) {
case TilemapFormat::Plain:
oldTile = std::make_shared<PlainTile>(currentTile->raw());
newTile = std::make_shared<PlainTile>(currentTile->raw());
newTile->setId(this->tile_selector->selectedTile);
break;
case TilemapFormat::BPP_4:
oldTile = std::make_shared<BPP4Tile>(currentTile->raw());
newTile = std::make_shared<BPP4Tile>(currentTile->raw());
newTile->setId(this->tile_selector->selectedTile);
newTile->setHFlip(this->tile_selector->tile_hFlip);
newTile->setVFlip(this->tile_selector->tile_vFlip);
newTile->setPalette(this->tile_selector->tile_palette);
break;
case TilemapFormat::BPP_8:
oldTile = std::make_shared<BPP8Tile>(currentTile->raw());
newTile = std::make_shared<BPP8Tile>(currentTile->raw());
newTile->setId(this->tile_selector->selectedTile);
newTile->setId(this->tile_selector->selectedTile);
newTile->setHFlip(this->tile_selector->tile_hFlip);
newTile->setVFlip(this->tile_selector->tile_vFlip);
break;
}
floodFill(x, y, oldTile, newTile);
draw();
}
}
void RegionMapPixmapItem::select(QGraphicsSceneMouseEvent *event) {
QPointF pos = event->pos();
int x = static_cast<int>(pos.x()) / 8;

View file

@ -12,7 +12,7 @@ void TilemapTileSelector::draw() {
this->numTilesWide = width_ / 8;
this->numTiles = ntiles_;
this->setPixmap(QPixmap::fromImage(tileset));
this->setPixmap(QPixmap::fromImage(this->setPalette(this->tile_palette)));
this->drawSelection();
}
@ -39,11 +39,7 @@ QPoint TilemapTileSelector::getTileIdCoords(unsigned tileId) {
return QPoint(index % this->numTilesWide, index / this->numTilesWide);
}
QImage TilemapTileSelector::tileImg(shared_ptr<TilemapTile> tile) {
// TODO: this is slow on the entries tab, so maybe do not do all of the redraw for every section change
unsigned tileId = tile->id();
QPoint pos = getTileIdCoords(tileId);
QImage TilemapTileSelector::setPalette(int paletteIndex) {
QImage tilesetImage = this->tileset;
tilesetImage.convertTo(QImage::Format::Format_Indexed8);
@ -54,7 +50,7 @@ QImage TilemapTileSelector::tileImg(shared_ptr<TilemapTile> tile) {
case TilemapFormat::BPP_4:
{
QVector<QRgb> newColorTable;
int palMinLength = tile->palette() * 16 + 16;
int palMinLength = paletteIndex * 16 + 16;
if ((this->palette.count() < palMinLength) || (tilesetImage.colorTable().count() != 16)) {
// either a) the palette has less than 256 colors, or b) the image is improperly indexed
for (QRgb color : tilesetImage.colorTable()) {
@ -65,9 +61,9 @@ QImage TilemapTileSelector::tileImg(shared_ptr<TilemapTile> tile) {
// use actual pal
// before Qt 6, the color table is a QVector which is deprecated now, and this method does not exits
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
newColorTable = this->palette.toVector().mid(tile->palette() * 16, 16);
newColorTable = this->palette.toVector().mid(paletteIndex * 16, 16);
#else
newColorTable = this->palette.mid(tile->palette() * 16, 16);
newColorTable = this->palette.mid(paletteIndex * 16, 16);
#endif
}
tilesetImage.setColorTable(newColorTable);
@ -87,6 +83,15 @@ QImage TilemapTileSelector::tileImg(shared_ptr<TilemapTile> tile) {
default: break;
}
return tilesetImage;
}
QImage TilemapTileSelector::tileImg(shared_ptr<TilemapTile> tile) {
unsigned tileId = tile->id();
QPoint pos = getTileIdCoords(tileId);
QImage tilesetImage = setPalette(tile->palette());
// take a tile from the tileset
QImage img = tilesetImage.copy(pos.x() * 8, pos.y() * 8, 8, 8);
img = img.mirrored(tile->hFlip(), tile->vFlip());