/* * Copyright 2008-2009 Ben Boeckel * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ // Header include #include "WorldMapItem.h" // Sigmodr widget includes #include "TileItem.h" #include "WorldMapPlacement.h" // Sigmod includes #include #include // KDE includes #include // Qt includes #include #include #include #include #include #include #include using namespace Sigmod; using namespace Sigmodr::Widgets; static bool isSetWorldMapItem(QGraphicsItem* item) { WorldMapItem* world = qgraphicsitem_cast(item); return world && world->isLocked(); } WorldMapItem::WorldMapItem(Game* game, Map* map, QGraphicsScene* parent) : QObject(parent), m_game(game), m_map(map), m_locked(false), m_tag(new QGraphicsSimpleTextItem(this)), m_label(new QGraphicsSimpleTextItem(this)) { setAcceptHoverEvents(true); setFlags(ItemIsMovable | ItemIsFocusable | ItemDoesntPropagateOpacityToChildren); setOpacity(.5); m_tag->setText(QString::number(m_map->id())); m_tag->setPos(-5, -8); m_label->hide(); mapChanged(); } WorldMapItem::~WorldMapItem() { qDeleteAll(m_tiles); } QRectF WorldMapItem::boundingRect() const { return QRect(0, 0, m_map->width(), m_map->height()).adjusted(-1, -1, 1, 1); } void WorldMapItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(widget) painter->setPen(QPen(m_locked ? Qt::red : Qt::black, 2)); painter->drawRect(QRect(0, 0, m_map->width(), m_map->height())); painter->setBrush(QBrush(Qt::yellow)); if (option->state & QStyle::State_HasFocus) { painter->setPen(QPen(KStatefulBrush(KColorScheme::View, KColorScheme::FocusColor).brush(QPalette::Active), 3)); painter->drawRect(boundingRect()); } if (option->state & QStyle::State_MouseOver) { painter->setPen(QPen(KStatefulBrush(KColorScheme::View, KColorScheme::HoverColor).brush(QPalette::Active), 3)); painter->drawRect(boundingRect()); } } bool WorldMapItem::collidesWithItem(const QGraphicsItem* other, Qt::ItemSelectionMode mode) const { Q_UNUSED(mode) const WorldMapItem* item = qgraphicsitem_cast(other); if (!item) return false; const QRectF rect = QRectF(scenePos(), QPointF(m_map->width(), m_map->height())).adjusted(1, 1, -1, -1); const QRectF otherRect(item->scenePos(), QPointF(item->m_map->width(), item->m_map->height())); return !rect.intersected(otherRect).isNull(); } int WorldMapItem::type() const { return Type; } bool WorldMapItem::isLocked() const { return m_locked; } void WorldMapItem::focusInEvent(QFocusEvent* event) { QGraphicsItem::focusInEvent(event); update(); } void WorldMapItem::focusOutEvent(QFocusEvent* event) { QGraphicsItem::focusOutEvent(event); update(); } void WorldMapItem::hoverEnterEvent(QGraphicsSceneHoverEvent* event) { m_label->show(); QGraphicsItem::hoverEnterEvent(event); update(); } void WorldMapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) { m_label->hide(); QGraphicsItem::hoverLeaveEvent(event); update(); } void WorldMapItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { QList items = scene()->items(); QList cItems = scene()->items(QRectF(event->scenePos() - event->buttonDownPos(Qt::LeftButton), QSizeF(m_map->width(), m_map->height()))); QtConcurrent::blockingFilter(items, isSetWorldMapItem); QtConcurrent::blockingFilter(cItems, isSetWorldMapItem); items.removeAll(this); cItems.removeAll(this); if (cItems.size()) { WorldMapPlacement placement(QSize(m_map->width(), m_map->height())); foreach (QGraphicsItem* item, items) { WorldMapItem* mapItem = qgraphicsitem_cast(item); placement.addRect(QRectF(item->scenePos(), QSizeF(mapItem->m_map->width(), mapItem->m_map->height()))); } setPos(placement.find(((QPointF(m_map->width(), m_map->height()) / 2.) + event->scenePos() - event->buttonDownPos(Qt::LeftButton)).toPoint())); } else setPos(event->scenePos() - event->buttonDownPos(Qt::LeftButton)); event->accept(); moveTo(scenePos().toPoint()); update(); } void WorldMapItem::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Space) { QList items; if (!m_locked) { items = scene()->items(QRectF(scenePos(), QSizeF(m_map->width(), m_map->height()))); QtConcurrent::blockingFilter(items, isSetWorldMapItem); items.removeAll(this); QMutableListIterator i(items); while (i.hasNext()) { i.next(); if (!collidesWithItem(i.value())) i.remove(); } } if (!items.size()) { event->accept(); m_locked = !m_locked; setFlag(ItemIsMovable, !m_locked); update(); WorldMapPlacement::invalidateCache(); return; } } event->ignore(); } void WorldMapItem::moveTo(const QPoint& point) { m_game->setMapPosition(m_map->id(), point); } void WorldMapItem::mapChanged() { qDeleteAll(m_tiles); m_tiles.clear(); for (int i = 0; i < m_map->tileCount(); ++i) { TileItem* item = new TileItem(m_map, m_map->tile(i), NULL); item->setAcceptHoverEvents(false); item->setFlag(ItemIsMovable, false); item->setFlag(ItemIsSelectable, false); addToGroup(item); m_tiles.append(item); connect(this, SIGNAL(maskTiles(bool)), item, SLOT(drawCollisionMask(bool))); } resetLabel(); } void WorldMapItem::resetLabel() { m_label->setText(m_map->name()); QSizeF size = m_label->boundingRect().size() / 2 - boundingRect().size() / 2; m_label->setPos(-size.width(), -size.height()); }