mapview.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. /*
  2. * mapview.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 "mapview.h"
  12. #include "mainwindow.h"
  13. #include <QGraphicsSceneMouseEvent>
  14. #include "mapcontroller.h"
  15. #include "../lib/mapObjectConstructors/AObjectTypeHandler.h"
  16. #include "../lib/mapObjectConstructors/CObjectClassesHandler.h"
  17. #include "../lib/mapping/CMap.h"
  18. #include "../lib/GameLibrary.h"
  19. MinimapView::MinimapView(QWidget * parent):
  20. QGraphicsView(parent)
  21. {
  22. // Disable scrollbars
  23. setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  24. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  25. }
  26. void MinimapView::dimensions()
  27. {
  28. fitInView(0, 0, controller->map()->width, controller->map()->height, Qt::KeepAspectRatio);
  29. }
  30. void MinimapView::setController(MapController * ctrl)
  31. {
  32. controller = ctrl;
  33. }
  34. void MinimapView::mouseMoveEvent(QMouseEvent *mouseEvent)
  35. {
  36. this->update();
  37. auto * sc = static_cast<MinimapScene*>(scene());
  38. if(!sc)
  39. return;
  40. auto pos = mapToScene(mouseEvent->pos());
  41. pos *= 32;
  42. cameraPositionChanged(pos);
  43. }
  44. void MinimapView::mousePressEvent(QMouseEvent* event)
  45. {
  46. mouseMoveEvent(event);
  47. }
  48. MapView::MapView(QWidget * parent):
  49. QGraphicsView(parent),
  50. selectionTool(MapView::SelectionTool::None)
  51. {
  52. }
  53. void MapView::cameraChanged(const QPointF & pos)
  54. {
  55. centerOn(pos);
  56. }
  57. void MapView::setController(MapController * ctrl)
  58. {
  59. controller = ctrl;
  60. }
  61. void MapView::mouseMoveEvent(QMouseEvent *mouseEvent)
  62. {
  63. this->update();
  64. auto * sc = static_cast<MapScene*>(scene());
  65. if(!sc || !controller->map())
  66. return;
  67. auto pos = mapToScene(mouseEvent->pos()); //TODO: do we need to check size?
  68. int3 tile(pos.x() / 32, pos.y() / 32, sc->level);
  69. //if scene will be scrolled without mouse movement, selection, object moving and rubber band will not be updated
  70. //to change this behavior, all this logic should be placed in viewportEvent
  71. if(rubberBand)
  72. rubberBand->setGeometry(QRect(mapFromScene(mouseStart), mouseEvent->pos()).normalized());
  73. if(tile == tilePrev) //do not redraw
  74. return;
  75. currentCoordinates(tile.x, tile.y);
  76. switch(selectionTool)
  77. {
  78. case MapView::SelectionTool::Brush:
  79. if(mouseEvent->buttons() & Qt::RightButton)
  80. sc->selectionTerrainView.erase(tile);
  81. else if(mouseEvent->buttons() == Qt::LeftButton)
  82. sc->selectionTerrainView.select(tile);
  83. sc->selectionTerrainView.draw();
  84. break;
  85. case MapView::SelectionTool::Brush2:
  86. {
  87. std::array<int3, 4> extra{ int3{0, 0, 0}, int3{1, 0, 0}, int3{0, 1, 0}, int3{1, 1, 0} };
  88. for(auto & e : extra)
  89. {
  90. if(mouseEvent->buttons() & Qt::RightButton)
  91. sc->selectionTerrainView.erase(tile + e);
  92. else if(mouseEvent->buttons() == Qt::LeftButton)
  93. sc->selectionTerrainView.select(tile + e);
  94. }
  95. }
  96. sc->selectionTerrainView.draw();
  97. break;
  98. case MapView::SelectionTool::Brush4:
  99. {
  100. std::array<int3, 16> extra{
  101. int3{-1, -1, 0}, int3{0, -1, 0}, int3{1, -1, 0}, int3{2, -1, 0},
  102. int3{-1, 0, 0}, int3{0, 0, 0}, int3{1, 0, 0}, int3{2, 0, 0},
  103. int3{-1, 1, 0}, int3{0, 1, 0}, int3{1, 1, 0}, int3{2, 1, 0},
  104. int3{-1, 2, 0}, int3{0, 2, 0}, int3{1, 2, 0}, int3{2, 2, 0}
  105. };
  106. for(auto & e : extra)
  107. {
  108. if(mouseEvent->buttons() & Qt::RightButton)
  109. sc->selectionTerrainView.erase(tile + e);
  110. else if(mouseEvent->buttons() == Qt::LeftButton)
  111. sc->selectionTerrainView.select(tile + e);
  112. }
  113. }
  114. sc->selectionTerrainView.draw();
  115. break;
  116. case MapView::SelectionTool::Area:
  117. if(mouseEvent->buttons() & Qt::RightButton || !(mouseEvent->buttons() & Qt::LeftButton))
  118. break;
  119. sc->selectionTerrainView.clear();
  120. for(int j = std::min(tile.y, tileStart.y); j < std::max(tile.y, tileStart.y); ++j)
  121. {
  122. for(int i = std::min(tile.x, tileStart.x); i < std::max(tile.x, tileStart.x); ++i)
  123. {
  124. sc->selectionTerrainView.select(int3(i, j, sc->level));
  125. }
  126. }
  127. sc->selectionTerrainView.draw();
  128. break;
  129. case MapView::SelectionTool::Line:
  130. {
  131. assert(tile.z == tileStart.z);
  132. const auto diff = tile - tileStart;
  133. if(diff == int3{})
  134. break;
  135. const int edge = std::max(abs(diff.x), abs(diff.y));
  136. int distMin = std::numeric_limits<int>::max();
  137. int3 dir;
  138. for(auto & d : int3::getDirs())
  139. {
  140. if(tile.dist2d(d * edge + tileStart) < distMin)
  141. {
  142. distMin = tile.dist2d(d * edge + tileStart);
  143. dir = d;
  144. }
  145. }
  146. assert(dir != int3{});
  147. if(mouseEvent->buttons() == Qt::LeftButton)
  148. {
  149. for(auto & ts : temporaryTiles)
  150. sc->selectionTerrainView.erase(ts);
  151. for(auto ts = tileStart; ts.dist2d(tileStart) < edge; ts += dir)
  152. {
  153. if(!controller->map()->isInTheMap(ts))
  154. break;
  155. if(!sc->selectionTerrainView.selection().count(ts))
  156. temporaryTiles.insert(ts);
  157. sc->selectionTerrainView.select(ts);
  158. }
  159. }
  160. if(mouseEvent->buttons() == Qt::RightButton)
  161. {
  162. for(auto & ts : temporaryTiles)
  163. sc->selectionTerrainView.select(ts);
  164. for(auto ts = tileStart; ts.dist2d(tileStart) < edge; ts += dir)
  165. {
  166. if(!controller->map()->isInTheMap(ts))
  167. break;
  168. if(sc->selectionTerrainView.selection().count(ts))
  169. temporaryTiles.insert(ts);
  170. sc->selectionTerrainView.erase(ts);
  171. }
  172. }
  173. sc->selectionTerrainView.draw();
  174. break;
  175. }
  176. case MapView::SelectionTool::Lasso:
  177. if(mouseEvent->buttons() == Qt::LeftButton)
  178. {
  179. for(auto i = tilePrev; i != tile;)
  180. {
  181. int length = std::numeric_limits<int>::max();
  182. int3 dir;
  183. for(auto & d : int3::getDirs())
  184. {
  185. if(tile.dist2dSQ(i + d) < length)
  186. {
  187. dir = d;
  188. length = tile.dist2dSQ(i + d);
  189. }
  190. }
  191. i += dir;
  192. sc->selectionTerrainView.select(i);
  193. }
  194. sc->selectionTerrainView.draw();
  195. }
  196. break;
  197. case MapView::SelectionTool::None:
  198. if(mouseEvent->buttons() & Qt::RightButton)
  199. break;
  200. auto sh = tile - tileStart;
  201. sc->selectionObjectsView.shift = QPoint(sh.x, sh.y);
  202. if(sh.x || sh.y)
  203. {
  204. if(!sc->selectionObjectsView.newObject && (mouseEvent->buttons() & Qt::LeftButton))
  205. {
  206. if(sc->selectionObjectsView.selectionMode == SelectionObjectsLayer::SELECTION)
  207. {
  208. sc->selectionObjectsView.clear();
  209. sc->selectionObjectsView.selectObjects(tileStart.x, tileStart.y, tile.x, tile.y);
  210. }
  211. }
  212. }
  213. sc->selectionObjectsView.draw();
  214. break;
  215. }
  216. tilePrev = tile;
  217. }
  218. void MapView::mousePressEvent(QMouseEvent *event)
  219. {
  220. this->update();
  221. auto * sc = static_cast<MapScene*>(scene());
  222. if(!sc || !controller->map())
  223. return;
  224. if(sc->objectPickerView.isVisible())
  225. return;
  226. mouseStart = mapToScene(event->pos());
  227. tileStart = tilePrev = int3(mouseStart.x() / 32, mouseStart.y() / 32, sc->level);
  228. if(sc->selectionTerrainView.selection().count(tileStart))
  229. pressedOnSelected = true;
  230. else
  231. pressedOnSelected = false;
  232. switch(selectionTool)
  233. {
  234. case MapView::SelectionTool::Brush:
  235. case MapView::SelectionTool::Line:
  236. sc->selectionObjectsView.clear();
  237. sc->selectionObjectsView.draw();
  238. if(event->button() == Qt::RightButton)
  239. sc->selectionTerrainView.erase(tileStart);
  240. else if(event->button() == Qt::LeftButton)
  241. sc->selectionTerrainView.select(tileStart);
  242. sc->selectionTerrainView.draw();
  243. break;
  244. case MapView::SelectionTool::Brush2:
  245. sc->selectionObjectsView.clear();
  246. sc->selectionObjectsView.draw();
  247. {
  248. std::array<int3, 4> extra{ int3{0, 0, 0}, int3{1, 0, 0}, int3{0, 1, 0}, int3{1, 1, 0} };
  249. for(auto & e : extra)
  250. {
  251. if(event->button() == Qt::RightButton)
  252. sc->selectionTerrainView.erase(tileStart + e);
  253. else if(event->button() == Qt::LeftButton)
  254. sc->selectionTerrainView.select(tileStart + e);
  255. }
  256. }
  257. sc->selectionTerrainView.draw();
  258. break;
  259. case MapView::SelectionTool::Brush4:
  260. sc->selectionObjectsView.clear();
  261. sc->selectionObjectsView.draw();
  262. {
  263. std::array<int3, 16> extra{
  264. int3{-1, -1, 0}, int3{0, -1, 0}, int3{1, -1, 0}, int3{2, -1, 0},
  265. int3{-1, 0, 0}, int3{0, 0, 0}, int3{1, 0, 0}, int3{2, 0, 0},
  266. int3{-1, 1, 0}, int3{0, 1, 0}, int3{1, 1, 0}, int3{2, 1, 0},
  267. int3{-1, 2, 0}, int3{0, 2, 0}, int3{1, 2, 0}, int3{2, 2, 0}
  268. };
  269. for(auto & e : extra)
  270. {
  271. if(event->button() == Qt::RightButton)
  272. sc->selectionTerrainView.erase(tileStart + e);
  273. else if(event->button() == Qt::LeftButton)
  274. sc->selectionTerrainView.select(tileStart + e);
  275. }
  276. }
  277. sc->selectionTerrainView.draw();
  278. break;
  279. case MapView::SelectionTool::Area:
  280. case MapView::SelectionTool::Lasso:
  281. if(event->button() == Qt::RightButton)
  282. break;
  283. sc->selectionTerrainView.clear();
  284. sc->selectionTerrainView.draw();
  285. sc->selectionObjectsView.clear();
  286. sc->selectionObjectsView.draw();
  287. break;
  288. case MapView::SelectionTool::Fill:
  289. {
  290. if(event->button() != Qt::RightButton && event->button() != Qt::LeftButton)
  291. break;
  292. std::vector<int3> queue;
  293. queue.push_back(tileStart);
  294. const std::array<int3, 4> dirs{ int3{1, 0, 0}, int3{-1, 0, 0}, int3{0, 1, 0}, int3{0, -1, 0} };
  295. while(!queue.empty())
  296. {
  297. auto tile = queue.back();
  298. queue.pop_back();
  299. if(event->button() == Qt::LeftButton)
  300. sc->selectionTerrainView.select(tile);
  301. else
  302. sc->selectionTerrainView.erase(tile);
  303. for(auto & d : dirs)
  304. {
  305. auto tilen = tile + d;
  306. if(!controller->map()->isInTheMap(tilen))
  307. continue;
  308. if(event->button() == Qt::LeftButton)
  309. {
  310. if(controller->map()->getTile(tile).roadType
  311. && controller->map()->getTile(tile).roadType != controller->map()->getTile(tilen).roadType)
  312. continue;
  313. else if(controller->map()->getTile(tile).riverType
  314. && controller->map()->getTile(tile).riverType != controller->map()->getTile(tilen).riverType)
  315. continue;
  316. else if(controller->map()->getTile(tile).terrainType != controller->map()->getTile(tilen).terrainType)
  317. continue;
  318. }
  319. if(event->button() == Qt::LeftButton && sc->selectionTerrainView.selection().count(tilen))
  320. continue;
  321. if(event->button() == Qt::RightButton && !sc->selectionTerrainView.selection().count(tilen))
  322. continue;
  323. queue.push_back(tilen);
  324. }
  325. }
  326. sc->selectionTerrainView.draw();
  327. sc->selectionObjectsView.clear();
  328. sc->selectionObjectsView.draw();
  329. break;
  330. }
  331. case MapView::SelectionTool::None:
  332. sc->selectionTerrainView.clear();
  333. sc->selectionTerrainView.draw();
  334. if(sc->selectionObjectsView.newObject && sc->selectionObjectsView.isSelected(sc->selectionObjectsView.newObject.get()))
  335. {
  336. if(event->button() == Qt::RightButton)
  337. controller->discardObject(sc->level);
  338. }
  339. else
  340. {
  341. if(event->button() == Qt::LeftButton)
  342. {
  343. //when paste, new object could be beyond initial object so we need to test two objects in order to select new one
  344. //if object is pasted at place where is multiple objects then proper selection is not guaranteed
  345. auto * firstSelectedObject = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y);
  346. auto * secondSelectedObject = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y, firstSelectedObject);
  347. if(firstSelectedObject)
  348. {
  349. if(sc->selectionObjectsView.isSelected(firstSelectedObject))
  350. {
  351. if(qApp->keyboardModifiers() & Qt::ControlModifier)
  352. {
  353. sc->selectionObjectsView.deselectObject(firstSelectedObject);
  354. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::SELECTION;
  355. }
  356. else
  357. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT;
  358. }
  359. else
  360. {
  361. if(!secondSelectedObject || !sc->selectionObjectsView.isSelected(secondSelectedObject))
  362. {
  363. if(!(qApp->keyboardModifiers() & Qt::ControlModifier))
  364. sc->selectionObjectsView.clear();
  365. sc->selectionObjectsView.selectObject(firstSelectedObject);
  366. }
  367. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT;
  368. }
  369. }
  370. else
  371. {
  372. sc->selectionObjectsView.clear();
  373. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::SELECTION;
  374. if(!rubberBand)
  375. rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
  376. rubberBand->setGeometry(QRect(mapFromScene(mouseStart), QSize()));
  377. rubberBand->show();
  378. }
  379. }
  380. sc->selectionObjectsView.shift = QPoint(0, 0);
  381. sc->selectionObjectsView.draw();
  382. }
  383. break;
  384. }
  385. //main->setStatusMessage(QString("x: %1 y: %2").arg(QString::number(event->pos().x()), QString::number(event->pos().y())));
  386. }
  387. void MapView::mouseReleaseEvent(QMouseEvent *event)
  388. {
  389. this->update();
  390. auto * sc = static_cast<MapScene*>(scene());
  391. if(!sc || !controller->map())
  392. return;
  393. if(rubberBand)
  394. rubberBand->hide();
  395. if(sc->objectPickerView.isVisible())
  396. {
  397. if(event->button() == Qt::RightButton)
  398. sc->objectPickerView.discard();
  399. if(event->button() == Qt::LeftButton)
  400. {
  401. mouseStart = mapToScene(event->pos());
  402. tileStart = tilePrev = int3(mouseStart.x() / 32, mouseStart.y() / 32, sc->level);
  403. if(auto * pickedObject = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y))
  404. sc->objectPickerView.select(pickedObject);
  405. }
  406. return;
  407. }
  408. switch(selectionTool)
  409. {
  410. case MapView::SelectionTool::Lasso: {
  411. if(event->button() == Qt::RightButton)
  412. break;
  413. //connect with initial tile
  414. for(auto i = tilePrev; i != tileStart;)
  415. {
  416. int length = std::numeric_limits<int>::max();
  417. int3 dir;
  418. for(auto & d : int3::getDirs())
  419. {
  420. if(tileStart.dist2dSQ(i + d) < length)
  421. {
  422. dir = d;
  423. length = tileStart.dist2dSQ(i + d);
  424. }
  425. }
  426. i += dir;
  427. sc->selectionTerrainView.select(i);
  428. }
  429. //key: y position of tile
  430. //value.first: x position of left tile
  431. //value.second: x postiion of right tile
  432. std::map<int, std::pair<int, int>> selectionRangeMapX;
  433. std::map<int, std::pair<int, int>> selectionRangeMapY;
  434. for(auto & t : sc->selectionTerrainView.selection())
  435. {
  436. auto pairIter = selectionRangeMapX.find(t.y);
  437. if(pairIter == selectionRangeMapX.end())
  438. selectionRangeMapX[t.y] = std::make_pair(t.x, t.x);
  439. else
  440. {
  441. pairIter->second.first = std::min(pairIter->second.first, t.x);
  442. pairIter->second.second = std::max(pairIter->second.second, t.x);
  443. }
  444. pairIter = selectionRangeMapY.find(t.x);
  445. if(pairIter == selectionRangeMapY.end())
  446. selectionRangeMapY[t.x] = std::make_pair(t.y, t.y);
  447. else
  448. {
  449. pairIter->second.first = std::min(pairIter->second.first, t.y);
  450. pairIter->second.second = std::max(pairIter->second.second, t.y);
  451. }
  452. }
  453. std::set<int3> selectionByX;
  454. std::set<int3> selectionByY;
  455. std::vector<int3> finalSelection;
  456. for(auto & selectionRange : selectionRangeMapX)
  457. {
  458. for(int i = selectionRange.second.first; i < selectionRange.second.second; ++i)
  459. selectionByX.insert(int3(i, selectionRange.first, sc->level));
  460. }
  461. for(auto & selectionRange : selectionRangeMapY)
  462. {
  463. for(int i = selectionRange.second.first; i < selectionRange.second.second; ++i)
  464. selectionByY.insert(int3(selectionRange.first, i, sc->level));
  465. }
  466. std::set_intersection(selectionByX.begin(), selectionByX.end(), selectionByY.begin(), selectionByY.end(), std::back_inserter(finalSelection));
  467. for(auto & lassoTile : finalSelection)
  468. sc->selectionTerrainView.select(lassoTile);
  469. sc->selectionTerrainView.draw();
  470. break;
  471. }
  472. case MapView::SelectionTool::Line:
  473. temporaryTiles.clear();
  474. break;
  475. case MapView::SelectionTool::None:
  476. if(event->button() == Qt::RightButton)
  477. break;
  478. //switch position
  479. bool tab = false;
  480. if(sc->selectionObjectsView.selectionMode == SelectionObjectsLayer::MOVEMENT)
  481. {
  482. tab = sc->selectionObjectsView.shift.isNull();
  483. controller->commitObjectShift(sc->level);
  484. }
  485. else
  486. {
  487. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::NOTHING;
  488. sc->selectionObjectsView.shift = QPoint(0, 0);
  489. sc->selectionObjectsView.draw();
  490. tab = true;
  491. }
  492. auto selection = sc->selectionObjectsView.getSelection();
  493. if(selection.size() == 1)
  494. {
  495. openObjectProperties(*selection.begin(), tab);
  496. }
  497. break;
  498. }
  499. }
  500. void MapView::dragEnterEvent(QDragEnterEvent * event)
  501. {
  502. if(!controller || !controller->map())
  503. return;
  504. auto * sc = static_cast<MapScene*>(scene());
  505. if(!sc)
  506. return;
  507. if(event->mimeData()->hasImage())
  508. {
  509. logGlobal->info("Drag'n'drop: dispatching object");
  510. QVariant vdata = event->mimeData()->imageData();
  511. auto data = vdata.toJsonObject();
  512. if(!data.empty())
  513. {
  514. auto preview = data["preview"];
  515. if(preview != QJsonValue::Undefined)
  516. {
  517. auto objId = data["id"].toInt();
  518. auto objSubId = data["subid"].toInt();
  519. auto templateId = data["template"].toInt();
  520. auto factory = LIBRARY->objtypeh->getHandlerFor(objId, objSubId);
  521. auto templ = factory->getTemplates()[templateId];
  522. controller->discardObject(sc->level);
  523. controller->createObject(sc->level, factory->create(nullptr, templ));
  524. }
  525. }
  526. event->acceptProposedAction();
  527. }
  528. }
  529. void MapView::dropEvent(QDropEvent * event)
  530. {
  531. if(!controller || !controller->map())
  532. return;
  533. auto * sc = static_cast<MapScene*>(scene());
  534. if(!sc)
  535. return;
  536. if(sc->selectionObjectsView.newObject)
  537. {
  538. QString errorMsg;
  539. if(controller->canPlaceObject(sc->level, sc->selectionObjectsView.newObject.get(), errorMsg))
  540. {
  541. auto obj = sc->selectionObjectsView.newObject;
  542. controller->commitObjectCreate(sc->level);
  543. openObjectProperties(obj.get(), false);
  544. }
  545. else
  546. {
  547. controller->discardObject(sc->level);
  548. QMessageBox::information(this, tr("Can't place object"), errorMsg);
  549. }
  550. }
  551. event->acceptProposedAction();
  552. }
  553. void MapView::dragMoveEvent(QDragMoveEvent * event)
  554. {
  555. auto * sc = static_cast<MapScene*>(scene());
  556. if(!sc)
  557. return;
  558. auto rect = event->answerRect();
  559. auto pos = mapToScene(rect.bottomRight()); //TODO: do we need to check size?
  560. int3 tile(pos.x() / 32 + 1, pos.y() / 32 + 1, sc->level);
  561. if(sc->selectionObjectsView.newObject)
  562. {
  563. sc->selectionObjectsView.shift = QPoint(tile.x, tile.y);
  564. sc->selectionObjectsView.selectObject(sc->selectionObjectsView.newObject.get());
  565. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT;
  566. sc->selectionObjectsView.draw();
  567. }
  568. event->acceptProposedAction();
  569. }
  570. void MapView::dragLeaveEvent(QDragLeaveEvent * event)
  571. {
  572. if(!controller || !controller->map())
  573. return;
  574. auto * sc = static_cast<MapScene*>(scene());
  575. if(!sc)
  576. return;
  577. controller->discardObject(sc->level);
  578. }
  579. bool MapView::viewportEvent(QEvent *event)
  580. {
  581. if(auto * sc = static_cast<MapScene*>(scene()))
  582. {
  583. auto rect = mapToScene(viewport()->geometry()).boundingRect();
  584. controller->miniScene(sc->level)->viewport.setViewport(rect.x() / 32, rect.y() / 32, rect.width() / 32, rect.height() / 32);
  585. }
  586. return QGraphicsView::viewportEvent(event);
  587. }
  588. MapSceneBase::MapSceneBase(int lvl):
  589. QGraphicsScene(nullptr),
  590. level(lvl)
  591. {
  592. }
  593. void MapSceneBase::initialize(MapController & controller)
  594. {
  595. for(auto * layer : getAbstractLayers())
  596. layer->initialize(controller);
  597. }
  598. void MapSceneBase::updateViews()
  599. {
  600. for(auto * layer : getAbstractLayers())
  601. layer->update();
  602. }
  603. MapScene::MapScene(int lvl):
  604. MapSceneBase(lvl),
  605. gridView(this),
  606. passabilityView(this),
  607. selectionTerrainView(this),
  608. terrainView(this),
  609. objectsView(this),
  610. selectionObjectsView(this),
  611. objectPickerView(this),
  612. isTerrainSelected(false),
  613. isObjectSelected(false)
  614. {
  615. connect(&selectionTerrainView, &SelectionTerrainLayer::selectionMade, this, &MapScene::terrainSelected);
  616. connect(&selectionObjectsView, &SelectionObjectsLayer::selectionMade, this, &MapScene::objectSelected);
  617. }
  618. std::list<AbstractLayer *> MapScene::getAbstractLayers()
  619. {
  620. //sequence is important because it defines rendering order
  621. return {
  622. &terrainView,
  623. &objectsView,
  624. &gridView,
  625. &passabilityView,
  626. &objectPickerView,
  627. &selectionTerrainView,
  628. &selectionObjectsView
  629. };
  630. }
  631. void MapScene::updateViews()
  632. {
  633. MapSceneBase::updateViews();
  634. terrainView.show(true);
  635. objectsView.show(true);
  636. selectionTerrainView.show(true);
  637. selectionObjectsView.show(true);
  638. objectPickerView.show(true);
  639. }
  640. void MapScene::terrainSelected(bool anythingSelected)
  641. {
  642. isTerrainSelected = anythingSelected;
  643. selected(isTerrainSelected || isObjectSelected);
  644. }
  645. void MapScene::objectSelected(bool anythingSelected)
  646. {
  647. isObjectSelected = anythingSelected;
  648. selected(isTerrainSelected || isObjectSelected);
  649. }
  650. MinimapScene::MinimapScene(int lvl):
  651. MapSceneBase(lvl),
  652. minimapView(this),
  653. viewport(this)
  654. {
  655. }
  656. std::list<AbstractLayer *> MinimapScene::getAbstractLayers()
  657. {
  658. //sequence is important because it defines rendering order
  659. return {
  660. &minimapView,
  661. &viewport
  662. };
  663. }
  664. void MinimapScene::updateViews()
  665. {
  666. MapSceneBase::updateViews();
  667. minimapView.show(true);
  668. viewport.show(true);
  669. }