QuestGraph.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  1. #include "QuestGraph.h"
  2. #include <Bild.h>
  3. #include <HashMap.h>
  4. #include <Scroll.h>
  5. #include <XML.h>
  6. #include "Globals.h"
  7. #include "Load.h"
  8. #include "World.h"
  9. QuestGraphElement::QuestGraphElement() {}
  10. bool QuestGraphElement::isApplicableFor(Framework::XML::Element& element)
  11. {
  12. return element.getName().istGleich("questGraph");
  13. }
  14. Framework::Zeichnung* QuestGraphElement::parseElement(
  15. Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
  16. {
  17. QuestGraph* graph = new QuestGraph();
  18. graph->collectionName = element.getAttributeValue("collectionName");
  19. graph->id = element.getAttributeValue("id");
  20. auto children = element.selectChildsByName("questGraphItem");
  21. Framework::HashMap<Framework::Text, QuestGraphItem*> map(
  22. 100, [](Framework::Text str) { return str.hashCode(); });
  23. // parse graph elements
  24. for (Framework::XML::Element* itemElement : children)
  25. {
  26. Framework::Zeichnung* parsed
  27. = generalFactory.parseElement(*itemElement, generalFactory);
  28. QuestGraphItem* item = dynamic_cast<QuestGraphItem*>(parsed);
  29. if (!item)
  30. {
  31. if (parsed)
  32. {
  33. parsed->release();
  34. }
  35. }
  36. else
  37. {
  38. map.put(item->getId(), item);
  39. }
  40. generalFactory.layout(*itemElement,
  41. *parsed,
  42. graph->getBreite(),
  43. graph->getHeight(),
  44. generalFactory);
  45. }
  46. // set connection references
  47. int connectionId = -1;
  48. for (MapEntry<Framework::Text, QuestGraphItem*> entry : map)
  49. {
  50. QuestGraphItem* item = entry.getValue();
  51. Framework::Text requirements = item->getRequirements();
  52. while (requirements.getLength() > 0)
  53. {
  54. connectionId++;
  55. Framework::Text* part = 0;
  56. if (requirements.hat("||"))
  57. {
  58. part = requirements.getTeilText(
  59. 0, requirements.positionVon("||"));
  60. requirements.remove(0, requirements.positionVon("||") + 2);
  61. }
  62. else
  63. {
  64. part = new Framework::Text(requirements);
  65. requirements = "";
  66. }
  67. while (part->getLength() > 0)
  68. {
  69. Framework::Text* requirement;
  70. if (part->hat("&&"))
  71. {
  72. requirement = part->getTeilText(0, part->positionVon("&&"));
  73. part->remove(0, part->positionVon("&&") + 2);
  74. }
  75. else
  76. {
  77. requirement = new Text(part->getText());
  78. part->setText("");
  79. }
  80. requirement->removeWhitespaceAfter(0);
  81. requirement->removeWhitespaceBefore(requirement->getLength());
  82. QuestGraphItem* requiredItem = map.get(*requirement);
  83. if (requiredItem)
  84. {
  85. requiredItem->addNextLayerRef({item, connectionId});
  86. item->addPreviousLayerRef({requiredItem, connectionId});
  87. }
  88. requirement->release();
  89. }
  90. part->release();
  91. }
  92. }
  93. // calculate layer index based on connections
  94. bool changed = 1;
  95. while (changed)
  96. {
  97. changed = 0;
  98. for (MapEntry<Framework::Text, QuestGraphItem*> entry : map)
  99. {
  100. changed |= entry.getValue()->calculateLaxerIndex();
  101. }
  102. }
  103. // add items to graph
  104. for (MapEntry<Framework::Text, QuestGraphItem*> entry : map)
  105. {
  106. if (entry.getValue()->getLayerIndex() < 0)
  107. {
  108. entry.getValue()->setVirtual(
  109. 1); // hide nodes witch layers could not be calculated because
  110. // of invalid circular connections
  111. }
  112. graph->addItem(entry.getValue());
  113. }
  114. graph->addVirtualConnectionNodes();
  115. graph->sortItems();
  116. return graph;
  117. }
  118. bool QuestGraphElement::updateElement(Framework::XML::Element& element,
  119. Framework::Zeichnung& z,
  120. Framework::UIMLContainer& generalFactory)
  121. {
  122. return false;
  123. }
  124. void QuestGraphElement::layout(Framework::XML::Element& element,
  125. Framework::Zeichnung& z,
  126. int pWidth,
  127. int pHeight,
  128. Framework::UIMLContainer& generalLayouter)
  129. {
  130. UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
  131. QuestGraph* graph = dynamic_cast<QuestGraph*>(&z);
  132. graph->fixItemPositions();
  133. }
  134. QuestGraphItemElement::QuestGraphItemElement() {}
  135. bool QuestGraphItemElement::isApplicableFor(Framework::XML::Element& element)
  136. {
  137. return element.getName().istGleich("questGraphItem");
  138. }
  139. Framework::Zeichnung* QuestGraphItemElement::parseElement(
  140. Framework::XML::Element& element, Framework::UIMLContainer& generalFactory)
  141. {
  142. QuestGraphItem* item = new QuestGraphItem();
  143. Framework::Text name = element.getAttributeValue("name");
  144. Framework::Text description = element.getAttributeValue("description");
  145. item->setToolTipText(name + "\n" + description,
  146. generalFactory.getFactory().initParam.bildschirm,
  147. generalFactory.getFactory().initParam.schrift);
  148. item->setHintergrundBildZ(loadImage(element.getAttributeValue("image")));
  149. item->finished = (int)element.getAttributeValue("finished") != 0;
  150. if (item->finished)
  151. {
  152. item->setRahmenFarbe(0xFF55FF00);
  153. }
  154. item->rewarded = (int)element.getAttributeValue("rewarded") != 0;
  155. item->mainQuest = (int)element.getAttributeValue("mainQuest") != 0;
  156. if (item->mainQuest)
  157. {
  158. item->setRahmenBreite(3);
  159. }
  160. item->id = element.getAttributeValue("id");
  161. item->requirements = element.getAttributeValue("requirements");
  162. item->virtualNode = 0;
  163. return item;
  164. }
  165. bool QuestGraphItemElement::updateElement(Framework::XML::Element& element,
  166. Framework::Zeichnung& z,
  167. Framework::UIMLContainer& generalFactory)
  168. {
  169. return false;
  170. }
  171. void QuestGraphItemElement::layout(Framework::XML::Element& element,
  172. Framework::Zeichnung& z,
  173. int pWidth,
  174. int pHeight,
  175. Framework::UIMLContainer& generalLayouter)
  176. {
  177. UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter);
  178. }
  179. Connection::Connection(QuestGraphItem* zSource)
  180. : ReferenceCounter(),
  181. zSource(zSource),
  182. vx(0),
  183. minY(0),
  184. maxY(0)
  185. {}
  186. void Connection::renderVertical(Framework::Bild& rObj)
  187. {
  188. if (targets.getEintragAnzahl())
  189. {
  190. rObj.drawLinieV(
  191. vx, minY, maxY - minY, isActive() ? 0xFFFFFFFF : 0xFF52525E);
  192. }
  193. }
  194. void Connection::renderHorizontal(Framework::Bild& rObj)
  195. {
  196. if (targets.getEintragAnzahl())
  197. {
  198. Framework::Punkt start = zSource->getPosition();
  199. start.x += zSource->getBreite();
  200. start.y += zSource->getHeight() / 2;
  201. rObj.drawLinieH(start.x, start.y - 2, vx - start.x, 0xA0000000);
  202. rObj.drawLinieH(start.x, start.y - 1, vx - start.x, 0xA0000000);
  203. rObj.drawLinieH(start.x,
  204. start.y,
  205. vx - start.x,
  206. isActive() ? 0xFFFFFFFF : 0xFF52525E);
  207. rObj.drawLinieH(start.x, start.y + 1, vx - start.x, 0xA0000000);
  208. rObj.drawLinieH(start.x, start.y + 2, vx - start.x, 0xA0000000);
  209. for (const ConnectionTarget& target : targets)
  210. {
  211. Framework::Punkt end
  212. = target.zTarget->getTargetPosition(target.targetIndex);
  213. rObj.drawLinieH(vx + 1, end.y - 2, end.x - vx - 1, 0xA0000000);
  214. rObj.drawLinieH(vx + 1, end.y - 1, end.x - vx - 1, 0xA0000000);
  215. rObj.drawLinieH(vx + 1,
  216. end.y,
  217. end.x - vx - 1,
  218. isActive() ? 0xFFFFFFFF : 0xFF52525E);
  219. rObj.drawLinieH(vx + 1, end.y + 1, end.x - vx - 1, 0xA0000000);
  220. rObj.drawLinieH(vx + 1, end.y + 2, end.x - vx - 1, 0xA0000000);
  221. }
  222. }
  223. }
  224. void Connection::setVx(int vx)
  225. {
  226. this->vx = vx;
  227. }
  228. void Connection::addConnectionTarget(ConnectionTarget target)
  229. {
  230. targets.add(target);
  231. }
  232. void Connection::setTargetIndex(AndNode* zTarget, int index)
  233. {
  234. for (auto target = targets.begin(); target; target++)
  235. {
  236. if (target.val().zTarget == zTarget)
  237. {
  238. target.set({index, target.val().zTarget});
  239. return;
  240. }
  241. }
  242. }
  243. void Connection::layout()
  244. {
  245. minY = 0;
  246. maxY = 0;
  247. bool start = 1;
  248. for (const ConnectionTarget& target : targets)
  249. {
  250. Framework::Punkt end
  251. = target.zTarget->getTargetPosition(target.targetIndex);
  252. if (start || end.y < minY)
  253. {
  254. minY = end.y;
  255. }
  256. if (start || end.y > maxY)
  257. {
  258. maxY = end.y;
  259. }
  260. start = 0;
  261. }
  262. Framework::Punkt origin = zSource->getPosition();
  263. origin.x += zSource->getBreite();
  264. origin.y += zSource->getHeight() / 2;
  265. if (minY > origin.y) minY = origin.y;
  266. if (maxY < origin.y) maxY = origin.y;
  267. maxY++;
  268. }
  269. bool Connection::isActive() const
  270. {
  271. return zSource->isFinished();
  272. }
  273. int Connection::getOrderNum() const
  274. {
  275. return zSource->getNodeIndex();
  276. }
  277. int Connection::getTargetCount() const
  278. {
  279. return targets.getEintragAnzahl();
  280. }
  281. int Connection::getVerticalLength() const
  282. {
  283. return maxY - minY;
  284. }
  285. int Connection::getVx() const
  286. {
  287. return vx;
  288. }
  289. AndNode::AndNode()
  290. : ZeichnungHintergrund()
  291. {
  292. setStyle(ZeichnungHintergrund::Style::Sichtbar
  293. | ZeichnungHintergrund::Style::Rahmen);
  294. setRahmenBreite(1);
  295. setRahmenFarbe(0xFF52525E);
  296. tr.setSchriftSize(12);
  297. tr.setSchriftZ(
  298. dynamic_cast<Schrift*>(uiFactory.initParam.schrift->getThis()));
  299. }
  300. void AndNode::addConnection(Connection* zConnection)
  301. {
  302. int pos = 0;
  303. for (Connection* other : connections)
  304. {
  305. if (other->getOrderNum() > zConnection->getOrderNum()) break;
  306. pos++;
  307. }
  308. zConnection->addConnectionTarget({pos, this});
  309. connections.add(zConnection, pos);
  310. pos = 0;
  311. for (Connection* con : connections)
  312. {
  313. con->setTargetIndex(this, pos);
  314. pos++;
  315. }
  316. }
  317. void AndNode::render(Framework::Bild& rObj)
  318. {
  319. setRahmenFarbe(isActive() ? 0xFFFFFFFF : 0xFF52525E);
  320. if (connections.getEintragAnzahl() > 1)
  321. {
  322. ZeichnungHintergrund::render(rObj);
  323. if (rObj.setDrawOptions(pos.x + getRahmenBreite(),
  324. pos.y + getRahmenBreite(),
  325. getInnenBreite(),
  326. getInnenHeight()))
  327. {
  328. tr.renderText(getInnenBreite() / 2 - tr.getTextBreite("&") / 2,
  329. getInnenHeight() / 2 - tr.getTextHeight("&") / 2,
  330. "&",
  331. rObj,
  332. isActive() ? 0xFFFFFFFF : 0xFF52525E);
  333. rObj.releaseDrawOptions();
  334. }
  335. }
  336. else if (connections.getEintragAnzahl() > 0)
  337. {
  338. if (rObj.setDrawOptions(pos, gr))
  339. {
  340. rObj.drawLinieH(0,
  341. 0,
  342. gr.x,
  343. connections.get(0)->isActive() ? 0xFFFFFFFF : 0xFF52525E);
  344. rObj.releaseDrawOptions();
  345. }
  346. }
  347. }
  348. Framework::Punkt AndNode::getTargetPosition(int index)
  349. {
  350. if (connections.getEintragAnzahl() == 1)
  351. {
  352. return pos;
  353. }
  354. return pos + Framework::Punkt(0, 10 + index * 11);
  355. }
  356. void AndNode::layout()
  357. {
  358. if (connections.getEintragAnzahl() == 1)
  359. {
  360. setSize(20, 1);
  361. }
  362. else
  363. {
  364. setSize(20, 10 + connections.getEintragAnzahl() * 11);
  365. }
  366. }
  367. bool AndNode::isActive() const
  368. {
  369. for (Connection* connection : connections)
  370. {
  371. if (!connection->isActive()) return false;
  372. }
  373. return connections.getEintragAnzahl() > 0;
  374. }
  375. int AndNode::getConnectionCount() const
  376. {
  377. return connections.getEintragAnzahl();
  378. }
  379. OrConnection::OrConnection(QuestGraphItem* zTarget,
  380. const Framework::Array<ConnectionInfo>& connections)
  381. : ReferenceCounter(),
  382. zTarget(zTarget),
  383. minY(0),
  384. maxY(0)
  385. {
  386. int currId = -1;
  387. AndNode* currNode = 0;
  388. for (const ConnectionInfo& info : connections)
  389. {
  390. if (info.id != currId)
  391. {
  392. currNode = new AndNode();
  393. andNodes.add(currNode);
  394. currId = info.id;
  395. }
  396. currNode->addConnection(info.target->zOutgoingConnection());
  397. }
  398. }
  399. void OrConnection::render(Framework::Bild& rObj)
  400. {
  401. if (andNodes.getEintragAnzahl() == 0) return;
  402. bool active = isActive();
  403. rObj.drawLinieV(zTarget->getX() - 11,
  404. minY,
  405. maxY - minY,
  406. active ? 0xFFFFFFFF : 0xFF52525E);
  407. rObj.drawLinieH(zTarget->getX() - 10,
  408. zTarget->getY() + zTarget->getHeight() / 2,
  409. 10,
  410. active ? 0xFFFFFFFF : 0xFF52525E);
  411. for (AndNode* node : andNodes)
  412. {
  413. rObj.drawLinieH(node->getX() + node->getBreite(),
  414. node->getY() + node->getHeight() / 2,
  415. 10,
  416. active ? 0xFFFFFFFF : 0xFF52525E);
  417. node->render(rObj);
  418. }
  419. }
  420. void OrConnection::layout()
  421. {
  422. int nodeHeight = -10;
  423. for (AndNode* node : andNodes)
  424. {
  425. node->layout();
  426. nodeHeight += node->getHeight() + 10;
  427. }
  428. int y = zTarget->getY() + zTarget->getHeight() / 2 - nodeHeight / 2;
  429. bool start = 1;
  430. AndNode* last = 0;
  431. for (AndNode* node : andNodes)
  432. {
  433. node->setPosition(zTarget->getX() - 21 - node->getBreite(), y);
  434. if (start)
  435. {
  436. minY = y + node->getHeight() / 2;
  437. }
  438. y += node->getHeight() + 10;
  439. start = 0;
  440. last = node;
  441. }
  442. if (last)
  443. {
  444. y -= 10 + last->getHeight();
  445. maxY = y + last->getHeight() / 2 + 1;
  446. }
  447. else
  448. {
  449. maxY = minY + 1;
  450. }
  451. }
  452. int OrConnection::getNeededHeight() const
  453. {
  454. int minY = 0;
  455. int maxY = 0;
  456. bool first = 1;
  457. for (AndNode* node : andNodes)
  458. {
  459. if (first || node->getY() < minY)
  460. {
  461. minY = node->getY();
  462. }
  463. if (first || node->getY() + node->getHeight() > maxY)
  464. {
  465. maxY = node->getY() + node->getHeight();
  466. }
  467. first = 0;
  468. }
  469. return maxY - minY;
  470. }
  471. bool OrConnection::isActive() const
  472. {
  473. for (AndNode* node : andNodes)
  474. {
  475. if (node->isActive()) return 1;
  476. }
  477. return 0;
  478. }
  479. bool OrConnection::isHorizontalLineConflict(int y) const
  480. {
  481. for (AndNode* node : andNodes)
  482. {
  483. for (int i = 0; i < node->getConnectionCount(); i++)
  484. {
  485. Punkt connection = node->getTargetPosition(i);
  486. if (abs(y - connection.y) < 5) return 1;
  487. }
  488. }
  489. return 0;
  490. }
  491. QuestGraphItem::QuestGraphItem()
  492. : ZeichnungHintergrund(),
  493. layerIndex(-1),
  494. nodeIndex(-1),
  495. outgoingConnection(0),
  496. incommingConnection(0),
  497. finished(0),
  498. rewarded(0),
  499. mainQuest(0),
  500. virtualNode(0),
  501. animationProgress(0)
  502. {
  503. addStyle(ZeichnungHintergrund::Style::Sichtbar
  504. | ZeichnungHintergrund::Style::Rahmen
  505. | ZeichnungHintergrund::Style::Erlaubt
  506. | ZeichnungHintergrund::Style::HBild
  507. | ZeichnungHintergrund::Style::HBildScale
  508. | ZeichnungHintergrund::Style::HAlpha
  509. | ZeichnungHintergrund::Style::Hintergrund);
  510. setRahmenFarbe(0xFF52525E);
  511. setRahmenBreite(1);
  512. setMausEreignis(Framework::_ret1ME);
  513. }
  514. QuestGraphItem::~QuestGraphItem()
  515. {
  516. if (outgoingConnection) outgoingConnection->release();
  517. if (incommingConnection) incommingConnection->release();
  518. }
  519. bool QuestGraphItem::tick(double tickVal)
  520. {
  521. animationProgress += tickVal * 20;
  522. if (animationProgress > getBreite() * 2 + getHeight() * 2 - 4)
  523. {
  524. animationProgress -= getBreite() * 2 + getHeight() * 2 - 4;
  525. }
  526. rend = 1;
  527. return ZeichnungHintergrund::tick(tickVal);
  528. }
  529. int getBorderX(int p, int width, int height)
  530. {
  531. if (p < width)
  532. {
  533. return p;
  534. }
  535. else if (p < width + height - 1)
  536. {
  537. return width - 1;
  538. }
  539. else if (p < width * 2 + height - 2)
  540. {
  541. return width - (p - width - height + 2);
  542. }
  543. else
  544. {
  545. return 0;
  546. }
  547. }
  548. int getBorderY(int p, int width, int height)
  549. {
  550. if (p < width)
  551. {
  552. return 0;
  553. }
  554. else if (p < width + height - 1)
  555. {
  556. return p - width + 1;
  557. }
  558. else if (p < width * 2 + height - 2)
  559. {
  560. return height - 1;
  561. }
  562. else
  563. {
  564. return height - (p - width * 2 - height + 3);
  565. }
  566. }
  567. void QuestGraphItem::render(Framework::Bild& rObj)
  568. {
  569. if (incommingConnection) incommingConnection->render(rObj);
  570. if (isVirtual())
  571. {
  572. rObj.drawLinieH(
  573. pos.x, pos.y, gr.x, isFinished() ? 0xFFFFFFFF : 0xFF52525E);
  574. return;
  575. }
  576. ZeichnungHintergrund::render(rObj);
  577. if (finished && !rewarded)
  578. {
  579. if (rObj.setDrawOptions(pos.x, pos.y, gr.x - 1, gr.y - 1))
  580. {
  581. for (int i = 0; i < 7; i++)
  582. {
  583. int p
  584. = ((int)animationProgress + i) % (gr.x * 2 + gr.y * 2 - 4);
  585. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  586. getBorderY(p, gr.x, gr.y),
  587. 0xFFFFFF00);
  588. rObj.setPixelDP(getBorderX(p, gr.x, gr.y) - 1,
  589. getBorderY(p, gr.x, gr.y),
  590. 0xFFFFFF00);
  591. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  592. getBorderY(p, gr.x, gr.y) - 1,
  593. 0xFFFFFF00);
  594. rObj.setPixelDP(getBorderX(p, gr.x, gr.y) + 1,
  595. getBorderY(p, gr.x, gr.y),
  596. 0xFFFFFF00);
  597. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  598. getBorderY(p, gr.x, gr.y) + 1,
  599. 0xFFFFFF00);
  600. p = ((int)animationProgress + i + gr.x - 1)
  601. % (gr.x * 2 + gr.y * 2 - 4);
  602. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  603. getBorderY(p, gr.x, gr.y),
  604. 0xFFFFFF00);
  605. rObj.setPixelDP(getBorderX(p, gr.x, gr.y) - 1,
  606. getBorderY(p, gr.x, gr.y),
  607. 0xFFFFFF00);
  608. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  609. getBorderY(p, gr.x, gr.y) - 1,
  610. 0xFFFFFF00);
  611. rObj.setPixelDP(getBorderX(p, gr.x, gr.y) + 1,
  612. getBorderY(p, gr.x, gr.y),
  613. 0xFFFFFF00);
  614. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  615. getBorderY(p, gr.x, gr.y) + 1,
  616. 0xFFFFFF00);
  617. p = ((int)animationProgress + i + gr.x + gr.y - 2)
  618. % (gr.x * 2 + gr.y * 2 - 4);
  619. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  620. getBorderY(p, gr.x, gr.y),
  621. 0xFFFFFF00);
  622. rObj.setPixelDP(getBorderX(p, gr.x, gr.y) - 1,
  623. getBorderY(p, gr.x, gr.y),
  624. 0xFFFFFF00);
  625. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  626. getBorderY(p, gr.x, gr.y) - 1,
  627. 0xFFFFFF00);
  628. rObj.setPixelDP(getBorderX(p, gr.x, gr.y) + 1,
  629. getBorderY(p, gr.x, gr.y),
  630. 0xFFFFFF00);
  631. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  632. getBorderY(p, gr.x, gr.y) + 1,
  633. 0xFFFFFF00);
  634. p = ((int)animationProgress + i + gr.x * 2 + gr.y - 3)
  635. % (gr.x * 2 + gr.y * 2 - 4);
  636. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  637. getBorderY(p, gr.x, gr.y),
  638. 0xFFFFFF00);
  639. rObj.setPixelDP(getBorderX(p, gr.x, gr.y) - 1,
  640. getBorderY(p, gr.x, gr.y),
  641. 0xFFFFFF00);
  642. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  643. getBorderY(p, gr.x, gr.y) - 1,
  644. 0xFFFFFF00);
  645. rObj.setPixelDP(getBorderX(p, gr.x, gr.y) + 1,
  646. getBorderY(p, gr.x, gr.y),
  647. 0xFFFFFF00);
  648. rObj.setPixelDP(getBorderX(p, gr.x, gr.y),
  649. getBorderY(p, gr.x, gr.y) + 1,
  650. 0xFFFFFF00);
  651. }
  652. rObj.releaseDrawOptions();
  653. }
  654. }
  655. }
  656. void QuestGraphItem::renderVerticalConnections(Framework::Bild& rObj)
  657. {
  658. if (outgoingConnection) outgoingConnection->renderVertical(rObj);
  659. }
  660. void QuestGraphItem::renderHorizontalConnections(Framework::Bild& rObj)
  661. {
  662. if (outgoingConnection) outgoingConnection->renderHorizontal(rObj);
  663. }
  664. void QuestGraphItem::replacePreviousConnections(
  665. QuestGraphItem* zBefore, QuestGraphItem* zAfter)
  666. {
  667. for (auto con = previousLayersConnections.begin(); con; con++)
  668. {
  669. if (con.val().target == zBefore) con.set({zAfter, con.val().id});
  670. }
  671. }
  672. const Framework::Text& QuestGraphItem::getId() const
  673. {
  674. return id;
  675. }
  676. const Framework::Text& QuestGraphItem::getRequirements() const
  677. {
  678. return requirements;
  679. }
  680. bool QuestGraphItem::calculateLaxerIndex()
  681. {
  682. int oldLayerIndex = layerIndex;
  683. int maxLayerIndex = -1;
  684. for (const ConnectionInfo& item : previousLayersConnections)
  685. {
  686. if (item.target->getLayerIndex() < 0) return 0;
  687. if (item.target->getLayerIndex() > maxLayerIndex)
  688. {
  689. maxLayerIndex = item.target->getLayerIndex();
  690. }
  691. }
  692. layerIndex = maxLayerIndex + 1;
  693. return oldLayerIndex != layerIndex;
  694. }
  695. int QuestGraphItem::getLayerIndex() const
  696. {
  697. return layerIndex;
  698. }
  699. void QuestGraphItem::setVirtual(bool virtualNode)
  700. {
  701. this->virtualNode = virtualNode;
  702. gr.y = virtualNode ? 1 : gr.y;
  703. gr.x = 1;
  704. setStyle(ZeichnungHintergrund::Style::Sichtbar, virtualNode);
  705. }
  706. void QuestGraphItem::setNodeIndex(int index)
  707. {
  708. this->nodeIndex = index;
  709. }
  710. void QuestGraphItem::addNextLayerRef(ConnectionInfo zItem)
  711. {
  712. nextLayersConnections.add(zItem);
  713. }
  714. void QuestGraphItem::addPreviousLayerRef(ConnectionInfo zItem)
  715. {
  716. previousLayersConnections.add(zItem);
  717. }
  718. void QuestGraphItem::initializeConnections()
  719. {
  720. outgoingConnection = new Connection(this);
  721. incommingConnection = new OrConnection(this, previousLayersConnections);
  722. }
  723. const Framework::Array<ConnectionInfo>&
  724. QuestGraphItem::getNextLayersConnections() const
  725. {
  726. return nextLayersConnections;
  727. }
  728. int QuestGraphItem::getNodeIndex() const
  729. {
  730. return nodeIndex;
  731. }
  732. bool QuestGraphItem::isMainQuest() const
  733. {
  734. return mainQuest;
  735. }
  736. bool QuestGraphItem::isVirtual() const
  737. {
  738. return virtualNode;
  739. }
  740. bool QuestGraphItem::isFinished() const
  741. {
  742. return virtualNode ? incommingConnection->isActive() : finished;
  743. }
  744. Connection* QuestGraphItem::zOutgoingConnection() const
  745. {
  746. return outgoingConnection;
  747. }
  748. OrConnection* QuestGraphItem::zIncommingConnection() const
  749. {
  750. return incommingConnection;
  751. }
  752. QuestGraphItemLayer::QuestGraphItemLayer()
  753. : ReferenceCounter()
  754. {}
  755. bool QuestGraphItemLayer::tick(double tickVal)
  756. {
  757. bool result = 0;
  758. for (QuestGraphItem* item : items)
  759. {
  760. result |= item->tick(tickVal);
  761. }
  762. return result;
  763. }
  764. void QuestGraphItemLayer::render(Framework::Bild& rObj)
  765. {
  766. for (QuestGraphItem* item : items)
  767. {
  768. item->render(rObj);
  769. item->renderVerticalConnections(rObj);
  770. }
  771. for (QuestGraphItem* item : items)
  772. {
  773. item->renderHorizontalConnections(rObj);
  774. }
  775. }
  776. void QuestGraphItemLayer::doMausEreignis(Framework::MausEreignis& me)
  777. {
  778. for (QuestGraphItem* item : items)
  779. {
  780. item->doPublicMausEreignis(me);
  781. }
  782. }
  783. void QuestGraphItemLayer::addItem(QuestGraphItem* item)
  784. {
  785. items.add(item);
  786. item->setNodeIndex(items.getEintragAnzahl() - 1);
  787. }
  788. bool QuestGraphItemLayer::sortItems()
  789. {
  790. bool changed = 0;
  791. for (int index = 0; index < items.getEintragAnzahl() - 1; index++)
  792. {
  793. QuestGraphItem* current = items.z(index);
  794. int conflicts = 0;
  795. int afterSwapConflicts = 0;
  796. QuestGraphItem* other = items.z(index + 1);
  797. for (const ConnectionInfo& connection :
  798. current->getNextLayersConnections())
  799. {
  800. for (const ConnectionInfo& otherConnection :
  801. other->getNextLayersConnections())
  802. {
  803. if ((otherConnection.target->getNodeIndex()
  804. < connection.target->getNodeIndex()))
  805. {
  806. conflicts++;
  807. }
  808. if ((otherConnection.target->getNodeIndex()
  809. > connection.target->getNodeIndex()))
  810. {
  811. afterSwapConflicts++;
  812. }
  813. }
  814. }
  815. if (conflicts > afterSwapConflicts)
  816. {
  817. // move node down
  818. QuestGraphItem* after = items.z(index + 1);
  819. after->setNodeIndex(index);
  820. current->setNodeIndex(index + 1);
  821. items.tausch(index, index + 1);
  822. changed = 1;
  823. }
  824. }
  825. return changed;
  826. }
  827. int QuestGraphItemLayer::fixItemPositions(int x)
  828. {
  829. // calculate size needed for & nodes and | nodes
  830. int maxWidth = 0;
  831. for (QuestGraphItem* item : items)
  832. {
  833. item->initializeConnections();
  834. item->zIncommingConnection()->layout();
  835. if (item->getBreite() > maxWidth)
  836. {
  837. maxWidth = item->getBreite();
  838. }
  839. }
  840. x += 20 + 21; // ofset for incomming connections
  841. int y = 0;
  842. // calculate y positions of nodes
  843. for (QuestGraphItem* item : items)
  844. {
  845. int height = 0;
  846. int lastId = -1;
  847. int nodeHeight = item->zIncommingConnection()->getNeededHeight();
  848. if (nodeHeight < item->getHeight()) nodeHeight = item->getHeight();
  849. item->setPosition(x + maxWidth / 2 - item->getBreite() / 2,
  850. y + nodeHeight / 2 - item->getHeight() / 2);
  851. y += nodeHeight + 20;
  852. }
  853. x += maxWidth; // this layers node size
  854. for (QuestGraphItem* item : items)
  855. {
  856. item->zIncommingConnection()->layout();
  857. item->zOutgoingConnection()->setVx(x);
  858. item->zOutgoingConnection()->layout();
  859. }
  860. x += items.getEintragAnzahl() * 11 + 10; // offset for outgoing connections
  861. return x + 20; // min space between layers
  862. }
  863. void QuestGraphItemLayer::sortConnections()
  864. {
  865. for (QuestGraphItem* item : items)
  866. {
  867. item->zIncommingConnection()->layout();
  868. item->zOutgoingConnection()->layout();
  869. }
  870. int connectionCount = 0;
  871. bool* sorted = new bool[items.getEintragAnzahl()];
  872. memset(sorted, 0, sizeof(bool) * items.getEintragAnzahl());
  873. int sortedCount = 0;
  874. while (true)
  875. {
  876. int minHeight = -1;
  877. QuestGraphItem* next = 0;
  878. for (QuestGraphItem* item : items)
  879. {
  880. if (sorted[item->getNodeIndex()]) continue;
  881. if (item->zOutgoingConnection()->getTargetCount()
  882. == connectionCount)
  883. {
  884. if (minHeight < 0
  885. || item->zOutgoingConnection()->getVerticalLength()
  886. < minHeight)
  887. {
  888. minHeight
  889. = item->zOutgoingConnection()->getVerticalLength();
  890. next = item;
  891. }
  892. }
  893. }
  894. if (!next)
  895. {
  896. if (sortedCount < items.getEintragAnzahl())
  897. {
  898. connectionCount++;
  899. }
  900. else
  901. {
  902. break;
  903. }
  904. }
  905. else
  906. {
  907. next->zOutgoingConnection()->setVx(
  908. next->zOutgoingConnection()->getVx() + 10 + sortedCount * 11);
  909. sorted[next->getNodeIndex()] = 1;
  910. sortedCount++;
  911. }
  912. }
  913. delete[] sorted;
  914. }
  915. const Framework::RCArray<QuestGraphItem>& QuestGraphItemLayer::getItems() const
  916. {
  917. return items;
  918. }
  919. int QuestGraphItemLayer::getLeyerHeight() const
  920. {
  921. int start = 0;
  922. int end = 0;
  923. bool first = 1;
  924. for (QuestGraphItem* item : items)
  925. {
  926. if (first || item->getY() < start) start = item->getY();
  927. if (first || item->getY() + item->getHeight() > end)
  928. end = item->getY() + item->getHeight();
  929. first = 0;
  930. }
  931. return end - start;
  932. }
  933. void QuestGraphItemLayer::centerVertically(int pos)
  934. {
  935. int height = getLeyerHeight();
  936. int yOffset = pos - height / 2;
  937. for (QuestGraphItem* item : items)
  938. {
  939. item->setPosition(item->getX(), item->getY() + yOffset);
  940. item->zIncommingConnection()->layout();
  941. item->zOutgoingConnection()->layout();
  942. }
  943. }
  944. void QuestGraphItemLayer::resolveHorizontalConflicts(
  945. const QuestGraphItemLayer* zNextLayer)
  946. {
  947. for (QuestGraphItem* item : items)
  948. {
  949. int outgoingY = item->getY() + item->getHeight() / 2;
  950. if (zNextLayer->isHorizontalLineConflict(outgoingY))
  951. {
  952. int offset = 0;
  953. for (int i = 1; i <= 10; i++)
  954. {
  955. if (!zNextLayer->isHorizontalLineConflict(outgoingY - i))
  956. {
  957. offset = -i;
  958. break;
  959. }
  960. if (!zNextLayer->isHorizontalLineConflict(outgoingY + i))
  961. {
  962. offset = i;
  963. break;
  964. }
  965. }
  966. item->setPosition(item->getX(), item->getY() + offset);
  967. item->zIncommingConnection()->layout();
  968. item->zOutgoingConnection()->layout();
  969. }
  970. }
  971. }
  972. bool QuestGraphItemLayer::isHorizontalLineConflict(int y) const
  973. {
  974. for (QuestGraphItem* item : items)
  975. {
  976. if (item->zIncommingConnection()->isHorizontalLineConflict(y)) return 1;
  977. }
  978. return 0;
  979. }
  980. QuestGraph::QuestGraph()
  981. : ZeichnungHintergrund()
  982. {
  983. addStyle(ZeichnungHintergrund::Style::Sichtbar
  984. | ZeichnungHintergrund::Style::Erlaubt
  985. | ZeichnungHintergrund::Style::Rahmen);
  986. setRahmenBreite(1);
  987. setRahmenFarbe(0xFF52525E);
  988. setMausEreignis(Framework::_ret1ME);
  989. }
  990. bool QuestGraph::tick(double tickVal)
  991. {
  992. for (QuestGraphItemLayer* layer : layers)
  993. {
  994. rend |= layer->tick(tickVal);
  995. }
  996. return ZeichnungHintergrund::tick(tickVal);
  997. }
  998. void QuestGraph::render(Framework::Bild& rObj)
  999. {
  1000. if (hatStyle(ZeichnungHintergrund::Style::Sichtbar)
  1001. && layers.getEintragAnzahl() > 0)
  1002. {
  1003. ZeichnungHintergrund::render(rObj);
  1004. if (rObj.setDrawOptions(pos, gr))
  1005. {
  1006. if (rObj.setDrawOptions(getRahmenBreite(),
  1007. getRahmenBreite(),
  1008. getInnenBreite(),
  1009. getInnenHeight()))
  1010. {
  1011. int hScrollOffset = 0;
  1012. if (hatStyle(ZeichnungHintergrund::Style::HScroll)
  1013. && horizontalScrollBar)
  1014. {
  1015. hScrollOffset = horizontalScrollBar->getScroll();
  1016. }
  1017. int vScrollOffset = 0;
  1018. if (hatStyle(ZeichnungHintergrund::Style::VScroll)
  1019. && vertikalScrollBar)
  1020. {
  1021. vScrollOffset = vertikalScrollBar->getScroll();
  1022. }
  1023. if (hScrollOffset || vScrollOffset)
  1024. {
  1025. rObj.addScrollOffset(hScrollOffset, vScrollOffset);
  1026. }
  1027. for (QuestGraphItemLayer* layer : layers)
  1028. {
  1029. layer->render(rObj);
  1030. }
  1031. rObj.releaseDrawOptions();
  1032. }
  1033. rObj.releaseDrawOptions();
  1034. }
  1035. }
  1036. }
  1037. void QuestGraph::doMausEreignis(Framework::MausEreignis& me, bool userRet)
  1038. {
  1039. userRet &= hatStyle(ZeichnungHintergrund::Style::Sichtbar);
  1040. bool vera = me.verarbeitet;
  1041. if (!userRet)
  1042. {
  1043. me.verarbeitet = 1;
  1044. }
  1045. for (QuestGraphItemLayer* layer : layers)
  1046. {
  1047. layer->doMausEreignis(me);
  1048. }
  1049. if (!userRet)
  1050. {
  1051. me.verarbeitet = vera;
  1052. }
  1053. }
  1054. void QuestGraph::addVirtualConnectionNodes()
  1055. {
  1056. int layerIndex = 0;
  1057. // add virtual items for connections that do not go directly to the next
  1058. // layer after this operation each node only have connections to the
  1059. // immediate following layer
  1060. for (QuestGraphItemLayer* layer : layers)
  1061. {
  1062. for (int i = 0; i < layer->getItems().getEintragAnzahl(); i++)
  1063. {
  1064. QuestGraphItem* item = layer->getItems().z(i);
  1065. auto iterator = item->getNextLayersConnections().begin();
  1066. QuestGraphItem* virtualItem = 0;
  1067. while (iterator)
  1068. {
  1069. if (iterator.val().target->getLayerIndex() > layerIndex + 1)
  1070. {
  1071. if (!virtualItem)
  1072. {
  1073. virtualItem = new QuestGraphItem();
  1074. virtualItem->addPreviousLayerRef(
  1075. {item, iterator.val().id});
  1076. virtualItem->addNextLayerRef(
  1077. {iterator.val().target, iterator.val().id});
  1078. iterator.val().target->replacePreviousConnections(
  1079. item, virtualItem);
  1080. virtualItem->setVirtual(true);
  1081. virtualItem->calculateLaxerIndex();
  1082. iterator.set({virtualItem, iterator.val().id});
  1083. iterator++;
  1084. }
  1085. else
  1086. {
  1087. virtualItem->addNextLayerRef(
  1088. {iterator.val().target, iterator.val().id});
  1089. iterator.val().target->replacePreviousConnections(
  1090. item, virtualItem);
  1091. iterator.remove();
  1092. }
  1093. }
  1094. else if (iterator.val().target->getLayerIndex() < 0)
  1095. { // remove connections to invalid nodes
  1096. iterator.remove();
  1097. }
  1098. else
  1099. {
  1100. iterator++;
  1101. }
  1102. }
  1103. if (virtualItem)
  1104. {
  1105. addItem(virtualItem);
  1106. }
  1107. }
  1108. layerIndex++;
  1109. }
  1110. }
  1111. void QuestGraph::sortItems()
  1112. {
  1113. bool changed = 1;
  1114. while (changed)
  1115. {
  1116. changed = 0;
  1117. for (QuestGraphItemLayer* layer : layers)
  1118. {
  1119. changed |= layer->sortItems();
  1120. }
  1121. }
  1122. }
  1123. void QuestGraph::fixItemPositions()
  1124. {
  1125. int height = 0;
  1126. int x = 0;
  1127. for (QuestGraphItemLayer* layer : layers)
  1128. {
  1129. x = layer->fixItemPositions(x);
  1130. if (layer->getLeyerHeight() > height)
  1131. {
  1132. height = layer->getLeyerHeight();
  1133. }
  1134. }
  1135. for (QuestGraphItemLayer* layer : layers)
  1136. {
  1137. layer->sortConnections();
  1138. }
  1139. if (height > getInnenHeight())
  1140. {
  1141. addStyle(ZeichnungHintergrund::Style::VScroll);
  1142. setVertikalKlickScroll(10);
  1143. vertikalScrollBar->update(height, getInnenHeight());
  1144. }
  1145. if (layers.getEintragAnzahl() * 150 - 80 > getInnenBreite())
  1146. {
  1147. addStyle(ZeichnungHintergrund::Style::HScroll);
  1148. setHorizontalKlickScroll(10);
  1149. horizontalScrollBar->update(
  1150. layers.getEintragAnzahl() * 150 - 80, getInnenBreite());
  1151. }
  1152. QuestGraphItemLayer *last = 0;
  1153. for (int i = layers.getEintragAnzahl() - 1; i >= 0; i--)
  1154. {
  1155. QuestGraphItemLayer* layer = layers.z(i);
  1156. layer->centerVertically(getHeight() / 2);
  1157. if (last) layer->resolveHorizontalConflicts(last);
  1158. last = layer;
  1159. }
  1160. }
  1161. void QuestGraph::addItem(QuestGraphItem* item)
  1162. {
  1163. int layerInex = item->getLayerIndex();
  1164. if (layerInex >= 0)
  1165. {
  1166. while (layerInex >= layers.getEintragAnzahl())
  1167. {
  1168. layers.add(new QuestGraphItemLayer());
  1169. }
  1170. layers.z(layerInex)->addItem(item);
  1171. }
  1172. else
  1173. {
  1174. invalidNodes.addItem(item);
  1175. }
  1176. }