QuestGraph.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. #include "QuestGraph.h"
  2. #include <Bild.h>
  3. #include <HashMap.h>
  4. #include <Scroll.h>
  5. #include <XML.h>
  6. #include "Load.h"
  7. #include "World.h"
  8. QuestGraphElement::QuestGraphElement() {}
  9. bool QuestGraphElement::isApplicableFor(Framework::XML::Element& element)
  10. {
  11. return element.getName().istGleich("questGraph");
  12. }
  13. Framework::Zeichnung* QuestGraphElement::parseElement(
  14. Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
  15. {
  16. QuestGraph* graph = new QuestGraph();
  17. graph->collectionName = element.getAttributeValue("collectionName");
  18. graph->id = element.getAttributeValue("id");
  19. auto children = element.selectChildsByName("questGraphItem");
  20. Framework::HashMap<Framework::Text, QuestGraphItem*> map(
  21. 100, [](Framework::Text str) { return str.hashCode(); });
  22. // parse graph elements
  23. for (Framework::XML::Element* itemElement : children)
  24. {
  25. Framework::Zeichnung* parsed
  26. = generalFactory.parseElement(*itemElement, generalFactory);
  27. QuestGraphItem* item = dynamic_cast<QuestGraphItem*>(parsed);
  28. if (!item)
  29. {
  30. if (parsed)
  31. {
  32. parsed->release();
  33. }
  34. }
  35. else
  36. {
  37. map.put(item->getId(), item);
  38. }
  39. generalFactory.layout(*itemElement,
  40. *parsed,
  41. graph->getBreite(),
  42. graph->getHeight(),
  43. generalFactory);
  44. }
  45. // set connection references
  46. for (MapEntry<Framework::Text, QuestGraphItem*> entry : map)
  47. {
  48. QuestGraphItem* item = entry.getValue();
  49. Framework::Text requirements = item->getRequirements();
  50. while (requirements.getLength() > 0)
  51. {
  52. Framework::Text* requirement;
  53. if (requirements.hat(","))
  54. {
  55. requirement = requirements.getTeilText(
  56. 0, requirements.positionVon(","));
  57. requirements.remove(0, requirements.positionVon(",") + 1);
  58. }
  59. else
  60. {
  61. requirement = new Text(requirements);
  62. requirements = "";
  63. }
  64. QuestGraphItem* requiredItem = map.get(*requirement);
  65. if (requiredItem)
  66. {
  67. requiredItem->addNextLayerRef(item);
  68. item->addPreviousLayerRef(requiredItem);
  69. }
  70. requirement->release();
  71. }
  72. }
  73. // calculate layer index based on connections
  74. bool changed = 1;
  75. while (changed)
  76. {
  77. changed = 0;
  78. for (MapEntry<Framework::Text, QuestGraphItem*> entry : map)
  79. {
  80. changed |= entry.getValue()->calculateLaxerIndex();
  81. }
  82. }
  83. // add items to graph
  84. for (MapEntry<Framework::Text, QuestGraphItem*> entry : map)
  85. {
  86. if (entry.getValue()->getLayerIndex() < 0)
  87. {
  88. entry.getValue()->setVirtual(
  89. 1); // hide nodes witch layers could not be calculated because
  90. // of invalid circular connections
  91. }
  92. graph->addItem(entry.getValue());
  93. }
  94. graph->addVirtualConnectionNodes();
  95. graph->sortItems();
  96. return graph;
  97. }
  98. bool QuestGraphElement::updateElement(Framework::XML::Element& element,
  99. Framework::Zeichnung& z,
  100. Framework::UIMLContainer& generalFactory)
  101. {
  102. return false;
  103. }
  104. void QuestGraphElement::layout(Framework::XML::Element& element,
  105. Framework::Zeichnung& z,
  106. int pWidth,
  107. int pHeight,
  108. Framework::UIMLContainer& generalLayouter)
  109. {
  110. UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
  111. QuestGraph *graph = dynamic_cast<QuestGraph*>(&z);
  112. graph->fixItemPositions();
  113. }
  114. QuestGraphItemElement::QuestGraphItemElement() {}
  115. bool QuestGraphItemElement::isApplicableFor(Framework::XML::Element& element)
  116. {
  117. return element.getName().istGleich("questGraphItem");
  118. }
  119. Framework::Zeichnung* QuestGraphItemElement::parseElement(
  120. Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
  121. {
  122. QuestGraphItem* item = new QuestGraphItem();
  123. Framework::Text name = element.getAttributeValue("name");
  124. Framework::Text description = element.getAttributeValue("description");
  125. item->setToolTipText(name + "\n" + description,
  126. generalFactory.getFactory().initParam.bildschirm,
  127. generalFactory.getFactory().initParam.schrift);
  128. item->setHintergrundBildZ(loadImage(element.getAttributeValue("image")));
  129. item->finished = (int)element.getAttributeValue("finished") != 0;
  130. if (item->finished)
  131. {
  132. item->setRahmenFarbe(0xFF55FF00);
  133. }
  134. item->mainQuest = (int)element.getAttributeValue("mainQuest") != 0;
  135. if (item->mainQuest)
  136. {
  137. item->setRahmenBreite(3);
  138. }
  139. item->id = element.getAttributeValue("id");
  140. item->requirements = element.getAttributeValue("requiredQuests");
  141. item->virtualNode = 0;
  142. return item;
  143. }
  144. bool QuestGraphItemElement::updateElement(Framework::XML::Element& element,
  145. Framework::Zeichnung& z,
  146. Framework::UIMLContainer& generalFactory)
  147. {
  148. return false;
  149. }
  150. void QuestGraphItemElement::layout(Framework::XML::Element& element,
  151. Framework::Zeichnung& z,
  152. int pWidth,
  153. int pHeight,
  154. Framework::UIMLContainer& generalLayouter)
  155. {
  156. UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
  157. }
  158. QuestGraphItem::QuestGraphItem()
  159. : ZeichnungHintergrund(),
  160. layerIndex(-1),
  161. nodeIndex(-1)
  162. {
  163. addStyle(ZeichnungHintergrund::Style::Sichtbar
  164. | ZeichnungHintergrund::Style::Rahmen
  165. | ZeichnungHintergrund::Style::Erlaubt
  166. | ZeichnungHintergrund::Style::HBild
  167. | ZeichnungHintergrund::Style::HBildScale
  168. | ZeichnungHintergrund::Style::HAlpha
  169. | ZeichnungHintergrund::Style::Hintergrund);
  170. setRahmenFarbe(0xFF52525E);
  171. setRahmenBreite(1);
  172. setMausEreignis(Framework::_ret1ME);
  173. }
  174. void QuestGraphItem::render(Framework::Bild& rObj)
  175. {
  176. ZeichnungHintergrund::render(rObj);
  177. // TODO
  178. }
  179. void QuestGraphItem::doMausEreignis(Framework::MausEreignis& me, bool userRet)
  180. {
  181. // TODO
  182. }
  183. const Framework::Text& QuestGraphItem::getId() const
  184. {
  185. return id;
  186. }
  187. const Framework::Text& QuestGraphItem::getRequirements() const
  188. {
  189. return requirements;
  190. }
  191. bool QuestGraphItem::calculateLaxerIndex()
  192. {
  193. int oldLayerIndex = layerIndex;
  194. int maxLayerIndex = -1;
  195. for (QuestGraphItem* item : previousLayersConnections)
  196. {
  197. if (item->getLayerIndex() < 0) return 0;
  198. if (item->getLayerIndex() > maxLayerIndex)
  199. {
  200. maxLayerIndex = item->getLayerIndex();
  201. }
  202. }
  203. layerIndex = maxLayerIndex + 1;
  204. return oldLayerIndex != layerIndex;
  205. }
  206. int QuestGraphItem::getLayerIndex() const
  207. {
  208. return layerIndex;
  209. }
  210. void QuestGraphItem::setVirtual(bool virtualNode)
  211. {
  212. this->virtualNode = virtualNode;
  213. setStyle(ZeichnungHintergrund::Style::Sichtbar, virtualNode);
  214. }
  215. void QuestGraphItem::setNodeIndex(int index)
  216. {
  217. this->nodeIndex = nodeIndex;
  218. }
  219. void QuestGraphItem::addNextLayerRef(QuestGraphItem* zItem)
  220. {
  221. previousLayersConnections.add(zItem);
  222. }
  223. void QuestGraphItem::addPreviousLayerRef(QuestGraphItem* zItem)
  224. {
  225. nextLayersConnections.add(zItem);
  226. }
  227. const Framework::Array<QuestGraphItem*>&
  228. QuestGraphItem::getNextLayersConnections() const
  229. {
  230. return nextLayersConnections;
  231. }
  232. int QuestGraphItem::getNodeIndex() const
  233. {
  234. return nodeIndex;
  235. }
  236. bool QuestGraphItem::isMainQuest() const
  237. {
  238. return mainQuest;
  239. }
  240. QuestGraphItemLayer::QuestGraphItemLayer()
  241. : ReferenceCounter()
  242. {}
  243. bool QuestGraphItemLayer::tick(double tickVal)
  244. {
  245. bool result = 0;
  246. for (QuestGraphItem* item : items)
  247. {
  248. result |= item->tick(tickVal);
  249. }
  250. return result;
  251. }
  252. void QuestGraphItemLayer::render(Framework::Bild& rObj)
  253. {
  254. for (QuestGraphItem* item : items)
  255. {
  256. item->render(rObj);
  257. }
  258. }
  259. void QuestGraphItemLayer::doMausEreignis(Framework::MausEreignis& me)
  260. {
  261. for (QuestGraphItem* item : items)
  262. {
  263. item->doPublicMausEreignis(me);
  264. }
  265. }
  266. void QuestGraphItemLayer::addItem(QuestGraphItem* item)
  267. {
  268. items.add(item);
  269. item->setNodeIndex(items.getEintragAnzahl() - 1);
  270. }
  271. bool QuestGraphItemLayer::sortItems()
  272. {
  273. bool changed = 0;
  274. for (int index = 0; index < items.getEintragAnzahl(); index++)
  275. {
  276. QuestGraphItem* current = items.z(index);
  277. int beforeConflicts = 0;
  278. int afterConflicts = 0;
  279. for (QuestGraphItem* connection : current->getNextLayersConnections())
  280. {
  281. for (int j = 0; j < items.getEintragAnzahl(); j++)
  282. {
  283. if (index != j)
  284. {
  285. QuestGraphItem* other = items.z(j);
  286. for (QuestGraphItem* otherConnection :
  287. other->getNextLayersConnections())
  288. {
  289. if (j < index
  290. && otherConnection->getNodeIndex()
  291. > connection->getNodeIndex())
  292. {
  293. beforeConflicts++;
  294. }
  295. if ((j > index
  296. && otherConnection->getNodeIndex()
  297. < connection->getNodeIndex()))
  298. {
  299. afterConflicts++;
  300. }
  301. }
  302. }
  303. }
  304. }
  305. if (afterConflicts > beforeConflicts)
  306. {
  307. // move node down
  308. QuestGraphItem* after = items.z(index + 1);
  309. after->setNodeIndex(index);
  310. current->setNodeIndex(index + 1);
  311. items.tausch(index, index + 1);
  312. changed = 1;
  313. }
  314. else if (afterConflicts < beforeConflicts)
  315. {
  316. // move node up
  317. QuestGraphItem* before = items.z(index - 1);
  318. before->setNodeIndex(index);
  319. current->setNodeIndex(index - 1);
  320. items.tausch(index - 1, index);
  321. changed = 1;
  322. }
  323. }
  324. return changed;
  325. }
  326. bool QuestGraphItemLayer::fixItemPositions()
  327. {
  328. int y = 0;
  329. for (QuestGraphItem* item : items)
  330. {
  331. item->setPosition(
  332. item->getLayerIndex() * 150 + 10 - item->isMainQuest() * 3, y);
  333. y += item->getHeight() + 20;
  334. }
  335. return 0;
  336. }
  337. const Framework::RCArray<QuestGraphItem>& QuestGraphItemLayer::getItems() const
  338. {
  339. return items;
  340. }
  341. int QuestGraphItemLayer::getLeyerHeight() const
  342. {
  343. int start = 0;
  344. int end = 0;
  345. for (QuestGraphItem* item : items)
  346. {
  347. if (item->getY() < start) start = item->getY();
  348. if (item->getY() + item->getHeight() > end)
  349. end = item->getY() + item->getHeight();
  350. }
  351. return end - start;
  352. }
  353. void QuestGraphItemLayer::centerVertically(int pos)
  354. {
  355. int height = getLeyerHeight();
  356. int y = pos - height / 2;
  357. for (QuestGraphItem* item : items)
  358. {
  359. item->setPosition(item->getX(), y);
  360. y += item->getHeight() + 20;
  361. }
  362. }
  363. QuestGraph::QuestGraph()
  364. : ZeichnungHintergrund()
  365. {
  366. addStyle(ZeichnungHintergrund::Style::Sichtbar
  367. | ZeichnungHintergrund::Style::Erlaubt
  368. | ZeichnungHintergrund::Style::Rahmen);
  369. setRahmenBreite(1);
  370. setRahmenFarbe(0xFF52525E);
  371. setMausEreignis(Framework::_ret1ME);
  372. }
  373. void QuestGraph::render(Framework::Bild& rObj)
  374. {
  375. if (hatStyle(ZeichnungHintergrund::Style::Sichtbar) && layers.getEintragAnzahl() > 0)
  376. {
  377. ZeichnungHintergrund::render(rObj);
  378. if (rObj.setDrawOptions(pos, gr))
  379. {
  380. if (rObj.setDrawOptions(getRahmenBreite(),
  381. getRahmenBreite(),
  382. getInnenBreite(),
  383. getInnenHeight()))
  384. {
  385. int hScrollOffset = 0;
  386. if (hatStyle(ZeichnungHintergrund::Style::HScroll)
  387. && horizontalScrollBar)
  388. {
  389. hScrollOffset = horizontalScrollBar->getScroll();
  390. }
  391. int vScrollOffset = 0;
  392. if (hatStyle(ZeichnungHintergrund::Style::VScroll)
  393. && vertikalScrollBar)
  394. {
  395. vScrollOffset = vertikalScrollBar->getScroll();
  396. }
  397. if (hScrollOffset || vScrollOffset)
  398. {
  399. rObj.addScrollOffset(hScrollOffset, vScrollOffset);
  400. }
  401. for (QuestGraphItemLayer* layer : layers)
  402. {
  403. layer->render(rObj);
  404. }
  405. rObj.releaseDrawOptions();
  406. }
  407. rObj.releaseDrawOptions();
  408. }
  409. }
  410. }
  411. void QuestGraph::doMausEreignis(Framework::MausEreignis& me, bool userRet)
  412. {
  413. userRet &= hatStyle(ZeichnungHintergrund::Style::Sichtbar);
  414. bool vera = me.verarbeitet;
  415. if (!userRet)
  416. {
  417. me.verarbeitet = 1;
  418. }
  419. for (QuestGraphItemLayer* layer : layers)
  420. {
  421. layer->doMausEreignis(me);
  422. }
  423. if (!userRet)
  424. {
  425. me.verarbeitet = vera;
  426. }
  427. }
  428. void QuestGraph::addVirtualConnectionNodes()
  429. {
  430. int layerIndex = 0;
  431. // add virtual items for connections that do not go directly to the next
  432. // layer after this operation each node only have connections to the
  433. // immediate following layer
  434. for (QuestGraphItemLayer* layer : layers)
  435. {
  436. for (int i = 0; i < layer->getItems().getEintragAnzahl(); i++)
  437. {
  438. QuestGraphItem* item = layer->getItems().z(i);
  439. auto iterator = item->getNextLayersConnections().begin();
  440. QuestGraphItem* virtualItem = 0;
  441. for (; iterator; iterator++)
  442. {
  443. if (iterator->getLayerIndex() > layerIndex + 1)
  444. {
  445. bool remove = 1;
  446. if (!virtualItem)
  447. {
  448. virtualItem = new QuestGraphItem();
  449. virtualItem->addPreviousLayerRef(item);
  450. virtualItem->setVirtual(true);
  451. virtualItem->calculateLaxerIndex();
  452. remove = 0;
  453. }
  454. item->addNextLayerRef(iterator);
  455. if (remove)
  456. {
  457. iterator.remove();
  458. }
  459. else
  460. {
  461. iterator.set(virtualItem);
  462. }
  463. }
  464. else if (iterator->getLayerIndex() < 0)
  465. { // remove connections to invalid nodes
  466. iterator.remove();
  467. }
  468. }
  469. if (virtualItem)
  470. {
  471. addItem(virtualItem);
  472. }
  473. }
  474. layerIndex++;
  475. }
  476. }
  477. void QuestGraph::sortItems()
  478. {
  479. bool changed = 1;
  480. while (changed)
  481. {
  482. changed = 0;
  483. for (QuestGraphItemLayer* layer : layers)
  484. {
  485. changed |= layer->sortItems();
  486. }
  487. }
  488. }
  489. void QuestGraph::fixItemPositions()
  490. {
  491. bool changed = 1;
  492. int height = 0;
  493. while (changed)
  494. {
  495. changed = 0;
  496. for (QuestGraphItemLayer* layer : layers)
  497. {
  498. changed |= layer->fixItemPositions();
  499. if (layer->getLeyerHeight() > height)
  500. {
  501. height = layer->getLeyerHeight();
  502. }
  503. }
  504. }
  505. if (height > getInnenHeight())
  506. {
  507. addStyle(ZeichnungHintergrund::Style::VScroll);
  508. setVertikalKlickScroll(10);
  509. vertikalScrollBar->update(height, getInnenHeight());
  510. }
  511. if (layers.getEintragAnzahl() * 150 - 80 > getInnenBreite())
  512. {
  513. addStyle(ZeichnungHintergrund::Style::HScroll);
  514. setHorizontalKlickScroll(10);
  515. horizontalScrollBar->update(
  516. layers.getEintragAnzahl() * 150 - 80, getInnenBreite());
  517. }
  518. for (QuestGraphItemLayer* layer : layers)
  519. {
  520. layer->centerVertically(getHeight() / 2);
  521. }
  522. }
  523. void QuestGraph::addItem(QuestGraphItem* item)
  524. {
  525. int layerInex = item->getLayerIndex();
  526. if (layerInex >= 0)
  527. {
  528. while (layerInex >= layers.getEintragAnzahl())
  529. {
  530. layers.add(new QuestGraphItemLayer());
  531. }
  532. layers.z(layerInex)->addItem(item);
  533. }
  534. else
  535. {
  536. invalidNodes.addItem(item);
  537. }
  538. }