campaigneditor.cpp 7.0 KB

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