diff --git a/Editor/common_features/items.cpp b/Editor/common_features/items.cpp index fbad94fc7..6a05c0ac6 100644 --- a/Editor/common_features/items.cpp +++ b/Editor/common_features/items.cpp @@ -121,6 +121,20 @@ void Items::getItemGFX(const obj_wld_generic *inObj, QPixmap &outImg, bool whole TPL_getItemGFX(inObj, outImg, whole, targetSize, imgType); } +void Items::getItemGFXCW(int itemType, unsigned long ItemID, QPixmap &outImg, bool whole, QSize targetSize) +{ + LevelEdit *l_edit = MainWinConnect::pMainWin->activeLvlEditWin(); + WorldEdit *w_edit = MainWinConnect::pMainWin->activeWldEditWin(); + QGraphicsScene *scene = nullptr; + + if(l_edit) + scene = l_edit->scene; + else if(w_edit) + scene = w_edit->scene; + + getItemGFX(itemType, ItemID, outImg, scene, whole, targetSize); +} + void Items::getItemGFX(int itemType, unsigned long ItemID, QPixmap &outImg, QGraphicsScene *scene, bool whole, QSize targetSize) { LvlScene *scene_lvl = dynamic_cast(scene); @@ -224,7 +238,7 @@ QString Items::getTilesetToolTip(int itemType, unsigned long ItemID, QGraphicsSc return ""; } -int Items::getItemType(QString type) +int Items::getItemType(const QString &type) { int target = 0; diff --git a/Editor/common_features/items.h b/Editor/common_features/items.h index 2add427b7..f2c029586 100644 --- a/Editor/common_features/items.h +++ b/Editor/common_features/items.h @@ -10,6 +10,17 @@ class Items { public: + + /*! + * \brief Retreives sprite or single frame of the requested element using currently active window, no scene needed + * \param [__in] itemType Type of the element (Block, BGO, NPC, Terrain tile, World map scenery, Path tile, Level tile) + * \param [__in] ItemID ID of requested element + * \param [__out] outImg Target Pixmap where will be stored requested sprite + * \param [__in] whole Retreive entire srite, overwise single default frame will be retured + * \param [__in] targetSize Scale image to requested size, if 0:0 sent, image will be returned as-is + */ + static void getItemGFXCW(int itemType, unsigned long ItemID, QPixmap &outImg, bool whole=false, QSize targetSize=QSize(0,0)); + /*! * \brief Retreives sprite or single frame of the requested element * \param [__in] itemType Type of the element (Block, BGO, NPC, Terrain tile, World map scenery, Path tile, Level tile) @@ -19,7 +30,7 @@ class Items * \param [__in] whole Retreive entire srite, overwise single default frame will be retured * \param [__in] targetSize Scale image to requested size, if 0:0 sent, image will be returned as-is */ - static void getItemGFX(int itemType, unsigned long ItemID, QPixmap &outImg, QGraphicsScene *scene=NULL, bool whole=false, QSize targetSize=QSize(0,0)); + static void getItemGFX(int itemType, unsigned long ItemID, QPixmap &outImg, QGraphicsScene *scene=nullptr, bool whole=false, QSize targetSize=QSize(0,0)); /*! * \brief Retreives sprite or single frame of the block object configuration @@ -65,7 +76,7 @@ class Items * \param type String contains a word which specifies item type * \return Item type ID enumerated value */ - static int getItemType(QString type); + static int getItemType(const QString &type); }; #endif // ITEMS_H diff --git a/Editor/main_window/_settings/settings_io.cpp b/Editor/main_window/_settings/settings_io.cpp index 04dd37424..fcb70465a 100644 --- a/Editor/main_window/_settings/settings_io.cpp +++ b/Editor/main_window/_settings/settings_io.cpp @@ -269,10 +269,14 @@ void MainWindow::loadSettings() GlobalSettings::testing.p1_state = settings.value("p1-state", 1).toInt(); GlobalSettings::testing.p1_vehicleID = settings.value("p1-vehicle-id", 0).toInt(); GlobalSettings::testing.p1_vehicleType = settings.value("p1-vehicle-type", 0).toInt(); + GlobalSettings::testing.p1_health = settings.value("p1-health", 0).toInt(); + GlobalSettings::testing.p1_item = settings.value("p1-item", 0).toInt(); GlobalSettings::testing.p2_char = settings.value("p2-char", 1).toInt(); GlobalSettings::testing.p2_state = settings.value("p2-state", 1).toInt(); GlobalSettings::testing.p2_vehicleID = settings.value("p2-vehicle-id", 0).toInt(); GlobalSettings::testing.p2_vehicleType = settings.value("p2-vehicle-type", 0).toInt(); + GlobalSettings::testing.p2_health = settings.value("p2-health", 0).toInt(); + GlobalSettings::testing.p2_item = settings.value("p2-item", 0).toInt(); } settings.endGroup(); @@ -423,10 +427,14 @@ void MainWindow::saveSettings() settings.setValue("p1-state", GlobalSettings::testing.p1_state); settings.setValue("p1-vehicle-id", GlobalSettings::testing.p1_vehicleID); settings.setValue("p1-vehicle-type", GlobalSettings::testing.p1_vehicleType); + settings.setValue("p1-health", GlobalSettings::testing.p1_health); + settings.setValue("p1-item", GlobalSettings::testing.p1_item); settings.setValue("p2-char", GlobalSettings::testing.p2_char); settings.setValue("p2-state", GlobalSettings::testing.p2_state); settings.setValue("p2-vehicle-id", GlobalSettings::testing.p2_vehicleID); settings.setValue("p2-vehicle-type", GlobalSettings::testing.p2_vehicleType); + settings.setValue("p2-health", GlobalSettings::testing.p2_health); + settings.setValue("p2-item", GlobalSettings::testing.p2_item); } settings.endGroup(); diff --git a/Editor/main_window/global_settings.h b/Editor/main_window/global_settings.h index f83c53b7d..190b9792e 100644 --- a/Editor/main_window/global_settings.h +++ b/Editor/main_window/global_settings.h @@ -88,10 +88,14 @@ struct SETTINGS_TestSettings int p1_state = 1; int p1_vehicleID = 0; int p1_vehicleType = 0; + int p1_health = -1; + int p1_item = 0; int p2_char = 2; int p2_state = 1; int p2_vehicleID = 0; int p2_vehicleType = 0; + int p2_health = -1; + int p2_item = 0; }; struct SETTINGS_ScreenGrabSettings diff --git a/Editor/main_window/testing/testing.cpp b/Editor/main_window/testing/testing.cpp index 3b508ed33..c6ca0f8a8 100644 --- a/Editor/main_window/testing/testing.cpp +++ b/Editor/main_window/testing/testing.cpp @@ -187,6 +187,22 @@ void MainWindow::initTesting() t.p2_vehicleType = vehicleType; } }); + + QObject::connect(&g_intEngine, &IntEngineSignals::enginePlayerStateUpdated2, + this, [](int playerID, int health, int reservedItem) + { + auto &t =GlobalSettings::testing; + if(playerID == 0) + { + t.p1_health = health; + t.p1_item = reservedItem; + } + else if(playerID == 1) + { + t.p2_health = health; + t.p2_item = reservedItem; + } + }); } void MainWindow::updateTestingCaps() diff --git a/Editor/main_window/testing/testing_settings.cpp b/Editor/main_window/testing/testing_settings.cpp index d2a788816..56faa546b 100644 --- a/Editor/main_window/testing/testing_settings.cpp +++ b/Editor/main_window/testing/testing_settings.cpp @@ -2,7 +2,9 @@ #include "ui_testing_settings.h" #include #include +#include #include +#include #include @@ -12,10 +14,11 @@ TestingSettings::TestingSettings(QWidget *parent) : { ui->setupUi(this); - MainWindow* mw = qobject_cast(this->parent()); - if(mw) + m_mw = qobject_cast(this->parent()); + + if(m_mw) { - QList& plr = mw->configs.main_characters; + QList& plr = m_mw->configs.main_characters; ui->p1_character->clear(); ui->p2_character->clear(); @@ -56,14 +59,26 @@ TestingSettings::TestingSettings(QWidget *parent) : ui->ex_physdebug->setChecked(GlobalSettings::testing.xtra_physdebug); ui->ex_freedom->setChecked(GlobalSettings::testing.xtra_worldfreedom); ui->ex_starsNum->setValue(GlobalSettings::testing.xtra_starsNum); + ui->p1_character->setCurrentIndex(GlobalSettings::testing.p1_char-1); ui->p1_state->setCurrentIndex(GlobalSettings::testing.p1_state-1); ui->p1_vehicleID->setCurrentIndex(GlobalSettings::testing.p1_vehicleID); ui->p1_vehicleType->setCurrentIndex(GlobalSettings::testing.p1_vehicleType); + ui->p1_health_en->setChecked(GlobalSettings::testing.p1_health > 0); + if(GlobalSettings::testing.p1_health > 0) + ui->p1_health->setValue(GlobalSettings::testing.p1_health); + m_curItemP1 = GlobalSettings::testing.p1_item; + updateNpcButton(ui->p1_reserved, m_curItemP1); + ui->p2_character->setCurrentIndex(GlobalSettings::testing.p2_char-1); ui->p2_state->setCurrentIndex(GlobalSettings::testing.p2_state-1); ui->p2_vehicleID->setCurrentIndex(GlobalSettings::testing.p2_vehicleID); ui->p2_vehicleType->setCurrentIndex(GlobalSettings::testing.p2_vehicleType); + ui->p2_health_en->setChecked(GlobalSettings::testing.p2_health > 0); + if(GlobalSettings::testing.p2_health > 0) + ui->p2_health->setValue(GlobalSettings::testing.p2_health); + m_curItemP2 = GlobalSettings::testing.p2_item; + updateNpcButton(ui->p2_reserved, m_curItemP2); switch(GlobalSettings::testing.numOfPlayers) { @@ -85,6 +100,15 @@ TestingSettings::TestingSettings(QWidget *parent) : default: case ConfStatus::ENGINE_MOONDUST: ui->initialState->setVisible(false); // Not implemented at Moondust Engine yet + // Not implemented at Moondust Engine yet + ui->p1_health_en->setVisible(false); + ui->p1_health->setVisible(false); + ui->p1_reserved_label->setVisible(false); + ui->p1_reserved->setVisible(false); + ui->p2_health_en->setVisible(false); + ui->p2_health->setVisible(false); + ui->p2_reserved_label->setVisible(false); + ui->p2_reserved->setVisible(false); break; case ConfStatus::ENGINE_THEXTECH: @@ -102,6 +126,14 @@ TestingSettings::TestingSettings(QWidget *parent) : ui->ex_flyup ->setVisible(false); ui->ex_debug ->setVisible(false); ui->ex_physdebug ->setVisible(false); + ui->p1_health_en->setVisible(false); + ui->p1_health->setVisible(false); + ui->p1_reserved_label->setVisible(false); + ui->p1_reserved->setVisible(false); + ui->p2_health_en->setVisible(false); + ui->p2_health->setVisible(false); + ui->p2_reserved_label->setVisible(false); + ui->p2_reserved->setVisible(false); break; case ConfStatus::ENGINE_38A: @@ -109,6 +141,14 @@ TestingSettings::TestingSettings(QWidget *parent) : ui->initialState->setVisible(false); ui->cheats->setVisible(false); ui->debug->setVisible(false); + ui->p1_health_en->setVisible(false); + ui->p1_health->setVisible(false); + ui->p1_reserved_label->setVisible(false); + ui->p1_reserved->setVisible(false); + ui->p2_health_en->setVisible(false); + ui->p2_health->setVisible(false); + ui->p2_reserved_label->setVisible(false); + ui->p2_reserved->setVisible(false); break; } } @@ -141,10 +181,15 @@ void TestingSettings::on_buttonBox_accepted() GlobalSettings::testing.p1_state = (ui->p1_state->currentIndex()+1); GlobalSettings::testing.p1_vehicleID = (ui->p1_vehicleID->currentIndex()); GlobalSettings::testing.p1_vehicleType = (ui->p1_vehicleType->currentIndex()); + GlobalSettings::testing.p1_health = ui->p1_health_en->isChecked() ? (ui->p1_health->value()) : -1; + GlobalSettings::testing.p1_item = m_curItemP1; + GlobalSettings::testing.p2_char = (ui->p2_character->currentIndex()+1); GlobalSettings::testing.p2_state = (ui->p2_state->currentIndex()+1); GlobalSettings::testing.p2_vehicleID = (ui->p2_vehicleID->currentIndex()); GlobalSettings::testing.p2_vehicleType = (ui->p2_vehicleType->currentIndex()); + GlobalSettings::testing.p2_health = ui->p2_health_en->isChecked() ? (ui->p2_health->value()) : -1; + GlobalSettings::testing.p2_item = m_curItemP2; this->close(); } @@ -256,3 +301,62 @@ void TestingSettings::refreshVehicleTypes() if(p2_sel_backup <= ui->p2_vehicleType->count()) ui->p2_vehicleType->setCurrentIndex(p2_sel_backup); } + +void TestingSettings::updateNpcButton(QPushButton *button, int npcId) +{ + QString npcTitle; + QPixmap icon; + + LevelEdit *edit = m_mw->activeLvlEditWin(); + + if(npcId > 0) + { + auto &source = edit ? edit->scene->m_localConfigNPCs : m_mw->configs.main_npc; + + if(source.contains(npcId)) + { + auto it = source[npcId]; + npcTitle = it.setup.name; + Items::getItemGFXCW(ItemTypes::LVL_NPC, npcId, icon, false, QSize(16, 16)); + } + } + + if(npcTitle.isEmpty()) + npcTitle = tr("", "Unknown NPC from the list"); + + button->setText(npcId <= 0 ? tr("[No item]", "Reserve box of player contains no item") : QString("NPC-%1 (%2)").arg(npcId).arg(npcTitle)); + + if(!icon.isNull()) + button->setIcon(QIcon(icon.scaledToHeight(16))); +} + +void TestingSettings::on_p1_reserved_clicked() +{ + if(!m_mw) + return; + + ItemSelectDialog *npcList = new ItemSelectDialog(&m_mw->configs, ItemSelectDialog::TAB_NPC, 0, 0, 0, m_curItemP1, 0, 0, 0, 0, 0, this); + util::DialogToCenter(npcList, true); + + if(npcList->exec() == QDialog::Accepted) + { + m_curItemP1 = npcList->npcID; + updateNpcButton(ui->p1_reserved, m_curItemP1); + } +} + +void TestingSettings::on_p2_reserved_clicked() +{ + if(!m_mw) + return; + + ItemSelectDialog *npcList = new ItemSelectDialog(&m_mw->configs, ItemSelectDialog::TAB_NPC, 0, 0, 0, m_curItemP2, 0, 0, 0, 0, 0, this); + util::DialogToCenter(npcList, true); + + if(npcList->exec() == QDialog::Accepted) + { + m_curItemP2 = npcList->npcID; + updateNpcButton(ui->p2_reserved, m_curItemP2); + } +} + diff --git a/Editor/main_window/testing/testing_settings.h b/Editor/main_window/testing/testing_settings.h index 578a94514..35fc3210d 100644 --- a/Editor/main_window/testing/testing_settings.h +++ b/Editor/main_window/testing/testing_settings.h @@ -8,10 +8,15 @@ namespace Ui { class TestingSettings; } +class MainWindow; + class TestingSettings : public QDialog { Q_OBJECT + int m_curItemP1 = 0; + int m_curItemP2 = 0; + MainWindow* m_mw = nullptr; public: explicit TestingSettings(QWidget *parent = 0); ~TestingSettings(); @@ -20,6 +25,9 @@ private slots: void on_buttonBox_accepted(); void reloadStates1(int index); void reloadStates2(int index); + void on_p1_reserved_clicked(); + void on_p2_reserved_clicked(); + signals: void windowShown(); @@ -31,6 +39,8 @@ private slots: void refreshVehicleID(); void refreshVehicleTypes(); + + void updateNpcButton(QPushButton *button, int npcId); }; #endif // TESTING_SETTINGS_H diff --git a/Editor/main_window/testing/testing_settings.ui b/Editor/main_window/testing/testing_settings.ui index d03f9800c..3b0d1605e 100644 --- a/Editor/main_window/testing/testing_settings.ui +++ b/Editor/main_window/testing/testing_settings.ui @@ -7,7 +7,7 @@ 0 0 606 - 542 + 644 @@ -237,42 +237,57 @@ 1 Player settings - - + + - PLSET_Character + [Empty] - - - - - ch1 - - + + - ch2 + [No vehicle] - ch3 + Vehicle 1 - ch4 + Vehicle 2 - ch5 + Vehicle 3 + + + + PLSET_VehicleID + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -319,103 +334,119 @@ - - - - Qt::Vertical - - - - 20 - 40 - + + + + PLSET_Character - + - - + + - [No vehicle] + [Unknown type] - Vehicle 1 + Type 1 - Vehicle 2 + Type 2 - Vehicle 3 + Type 3 - - - - - [Unknown type] + Type 4 - Type 1 + Type 5 - Type 2 + Type 6 - Type 3 + Type 7 - Type 4 + Type 8 + + + + + + PLSET_VehicleType + + + + + - Type 5 + ch1 - Type 6 + ch2 - Type 7 + ch3 - Type 8 + ch4 + + + + + ch5 - + - PLSET_VehicleID + Set custom health level - + - PLSET_VehicleType + Reserved item + + + + + + + false + + + 1 @@ -434,18 +465,12 @@ 2 Player settings - - - - Qt::Vertical - - - - 20 - 40 - + + + + Reserved item - + @@ -486,12 +511,18 @@ - - - - PLSET_State + + + + Qt::Vertical - + + + 20 + 40 + + + @@ -500,6 +531,20 @@ + + + + PLSET_VehicleID + + + + + + + PLSET_State + + + @@ -529,93 +574,110 @@ - - + + - [No vehicle] + [Unknown type] - Vehicle 1 + Type 1 - Vehicle 2 + Type 2 - Vehicle 3 + Type 3 - - - - - - PLSET_VehicleID - - - - - - - PLSET_VehicleType - - - - - - [Unknown type] + Type 4 - Type 1 + Type 5 - Type 2 + Type 6 - Type 3 + Type 7 - Type 4 + Type 8 + + + + + + [Empty] + + + + + + + PLSET_VehicleType + + + + + - Type 5 + [No vehicle] - Type 6 + Vehicle 1 - Type 7 + Vehicle 2 - Type 8 + Vehicle 3 + + + + false + + + 1 + + + + + + + Set custom health level + + + @@ -655,8 +717,8 @@ close() - 158 - 371 + 167 + 634 153 @@ -664,5 +726,37 @@ + + p2_health_en + toggled(bool) + p2_health + setEnabled(bool) + + + 325 + 380 + + + 339 + 396 + + + + + p1_health_en + toggled(bool) + p1_health + setEnabled(bool) + + + 84 + 384 + + + 93 + 404 + + + diff --git a/Editor/networking/engine_intproc.h b/Editor/networking/engine_intproc.h index 4aecd2ec6..8722abf3b 100644 --- a/Editor/networking/engine_intproc.h +++ b/Editor/networking/engine_intproc.h @@ -49,6 +49,7 @@ class IntEngineSignals : public QObject void engineTakenNPC(const LevelNPC &npc); void engineNumStarsChanged(int numStars); void enginePlayerStateUpdated(int playerID, int character, int state, int vehicleID, int vehicleType); + void enginePlayerStateUpdated2(int playerID, int health, int reservedItem); void engineCloseProperties(); }; diff --git a/Editor/testing/ipc/pge_engine_ipc.cpp b/Editor/testing/ipc/pge_engine_ipc.cpp index ddb00f629..4cb9de736 100644 --- a/Editor/testing/ipc/pge_engine_ipc.cpp +++ b/Editor/testing/ipc/pge_engine_ipc.cpp @@ -179,6 +179,27 @@ void PgeEngineIpcClient::onInputData() if(ok) emit enginePlayerStateUpdated(val[0], val[1], val[2], val[3], val[4]); } + else if(std::strncmp(msgP, "PLAYER_SETUP_UPDATE2 ", 21) == 0) + { + qApp->processEvents(); + int val[5]; + bool ok; + QString playernum = QString::fromUtf8(msgP + 21); + QStringList p = playernum.split(' '); + + if(p.size() != 3) + return; + + for(int i = 0; i < 3; i++) + { + val[i] = p[i].toInt(&ok); + if(!ok) + break; + } + + if(ok) + emit enginePlayerStateUpdated2(val[0], val[1], val[2]); + } else if(std::strcmp(msgP, "CLOSE_PROPERTIES") == 0) emit engineCloseProperties(); else if(std::strcmp(msgP, "CONNECT_TO_ENGINE") == 0) @@ -232,6 +253,8 @@ void PgeEngineIpcClient::init(QProcess *engine) &g_intEngine, &IntEngineSignals::engineNumStarsChanged, Qt::QueuedConnection); QObject::connect(this, &PgeEngineIpcClient::enginePlayerStateUpdated, &g_intEngine, &IntEngineSignals::enginePlayerStateUpdated, Qt::QueuedConnection); + QObject::connect(this, &PgeEngineIpcClient::enginePlayerStateUpdated2, + &g_intEngine, &IntEngineSignals::enginePlayerStateUpdated2, Qt::QueuedConnection); QObject::connect(this, &PgeEngineIpcClient::engineCloseProperties, &g_intEngine, &IntEngineSignals::engineCloseProperties, Qt::QueuedConnection); } diff --git a/Editor/testing/ipc/pge_engine_ipc.h b/Editor/testing/ipc/pge_engine_ipc.h index 4c7199c9c..2d644264f 100644 --- a/Editor/testing/ipc/pge_engine_ipc.h +++ b/Editor/testing/ipc/pge_engine_ipc.h @@ -162,6 +162,14 @@ private slots: */ void enginePlayerStateUpdated(int playerID, int character, int state, int vehicleID, int vehicleType); + /*! + * \brief A hook for extra player state being updated + * \param playerID Player ID + * \param helath Health level + * \param reservedItem Reserved NPC-ID + */ + void enginePlayerStateUpdated2(int playerID, int helath, int reservedItem); + /** * @brief A hook for the properties close request */ diff --git a/Editor/testing/thextech_engine.cpp b/Editor/testing/thextech_engine.cpp index 6eae7231e..bf8b32775 100644 --- a/Editor/testing/thextech_engine.cpp +++ b/Editor/testing/thextech_engine.cpp @@ -1204,18 +1204,36 @@ bool TheXTechEngine::doTestLevelIPC(const LevelData &d) args << "--never-pause"; + bool hasHealthAndItem = m_caps.features.contains("ipc-player-health") && m_caps.features.contains("ipc-player-item"); + SETTINGS_TestSettings t = GlobalSettings::testing; args << "--num-players" << QString::number(t.numOfPlayers); - args << "--player1" << QString("c%1;s%2;m%3;t%4") + args << "--player1" << (hasHealthAndItem ? + QString("c%1;s%2;m%3;t%4;h%5;r%6") .arg(t.p1_char) .arg(t.p1_state) .arg(t.p1_vehicleID) - .arg(t.p1_vehicleType); - args << "--player2" << QString("c%1;s%2;m%3;t%4") + .arg(t.p1_vehicleType) + .arg(t.p1_health) + .arg(t.p1_item) : + QString("c%1;s%2;m%3;t%4") + .arg(t.p1_char) + .arg(t.p1_state) + .arg(t.p1_vehicleID) + .arg(t.p1_vehicleType)); + args << "--player2" << (hasHealthAndItem ? + QString("c%1;s%2;m%3;t%4;h%5;r%6") .arg(t.p2_char) .arg(t.p2_state) .arg(t.p2_vehicleID) - .arg(t.p2_vehicleType); + .arg(t.p2_vehicleType) + .arg(t.p2_health) + .arg(t.p2_item) : + QString("c%1;s%2;m%3;t%4") + .arg(t.p2_char) + .arg(t.p2_state) + .arg(t.p2_vehicleID) + .arg(t.p2_vehicleType)); if(t.xtra_god) args << "--god-mode"; if(t.xtra_showFPS) args << "--show-fps"; diff --git a/changelog.editor.txt b/changelog.editor.txt index 6f0f10b1a..56ede41aa 100644 --- a/changelog.editor.txt +++ b/changelog.editor.txt @@ -55,6 +55,7 @@ beta2 - Resolved the problem of abnormal duplicates of layers and events entries appear in the GUI lists - Added On-Exit warp event entry for supported engines - Fixed the incorrect refreshing of selected layers and events in some toolboxes when switching between opened files +- Added "Health" and "Reserved item" per-player test settings Editor 0.3.2 - Added support for an element (Block, BGO, NPC), section, and level-wide Extra Settings