address feedback, fix oversights
This commit is contained in:
parent
15b29ff065
commit
813845e0da
14 changed files with 192 additions and 29 deletions
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in a new issue