Properly paint prefabs and create them from dialog box

This commit is contained in:
Marcus Huderle 2022-09-07 20:38:30 -05:00
parent bc4cbbabfa
commit 96ad32c6db
11 changed files with 358 additions and 21 deletions

View file

@ -1270,7 +1270,7 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="pushButton">
<widget class="QPushButton" name="pushButton_CreatePrefab">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>

View file

@ -0,0 +1,201 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PrefabCreationDialog</class>
<widget class="QDialog" name="PrefabCreationDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Tip&lt;/span&gt;: Click on individual metatiles to remove them from the Prefab&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>363</width>
<height>192</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="ClickableGraphicsView" name="graphicsView_Prefab">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">background-color: transparent</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Prefab Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_PrefabName">
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ClickableGraphicsView</class>
<extends>QGraphicsView</extends>
<header>graphicsview.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PrefabCreationDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PrefabCreationDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -354,6 +354,7 @@ private slots:
void on_pushButton_NewWildMonGroup_clicked();
void on_pushButton_DeleteWildMonGroup_clicked();
void on_pushButton_ConfigureEncountersJSON_clicked();
void on_pushButton_CreatePrefab_clicked();
void on_actionRegion_Map_Editor_triggered();
void on_actionEdit_Preferences_triggered();

View file

@ -14,11 +14,15 @@ public:
public:
void mousePressEvent(QMouseEvent *event) {
QGraphicsView::mousePressEvent(event);
emit this->clicked();
emit this->clicked(event);
}
void mouseDoubleClickEvent(QMouseEvent *event) {
QGraphicsView::mouseDoubleClickEvent(event);
emit this->clicked(event);
}
signals:
void clicked();
void clicked(QMouseEvent *event);
};
class Editor;

View file

@ -18,11 +18,16 @@ struct PrefabItem
class Prefab
{
public:
void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, QString primaryTileset, QString secondaryTileset, Map *map);
void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map);
void addPrefab(MetatileSelection selection, Map *map, QString name);
private:
MetatileSelector *selector;
QWidget *prefabWidget;
QLabel *emptyPrefabLabel;
QList<PrefabItem> items;
void loadPrefabs();
void updatePrefabUi(Map *map);
QList<PrefabItem> getPrefabsForTilesets(QString primaryTileset, QString secondaryTileset);
};

View file

@ -0,0 +1,28 @@
#ifndef PREFABCREATIONDIALOG_H
#define PREFABCREATIONDIALOG_H
#include "metatileselector.h"
#include "map.h"
#include <QDialog>
namespace Ui {
class PrefabCreationDialog;
}
class PrefabCreationDialog : public QDialog
{
Q_OBJECT
public:
explicit PrefabCreationDialog(QWidget *parent, MetatileSelector *metatileSelector, Map *map);
~PrefabCreationDialog();
void savePrefab();
private:
Map *map;
Ui::PrefabCreationDialog *ui;
MetatileSelection selection;
};
#endif // PREFABCREATIONDIALOG_H

View file

@ -55,6 +55,7 @@ SOURCES += src/core/block.cpp \
src/ui/graphicsview.cpp \
src/ui/imageproviders.cpp \
src/ui/mappixmapitem.cpp \
src/ui/prefabcreationdialog.cpp \
src/ui/regionmappixmapitem.cpp \
src/ui/citymappixmapitem.cpp \
src/ui/mapsceneeventfilter.cpp \
@ -138,6 +139,7 @@ HEADERS += include/core/block.h \
include/ui/graphicsview.h \
include/ui/imageproviders.h \
include/ui/mappixmapitem.h \
include/ui/prefabcreationdialog.h \
include/ui/regionmappixmapitem.h \
include/ui/citymappixmapitem.h \
include/ui/mapsceneeventfilter.h \
@ -180,6 +182,7 @@ HEADERS += include/core/block.h \
FORMS += forms/mainwindow.ui \
forms/eventpropertiesframe.ui \
forms/prefabcreationdialog.ui \
forms/prefabframe.ui \
forms/tileseteditor.ui \
forms/paletteeditor.ui \

View file

@ -6,6 +6,7 @@
#include "editor.h"
#include "eventpropertiesframe.h"
#include "ui_eventpropertiesframe.h"
#include "prefabcreationdialog.h"
#include "bordermetatilespixmapitem.h"
#include "currentselectedmetatilespixmapitem.h"
#include "customattributestable.h"
@ -557,8 +558,6 @@ bool MainWindow::openProject(QString dir) {
editor->metatile_selector_item,
ui->scrollAreaWidgetContents_Prefabs,
ui->label_prefabHelp,
editor->ui->comboBox_PrimaryTileset->currentText(),
editor->ui->comboBox_SecondaryTileset->currentText(),
editor->map);
for (auto action : this->registeredActions) {
this->ui->menuTools->removeAction(action);
@ -3176,6 +3175,15 @@ void MainWindow::on_actionRegion_Map_Editor_triggered() {
}
}
void MainWindow::on_pushButton_CreatePrefab_clicked() {
PrefabCreationDialog dialog(this, this->editor->metatile_selector_item, this->editor->map);
dialog.setWindowTitle("Create Prefab");
dialog.setWindowModality(Qt::NonModal);
if (dialog.exec() == QDialog::Accepted) {
dialog.savePrefab();
}
}
bool MainWindow::initRegionMapEditor() {
this->regionMapEditor = new RegionMapEditor(this, this->editor->project);
this->regionMapEditor->setAttribute(Qt::WA_DeleteOnClose);

View file

@ -177,11 +177,22 @@ bool isSmartPathTile(QList<MetatileSelectionItem> metatileItems, uint16_t metati
return false;
}
bool isValidSmartPathSelection(MetatileSelection selection) {
if (selection.dimensions.x() != 3 || selection.dimensions.y() != 3)
return false;
for (int i = 0; i < selection.metatileItems.length(); i++) {
if (!selection.metatileItems.at(i).enabled)
return false;
}
return true;
}
void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) {
MetatileSelection selection = this->metatileSelector->getMetatileSelection();
// Smart path should never be enabled without a 3x3 block selection.
if (selection.dimensions.x() != 3 || selection.dimensions.y() != 3) return;
if (!isValidSmartPathSelection(selection))
return;
// Shift to the middle tile of the smart path selection.
uint16_t openTile = selection.metatileItems.at(4).metatileId;
@ -420,6 +431,7 @@ void MapPixmapItem::magicFill(
if (i < 0) i = selectionDimensions.x() + i;
if (j < 0) j = selectionDimensions.y() + j;
int index = j * selectionDimensions.x() + i;
if (selectedMetatiles.at(index).enabled) {
block.metatileId = selectedMetatiles.at(index).metatileId;
if (setCollisions) {
CollisionSelectionItem item = selectedCollisions.at(index);
@ -430,6 +442,7 @@ void MapPixmapItem::magicFill(
}
}
}
}
if (!fromScriptCall && map->layout->blockdata != oldMetatiles) {
map->editHistory.push(new MagicFillMetatile(map, oldMetatiles, map->layout->blockdata, actionId_));
@ -480,7 +493,7 @@ void MapPixmapItem::floodFill(
int index = j * selectionDimensions.x() + i;
uint16_t metatileId = selectedMetatiles.at(index).metatileId;
uint16_t old_metatileId = block.metatileId;
if (selectedMetatiles.count() != 1 || old_metatileId != metatileId) {
if (selectedMetatiles.at(index).enabled && (selectedMetatiles.count() != 1 || old_metatileId != metatileId)) {
block.metatileId = metatileId;
if (setCollisions) {
CollisionSelectionItem item = selectedCollisions.at(index);
@ -514,9 +527,8 @@ void MapPixmapItem::floodFill(
void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScriptCall) {
MetatileSelection selection = this->metatileSelector->getMetatileSelection();
// Smart path should never be enabled without a 3x3 block selection.
if (selection.dimensions.x() != 3 || selection.dimensions.y() != 3) return;
if (!isValidSmartPathSelection(selection))
return;
// Shift to the middle tile of the smart path selection.
uint16_t openTile = selection.metatileItems.at(4).metatileId;

View file

@ -4,6 +4,7 @@
#include "ui_prefabframe.h"
#include "parseutil.h"
#include "currentselectedmetatilespixmapitem.h"
#include "log.h"
#include <QJsonDocument>
#include <QJsonObject>
@ -86,9 +87,29 @@ QList<PrefabItem> Prefab::getPrefabsForTilesets(QString primaryTileset, QString
return filteredPrefabs;
}
void Prefab::initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, QString primaryTileset, QString secondaryTileset, Map *map) {
void Prefab::initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map) {
logInfo("initPrefabUI");
this->selector = selector;
this->prefabWidget = prefabWidget;
this->emptyPrefabLabel = emptyPrefabLabel;
this->loadPrefabs();
QList<PrefabItem> prefabs = this->getPrefabsForTilesets(primaryTileset, secondaryTileset);
logInfo("initPrefabUI loaded prefabs");
this->updatePrefabUi(map);
logInfo("initPrefabUI after updatePrefabUi");
}
void Prefab::updatePrefabUi(Map *map) {
// Cleanup the PrefabFrame to have a clean slate.
auto layout = this->prefabWidget->layout();
while (layout && layout->count() > 1) {
auto child = layout->takeAt(1);
if (child->widget()) {
delete child->widget();
}
delete child;
}
QList<PrefabItem> prefabs = this->getPrefabsForTilesets(map->layout->tileset_primary_label, map->layout->tileset_secondary_label);
if (prefabs.isEmpty()) {
emptyPrefabLabel->setVisible(true);
return;
@ -115,5 +136,10 @@ void Prefab::initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLa
prefabWidget->layout()->addItem(spacer);
}
void Prefab::addPrefab(MetatileSelection selection, Map *map, QString name) {
this->items.append(PrefabItem{name, map->layout->tileset_primary_label, map->layout->tileset_secondary_label, selection});
this->updatePrefabUi(map);
}
Prefab prefab;

View file

@ -0,0 +1,49 @@
#include "prefabcreationdialog.h"
#include "ui_prefabcreationdialog.h"
#include "currentselectedmetatilespixmapitem.h"
#include "graphicsview.h"
#include "prefab.h"
#include <QObject>
PrefabCreationDialog::PrefabCreationDialog(QWidget *parent, MetatileSelector *metatileSelector, Map *map) :
QDialog(parent),
ui(new Ui::PrefabCreationDialog)
{
ui->setupUi(this);
this->map = map;
this->selection = metatileSelector->getMetatileSelection();
QGraphicsScene *scene = new QGraphicsScene;
QGraphicsPixmapItem *pixmapItem = scene->addPixmap(drawMetatileSelection(this->selection, map));
scene->setSceneRect(scene->itemsBoundingRect());
this->ui->graphicsView_Prefab->setScene(scene);
this->ui->graphicsView_Prefab->setFixedSize(scene->itemsBoundingRect().width() + 2,
scene->itemsBoundingRect().height() + 2);
QObject::connect(this->ui->graphicsView_Prefab, &ClickableGraphicsView::clicked, [=](QMouseEvent *event){
auto pos = event->pos();
int selectionWidth = this->selection.dimensions.x() * 16;
int selectionHeight = this->selection.dimensions.y() * 16;
if (pos.x() < 0 || pos.x() >= selectionWidth || pos.y() < 0 || pos.y() >= selectionHeight)
return;
int metatileX = pos.x() / 16;
int metatileY = pos.y() / 16;
int index = metatileY * this->selection.dimensions.x() + metatileX;
bool toggledState = !this->selection.metatileItems[index].enabled;
this->selection.metatileItems[index].enabled = toggledState;
if (this->selection.hasCollision) {
this->selection.collisionItems[index].enabled = toggledState;
}
pixmapItem->setPixmap(drawMetatileSelection(this->selection, map));
});
}
PrefabCreationDialog::~PrefabCreationDialog()
{
delete ui;
}
void PrefabCreationDialog::savePrefab() {
prefab.addPrefab(this->selection, this->map, this->ui->lineEdit_PrefabName->text());
}