mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-17 04:27:45 -07:00
Took 3 hours 38 minutes Took 11 seconds Took 9 minutes Took 2 minutes Took 22 minutes Took 43 minutes Took 4 minutes Took 31 minutes Took 7 seconds Took 1 minute [Game][Player] Pull out graphics_items out of player_logic Took 3 minutes Took 24 seconds Took 5 minutes Took 19 minutes Took 7 minutes Took 32 seconds Took 3 minutes Took 14 minutes Took 5 seconds Took 28 minutes Took 5 minutes Took 28 minutes Took 7 seconds Took 12 minutes Took 20 minutes Took 2 minutes
148 lines
6 KiB
C++
148 lines
6 KiB
C++
/**
|
|
* @file select_zone.h
|
|
* @ingroup GameGraphicsZones
|
|
* @brief Base class for zones where cards are laid out and individually interactable.
|
|
*/
|
|
|
|
#ifndef SELECTZONE_H
|
|
#define SELECTZONE_H
|
|
|
|
#include "card_zone.h"
|
|
|
|
#include <QSet>
|
|
#include <optional>
|
|
|
|
class QGraphicsRectItem;
|
|
|
|
/**
|
|
* A CardZone where the cards are laid out, with each card directly interactable by clicking.
|
|
*/
|
|
class SelectZone : public CardZone
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
/**
|
|
* @brief Finds the SelectZone that owns a card, regardless of whether the card is parented
|
|
* to the zone directly or to its clip container. Returns nullptr if not in a SelectZone.
|
|
*/
|
|
static SelectZone *findOwningSelectZone(const QGraphicsItem *card);
|
|
|
|
SelectZone(CardZoneLogic *logic, QGraphicsItem *parent = nullptr);
|
|
~SelectZone() override;
|
|
void onCardAdded(CardState *addedCard, int x, int y) override;
|
|
|
|
/**
|
|
* @brief Temporarily reparents a card from the clip container to this zone so hover scaling is visible beyond clip
|
|
* bounds. Safe no-op if no clip container exists. Coordinates are preserved (clip container is at (0,0) with no
|
|
* transform).
|
|
*/
|
|
void escapeClipForHover(QGraphicsItem *card);
|
|
/**
|
|
* @brief Restores a hover-escaped card back to the clip container. Guards against zone transitions that already
|
|
* reparented the card.
|
|
*/
|
|
void restoreClipAfterHover(QGraphicsItem *card);
|
|
|
|
private:
|
|
QPointF selectionOrigin;
|
|
QSet<CardItem *> cardsInSelectionRect;
|
|
/**
|
|
* @brief Invisible clipping parent for cards; owned by Qt parent-child tree (parented to this zone).
|
|
* Created by setupClipContainer(); null when no clip container is active.
|
|
*/
|
|
QGraphicsRectItem *cardClipContainer = nullptr;
|
|
|
|
protected:
|
|
// -- Layout computation --
|
|
|
|
/** @brief Parameters describing a vertical card stack's geometry. */
|
|
struct StackLayoutParams
|
|
{
|
|
int cardCount; ///< Number of cards in the stack
|
|
qreal totalHeight; ///< Available height for the stack (zone height)
|
|
qreal cardHeight; ///< Height of a single card
|
|
qreal desiredOffset; ///< Preferred vertical offset between card tops
|
|
qreal minOffset = 0.0; ///< Minimum offset to preserve (0 allows full compression)
|
|
/**
|
|
* @brief When false (default), reserves full cardHeight for the bottom card, ensuring
|
|
* all cards remain within zone bounds. When true, allows the bottom card to
|
|
* partially overflow using sqrt-scaled allowance. Use with setupClipContainer()
|
|
* for zones too short to fit a full card.
|
|
*/
|
|
bool allowBottomOverflow = false;
|
|
};
|
|
|
|
/** @brief Result of computing a vertical stack layout. */
|
|
struct ZoneLayout
|
|
{
|
|
qreal effectiveOffset; ///< Actual offset between card tops (may be compressed)
|
|
qreal start; ///< Y coordinate of the first card's top edge
|
|
};
|
|
|
|
/** @brief Minimum visible pixels of each card's top edge when stacking compresses offsets in tight zones. */
|
|
static constexpr qreal MIN_CARD_VISIBLE = 10.0;
|
|
|
|
/**
|
|
* @brief Computes layout for a vertical card stack (effective offset and start position).
|
|
*
|
|
* Three regimes:
|
|
* 1. Minimized zone (totalHeight < card height with minOffset > 0): offsets compress
|
|
* so each card retains at least minOffset visible pixels of its top edge.
|
|
* 2. Normal zone with allowBottomOverflow=false (default): the bottom card is
|
|
* guaranteed to fit within the zone boundary. Offsets compress as needed.
|
|
* 3. Normal zone with allowBottomOverflow=true: the bottom card may partially
|
|
* overflow. The overflow allowance is scaled by sqrt(cardCount-1) so that
|
|
* adding one card shifts existing cards smoothly.
|
|
*
|
|
* When the stack fits with room to spare, it is centered vertically.
|
|
*/
|
|
static ZoneLayout computeZoneLayout(const StackLayoutParams ¶ms);
|
|
|
|
/** @brief Builds StackLayoutParams from the current card list and zone geometry. */
|
|
StackLayoutParams buildStackParams(qreal minOffset = 0.0) const;
|
|
|
|
/**
|
|
* @brief Computes the card index at a given y-coordinate within the zone's vertical layout.
|
|
* Returns 0 if the zone has no cards or the offset is zero.
|
|
*/
|
|
int calcDropIndexFromY(qreal dropY, qreal minOffset = 0.0) const;
|
|
|
|
/**
|
|
* @brief Positions cards vertically with alternating left/right x-offsets.
|
|
*
|
|
* Cards alternate between left and right margins (5px padding from zone edges):
|
|
* even-indexed cards at left, odd-indexed at right.
|
|
* Cards are assigned ascending z-values.
|
|
*
|
|
* @param params Stack layout geometry parameters (use allowBottomOverflow to control overflow)
|
|
*/
|
|
void layoutCardsVertically(const StackLayoutParams ¶ms);
|
|
|
|
// -- Clip container --
|
|
// The clip container mechanism is available for future zones that need visual clipping
|
|
// (e.g., zones too short to fit a full card). To enable: call setupClipContainer() in the
|
|
// zone's constructor, and set allowBottomOverflow=true in layout params.
|
|
|
|
/**
|
|
* @brief Restores any cards that were hover-escaped but whose hover state was not properly cleaned up.
|
|
* Call at the start of reorganizeCards() in zones that use a clip container.
|
|
*/
|
|
void restoreStaleEscapedCards();
|
|
|
|
/**
|
|
* @brief Creates a clip container child item that clips card overflow to zone bounds.
|
|
* Cards entering this zone are reparented to this container by the onCardAdded override.
|
|
* Disables zone-level child clipping; clipping is delegated to the container.
|
|
* @param zValue Optional z-value for the clip container (e.g. ZValues::CARD_BASE)
|
|
*/
|
|
void setupClipContainer(std::optional<qreal> zValue = std::nullopt);
|
|
|
|
/** @brief Updates the clip container rect to match this zone's current boundingRect(). */
|
|
void updateClipRect();
|
|
|
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
|
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
|
};
|
|
|
|
#endif
|