#include "QuestGraph.h" #include #include #include #include #include "Load.h" #include "World.h" QuestGraphElement::QuestGraphElement() {} bool QuestGraphElement::isApplicableFor(Framework::XML::Element& element) { return element.getName().istGleich("questGraph"); } Framework::Zeichnung* QuestGraphElement::parseElement( Framework::XML::Element& element, Framework::UIMLContainer& generalFactory) { QuestGraph* graph = new QuestGraph(); graph->collectionName = element.getAttributeValue("collectionName"); graph->id = element.getAttributeValue("id"); auto children = element.selectChildsByName("questGraphItem"); Framework::HashMap map( 100, [](Framework::Text str) { return str.hashCode(); }); // parse graph elements for (Framework::XML::Element* itemElement : children) { Framework::Zeichnung* parsed = generalFactory.parseElement(*itemElement, generalFactory); QuestGraphItem* item = dynamic_cast(parsed); if (!item) { if (parsed) { parsed->release(); } } else { map.put(item->getId(), item); } generalFactory.layout(*itemElement, *parsed, graph->getBreite(), graph->getHeight(), generalFactory); } // set connection references for (MapEntry entry : map) { QuestGraphItem* item = entry.getValue(); Framework::Text requirements = item->getRequirements(); while (requirements.getLength() > 0) { Framework::Text* requirement; if (requirements.hat(",")) { requirement = requirements.getTeilText( 0, requirements.positionVon(",")); requirements.remove(0, requirements.positionVon(",") + 1); } else { requirement = new Text(requirements); requirements = ""; } QuestGraphItem* requiredItem = map.get(*requirement); if (requiredItem) { requiredItem->addNextLayerRef(item); item->addPreviousLayerRef(requiredItem); } requirement->release(); } } // calculate layer index based on connections bool changed = 1; while (changed) { changed = 0; for (MapEntry entry : map) { changed |= entry.getValue()->calculateLaxerIndex(); } } // add items to graph for (MapEntry entry : map) { if (entry.getValue()->getLayerIndex() < 0) { entry.getValue()->setVirtual( 1); // hide nodes witch layers could not be calculated because // of invalid circular connections } graph->addItem(entry.getValue()); } graph->addVirtualConnectionNodes(); graph->sortItems(); return graph; } bool QuestGraphElement::updateElement(Framework::XML::Element& element, Framework::Zeichnung& z, Framework::UIMLContainer& generalFactory) { return false; } void QuestGraphElement::layout(Framework::XML::Element& element, Framework::Zeichnung& z, int pWidth, int pHeight, Framework::UIMLContainer& generalLayouter) { UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter); QuestGraph *graph = dynamic_cast(&z); graph->fixItemPositions(); } QuestGraphItemElement::QuestGraphItemElement() {} bool QuestGraphItemElement::isApplicableFor(Framework::XML::Element& element) { return element.getName().istGleich("questGraphItem"); } Framework::Zeichnung* QuestGraphItemElement::parseElement( Framework::XML::Element& element, Framework::UIMLContainer& generalFactory) { QuestGraphItem* item = new QuestGraphItem(); Framework::Text name = element.getAttributeValue("name"); Framework::Text description = element.getAttributeValue("description"); item->setToolTipText(name + "\n" + description, generalFactory.getFactory().initParam.bildschirm, generalFactory.getFactory().initParam.schrift); item->setHintergrundBildZ(loadImage(element.getAttributeValue("image"))); item->finished = (int)element.getAttributeValue("finished") != 0; if (item->finished) { item->setRahmenFarbe(0xFF55FF00); } item->mainQuest = (int)element.getAttributeValue("mainQuest") != 0; if (item->mainQuest) { item->setRahmenBreite(3); } item->id = element.getAttributeValue("id"); item->requirements = element.getAttributeValue("requiredQuests"); item->virtualNode = 0; return item; } bool QuestGraphItemElement::updateElement(Framework::XML::Element& element, Framework::Zeichnung& z, Framework::UIMLContainer& generalFactory) { return false; } void QuestGraphItemElement::layout(Framework::XML::Element& element, Framework::Zeichnung& z, int pWidth, int pHeight, Framework::UIMLContainer& generalLayouter) { UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter); } QuestGraphItem::QuestGraphItem() : ZeichnungHintergrund(), layerIndex(-1), nodeIndex(-1) { addStyle(ZeichnungHintergrund::Style::Sichtbar | ZeichnungHintergrund::Style::Rahmen | ZeichnungHintergrund::Style::Erlaubt | ZeichnungHintergrund::Style::HBild | ZeichnungHintergrund::Style::HBildScale | ZeichnungHintergrund::Style::HAlpha | ZeichnungHintergrund::Style::Hintergrund); setRahmenFarbe(0xFF52525E); setRahmenBreite(1); setMausEreignis(Framework::_ret1ME); } void QuestGraphItem::render(Framework::Bild& rObj) { ZeichnungHintergrund::render(rObj); // TODO } void QuestGraphItem::doMausEreignis(Framework::MausEreignis& me, bool userRet) { // TODO } const Framework::Text& QuestGraphItem::getId() const { return id; } const Framework::Text& QuestGraphItem::getRequirements() const { return requirements; } bool QuestGraphItem::calculateLaxerIndex() { int oldLayerIndex = layerIndex; int maxLayerIndex = -1; for (QuestGraphItem* item : previousLayersConnections) { if (item->getLayerIndex() < 0) return 0; if (item->getLayerIndex() > maxLayerIndex) { maxLayerIndex = item->getLayerIndex(); } } layerIndex = maxLayerIndex + 1; return oldLayerIndex != layerIndex; } int QuestGraphItem::getLayerIndex() const { return layerIndex; } void QuestGraphItem::setVirtual(bool virtualNode) { this->virtualNode = virtualNode; setStyle(ZeichnungHintergrund::Style::Sichtbar, virtualNode); } void QuestGraphItem::setNodeIndex(int index) { this->nodeIndex = nodeIndex; } void QuestGraphItem::addNextLayerRef(QuestGraphItem* zItem) { previousLayersConnections.add(zItem); } void QuestGraphItem::addPreviousLayerRef(QuestGraphItem* zItem) { nextLayersConnections.add(zItem); } const Framework::Array& QuestGraphItem::getNextLayersConnections() const { return nextLayersConnections; } int QuestGraphItem::getNodeIndex() const { return nodeIndex; } bool QuestGraphItem::isMainQuest() const { return mainQuest; } QuestGraphItemLayer::QuestGraphItemLayer() : ReferenceCounter() {} bool QuestGraphItemLayer::tick(double tickVal) { bool result = 0; for (QuestGraphItem* item : items) { result |= item->tick(tickVal); } return result; } void QuestGraphItemLayer::render(Framework::Bild& rObj) { for (QuestGraphItem* item : items) { item->render(rObj); } } void QuestGraphItemLayer::doMausEreignis(Framework::MausEreignis& me) { for (QuestGraphItem* item : items) { item->doPublicMausEreignis(me); } } void QuestGraphItemLayer::addItem(QuestGraphItem* item) { items.add(item); item->setNodeIndex(items.getEintragAnzahl() - 1); } bool QuestGraphItemLayer::sortItems() { bool changed = 0; for (int index = 0; index < items.getEintragAnzahl(); index++) { QuestGraphItem* current = items.z(index); int beforeConflicts = 0; int afterConflicts = 0; for (QuestGraphItem* connection : current->getNextLayersConnections()) { for (int j = 0; j < items.getEintragAnzahl(); j++) { if (index != j) { QuestGraphItem* other = items.z(j); for (QuestGraphItem* otherConnection : other->getNextLayersConnections()) { if (j < index && otherConnection->getNodeIndex() > connection->getNodeIndex()) { beforeConflicts++; } if ((j > index && otherConnection->getNodeIndex() < connection->getNodeIndex())) { afterConflicts++; } } } } } if (afterConflicts > beforeConflicts) { // move node down QuestGraphItem* after = items.z(index + 1); after->setNodeIndex(index); current->setNodeIndex(index + 1); items.tausch(index, index + 1); changed = 1; } else if (afterConflicts < beforeConflicts) { // move node up QuestGraphItem* before = items.z(index - 1); before->setNodeIndex(index); current->setNodeIndex(index - 1); items.tausch(index - 1, index); changed = 1; } } return changed; } bool QuestGraphItemLayer::fixItemPositions() { int y = 0; for (QuestGraphItem* item : items) { item->setPosition( item->getLayerIndex() * 150 + 10 - item->isMainQuest() * 3, y); y += item->getHeight() + 20; } return 0; } const Framework::RCArray& QuestGraphItemLayer::getItems() const { return items; } int QuestGraphItemLayer::getLeyerHeight() const { int start = 0; int end = 0; for (QuestGraphItem* item : items) { if (item->getY() < start) start = item->getY(); if (item->getY() + item->getHeight() > end) end = item->getY() + item->getHeight(); } return end - start; } void QuestGraphItemLayer::centerVertically(int pos) { int height = getLeyerHeight(); int y = pos - height / 2; for (QuestGraphItem* item : items) { item->setPosition(item->getX(), y); y += item->getHeight() + 20; } } QuestGraph::QuestGraph() : ZeichnungHintergrund() { addStyle(ZeichnungHintergrund::Style::Sichtbar | ZeichnungHintergrund::Style::Erlaubt | ZeichnungHintergrund::Style::Rahmen); setRahmenBreite(1); setRahmenFarbe(0xFF52525E); setMausEreignis(Framework::_ret1ME); } void QuestGraph::render(Framework::Bild& rObj) { if (hatStyle(ZeichnungHintergrund::Style::Sichtbar) && layers.getEintragAnzahl() > 0) { ZeichnungHintergrund::render(rObj); if (rObj.setDrawOptions(pos, gr)) { if (rObj.setDrawOptions(getRahmenBreite(), getRahmenBreite(), getInnenBreite(), getInnenHeight())) { int hScrollOffset = 0; if (hatStyle(ZeichnungHintergrund::Style::HScroll) && horizontalScrollBar) { hScrollOffset = horizontalScrollBar->getScroll(); } int vScrollOffset = 0; if (hatStyle(ZeichnungHintergrund::Style::VScroll) && vertikalScrollBar) { vScrollOffset = vertikalScrollBar->getScroll(); } if (hScrollOffset || vScrollOffset) { rObj.addScrollOffset(hScrollOffset, vScrollOffset); } for (QuestGraphItemLayer* layer : layers) { layer->render(rObj); } rObj.releaseDrawOptions(); } rObj.releaseDrawOptions(); } } } void QuestGraph::doMausEreignis(Framework::MausEreignis& me, bool userRet) { userRet &= hatStyle(ZeichnungHintergrund::Style::Sichtbar); bool vera = me.verarbeitet; if (!userRet) { me.verarbeitet = 1; } for (QuestGraphItemLayer* layer : layers) { layer->doMausEreignis(me); } if (!userRet) { me.verarbeitet = vera; } } void QuestGraph::addVirtualConnectionNodes() { int layerIndex = 0; // add virtual items for connections that do not go directly to the next // layer after this operation each node only have connections to the // immediate following layer for (QuestGraphItemLayer* layer : layers) { for (int i = 0; i < layer->getItems().getEintragAnzahl(); i++) { QuestGraphItem* item = layer->getItems().z(i); auto iterator = item->getNextLayersConnections().begin(); QuestGraphItem* virtualItem = 0; for (; iterator; iterator++) { if (iterator->getLayerIndex() > layerIndex + 1) { bool remove = 1; if (!virtualItem) { virtualItem = new QuestGraphItem(); virtualItem->addPreviousLayerRef(item); virtualItem->setVirtual(true); virtualItem->calculateLaxerIndex(); remove = 0; } item->addNextLayerRef(iterator); if (remove) { iterator.remove(); } else { iterator.set(virtualItem); } } else if (iterator->getLayerIndex() < 0) { // remove connections to invalid nodes iterator.remove(); } } if (virtualItem) { addItem(virtualItem); } } layerIndex++; } } void QuestGraph::sortItems() { bool changed = 1; while (changed) { changed = 0; for (QuestGraphItemLayer* layer : layers) { changed |= layer->sortItems(); } } } void QuestGraph::fixItemPositions() { bool changed = 1; int height = 0; while (changed) { changed = 0; for (QuestGraphItemLayer* layer : layers) { changed |= layer->fixItemPositions(); if (layer->getLeyerHeight() > height) { height = layer->getLeyerHeight(); } } } if (height > getInnenHeight()) { addStyle(ZeichnungHintergrund::Style::VScroll); setVertikalKlickScroll(10); vertikalScrollBar->update(height, getInnenHeight()); } if (layers.getEintragAnzahl() * 150 - 80 > getInnenBreite()) { addStyle(ZeichnungHintergrund::Style::HScroll); setHorizontalKlickScroll(10); horizontalScrollBar->update( layers.getEintragAnzahl() * 150 - 80, getInnenBreite()); } for (QuestGraphItemLayer* layer : layers) { layer->centerVertically(getHeight() / 2); } } void QuestGraph::addItem(QuestGraphItem* item) { int layerInex = item->getLayerIndex(); if (layerInex >= 0) { while (layerInex >= layers.getEintragAnzahl()) { layers.add(new QuestGraphItemLayer()); } layers.z(layerInex)->addItem(item); } else { invalidNodes.addItem(item); } }