#include "roompropertiesdialog.h" #include "ui_roompropertiesdialog.h" #include #include #include #include #include #include #include "projectcontainer.h" #include "models/projecttreemodel.h" #include "roomscene.h" #include "editorguiutils.h" #include "genericcodeeditordialog.h" #include "mainwindow.h" RoomPropertiesDialog::RoomPropertiesDialog(Room &room, ProjectTreeModel &projectModel, MainWindow &mainWindow) : QDialog{&mainWindow}, m_ui{std::make_unique()}, m_room{room}, m_projectModel{projectModel}, m_objects{m_room.objects}, m_scene{std::make_unique(this)}, m_creationCode{m_room.creationCode}, m_spinBoxSnapX{new QSpinBox{this}}, m_spinBoxSnapY{new QSpinBox{this}}, m_menuObjects{new QMenu{this}}, m_labelX{new QLabel{tr("x: %0").arg(0)}}, m_labelY{new QLabel{tr("y: %0").arg(0)}} { m_ui->setupUi(this); updateTitle(); m_ui->roomEditWidget->setObjects(&m_objects); m_ui->roomEditWidget->setFixedWidth(m_room.width); m_ui->roomEditWidget->setFixedHeight(m_room.height); m_ui->roomEditWidget->setSnapX(m_room.snapX); m_ui->roomEditWidget->setSnapY(m_room.snapY); m_ui->roomEditWidget->setGridEnabled(m_room.gridEnabled); m_ui->roomEditWidget->setIsometricGrid(m_room.isometricGrid); m_ui->roomEditWidget->setProjectTreeModel(&m_projectModel); m_ui->graphicsView->setScene(m_scene.get()); m_ui->graphicsView->setBackgroundBrush(makeGridBrush(16, 16, QPen{Qt::black}, Qt::white)); { int index{11}; { auto label = new QLabel{tr("Snap &X:"), this}; label->setBuddy(m_spinBoxSnapX); m_ui->toolBar->insertWidget(m_ui->toolBar->actions().at(index++), label); } m_spinBoxSnapX->setValue(m_ui->roomEditWidget->snapX()); m_spinBoxSnapX->setMaximumWidth(50); m_ui->toolBar->insertWidget(m_ui->toolBar->actions().at(index++), m_spinBoxSnapX); { auto label = new QLabel{tr("Snap &Y:"), this}; label->setBuddy(m_spinBoxSnapY); m_ui->toolBar->insertWidget(m_ui->toolBar->actions().at(index++), label); } m_spinBoxSnapY->setValue(m_ui->roomEditWidget->snapY()); m_spinBoxSnapY->setMaximumWidth(50); m_ui->toolBar->insertWidget(m_ui->toolBar->actions().at(index++), m_spinBoxSnapY); } m_ui->actionGridEnabled->setChecked(m_ui->roomEditWidget->gridEnabled()); m_ui->actionIsometricGrid->setChecked(m_ui->roomEditWidget->isometricGrid()); { auto toolButton = new QToolButton{this}; toolButton->setText(tr("Show")); toolButton->setIcon(QIcon{":/qtgameengine/icons/find.png"}); toolButton->setPopupMode(QToolButton::InstantPopup); toolButton->addAction(m_ui->actionShowObjects); toolButton->addAction(m_ui->actionShowTiles); toolButton->addAction(m_ui->actionShowBackgrounds); toolButton->addAction(m_ui->actionShowForegrounds); toolButton->addAction(m_ui->actionShowViews); m_ui->toolBar->addWidget(toolButton); } m_ui->toolButtonObject->setMenu(m_menuObjects); m_ui->lineEditObject->setMenu(m_menuObjects); m_ui->scrollAreaObject->setMenu(m_menuObjects); m_ui->scrollAreaRoom->setBackgroundRole(QPalette::Dark); m_labelX->setFrameStyle(QFrame::Sunken); m_ui->statusbar->addWidget(m_labelX, 1); m_labelY->setFrameStyle(QFrame::Sunken); m_ui->statusbar->addWidget(m_labelY, 1); { auto frame = new QFrame{this}; frame->setFrameStyle(QFrame::Sunken); m_ui->statusbar->addPermanentWidget(frame, 4); } m_ui->lineEditName->setText(m_room.name); m_ui->lineEditCaption->setText(m_room.caption); m_ui->spinBoxWidth->setValue(m_ui->roomEditWidget->width()); m_ui->spinBoxHeight->setValue(m_ui->roomEditWidget->height()); m_ui->spinBoxSpeed->setValue(m_room.speed); m_ui->checkBoxPersistent->setChecked(m_room.persistent); connect(&m_projectModel, &ProjectTreeModel::roomNameChanged, this, &RoomPropertiesDialog::roomNameChanged); connect(&m_projectModel, &ProjectTreeModel::spritePixmapsChanged, this, &RoomPropertiesDialog::spritePixmapsChanged); connect(&m_projectModel, &ProjectTreeModel::objectNameChanged, this, &RoomPropertiesDialog::objectNameChanged); connect(&m_projectModel, &ProjectTreeModel::objectAboutToBeRemoved, this, &RoomPropertiesDialog::objectAboutToBeRemoved); connect(&m_projectModel, &ProjectTreeModel::objectSpriteNameChanged, this, &RoomPropertiesDialog::objectSpriteNameChanged); connect(m_ui->actionUndo, &QAction::triggered, this, &RoomPropertiesDialog::undo); connect(m_ui->actionClear, &QAction::triggered, this, &RoomPropertiesDialog::undo); connect(m_ui->actionShift, &QAction::triggered, this, &RoomPropertiesDialog::undo); connect(m_ui->actionSortX, &QAction::triggered, this, &RoomPropertiesDialog::undo); connect(m_ui->actionSortY, &QAction::triggered, this, &RoomPropertiesDialog::undo); connect(m_ui->actionLock, &QAction::triggered, this, &RoomPropertiesDialog::undo); connect(m_ui->actionUnlock, &QAction::triggered, this, &RoomPropertiesDialog::undo); connect(m_spinBoxSnapX, &QSpinBox::valueChanged, m_ui->roomEditWidget, &RoomEditWidget::setSnapX); connect(m_spinBoxSnapY, &QSpinBox::valueChanged, m_ui->roomEditWidget, &RoomEditWidget::setSnapY); connect(m_ui->actionGridEnabled, &QAction::toggled, m_ui->roomEditWidget, &RoomEditWidget::setGridEnabled); connect(m_ui->actionIsometricGrid, &QAction::toggled, m_ui->roomEditWidget, &RoomEditWidget::setIsometricGrid); connect(m_ui->spinBoxWidth, &QSpinBox::valueChanged, m_ui->roomEditWidget, &RoomEditWidget::setFixedWidth); connect(m_ui->spinBoxHeight, &QSpinBox::valueChanged, m_ui->roomEditWidget, &RoomEditWidget::setFixedHeight); connect(m_spinBoxSnapX, &QSpinBox::valueChanged, this, &RoomPropertiesDialog::changed); connect(m_spinBoxSnapY, &QSpinBox::valueChanged, this, &RoomPropertiesDialog::changed); connect(m_ui->actionGridEnabled, &QAction::toggled, this, &RoomPropertiesDialog::changed); connect(m_ui->actionIsometricGrid, &QAction::toggled, this, &RoomPropertiesDialog::changed); connect(m_ui->lineEditName, &QLineEdit::textChanged, this, &RoomPropertiesDialog::changed); connect(m_ui->lineEditCaption, &QLineEdit::textChanged, this, &RoomPropertiesDialog::changed); connect(m_ui->spinBoxWidth, &QSpinBox::valueChanged, this, &RoomPropertiesDialog::changed); connect(m_ui->spinBoxHeight, &QSpinBox::valueChanged, this, &RoomPropertiesDialog::changed); connect(m_ui->spinBoxSpeed, &QSpinBox::valueChanged, this, &RoomPropertiesDialog::changed); connect(m_ui->checkBoxPersistent, &QCheckBox::toggled, this, &RoomPropertiesDialog::changed); connect(m_ui->pushButtonCreationCode, &QAbstractButton::clicked, this, &RoomPropertiesDialog::editCreationCode); connect(m_ui->roomEditWidget, &RoomEditWidget::snapXChanged, m_spinBoxSnapX, &QSpinBox::setValue); connect(m_ui->roomEditWidget, &RoomEditWidget::snapYChanged, m_spinBoxSnapY, &QSpinBox::setValue); connect(m_ui->roomEditWidget, &RoomEditWidget::gridEnabledChanged, m_ui->actionGridEnabled, &QAction::setChecked); connect(m_ui->roomEditWidget, &RoomEditWidget::isometricGridChanged, m_ui->actionIsometricGrid, &QAction::setChecked); connect(m_ui->roomEditWidget, &RoomEditWidget::cursorMoved, this, &RoomPropertiesDialog::cursorMoved); connect(m_ui->roomEditWidget, &RoomEditWidget::changed, this, &RoomPropertiesDialog::changed); connect(m_menuObjects, &QMenu::aboutToShow, this, &RoomPropertiesDialog::objectsMenuAboutToShow); if (!m_projectModel.project()->objects.empty()) setObject(m_projectModel.project()->objects.back()); } RoomPropertiesDialog::~RoomPropertiesDialog() = default; void RoomPropertiesDialog::accept() { if (!m_unsavedChanges) { QDialog::reject(); return; } if (m_room.name != m_ui->lineEditName->text()) { if (!m_projectModel.rename(m_room, m_ui->lineEditName->text())) { QMessageBox::critical(this, tr("Renaming Room failed!"), tr("Renaming Room failed!")); return; } } m_room.caption = m_ui->lineEditCaption->text(); m_room.width = m_ui->spinBoxWidth->value(); m_room.height = m_ui->spinBoxHeight->value(); m_room.speed = m_ui->spinBoxSpeed->value(); m_room.persistent = m_ui->checkBoxPersistent->isChecked(); m_room.creationCode = m_creationCode; m_room.snapX = m_spinBoxSnapX->value(); m_room.snapY = m_spinBoxSnapY->value(); m_room.gridEnabled = m_ui->actionGridEnabled->isChecked(); m_room.isometricGrid = m_ui->actionIsometricGrid->isChecked(); m_room.objects = m_objects; QDialog::accept(); } void RoomPropertiesDialog::reject() { if (!m_unsavedChanges) { QDialog::reject(); return; } const auto result = QMessageBox::warning( this, tr("The Room has been modified."), tr("Do you want to save your changes?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save ); switch (result) { case QMessageBox::Save: accept(); return; case QMessageBox::Discard: QDialog::reject(); return; case QMessageBox::Cancel: return; default: qWarning() << "unexpected dialog result" << result; } } void RoomPropertiesDialog::undo() { QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented")); } void RoomPropertiesDialog::clearInstances() { QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented")); } void RoomPropertiesDialog::shiftInstances() { QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented")); } void RoomPropertiesDialog::sortInstancesX() { QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented")); } void RoomPropertiesDialog::sortInstancesY() { QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented")); } void RoomPropertiesDialog::lockInstances() { QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented")); } void RoomPropertiesDialog::unlockInstances() { QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented")); } void RoomPropertiesDialog::editCreationCode() { GenericCodeEditorDialog dialog{tr("Room Creation Code"), this}; dialog.setScript(m_creationCode); if (dialog.exec() == QDialog::Accepted) { m_creationCode = dialog.script(); changed(); } } void RoomPropertiesDialog::changed() { if (!m_unsavedChanges) { m_unsavedChanges = true; updateTitle(); } } void RoomPropertiesDialog::roomNameChanged(const Room &room) { if (&room != &m_room) return; { QSignalBlocker blocker{m_ui->lineEditName}; m_ui->lineEditName->setText(room.name); } updateTitle(); } void RoomPropertiesDialog::spritePixmapsChanged(const Sprite &sprite) { if (!m_selectedObject) return; if (m_selectedObject->spriteName.isEmpty()) return; if (m_selectedObject->spriteName != sprite.name) return; QPixmap pixmap; if (!sprite.pixmaps.empty() && !sprite.pixmaps.front().isNull()) pixmap = sprite.pixmaps.front(); m_ui->labelObjectPreview->setPixmap(std::move(pixmap)); } void RoomPropertiesDialog::objectNameChanged(const Object &object, const QString &oldName) { if (m_selectedObject && &object == m_selectedObject) m_ui->lineEditObject->setText(object.name); for (auto &obj : m_objects) { if (obj.objectName != oldName) continue; obj.objectName = object.name; } } void RoomPropertiesDialog::objectAboutToBeRemoved(const Object &object) { if (m_selectedObject && &object == m_selectedObject) { m_selectedObject = nullptr; m_ui->lineEditObject->clear(); m_ui->labelObjectPreview->setPixmap({}); m_ui->roomEditWidget->setSelectedObject(nullptr); } for (auto iter = std::begin(m_objects); iter != std::end(m_objects);) if (iter->objectName == object.name) iter = m_objects.erase(iter); else iter++; } void RoomPropertiesDialog::objectSpriteNameChanged(const Object &object) { if (!m_selectedObject) return; if (&object != m_selectedObject) return; QPixmap pixmap; if (!object.spriteName.isEmpty()) { const auto iter = std::find_if(std::cbegin(m_projectModel.project()->sprites), std::cend(m_projectModel.project()->sprites), [&object](const auto &sprite){ return object.spriteName == sprite.name; }); if (iter == std::cend(m_projectModel.project()->sprites)) qWarning() << "invalid sprite" << object.spriteName; else if (!iter->pixmaps.empty() && !iter->pixmaps.front().isNull()) pixmap = iter->pixmaps.front(); } m_ui->labelObjectPreview->setPixmap(std::move(pixmap)); } void RoomPropertiesDialog::objectsMenuAboutToShow() { m_menuObjects->clear(); for (const auto &object : m_projectModel.project()->objects) { QIcon icon; if (!object.spriteName.isEmpty()) { const auto iter = std::find_if(std::cbegin(m_projectModel.project()->sprites), std::cend(m_projectModel.project()->sprites), [&object](const auto &sprite){ return object.spriteName == sprite.name; }); if (iter == std::cend(m_projectModel.project()->sprites)) qWarning() << "invalid sprite" << object.spriteName; else if (!iter->pixmaps.empty() && !iter->pixmaps.front().isNull()) icon = iter->pixmaps.front(); } m_menuObjects->addAction(icon, object.name, this, [&object,this](){ setObject(object); }); } } void RoomPropertiesDialog::cursorMoved(const QPoint &point) { m_labelX->setText(tr("X: %0").arg(point.x())); m_labelY->setText(tr("Y: %0").arg(point.y())); } void RoomPropertiesDialog::setObject(const Object &object) { m_selectedObject = &object; QPixmap pixmap; if (!object.spriteName.isEmpty()) { const auto iter = std::find_if(std::cbegin(m_projectModel.project()->sprites), std::cend(m_projectModel.project()->sprites), [&object](const auto &sprite){ return object.spriteName == sprite.name; }); if (iter == std::cend(m_projectModel.project()->sprites)) qWarning() << "invalid sprite" << object.spriteName; else if (!iter->pixmaps.empty() && !iter->pixmaps.front().isNull()) pixmap = iter->pixmaps.front(); } m_ui->labelObjectPreview->setPixmap(std::move(pixmap)); m_ui->lineEditObject->setText(object.name); m_ui->roomEditWidget->setSelectedObject(&object); } void RoomPropertiesDialog::updateTitle() { setWindowTitle(tr("Room Properties: %0%1") .arg(m_room.name) .arg(m_unsavedChanges ? tr("*") : QString{}) ); }