campaigneditor.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * campaigneditor.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "campaigneditor.h"
  12. #include "ui_campaigneditor.h"
  13. #include "campaignproperties.h"
  14. #include "scenarioproperties.h"
  15. #include "../BitmapHandler.h"
  16. #include "../helper.h"
  17. #include "../../lib/VCMIDirs.h"
  18. #include "../../lib/json/JsonNode.h"
  19. #include "../../lib/campaign/CampaignState.h"
  20. #include "../../lib/mapping/CMap.h"
  21. CampaignEditor::CampaignEditor():
  22. ui(new Ui::CampaignEditor),
  23. selectedScenario(CampaignScenarioID::NONE)
  24. {
  25. ui->setupUi(this);
  26. setWindowIcon(QIcon{":/icons/menu-game.png"});
  27. ui->actionOpen->setIcon(QIcon{":/icons/document-open.png"});
  28. ui->actionSave->setIcon(QIcon{":/icons/document-save.png"});
  29. ui->actionNew->setIcon(QIcon{":/icons/document-new.png"});
  30. ui->actionScenarioProperties->setIcon(QIcon{":/icons/menu-settings.png"});
  31. ui->actionCampaignProperties->setIcon(QIcon{":/icons/menu-mods.png"});
  32. campaignScene.reset(new CampaignScene());
  33. ui->campaignView->setScene(campaignScene.get());
  34. redraw();
  35. setTitle();
  36. setWindowModality(Qt::ApplicationModal);
  37. show();
  38. }
  39. CampaignEditor::~CampaignEditor()
  40. {
  41. delete ui;
  42. }
  43. void CampaignEditor::redraw()
  44. {
  45. ui->actionSave->setEnabled(campaignState != nullptr);
  46. ui->actionSave_as->setEnabled(campaignState != nullptr);
  47. ui->actionScenarioProperties->setEnabled(campaignState != nullptr && campaignState->scenarios.count(selectedScenario));
  48. ui->actionCampaignProperties->setEnabled(campaignState != nullptr);
  49. if(!campaignState)
  50. return;
  51. campaignScene->clear();
  52. auto background = BitmapHandler::loadBitmap(campaignState->getRegions().getBackgroundName().getName());
  53. campaignScene->addItem(new QGraphicsPixmapItem(QPixmap::fromImage(background)));
  54. for (auto & s : campaignState->scenarios)
  55. {
  56. auto scenario = s.first;
  57. auto color = campaignState->scenarios.at(scenario).regionColor;
  58. auto image = BitmapHandler::loadBitmap(campaignState->getRegions().getAvailableName(scenario, color).getName());
  59. if(selectedScenario == scenario)
  60. image = BitmapHandler::loadBitmap(campaignState->getRegions().getSelectedName(scenario, color).getName());
  61. else if(campaignState->scenarios.at(scenario).mapName == "")
  62. image = BitmapHandler::loadBitmap(campaignState->getRegions().getConqueredName(scenario, color).getName());
  63. auto pixmap = new ClickablePixmapItem(QPixmap::fromImage(image), [this, scenario]()
  64. {
  65. bool redrawRequired = selectedScenario != scenario;
  66. selectedScenario = scenario;
  67. if(redrawRequired)
  68. redraw();
  69. }, [this, scenario]()
  70. {
  71. if(ScenarioProperties::showScenarioProperties(campaignState, scenario))
  72. changed();
  73. redraw();
  74. }, [this, scenario](QGraphicsSceneContextMenuEvent * event)
  75. {
  76. QMenu contextMenu(this);
  77. QAction *actionScenarioProperties = contextMenu.addAction(tr("Scenario editor"));
  78. actionScenarioProperties->setIcon(ui->actionScenarioProperties->icon());
  79. connect(actionScenarioProperties, &QAction::triggered, this, [this, scenario]() {
  80. if(ScenarioProperties::showScenarioProperties(campaignState, scenario))
  81. changed();
  82. redraw();
  83. });
  84. contextMenu.exec(event->screenPos());
  85. });
  86. auto pos = campaignState->getRegions().getPosition(scenario);
  87. pixmap->setPos(pos.x, pos.y);
  88. pixmap->setToolTip(QString::fromStdString(campaignState->scenarios.at(scenario).mapName));
  89. campaignScene->addItem(pixmap);
  90. }
  91. ui->campaignView->show();
  92. }
  93. bool CampaignEditor::getAnswerAboutUnsavedChanges()
  94. {
  95. if(unsaved)
  96. {
  97. auto sure = QMessageBox::question(this, tr("Confirmation"), tr("Unsaved changes will be lost, are you sure?"));
  98. if(sure == QMessageBox::No)
  99. {
  100. return false;
  101. }
  102. }
  103. return true;
  104. }
  105. void CampaignEditor::setTitle()
  106. {
  107. QFileInfo fileInfo(filename);
  108. QString title = QString("%1%2 - %3 (%4)").arg(fileInfo.fileName(), unsaved ? "*" : "", tr("VCMI Campaign Editor"), GameConstants::VCMI_VERSION.c_str());
  109. setWindowTitle(title);
  110. }
  111. void CampaignEditor::changed()
  112. {
  113. unsaved = true;
  114. setTitle();
  115. }
  116. bool CampaignEditor::saveCampaign()
  117. {
  118. if(campaignState->mapPieces.size() != campaignState->campaignRegions.regions.size())
  119. {
  120. auto reply = QMessageBox::question(nullptr, tr("Maps missing"), tr("Not all regions have a map. Do you want to continue?"), QMessageBox::Yes|QMessageBox::No);
  121. if (reply != QMessageBox::Yes)
  122. return false;
  123. }
  124. Helper::saveCampaign(campaignState, filename);
  125. return true;
  126. }
  127. void CampaignEditor::showCampaignEditor()
  128. {
  129. auto * dialog = new CampaignEditor();
  130. dialog->setAttribute(Qt::WA_DeleteOnClose);
  131. }
  132. void CampaignEditor::on_actionOpen_triggered()
  133. {
  134. if(!getAnswerAboutUnsavedChanges())
  135. return;
  136. auto filenameSelect = QFileDialog::getOpenFileName(this, tr("Open map"),
  137. QString::fromStdString(VCMIDirs::get().userDataPath().make_preferred().string()),
  138. tr("All supported campaigns (*.vcmp *.h3c);;VCMI campaigns(*.vcmp);;HoMM3 campaigns(*.h3c)"));
  139. if(filenameSelect.isEmpty())
  140. return;
  141. campaignState = Helper::openCampaignInternal(filenameSelect);
  142. selectedScenario = *campaignState->allScenarios().begin();
  143. redraw();
  144. }
  145. void CampaignEditor::on_actionSave_as_triggered()
  146. {
  147. if(!campaignState)
  148. return;
  149. auto filenameSelect = QFileDialog::getSaveFileName(this, tr("Save campaign"), "", tr("VCMI campaigns (*.vcmp)"));
  150. if(filenameSelect.isNull())
  151. return;
  152. QFileInfo fileInfo(filenameSelect);
  153. if(fileInfo.suffix().toLower() != "vcmp")
  154. filenameSelect += ".vcmp";
  155. filename = filenameSelect;
  156. if(saveCampaign())
  157. unsaved = false;
  158. setTitle();
  159. }
  160. void CampaignEditor::on_actionNew_triggered()
  161. {
  162. if(!getAnswerAboutUnsavedChanges())
  163. return;
  164. campaignState = std::make_unique<CampaignState>();
  165. campaignState->campaignRegions = CampaignRegions::getLegacy(0);
  166. for (int i = 0; i < campaignState->campaignRegions.regions.size(); i++)
  167. {
  168. CampaignScenario s;
  169. s.travelOptions.startOptions = CampaignStartOptions::START_BONUS;
  170. campaignState->scenarios.emplace(CampaignScenarioID(i), s);
  171. }
  172. campaignState->modName = "mapEditor";
  173. campaignState->creationDateTime = std::time(nullptr);
  174. changed();
  175. redraw();
  176. }
  177. void CampaignEditor::on_actionSave_triggered()
  178. {
  179. if(!campaignState)
  180. return;
  181. if(filename.isNull())
  182. on_actionSave_as_triggered();
  183. else if(saveCampaign())
  184. unsaved = false;
  185. setTitle();
  186. }
  187. void CampaignEditor::on_actionCampaignProperties_triggered()
  188. {
  189. if(!campaignState)
  190. return;
  191. if(CampaignProperties::showCampaignProperties(campaignState))
  192. changed();
  193. redraw();
  194. }
  195. void CampaignEditor::on_actionScenarioProperties_triggered()
  196. {
  197. if(!campaignState || selectedScenario == CampaignScenarioID::NONE)
  198. return;
  199. if(ScenarioProperties::showScenarioProperties(campaignState, selectedScenario))
  200. changed();
  201. redraw();
  202. }
  203. void CampaignEditor::closeEvent(QCloseEvent *event)
  204. {
  205. if(getAnswerAboutUnsavedChanges())
  206. QDialog::closeEvent(event);
  207. else
  208. event->ignore();
  209. }