mapview.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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. MinimapView::MinimapView(QWidget * parent):
  16. QGraphicsView(parent)
  17. {
  18. // Disable scrollbars
  19. setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  20. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  21. }
  22. void MinimapView::dimensions()
  23. {
  24. fitInView(0, 0, controller->map()->width, controller->map()->height, Qt::KeepAspectRatio);
  25. }
  26. void MinimapView::setController(MapController * ctrl)
  27. {
  28. controller = ctrl;
  29. }
  30. void MinimapView::mouseMoveEvent(QMouseEvent *mouseEvent)
  31. {
  32. this->update();
  33. auto * sc = static_cast<MinimapScene*>(scene());
  34. if(!sc)
  35. return;
  36. int w = sc->viewport.viewportWidth();
  37. int h = sc->viewport.viewportHeight();
  38. auto pos = mapToScene(mouseEvent->pos());
  39. pos.setX(pos.x() - w / 2);
  40. pos.setY(pos.y() - h / 2);
  41. QPointF point = pos * 32;
  42. emit cameraPositionChanged(point);
  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. //ui->mapView->translate(pos.x(), pos.y());
  56. horizontalScrollBar()->setValue(pos.x());
  57. verticalScrollBar()->setValue(pos.y());
  58. }
  59. void MapView::setController(MapController * ctrl)
  60. {
  61. controller = ctrl;
  62. }
  63. void MapView::mouseMoveEvent(QMouseEvent *mouseEvent)
  64. {
  65. this->update();
  66. auto * sc = static_cast<MapScene*>(scene());
  67. if(!sc || !controller->map())
  68. return;
  69. auto pos = mapToScene(mouseEvent->pos()); //TODO: do we need to check size?
  70. int3 tile(pos.x() / 32, pos.y() / 32, sc->level);
  71. if(tile == tilePrev) //do not redraw
  72. return;
  73. tilePrev = tile;
  74. //TODO: cast parent->parent to MainWindow in order to show coordinates or another way to do it?
  75. //main->setStatusMessage(QString("x: %1 y: %2").arg(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::None:
  130. if(mouseEvent->buttons() & Qt::RightButton)
  131. break;
  132. auto sh = tile - tileStart;
  133. sc->selectionObjectsView.shift = QPoint(sh.x, sh.y);
  134. if(sh.x || sh.y)
  135. {
  136. if(sc->selectionObjectsView.newObject)
  137. {
  138. sc->selectionObjectsView.shift = QPoint(tile.x, tile.y);
  139. sc->selectionObjectsView.selectObject(sc->selectionObjectsView.newObject);
  140. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT;
  141. }
  142. else if(mouseEvent->buttons() & Qt::LeftButton)
  143. {
  144. if(sc->selectionObjectsView.selectionMode == SelectionObjectsLayer::SELECTION)
  145. {
  146. sc->selectionObjectsView.clear();
  147. sc->selectionObjectsView.selectObjects(tileStart.x, tileStart.y, tile.x, tile.y);
  148. }
  149. }
  150. }
  151. sc->selectionObjectsView.draw();
  152. break;
  153. }
  154. }
  155. void MapView::mousePressEvent(QMouseEvent *event)
  156. {
  157. this->update();
  158. auto * sc = static_cast<MapScene*>(scene());
  159. if(!sc || !controller->map())
  160. return;
  161. mouseStart = mapToScene(event->pos());
  162. tileStart = tilePrev = int3(mouseStart.x() / 32, mouseStart.y() / 32, sc->level);
  163. if(sc->selectionTerrainView.selection().count(tileStart))
  164. pressedOnSelected = true;
  165. else
  166. pressedOnSelected = false;
  167. switch(selectionTool)
  168. {
  169. case MapView::SelectionTool::Brush:
  170. sc->selectionObjectsView.clear();
  171. sc->selectionObjectsView.draw();
  172. if(event->button() == Qt::RightButton)
  173. sc->selectionTerrainView.erase(tileStart);
  174. else if(event->button() == Qt::LeftButton)
  175. sc->selectionTerrainView.select(tileStart);
  176. sc->selectionTerrainView.draw();
  177. break;
  178. case MapView::SelectionTool::Brush2:
  179. sc->selectionObjectsView.clear();
  180. sc->selectionObjectsView.draw();
  181. {
  182. std::array<int3, 4> extra{ int3{0, 0, 0}, int3{1, 0, 0}, int3{0, 1, 0}, int3{1, 1, 0} };
  183. for(auto & e : extra)
  184. {
  185. if(event->button() == Qt::RightButton)
  186. sc->selectionTerrainView.erase(tileStart + e);
  187. else if(event->button() == Qt::LeftButton)
  188. sc->selectionTerrainView.select(tileStart + e);
  189. }
  190. }
  191. sc->selectionTerrainView.draw();
  192. break;
  193. case MapView::SelectionTool::Brush4:
  194. sc->selectionObjectsView.clear();
  195. sc->selectionObjectsView.draw();
  196. {
  197. std::array<int3, 16> extra{
  198. int3{-1, -1, 0}, int3{0, -1, 0}, int3{1, -1, 0}, int3{2, -1, 0},
  199. int3{-1, 0, 0}, int3{0, 0, 0}, int3{1, 0, 0}, int3{2, 0, 0},
  200. int3{-1, 1, 0}, int3{0, 1, 0}, int3{1, 1, 0}, int3{2, 1, 0},
  201. int3{-1, 2, 0}, int3{0, 2, 0}, int3{1, 2, 0}, int3{2, 2, 0}
  202. };
  203. for(auto & e : extra)
  204. {
  205. if(event->button() == Qt::RightButton)
  206. sc->selectionTerrainView.erase(tileStart + e);
  207. else if(event->button() == Qt::LeftButton)
  208. sc->selectionTerrainView.select(tileStart + e);
  209. }
  210. }
  211. sc->selectionTerrainView.draw();
  212. break;
  213. case MapView::SelectionTool::Area:
  214. if(event->button() == Qt::RightButton)
  215. break;
  216. sc->selectionTerrainView.clear();
  217. sc->selectionTerrainView.draw();
  218. sc->selectionObjectsView.clear();
  219. sc->selectionObjectsView.draw();
  220. break;
  221. case MapView::SelectionTool::None:
  222. sc->selectionTerrainView.clear();
  223. sc->selectionTerrainView.draw();
  224. if(sc->selectionObjectsView.newObject && sc->selectionObjectsView.isSelected(sc->selectionObjectsView.newObject))
  225. {
  226. if(event->button() == Qt::RightButton)
  227. controller->discardObject(sc->level);
  228. }
  229. else
  230. {
  231. if(event->button() == Qt::LeftButton)
  232. {
  233. auto * obj = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y);
  234. if(obj)
  235. {
  236. if(sc->selectionObjectsView.isSelected(obj))
  237. {
  238. if(qApp->keyboardModifiers() & Qt::ControlModifier)
  239. {
  240. sc->selectionObjectsView.deselectObject(obj);
  241. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::SELECTION;
  242. }
  243. else
  244. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT;
  245. }
  246. else
  247. {
  248. if(!(qApp->keyboardModifiers() & Qt::ControlModifier))
  249. sc->selectionObjectsView.clear();
  250. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT;
  251. sc->selectionObjectsView.selectObject(obj);
  252. }
  253. }
  254. else
  255. {
  256. sc->selectionObjectsView.clear();
  257. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::SELECTION;
  258. }
  259. }
  260. sc->selectionObjectsView.shift = QPoint(0, 0);
  261. sc->selectionObjectsView.draw();
  262. }
  263. break;
  264. }
  265. //main->setStatusMessage(QString("x: %1 y: %2").arg(QString::number(event->pos().x()), QString::number(event->pos().y())));
  266. }
  267. void MapView::mouseReleaseEvent(QMouseEvent *event)
  268. {
  269. this->update();
  270. auto * sc = static_cast<MapScene*>(scene());
  271. if(!sc || !controller->map())
  272. return;
  273. switch(selectionTool)
  274. {
  275. case MapView::SelectionTool::None:
  276. if(event->button() == Qt::RightButton)
  277. break;
  278. //switch position
  279. bool tab = false;
  280. if(sc->selectionObjectsView.selectionMode == SelectionObjectsLayer::MOVEMENT)
  281. {
  282. if(sc->selectionObjectsView.newObject)
  283. {
  284. QString errorMsg;
  285. if(controller->canPlaceObject(sc->level, sc->selectionObjectsView.newObject, errorMsg))
  286. controller->commitObjectCreate(sc->level);
  287. else
  288. {
  289. QMessageBox::information(this, "Can't place object", errorMsg);
  290. break;
  291. }
  292. }
  293. else
  294. controller->commitObjectShift(sc->level);
  295. }
  296. else
  297. {
  298. sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::NOTHING;
  299. sc->selectionObjectsView.shift = QPoint(0, 0);
  300. sc->selectionObjectsView.draw();
  301. tab = true;
  302. //check if we have only one object
  303. }
  304. auto selection = sc->selectionObjectsView.getSelection();
  305. if(selection.size() == 1)
  306. {
  307. emit openObjectProperties(*selection.begin(), tab);
  308. }
  309. break;
  310. }
  311. }
  312. bool MapView::viewportEvent(QEvent *event)
  313. {
  314. if(auto * sc = static_cast<MapScene*>(scene()))
  315. {
  316. //auto rect = sceneRect();
  317. auto rect = mapToScene(viewport()->geometry()).boundingRect();
  318. controller->miniScene(sc->level)->viewport.setViewport(rect.x() / 32, rect.y() / 32, rect.width() / 32, rect.height() / 32);
  319. }
  320. return QGraphicsView::viewportEvent(event);
  321. }
  322. MapSceneBase::MapSceneBase(int lvl):
  323. QGraphicsScene(nullptr),
  324. level(lvl)
  325. {
  326. }
  327. void MapSceneBase::initialize(MapController & controller)
  328. {
  329. for(auto * layer : getAbstractLayers())
  330. layer->initialize(controller);
  331. }
  332. void MapSceneBase::updateViews()
  333. {
  334. for(auto * layer : getAbstractLayers())
  335. layer->update();
  336. }
  337. MapScene::MapScene(int lvl):
  338. MapSceneBase(lvl),
  339. gridView(this),
  340. passabilityView(this),
  341. selectionTerrainView(this),
  342. terrainView(this),
  343. objectsView(this),
  344. selectionObjectsView(this),
  345. isTerrainSelected(false),
  346. isObjectSelected(false)
  347. {
  348. connect(&selectionTerrainView, &SelectionTerrainLayer::selectionMade, this, &MapScene::terrainSelected);
  349. connect(&selectionObjectsView, &SelectionObjectsLayer::selectionMade, this, &MapScene::objectSelected);
  350. }
  351. std::list<AbstractLayer *> MapScene::getAbstractLayers()
  352. {
  353. //sequence is important because it defines rendering order
  354. return {
  355. &terrainView,
  356. &objectsView,
  357. &gridView,
  358. &passabilityView,
  359. &selectionTerrainView,
  360. &selectionObjectsView
  361. };
  362. }
  363. void MapScene::updateViews()
  364. {
  365. MapSceneBase::updateViews();
  366. terrainView.show(true);
  367. objectsView.show(true);
  368. selectionTerrainView.show(true);
  369. selectionObjectsView.show(true);
  370. }
  371. void MapScene::terrainSelected(bool anythingSelected)
  372. {
  373. isTerrainSelected = anythingSelected;
  374. emit selected(isTerrainSelected || isObjectSelected);
  375. }
  376. void MapScene::objectSelected(bool anythingSelected)
  377. {
  378. isObjectSelected = anythingSelected;
  379. emit selected(isTerrainSelected || isObjectSelected);
  380. }
  381. MinimapScene::MinimapScene(int lvl):
  382. MapSceneBase(lvl),
  383. minimapView(this),
  384. viewport(this)
  385. {
  386. }
  387. std::list<AbstractLayer *> MinimapScene::getAbstractLayers()
  388. {
  389. //sequence is important because it defines rendering order
  390. return {
  391. &minimapView,
  392. &viewport
  393. };
  394. }
  395. void MinimapScene::updateViews()
  396. {
  397. MapSceneBase::updateViews();
  398. minimapView.show(true);
  399. viewport.show(true);
  400. }