mapview.cpp 11 KB

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