windownewmap.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /*
  2. * windownewmap.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 "../lib/mapping/CMap.h"
  12. #include "../lib/rmg/CRmgTemplateStorage.h"
  13. #include "../lib/rmg/CRmgTemplate.h"
  14. #include "../lib/rmg/CMapGenerator.h"
  15. #include "../lib/VCMI_Lib.h"
  16. #include "../lib/mapping/CMapEditManager.h"
  17. #include "../lib/mapping/MapFormat.h"
  18. #include "../lib/texts/CGeneralTextHandler.h"
  19. #include "../lib/CRandomGenerator.h"
  20. #include "../lib/serializer/JsonSerializer.h"
  21. #include "../lib/serializer/JsonDeserializer.h"
  22. #include "jsonutils.h"
  23. #include "windownewmap.h"
  24. #include "ui_windownewmap.h"
  25. #include "mainwindow.h"
  26. #include "generatorprogress.h"
  27. WindowNewMap::WindowNewMap(QWidget *parent) :
  28. QDialog(parent),
  29. ui(new Ui::WindowNewMap)
  30. {
  31. ui->setupUi(this);
  32. setAttribute(Qt::WA_DeleteOnClose);
  33. setWindowModality(Qt::ApplicationModal);
  34. for(auto * combo : {ui->humanCombo, ui->cpuCombo, ui->humanTeamsCombo, ui->cpuTeamsCombo})
  35. combo->clear();
  36. //prepare human players combo box
  37. for(int i = 0; i <= PlayerColor::PLAYER_LIMIT_I; ++i)
  38. {
  39. ui->humanCombo->addItem(!i ? randomString : QString::number(players.at(i)));
  40. ui->humanCombo->setItemData(i, QVariant(players.at(i)));
  41. ui->cpuCombo->addItem(!i ? randomString : QString::number(cpuPlayers.at(i)));
  42. ui->cpuCombo->setItemData(i, QVariant(cpuPlayers.at(i)));
  43. ui->humanTeamsCombo->addItem(!i ? randomString : QString::number(cpuPlayers.at(i)));
  44. ui->humanTeamsCombo->setItemData(i, QVariant(cpuPlayers.at(i)));
  45. ui->cpuTeamsCombo->addItem(!i ? randomString : QString::number(cpuPlayers.at(i)));
  46. ui->cpuTeamsCombo->setItemData(i, QVariant(cpuPlayers.at(i)));
  47. }
  48. bool useLoaded = loadUserSettings();
  49. if (!useLoaded)
  50. {
  51. for(auto * combo : {ui->humanCombo, ui->cpuCombo, ui->humanTeamsCombo, ui->cpuTeamsCombo})
  52. combo->setCurrentIndex(0);
  53. }
  54. show();
  55. if (!useLoaded)
  56. {
  57. //setup initial parameters
  58. int width = ui->widthTxt->text().toInt();
  59. int height = ui->heightTxt->text().toInt();
  60. mapGenOptions.setWidth(width ? width : 1);
  61. mapGenOptions.setHeight(height ? height : 1);
  62. bool twoLevel = ui->twoLevelCheck->isChecked();
  63. mapGenOptions.setHasTwoLevels(twoLevel);
  64. updateTemplateList();
  65. }
  66. }
  67. WindowNewMap::~WindowNewMap()
  68. {
  69. delete ui;
  70. }
  71. bool WindowNewMap::loadUserSettings()
  72. {
  73. bool ret = false;
  74. CRmgTemplate * templ = nullptr;
  75. QSettings s(Ui::teamName, Ui::appName);
  76. auto generateRandom = s.value(newMapGenerateRandom);
  77. if (generateRandom.isValid())
  78. {
  79. ui->randomMapCheck->setChecked(generateRandom.toBool());
  80. }
  81. auto settings = s.value(newMapWindow);
  82. if (settings.isValid())
  83. {
  84. auto node = JsonUtils::toJson(settings);
  85. JsonDeserializer handler(nullptr, node);
  86. handler.serializeStruct("lastSettings", mapGenOptions);
  87. templ = const_cast<CRmgTemplate*>(mapGenOptions.getMapTemplate()); // Remember for later
  88. ui->widthTxt->setText(QString::number(mapGenOptions.getWidth()));
  89. ui->heightTxt->setText(QString::number(mapGenOptions.getHeight()));
  90. for(const auto & sz : mapSizes)
  91. {
  92. if(sz.second.first == mapGenOptions.getWidth() &&
  93. sz.second.second == mapGenOptions.getHeight())
  94. {
  95. ui->sizeCombo->setCurrentIndex(sz.first);
  96. break;
  97. }
  98. }
  99. ui->twoLevelCheck->setChecked(mapGenOptions.getHasTwoLevels());
  100. ui->humanCombo->setCurrentIndex(mapGenOptions.getHumanOrCpuPlayerCount());
  101. ui->cpuCombo->setCurrentIndex(mapGenOptions.getCompOnlyPlayerCount());
  102. ui->humanTeamsCombo->setCurrentIndex(mapGenOptions.getTeamCount());
  103. ui->cpuTeamsCombo->setCurrentIndex(mapGenOptions.getCompOnlyTeamCount());
  104. switch (mapGenOptions.getWaterContent())
  105. {
  106. case EWaterContent::RANDOM:
  107. ui->waterOpt1->setChecked(true); break;
  108. case EWaterContent::NONE:
  109. ui->waterOpt2->setChecked(true); break;
  110. case EWaterContent::NORMAL:
  111. ui->waterOpt3->setChecked(true); break;
  112. case EWaterContent::ISLANDS:
  113. ui->waterOpt4->setChecked(true); break;
  114. }
  115. switch (mapGenOptions.getMonsterStrength())
  116. {
  117. case EMonsterStrength::RANDOM:
  118. ui->monsterOpt1->setChecked(true); break;
  119. case EMonsterStrength::GLOBAL_WEAK:
  120. ui->monsterOpt2->setChecked(true); break;
  121. case EMonsterStrength::GLOBAL_NORMAL:
  122. ui->monsterOpt3->setChecked(true); break;
  123. case EMonsterStrength::GLOBAL_STRONG:
  124. ui->monsterOpt4->setChecked(true); break;
  125. }
  126. ret = true;
  127. }
  128. updateTemplateList();
  129. mapGenOptions.setMapTemplate(templ); // Can be null
  130. if (templ)
  131. {
  132. std::string name = templ->getName();
  133. for (size_t i = 0; i < ui->templateCombo->count(); i++)
  134. {
  135. if (ui->templateCombo->itemText(i).toStdString() == name)
  136. {
  137. ui->templateCombo->setCurrentIndex(i);
  138. break;
  139. }
  140. }
  141. ret = true;
  142. }
  143. return ret;
  144. }
  145. void WindowNewMap::saveUserSettings()
  146. {
  147. QSettings s(Ui::teamName, Ui::appName);
  148. JsonNode data;
  149. JsonSerializer ser(nullptr, data);
  150. ser.serializeStruct("lastSettings", mapGenOptions);
  151. auto variant = JsonUtils::toVariant(data);
  152. s.setValue(newMapWindow, variant);
  153. s.setValue(newMapGenerateRandom, ui->randomMapCheck->isChecked());
  154. }
  155. void WindowNewMap::on_cancelButton_clicked()
  156. {
  157. saveUserSettings();
  158. close();
  159. }
  160. void generateRandomMap(CMapGenerator & gen, MainWindow * window)
  161. {
  162. window->controller.setMap(gen.generate());
  163. }
  164. std::unique_ptr<CMap> generateEmptyMap(CMapGenOptions & options)
  165. {
  166. auto map = std::make_unique<CMap>(nullptr);
  167. map->version = EMapFormat::VCMI;
  168. map->creationDateTime = std::time(nullptr);
  169. map->width = options.getWidth();
  170. map->height = options.getHeight();
  171. map->twoLevel = options.getHasTwoLevels();
  172. map->initTerrain();
  173. map->getEditManager()->clearTerrain(&CRandomGenerator::getDefault());
  174. return map;
  175. }
  176. void WindowNewMap::on_okButton_clicked()
  177. {
  178. EWaterContent::EWaterContent water = EWaterContent::RANDOM;
  179. EMonsterStrength::EMonsterStrength monster = EMonsterStrength::RANDOM;
  180. if(ui->waterOpt1->isChecked())
  181. water = EWaterContent::RANDOM;
  182. if(ui->waterOpt2->isChecked())
  183. water = EWaterContent::NONE;
  184. if(ui->waterOpt3->isChecked())
  185. water = EWaterContent::NORMAL;
  186. if(ui->waterOpt4->isChecked())
  187. water = EWaterContent::ISLANDS;
  188. if(ui->monsterOpt1->isChecked())
  189. monster = EMonsterStrength::RANDOM;
  190. if(ui->monsterOpt2->isChecked())
  191. monster = EMonsterStrength::GLOBAL_WEAK;
  192. if(ui->monsterOpt3->isChecked())
  193. monster = EMonsterStrength::GLOBAL_NORMAL;
  194. if(ui->monsterOpt4->isChecked())
  195. monster = EMonsterStrength::GLOBAL_STRONG;
  196. mapGenOptions.setWaterContent(water);
  197. mapGenOptions.setMonsterStrength(monster);
  198. saveUserSettings();
  199. std::unique_ptr<CMap> nmap;
  200. if(ui->randomMapCheck->isChecked())
  201. {
  202. //verify map template
  203. if(mapGenOptions.getPossibleTemplates().empty())
  204. {
  205. QMessageBox::warning(this, tr("No template"), tr("No template for parameters specified. Random map cannot be generated."));
  206. return;
  207. }
  208. int seed = std::time(nullptr);
  209. if(ui->checkSeed->isChecked() && !ui->lineSeed->text().isEmpty())
  210. seed = ui->lineSeed->text().toInt();
  211. CMapGenerator generator(mapGenOptions, nullptr, seed);
  212. auto progressBarWnd = new GeneratorProgress(generator, this);
  213. progressBarWnd->show();
  214. try
  215. {
  216. auto f = std::async(std::launch::async, &CMapGenerator::generate, &generator);
  217. progressBarWnd->update();
  218. nmap = f.get();
  219. }
  220. catch(const std::exception & e)
  221. {
  222. QMessageBox::critical(this, tr("RMG failure"), e.what());
  223. }
  224. }
  225. else
  226. {
  227. auto f = std::async(std::launch::async, &::generateEmptyMap, std::ref(mapGenOptions));
  228. nmap = f.get();
  229. }
  230. nmap->mods = MapController::modAssessmentAll();
  231. static_cast<MainWindow*>(parent())->controller.setMap(std::move(nmap));
  232. static_cast<MainWindow*>(parent())->initializeMap(true);
  233. close();
  234. }
  235. void WindowNewMap::on_sizeCombo_activated(int index)
  236. {
  237. ui->widthTxt->setText(QString::number(mapSizes.at(index).first));
  238. ui->heightTxt->setText(QString::number(mapSizes.at(index).second));
  239. }
  240. void WindowNewMap::on_twoLevelCheck_stateChanged(int arg1)
  241. {
  242. bool twoLevel = ui->twoLevelCheck->isChecked();
  243. mapGenOptions.setHasTwoLevels(twoLevel);
  244. updateTemplateList();
  245. }
  246. void WindowNewMap::on_humanCombo_activated(int index)
  247. {
  248. int humans = ui->humanCombo->currentData().toInt();
  249. if(humans > PlayerColor::PLAYER_LIMIT_I)
  250. {
  251. humans = PlayerColor::PLAYER_LIMIT_I;
  252. ui->humanCombo->setCurrentIndex(humans);
  253. }
  254. mapGenOptions.setHumanOrCpuPlayerCount(humans);
  255. int teams = mapGenOptions.getTeamCount();
  256. if(teams > humans - 1)
  257. {
  258. teams = humans > 0 ? humans - 1 : CMapGenOptions::RANDOM_SIZE;
  259. ui->humanTeamsCombo->setCurrentIndex(teams + 1); //skip one element because first is random
  260. }
  261. int cpu = mapGenOptions.getCompOnlyPlayerCount();
  262. if(cpu > PlayerColor::PLAYER_LIMIT_I - humans)
  263. {
  264. cpu = PlayerColor::PLAYER_LIMIT_I - humans;
  265. ui->cpuCombo->setCurrentIndex(cpu + 1); //skip one element because first is random
  266. }
  267. int cpuTeams = mapGenOptions.getCompOnlyTeamCount(); //comp only players - 1
  268. if(cpuTeams > cpu - 1)
  269. {
  270. cpuTeams = cpu > 0 ? cpu - 1 : CMapGenOptions::RANDOM_SIZE;
  271. ui->cpuTeamsCombo->setCurrentIndex(cpuTeams + 1); //skip one element because first is random
  272. }
  273. updateTemplateList();
  274. }
  275. void WindowNewMap::on_cpuCombo_activated(int index)
  276. {
  277. int humans = mapGenOptions.getHumanOrCpuPlayerCount();
  278. int cpu = ui->cpuCombo->currentData().toInt();
  279. // FIXME: Use mapGenOption method only to calculate actual number of players for current template
  280. if(cpu > PlayerColor::PLAYER_LIMIT_I - humans)
  281. {
  282. cpu = PlayerColor::PLAYER_LIMIT_I - humans;
  283. ui->cpuCombo->setCurrentIndex(cpu + 1); //skip one element because first is random
  284. }
  285. mapGenOptions.setCompOnlyPlayerCount(cpu);
  286. int cpuTeams = mapGenOptions.getCompOnlyTeamCount(); //comp only players - 1
  287. if(cpuTeams > cpu - 1)
  288. {
  289. cpuTeams = cpu > 0 ? cpu - 1 : CMapGenOptions::RANDOM_SIZE;
  290. ui->cpuTeamsCombo->setCurrentIndex(cpuTeams + 1); //skip one element because first is random
  291. }
  292. updateTemplateList();
  293. }
  294. void WindowNewMap::on_randomMapCheck_stateChanged(int arg1)
  295. {
  296. randomMap = ui->randomMapCheck->isChecked();
  297. ui->templateCombo->setEnabled(randomMap);
  298. updateTemplateList();
  299. }
  300. void WindowNewMap::on_templateCombo_activated(int index)
  301. {
  302. if(index == 0)
  303. {
  304. mapGenOptions.setMapTemplate(nullptr);
  305. return;
  306. }
  307. auto * templ = data_cast<const CRmgTemplate>(ui->templateCombo->currentData().toLongLong());
  308. mapGenOptions.setMapTemplate(templ);
  309. }
  310. void WindowNewMap::on_widthTxt_textChanged(const QString &arg1)
  311. {
  312. int sz = arg1.toInt();
  313. if(sz > 1)
  314. {
  315. mapGenOptions.setWidth(arg1.toInt());
  316. updateTemplateList();
  317. }
  318. }
  319. void WindowNewMap::on_heightTxt_textChanged(const QString &arg1)
  320. {
  321. int sz = arg1.toInt();
  322. if(sz > 1)
  323. {
  324. mapGenOptions.setHeight(arg1.toInt());
  325. updateTemplateList();
  326. }
  327. }
  328. void WindowNewMap::updateTemplateList()
  329. {
  330. ui->templateCombo->clear();
  331. ui->templateCombo->setCurrentIndex(-1);
  332. if(!randomMap)
  333. return;
  334. mapGenOptions.setMapTemplate(nullptr);
  335. auto templates = mapGenOptions.getPossibleTemplates();
  336. if(templates.empty())
  337. return;
  338. ui->templateCombo->addItem("[default]", 0);
  339. for(auto * templ : templates)
  340. {
  341. ui->templateCombo->addItem(QString::fromStdString(templ->getName()), data_cast(templ));
  342. }
  343. ui->templateCombo->setCurrentIndex(0);
  344. }
  345. void WindowNewMap::on_checkSeed_toggled(bool checked)
  346. {
  347. ui->lineSeed->setEnabled(checked);
  348. }
  349. void WindowNewMap::on_humanTeamsCombo_activated(int index)
  350. {
  351. int humans = mapGenOptions.getHumanOrCpuPlayerCount();
  352. int teams = ui->humanTeamsCombo->currentData().toInt();
  353. if(teams >= humans)
  354. {
  355. teams = humans > 0 ? humans - 1 : CMapGenOptions::RANDOM_SIZE;
  356. ui->humanTeamsCombo->setCurrentIndex(teams + 1); //skip one element because first is random
  357. }
  358. mapGenOptions.setTeamCount(teams);
  359. updateTemplateList();
  360. }
  361. void WindowNewMap::on_cpuTeamsCombo_activated(int index)
  362. {
  363. int cpu = mapGenOptions.getCompOnlyPlayerCount();
  364. int cpuTeams = ui->cpuTeamsCombo->currentData().toInt();
  365. if(cpuTeams >= cpu)
  366. {
  367. cpuTeams = cpu > 0 ? cpu - 1 : CMapGenOptions::RANDOM_SIZE;
  368. ui->cpuTeamsCombo->setCurrentIndex(cpuTeams + 1); //skip one element because first is random
  369. }
  370. mapGenOptions.setCompOnlyTeamCount(cpuTeams);
  371. updateTemplateList();
  372. }