File indexing completed on 2024-05-19 04:07:50

0001 /*
0002     SPDX-FileCopyrightText: 2010 Stefan Majewsky <majewsky@gmx.net>
0003     SPDX-FileCopyrightText: 2010 Johannes Löhnert <loehnert.kde@gmx.de>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #ifndef PALAPELI_PIECE_H
0009 #define PALAPELI_PIECE_H
0010 
0011 #include "basics.h"
0012 #include "piecevisuals.h"
0013 
0014 class QPropertyAnimation;
0015 
0016 namespace Palapeli
0017 {
0018     class MovePieceInteractor;
0019     class PieceVisuals;
0020 
0021     class Piece : public Palapeli::GraphicsObject<Palapeli::PieceUserType>
0022     {
0023         Q_OBJECT
0024         Q_PROPERTY(qreal activeShadowOpacity READ activeShadowOpacity WRITE setActiveShadowOpacity)
0025         public:
0026             /// This constructor is used when the piece is loaded
0027             /// from the puzzle file as a single unjoined piece.
0028             explicit Piece(const QImage& pieceImage, const QPoint& offset);
0029             /// This constructor is used when several pieces are
0030             /// joined to create a new piece, either after a user's
0031             /// move or when such a piece is re-created at puzzle
0032             /// load time (without animation). The joined piece will
0033             /// be without a shadow, unless shadows are provided
0034             /// explicitly.
0035             explicit Piece(const Palapeli::PieceVisuals& pieceVisuals, const Palapeli::PieceVisuals& shadowVisuals = Palapeli::PieceVisuals(), const Palapeli::PieceVisuals& highlightVisuals = Palapeli::PieceVisuals());
0036             ///This method will
0037             ///\li create a shadow for this piece if there is none ATM.
0038             ///\li apply the bevel map to the piece pixmap.
0039             ///These operations need not be done until the piece is about to be shown.
0040             ///\return whether something needed to be done
0041             bool completeVisuals();
0042 
0043             ///Returns the bounding rect without shadows.
0044             QRectF bareBoundingRect() const;
0045             QRectF sceneBareBoundingRect() const;
0046             Palapeli::PieceVisuals pieceVisuals() const;
0047             bool hasShadow() const;
0048             bool hasHighlight() const;
0049             Palapeli::PieceVisuals shadowVisuals() const;
0050             Palapeli::PieceVisuals highlightVisuals() const;
0051             void createHighlight(const QSizeF& pieceAreaSize);
0052 
0053             bool isSelected() const;
0054             void setSelected(bool selected);
0055             void startClick();
0056             void endClick();
0057             ///Returns the corresponding piece for an \a item found e.g. in QGraphicsScene::selectedItems(). This is different from a simple qgraphicsitem_cast because, internally, when you call setSelected(true) on a piece, a child item of this Piece is selected.
0058             ///\return 0 if the given \a item does not belong to a Piece
0059             static Palapeli::Piece* fromSelectedItem(QGraphicsItem* item);
0060 
0061             ///This method lets the piece remember which atomic pieces it represents. (Atomic pieces are what the scene creates when the puzzle is loaded.)
0062             void addRepresentedAtomicPieces(const QList<int>& representedAtomicPieces);
0063             QList<int> representedAtomicPieces() const;
0064             void addLogicalNeighbors(const QList<Palapeli::Piece*>& logicalNeighbors);
0065             QList<Palapeli::Piece*> logicalNeighbors() const;
0066             void addAtomicSize(const QSize& size);
0067             ///This method returns the biggest size of an atomic piece contained in this piece.
0068             QSize atomicSize() const;
0069 
0070             ///When piece instances have been replaced by other piece instances, this method can be used to update the internal data structures of their logical neighbors.
0071             void rewriteLogicalNeighbors(const QList<Palapeli::Piece*>& oldPieces, Palapeli::Piece* newPiece);
0072             ///Call this when this piece instance has been replaced by another piece instance. This will also delete this instance.
0073             void announceReplaced(Palapeli::Piece* replacement);
0074             /// Place piece in a grid-cell, randomly or centered.
0075             void setPlace(const QPointF& topLeft, int x, int y,
0076                     const QSizeF& area, bool random);
0077         Q_SIGNALS:
0078             void moved(bool finished);
0079             void replacedBy(Palapeli::Piece* newPiece);
0080         protected:
0081             friend class MovePieceInteractor;
0082             void beginMove();
0083             void doMove();
0084             void endMove();
0085         private Q_SLOTS:
0086             void pieceItemSelectedChanged(bool selected);
0087         private:
0088             void commonInit(const Palapeli::PieceVisuals& pieceVisuals);
0089             void createShadowItems(const Palapeli::PieceVisuals& shadowVisuals);
0090             qreal activeShadowOpacity() const;
0091             void setActiveShadowOpacity(qreal opacity);
0092 
0093             QGraphicsPixmapItem* m_pieceItem;
0094             QGraphicsPixmapItem* m_inactiveShadowItem;
0095             QGraphicsPixmapItem* m_activeShadowItem;
0096             QGraphicsPixmapItem* m_highlightItem; // IDW test.
0097             QPropertyAnimation* m_animator;
0098             QPoint m_offset; // IDW test.
0099 
0100             QList<int> m_representedAtomicPieces;
0101             QList<Palapeli::Piece*> m_logicalNeighbors;
0102             QSize m_atomicSize;
0103     };
0104 }
0105 
0106 #endif // PALAPELI_PIECE_H