diff --git a/src/gameremovedtiles.cpp b/src/gameremovedtiles.cpp index ca91170..966ecb8 100644 --- a/src/gameremovedtiles.cpp +++ b/src/gameremovedtiles.cpp @@ -1,221 +1,221 @@ /* Copyright (C) 2019 Christian Krippendorf * * Kmahjongg 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 2 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, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // own #include "gameremovedtiles.h" #include "kmahjonggtileset.h" #include "gamedata.h" // Qt #include #include #include #include #include GameRemovedTiles::GameRemovedTiles(QGraphicsObject * object) : QGraphicsObject(object) , m_width(100) , m_height(100) , m_borderWidthFrac(0.05) , m_tileScale(0.9) , m_titleHeightFrac(0.1) , m_borderWidthPixel(0) , m_titleHeightPixel(0) , m_tileSpaceRow(0) , m_tileSpaceCol(0) , m_tileFaceWidth(0) , m_tileFaceHeight(0) , m_faceScale(1.0) , m_tileFaceWidthScaled(0) , m_tileFaceHeightScaled(0) , m_maxTilesRow(0) , m_maxTilesCol(0) , m_itemFaces(new QList()) , m_tiles(nullptr) , m_gameData(nullptr) { } GameRemovedTiles::~GameRemovedTiles() { delete m_itemFaces; } void GameRemovedTiles::setSize(qreal width, qreal height) { m_width = width; m_height = height; } void GameRemovedTiles::setTileset(KMahjonggTileset * tiles) { m_tiles = tiles; } void GameRemovedTiles::prepareForGeometryChange() { prepareGeometryChange(); } void GameRemovedTiles::setGameData(GameData * gameData) { m_gameData = gameData; } void GameRemovedTiles::updateTileCalculations() { int maxTilesRow = 0; int maxTilesCol = 0; // Get the height and the width of the face tile. This has to be multiplied // by two, cause the value is related to half tile. (half positioning) m_tileFaceWidth = m_tiles->qWidth() * 2.0; m_tileFaceHeight = m_tiles->qHeight() * 2.0; m_tileFaceWidthScaled = m_tileFaceWidth * m_faceScale; m_tileFaceHeightScaled = m_tileFaceHeight * m_faceScale; m_borderWidthPixel = m_borderWidthFrac * m_width; m_titleHeightPixel = m_titleHeightFrac * m_height; maxTilesRow = static_cast( (m_width - 2 * m_borderWidthPixel) / m_tileFaceWidthScaled ); maxTilesCol = static_cast( (m_height - 2 * m_borderWidthPixel - m_titleHeightPixel) / m_tileFaceHeightScaled ); m_tileSpaceRow = ((m_width - 2 * m_borderWidthPixel) - maxTilesRow * m_tileFaceWidthScaled) / (maxTilesRow - 1); m_tileSpaceCol = ((m_height - 2 * m_borderWidthPixel - m_titleHeightPixel) - maxTilesCol * m_tileFaceHeightScaled) / (maxTilesCol - 1); m_maxTilesRow = maxTilesRow; m_maxTilesCol = maxTilesCol; } void GameRemovedTiles::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { updateTileCalculations(); // General painter settings. painter->setRenderHint(QPainter::Antialiasing); // Paint the background. painter->setOpacity(0.5); QPainterPath path; path.addRoundedRect(QRectF(0, 0, m_width, m_height), 10, 10); painter->fillPath(path, Qt::black); // Paint the title text. painter->setPen(Qt::white); QFont font(painter->font()); font.setPointSize(m_titleHeightPixel * 0.15); painter->setFont(font); painter->drawText( QRectF(m_borderWidthPixel, m_borderWidthPixel, m_width, m_titleHeightPixel), i18n("Removed tiles") ); // Exit if no tileset has been set to this object. - if (nullptr == m_tiles || m_itemFaces->size() <= 0) { + if (m_tiles == nullptr || m_itemFaces->isEmpty()) { return; } // Paint all the tiles. painter->setPen(QPen(Qt::white, 10)); unsigned int row = 0; unsigned int col = 0; int start = m_itemFaces->size() - (m_maxTilesCol * m_maxTilesRow * 2); if (start < 0) { start *= 0; } for (int pos = start; pos < m_itemFaces->size() - 1; pos+=2) { if (col >= m_maxTilesRow) { row++; col = 0; } // Get the pixmap of the face. QPixmap face; face = m_tiles->tileface(m_itemFaces->at(pos)); face = face.scaledToHeight( m_tileFaceHeightScaled, Qt::SmoothTransformation ); // Paint the background of the face. QPainterPath pixPath; pixPath.addRoundedRect( QRectF( m_borderWidthPixel + col * m_tileSpaceRow + col * m_tileFaceWidth, m_titleHeightPixel + row * m_tileSpaceCol + row * m_tileFaceHeight, m_tileFaceWidth, m_tileFaceHeight ), 10, 10 ); painter->setOpacity(1.0 - (m_itemFaces->size() - pos) / 100.0); painter->fillPath(pixPath, Qt::white); // Paint the pixmap of the face. painter->setOpacity(1.0 - (m_itemFaces->size() - pos) / 100.0); painter->drawPixmap( QPointF( m_borderWidthPixel + col * m_tileSpaceRow + col * m_tileFaceWidth, m_titleHeightPixel + row * m_tileSpaceCol + row * m_tileFaceHeight ), face ); col++; } } void GameRemovedTiles::undo() { if (m_itemFaces->size() >= 2) { m_itemFaces->removeLast(); m_itemFaces->removeLast(); } } void GameRemovedTiles::reset() { m_itemFaces->clear(); } QRectF GameRemovedTiles::boundingRect() const { return QRectF(QPointF(0.0, 0.0), QSizeF(m_width, m_height)); } QRectF GameRemovedTiles::rect() const { return boundingRect(); } void GameRemovedTiles::addItem(const POSITION & itemPos) { m_itemFaces->append(itemPos.f); } void GameRemovedTiles::removeLastItem() { m_itemFaces->removeLast(); } diff --git a/src/gamescene.cpp b/src/gamescene.cpp index 30cc78a..3028605 100644 --- a/src/gamescene.cpp +++ b/src/gamescene.cpp @@ -1,293 +1,293 @@ /* Copyright (C) 2012 Christian Krippendorf * * Kmahjongg 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ // own #include "gamescene.h" // Qt #include #include // KMahjongg #include "gamedata.h" #include "gameitem.h" #include "gameview.h" #include "kmahjongglayout.h" #include "gamebackground.h" #include "gameremovedtiles.h" GameScene::GameScene(QObject * parent) : QGraphicsScene(parent) , m_pFirstSelectedItem(nullptr) , m_pSecondSelectedItem(nullptr) , m_gameBackground(nullptr) , m_gameRemovedTiles(nullptr) { initializeGameItemsArray(); } GameScene::~GameScene() { } void GameScene::clearGameItems() { // Remove all GameItem objects and DON'T remove GameBackground object. QList items = QGraphicsScene::items(); for (int i = 0; i < items.size(); i++) { GameItem *gameItem = dynamic_cast(items.at(i)); - if (nullptr != gameItem) { + if (gameItem != nullptr) { QGraphicsScene::removeItem(gameItem); } } initializeGameItemsArray(); m_pFirstSelectedItem = nullptr; m_pSecondSelectedItem = nullptr; } void GameScene::clear() { QGraphicsScene::clear(); initializeGameItemsArray(); m_pFirstSelectedItem = nullptr; m_pSecondSelectedItem = nullptr; } void GameScene::initializeGameItemsArray() { // initialize all array pointers with nullptr. for (int i = 0; i < BOARD_WIDTH; ++i) { for (int j = 0; j < BOARD_HEIGHT; ++j) { for (int k = 0; k < BOARD_DEPTH; ++k) { m_pGameItemsArray[i][j][k] = nullptr; } } } } void GameScene::setRemovedTilesItem(GameRemovedTiles * gameRemovedTiles) { // If a removedtiles object already exist, delete it from scene - if (nullptr != m_gameRemovedTiles) { + if (m_gameRemovedTiles != nullptr) { QGraphicsScene::removeItem(m_gameRemovedTiles); } m_gameRemovedTiles = gameRemovedTiles; QGraphicsScene::addItem(gameRemovedTiles); } void GameScene::setBackgroundItem(GameBackground * gameBackground) { // If a background exist, delete it from scene - if (nullptr != m_gameBackground) { + if (m_gameBackground != nullptr) { QGraphicsScene::removeItem(m_gameBackground); } m_gameBackground = gameBackground; QGraphicsScene::addItem(gameBackground); } void GameScene::addItem(GameItem * gameItem) { QGraphicsScene::addItem(gameItem); // Add the item to the position array. addItemToPositionArray(gameItem); } void GameScene::removeItem(GameItem * gameItem) { USHORT x = gameItem->getGridPosX(); USHORT y = gameItem->getGridPosY(); USHORT z = gameItem->getGridPosZ(); m_pGameItemsArray[x][y][z] = nullptr; QGraphicsScene::removeItem(gameItem); } void GameScene::removeItem(POSITION const & stItemPos) { GameItem * gameItem = m_pGameItemsArray[stItemPos.x][stItemPos.y][stItemPos.z]; if (gameItem != nullptr) { removeItem(gameItem); } } void GameScene::addItemToPositionArray(GameItem * const gameItem) { // Take a look, if the place is already taken. USHORT x = gameItem->getGridPosX(); USHORT y = gameItem->getGridPosY(); USHORT z = gameItem->getGridPosZ(); if (m_pGameItemsArray[x][y][z] == nullptr) { m_pGameItemsArray[x][y][z] = gameItem; } } GameItem * GameScene::getItemOnGridPos(int x, int y, int z) { // Test for range if ((x < 0 || x > BOARD_WIDTH - 1) || (y < 0 || y > BOARD_HEIGHT - 1) || (z < 0 || z > BOARD_DEPTH - 1)) { return nullptr; } return m_pGameItemsArray[x][y][z]; } GameItem * GameScene::getItemOnGridPos(POSITION & stItemPos) { return getItemOnGridPos(stItemPos.x, stItemPos.y, stItemPos.z); } bool GameScene::isItemOnGridPos(int x, int y, int z) const { // Test for range if ((x < 0 || x > BOARD_WIDTH - 1) || (y < 0 || y > BOARD_HEIGHT - 1) || (z < 0 || z > BOARD_DEPTH - 1)) { return false; } return !(m_pGameItemsArray[x][y][z] == nullptr); } QList GameScene::selectedItems() const { QList originalList = QGraphicsScene::selectedItems(); QList tmpList; for (int i = 0; i < originalList.size(); ++i) { tmpList.append(dynamic_cast(originalList.at(i))); } return tmpList; } QList GameScene::items() const { QList originalList = QGraphicsScene::items(); QList tmpList; for (int i = 0; i < originalList.size(); ++i) { GameItem * gameItem = dynamic_cast(originalList.at(i)); - if (nullptr != gameItem) { + if (gameItem != nullptr) { tmpList.append(gameItem); } } return tmpList; } bool GameScene::isSelectable(const GameItem * const gameItem) const { USHORT x = gameItem->getGridPosX(); USHORT y = gameItem->getGridPosY(); USHORT z = gameItem->getGridPosZ(); // Test for items above... // We need one layer above. ++z; for (int i = x - 1; i <= x + 1; ++i) { for (int j = y - 1; j <= y + 1; ++j) { // If there is a stone on the position, the item is not selectable. if (isItemOnGridPos(i, j, z)) { return false; } } } // Test for items beside... // Go back to the layer of the item. --z; bool sideFree = true; for (int i = x - 2; i <= x + 2; i += 4) { for (int j = y - 1; j <= y + 1; ++j) { // If there is one item on the side, it is no longer free. if (isItemOnGridPos(i, j, z)) { sideFree = false; } } // If a side is free the item is selectable. if (sideFree == true) { return true; } else { sideFree = true; } } return false; } void GameScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * mouseEvent) { // Swallow this event. A double-click causes a mousePressEvent() AND a // mouseDoubleClickEvent(). The second event could cause a tile that is // NOT removable to become selected (by default), allowing it to be removed // illegally (ie. it has a tile on each side or is half under another tile). mouseEvent->accept(); // Double-click ==> single-click in KMahjongg. } void GameScene::mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent) { // N.B. Event occurs when there is a click OR double-click with ANY button. GameItem * gameItem = dynamic_cast( itemAt(mouseEvent->scenePos().x(), mouseEvent->scenePos().y(), QTransform()) ); // An item was clicked. if (gameItem != nullptr) { // If we click on a shadow of the actual item, we have to correct the // clicking position, in order to simulate a transparent shadow. if (gameItem->isShadow(mouseEvent->scenePos() - gameItem->pos())) { gameItem = dynamic_cast( itemAt(mouseEvent->scenePos().x() + gameItem->getShadowDeltaX(), mouseEvent->scenePos().y() + gameItem->getShadowDeltaY(), QTransform()) ); } } // No item was clicked. if (gameItem == nullptr) { emit clearSelectedTile(); mouseEvent->ignore(); return; } // If the item is selectable go on with selection. if (isSelectable(gameItem)) { clearSelection(); gameItem->setSelected(true); mouseEvent->accept(); } else { emit clearSelectedTile(); } } void GameScene::wheelEvent(QGraphicsSceneWheelEvent * mouseEvent) { if (mouseEvent->delta() < 0) { emit rotateCW(); } else { emit rotateCCW(); } }