mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
292 lines
9.6 KiB
C++
292 lines
9.6 KiB
C++
/*
|
|
* graphicelements.cpp, part of VCMI engine
|
|
*
|
|
* Authors: listed in file AUTHORS in main folder
|
|
*
|
|
* License: GNU General Public License v2.0 or later
|
|
* Full text of license available in license.txt file, in main folder
|
|
*
|
|
*/
|
|
#include "StdInc.h"
|
|
|
|
#include "graphicelements.h"
|
|
|
|
#include <QObject>
|
|
|
|
#include "../../lib/constants/EntityIdentifiers.h"
|
|
#include "../../lib/rmg/CRmgTemplate.h"
|
|
|
|
QDomElement CardItem::getElementById(const QDomDocument& doc, const QString& id)
|
|
{
|
|
QDomElement root = doc.documentElement();
|
|
|
|
std::function<QDomElement(const QDomElement&)> findById = [&](const QDomElement& elem) -> QDomElement {
|
|
if (elem.attribute("id") == id)
|
|
return elem;
|
|
|
|
QDomElement child = elem.firstChildElement();
|
|
while (!child.isNull())
|
|
{
|
|
QDomElement found = findById(child);
|
|
if (!found.isNull())
|
|
return found;
|
|
child = child.nextSiblingElement();
|
|
}
|
|
return QDomElement();
|
|
};
|
|
|
|
return findById(root);
|
|
}
|
|
|
|
bool isBlackTextNeeded(const QColor& bg)
|
|
{
|
|
int r = bg.red();
|
|
int g = bg.green();
|
|
int b = bg.blue();
|
|
|
|
double luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
return luminance > 0.5;
|
|
}
|
|
|
|
CardItem::CardItem():
|
|
selectCallback(nullptr),
|
|
posChangeCallback(nullptr),
|
|
useBlackText(false),
|
|
mousePressed(false)
|
|
{
|
|
QFile file(":/icons/templateSquare.svg");
|
|
file.open(QIODevice::ReadOnly);
|
|
QByteArray data = file.readAll();
|
|
doc.setContent(data);
|
|
|
|
updateContent();
|
|
}
|
|
|
|
void CardItem::setSelectCallback(std::function<void(bool)> func)
|
|
{
|
|
selectCallback = func;
|
|
}
|
|
|
|
void CardItem::setPosChangeCallback(std::function<void(QPointF)> func)
|
|
{
|
|
posChangeCallback = func;
|
|
}
|
|
|
|
void CardItem::updateContent()
|
|
{
|
|
setSharedRenderer(new QSvgRenderer(doc.toByteArray()));
|
|
}
|
|
|
|
void CardItem::setFillColor(QColor color)
|
|
{
|
|
auto squareElem = getElementById(doc, "rect");
|
|
squareElem.setAttribute("style", squareElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:" + color.name() + ";"));
|
|
|
|
useBlackText = isBlackTextNeeded(color);
|
|
}
|
|
|
|
void CardItem::setMultiFillColor(QColor color1, QColor color2)
|
|
{
|
|
auto squareElem = getElementById(doc, "rect");
|
|
squareElem.setAttribute("style", squareElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:url(#gradientExtra);"));
|
|
auto gradientStopElem1 = getElementById(doc, "gradientExtraColorStop1");
|
|
auto gradientStopElem2 = getElementById(doc, "gradientExtraColorStop2");
|
|
auto gradientStopElem3 = getElementById(doc, "gradientExtraColorStop3");
|
|
auto gradientStopElem4 = getElementById(doc, "gradientExtraColorStop4");
|
|
auto gradientStopElem5 = getElementById(doc, "gradientExtraColorStop5");
|
|
gradientStopElem1.setAttribute("style", gradientStopElem1.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + color1.name() + ";"));
|
|
gradientStopElem2.setAttribute("style", gradientStopElem2.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + color2.name() + ";"));
|
|
gradientStopElem3.setAttribute("style", gradientStopElem3.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + color1.name() + ";"));
|
|
gradientStopElem4.setAttribute("style", gradientStopElem4.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + color2.name() + ";"));
|
|
gradientStopElem5.setAttribute("style", gradientStopElem5.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + color1.name() + ";"));
|
|
|
|
useBlackText = isBlackTextNeeded(color1);
|
|
}
|
|
|
|
void CardItem::setPlayerColor(PlayerColor color)
|
|
{
|
|
std::map<PlayerColor, std::pair<QString, QString>> colors =
|
|
{
|
|
{ PlayerColor(0), { "#F80000", "#920000" } }, //red
|
|
{ PlayerColor(1), { "#0000F8", "#000092" } }, //blue
|
|
{ PlayerColor(2), { "#9B7251", "#35271C" } }, //tan
|
|
{ PlayerColor(3), { "#00FC00", "#009600" } }, //green
|
|
{ PlayerColor(4), { "#F88000", "#924B00" } }, //orange
|
|
{ PlayerColor(5), { "#F800F8", "#920092" } }, //purple
|
|
{ PlayerColor(6), { "#00FCF8", "#009694" } }, //teal
|
|
{ PlayerColor(7), { "#C07888", "#5A3840" } }, //pink
|
|
};
|
|
auto squareElem = getElementById(doc, "rect");
|
|
squareElem.setAttribute("style", squareElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:url(#gradientPlayer);"));
|
|
auto gradientStopElem1 = getElementById(doc, "gradientPlayerColorStop1");
|
|
auto gradientStopElem2 = getElementById(doc, "gradientPlayerColorStop2");
|
|
gradientStopElem1.setAttribute("style", gradientStopElem1.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + colors[color].first + ";"));
|
|
gradientStopElem2.setAttribute("style", gradientStopElem2.attribute("style").replace(QRegularExpression("stop-color:.*?;"), "stop-color:" + colors[color].second + ";"));
|
|
|
|
useBlackText = isBlackTextNeeded(QColor(colors[color].first));
|
|
}
|
|
|
|
void CardItem::setJunction(bool val)
|
|
{
|
|
auto squareElem = getElementById(doc, "rectJunction");
|
|
squareElem.setAttribute("style", squareElem.attribute("style").replace(QRegularExpression("stroke-opacity:.*?;"), "stroke-opacity:" + QString::fromStdString(val ? "0.3" : "0.0") + ";"));
|
|
}
|
|
|
|
void CardItem::setId(int val)
|
|
{
|
|
auto textIdElem = getElementById(doc, "textId");
|
|
textIdElem.setAttribute("style", textIdElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:" + QColor(useBlackText ? Qt::black : Qt::white).name() + ";"));
|
|
textIdElem.firstChild().setNodeValue(QString::number(val));
|
|
|
|
id = val;
|
|
}
|
|
|
|
int CardItem::getId()
|
|
{
|
|
return id;
|
|
}
|
|
|
|
void CardItem::setResAmount(GameResID res, int val)
|
|
{
|
|
std::map<GameResID, QString> names =
|
|
{
|
|
{ GameResID::WOOD, "Wood" },
|
|
{ GameResID::ORE, "Ore" },
|
|
{ GameResID::MERCURY, "Mercury" },
|
|
{ GameResID::SULFUR, "Sulfur" },
|
|
{ GameResID::CRYSTAL, "Crystal" },
|
|
{ GameResID::GEMS, "Gems" },
|
|
{ GameResID::GOLD, "Gold" },
|
|
};
|
|
auto textElem = getElementById(doc, "text" + names[res]);
|
|
textElem.setAttribute("style", textElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:" + QColor(useBlackText ? Qt::black : Qt::white).name() + ";"));
|
|
textElem.firstChild().setNodeValue(val ? QString::number(val) : "");
|
|
|
|
auto iconElem = getElementById(doc, "icon" + names[res]);
|
|
iconElem.setAttribute("opacity", val ? "1.0" : "0.1");
|
|
}
|
|
|
|
void CardItem::setChestValue(int val)
|
|
{
|
|
auto textElem = getElementById(doc, "textChest");
|
|
textElem.setAttribute("style", textElem.attribute("style").replace(QRegularExpression("fill:.*?;"), "fill:" + QColor(useBlackText ? Qt::black : Qt::white).name() + ";"));
|
|
textElem.firstChild().setNodeValue(val ? QString::number(val) : "");
|
|
|
|
auto iconElem = getElementById(doc, "iconChest");
|
|
iconElem.setAttribute("opacity", val ? "1.0" : "0.1");
|
|
}
|
|
|
|
void CardItem::setSword(EMonsterStrength::EMonsterStrength val)
|
|
{
|
|
int level = 0;
|
|
if(val == EMonsterStrength::ZONE_WEAK || val == EMonsterStrength::GLOBAL_WEAK)
|
|
level = 1;
|
|
else if(val == EMonsterStrength::ZONE_NORMAL || val == EMonsterStrength::GLOBAL_NORMAL)
|
|
level = 2;
|
|
else if(val == EMonsterStrength::ZONE_STRONG || val == EMonsterStrength::GLOBAL_STRONG)
|
|
level = 3;
|
|
|
|
getElementById(doc, "iconSword1").setAttribute("opacity", level > 0 ? "1.0" : "0.1");
|
|
getElementById(doc, "iconSword2").setAttribute("opacity", level > 1 ? "1.0" : "0.1");
|
|
getElementById(doc, "iconSword3").setAttribute("opacity", level > 2 ? "1.0" : "0.1");
|
|
}
|
|
|
|
void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if(event->button() == Qt::LeftButton)
|
|
{
|
|
// set element in grid
|
|
double xx = x() + (boundingRect().width() / 2);
|
|
double yy = y() + (boundingRect().height() / 2);
|
|
xx = GRID_SIZE * round(xx / GRID_SIZE);
|
|
yy = GRID_SIZE * round(yy / GRID_SIZE);
|
|
setPos(xx - (boundingRect().width() / 2), yy - (boundingRect().height() / 2));
|
|
}
|
|
|
|
QGraphicsSvgItem::mouseReleaseEvent(event);
|
|
|
|
if(posChangeCallback)
|
|
posChangeCallback(pos());
|
|
|
|
mousePressed = false;
|
|
}
|
|
|
|
void CardItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
QGraphicsSvgItem::mousePressEvent(event);
|
|
|
|
mousePressed = true;
|
|
}
|
|
|
|
QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value)
|
|
{
|
|
if(change == ItemSelectedHasChanged && selectCallback)
|
|
selectCallback(isSelected());
|
|
else if(change == ItemPositionHasChanged && posChangeCallback && mousePressed)
|
|
posChangeCallback(pos());
|
|
|
|
return QGraphicsSvgItem::itemChange(change, value);
|
|
}
|
|
|
|
LineItem::LineItem():
|
|
clickCallback(nullptr)
|
|
{
|
|
setZValue(-2);
|
|
for(int i = 0; i < 10; i++) // render multiple times to increase outline effect
|
|
{
|
|
auto tmpTextItem = new QGraphicsTextItem(this);
|
|
tmpTextItem->setZValue(-1);
|
|
QFont font;
|
|
font.setPointSize(18);
|
|
tmpTextItem->setFont(font);
|
|
QGraphicsDropShadowEffect *shadowEffect = new QGraphicsDropShadowEffect();
|
|
shadowEffect->setBlurRadius(10);
|
|
shadowEffect->setEnabled(true);
|
|
shadowEffect->setOffset(0, 0);
|
|
shadowEffect->setColor(Qt::black);
|
|
tmpTextItem->setGraphicsEffect(shadowEffect);
|
|
tmpTextItem->setDefaultTextColor(Qt::white);
|
|
textItem.push_back(tmpTextItem);
|
|
}
|
|
}
|
|
|
|
void LineItem::setLineToolTip(const QString &toolTip)
|
|
{
|
|
for(auto & tmpTextItem : textItem)
|
|
tmpTextItem->setToolTip(toolTip);
|
|
setToolTip(toolTip);
|
|
}
|
|
|
|
void LineItem::setClickCallback(std::function<void()> func)
|
|
{
|
|
clickCallback = func;
|
|
}
|
|
|
|
void LineItem::setText(QString text)
|
|
{
|
|
for(auto & tmpTextItem : textItem)
|
|
{
|
|
tmpTextItem->setPlainText(text);
|
|
QRectF lineRect = boundingRect();
|
|
QRectF textRect = tmpTextItem->boundingRect();
|
|
tmpTextItem->setPos(QPointF(lineRect.x() + (lineRect.width() / 2) - (textRect.width() / 2), lineRect.y() + (lineRect.height() / 2) - (textRect.height() / 2)));
|
|
}
|
|
}
|
|
|
|
void LineItem::setId(int val)
|
|
{
|
|
id = val;
|
|
}
|
|
|
|
int LineItem::getId()
|
|
{
|
|
return id;
|
|
}
|
|
|
|
void LineItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if(event->button() == Qt::LeftButton && clickCallback)
|
|
clickCallback();
|
|
|
|
QGraphicsLineItem::mousePressEvent(event);
|
|
} |