Compare commits

..

No commits in common. "48776cfebaae943dff65509be438da1344431b05" and "ef3929356b4b6a6b2d1a242c4609b39bb2106839" have entirely different histories.

10 changed files with 22 additions and 144 deletions

View file

@ -1,26 +0,0 @@
#ifndef ANIMATED_ITEM_H
#define ANIMATED_ITEM_H
/**
* @file animated_item.h
* @ingroup GameGraphics
* @brief Interface for scene items driven by GameScene's shared animation timer.
*
* Items that want per-tick animation while a single QBasicTimer runs (instead of
* owning their own QTimer) implement this interface and register with the scene
* via GameScene::registerAnimationItem.
*/
class IAnimatedItem
{
public:
virtual ~IAnimatedItem() = default;
/**
* @brief Advances the item's animation by one timer tick.
* @return true while the animation is still running, false once it has finished.
*/
virtual bool animationEvent() = 0;
};
#endif

View file

@ -305,11 +305,6 @@ void AbstractCardItem::setTapped(bool _tapped, bool canAnimate)
}
}
bool AbstractCardItem::animationEvent()
{
return false;
}
void AbstractCardItem::setFaceDown(bool _facedown)
{
facedown = _facedown;

View file

@ -7,7 +7,6 @@
#ifndef ABSTRACTCARDITEM_H
#define ABSTRACTCARDITEM_H
#include "../animated_item.h"
#include "../card_dimensions.h"
#include "arrow_target.h"
#include "graphics_item_type.h"
@ -17,7 +16,7 @@
class PlayerLogic;
class AbstractCardItem : public ArrowTarget, public IAnimatedItem
class AbstractCardItem : public ArrowTarget
{
Q_OBJECT
protected:
@ -127,9 +126,6 @@ public:
emit deleteCardInfoPopup(cardRef.name);
}
/** @brief Default: no per-tick animation. Subclasses override to animate. */
bool animationEvent() override;
protected:
void transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle);
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;

View file

@ -137,7 +137,7 @@ public:
void resetState(bool keepAnnotations = false);
void processCardInfo(const ServerInfo_Card &_info);
bool animationEvent() override;
bool animationEvent();
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool forceFaceDown);
void deleteDragItem();
void drawArrow(const QColor &arrowColor);

View file

@ -17,6 +17,7 @@
#include <QDebug>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>
#include <QSet>
#include <QtMath>
#include <libcockatrice/settings/interface_settings.h>
#include <libcockatrice/utility/zone_names.h>
@ -44,14 +45,7 @@ GameScene::GameScene(PhasesToolbar *_phasesToolbar, QObject *parent)
GameScene::~GameScene()
{
// Sever all incoming connections (animated item destroy-tracking) before the
// members below are destroyed: the base QGraphicsScene destructor destroys the
// remaining items, and their destroyed() signals must not reach slots that
// reference members that no longer exist.
disconnect(this);
delete animationTimer;
animationTimer = nullptr;
// Delete all ArrowItems before QGraphicsScene's base destructor runs.
// QGraphicsScene::~QGraphicsScene() destroys items in arbitrary order.
@ -742,45 +736,30 @@ bool GameScene::event(QEvent *event)
void GameScene::timerEvent(QTimerEvent * /*event*/)
{
QMutableHashIterator<QObject *, IAnimatedItem *> i(animatedItems);
QMutableSetIterator<CardItem *> i(cardsToAnimate);
while (i.hasNext()) {
i.next();
if (!i.value()->animationEvent()) {
i.remove();
}
}
if (animatedItems.isEmpty()) {
if (cardsToAnimate.isEmpty()) {
animationTimer->stop();
}
}
void GameScene::registerAnimationItem(IAnimatedItem *item)
void GameScene::registerAnimationItem(AbstractCardItem *card)
{
auto *object = dynamic_cast<QObject *>(item);
if (!object) {
return;
}
if (!animatedItems.contains(object)) {
connect(object, &QObject::destroyed, this, &GameScene::removeAnimatedItem);
}
animatedItems.insert(object, item);
if (animationTimer && !animationTimer->isActive()) {
cardsToAnimate.insert(static_cast<CardItem *>(card));
if (!animationTimer->isActive()) {
animationTimer->start(10, this);
}
}
void GameScene::unregisterAnimationItem(IAnimatedItem *item)
void GameScene::unregisterAnimationItem(AbstractCardItem *card)
{
animatedItems.remove(dynamic_cast<QObject *>(item));
if (animationTimer && animatedItems.isEmpty()) {
animationTimer->stop();
}
}
void GameScene::removeAnimatedItem(QObject *item)
{
animatedItems.remove(item);
if (animationTimer && animatedItems.isEmpty()) {
cardsToAnimate.remove(static_cast<CardItem *>(card));
if (cardsToAnimate.isEmpty()) {
animationTimer->stop();
}
}

View file

@ -4,14 +4,13 @@
#include "../game/arrow_registry.h"
#include "../game/board/arrow_data.h"
#include "../game/zones/card_zone_logic.h"
#include "animated_item.h"
#include "board/arrow_item.h"
#include <QGraphicsScene>
#include <QHash>
#include <QList>
#include <QLoggingCategory>
#include <QPointer>
#include <QSet>
inline Q_LOGGING_CATEGORY(GameSceneLog, "game_scene");
inline Q_LOGGING_CATEGORY(GameScenePlayerAdditionRemovalLog, "game_scene.player_addition_removal");
@ -25,7 +24,6 @@ class CardItem;
class ServerInfo_Card;
class PhasesToolbar;
class QBasicTimer;
class QObject;
/**
* @class GameScene
@ -52,8 +50,8 @@ private:
QList<ZoneViewWidget *> zoneViews; ///< Active zone view widgets
QSize viewSize; ///< Current view size
QPointer<CardItem> hoveredCard; ///< Currently hovered card
QBasicTimer *animationTimer; ///< Timer for scene animations
QHash<QObject *, IAnimatedItem *> animatedItems; ///< Items currently animating
QBasicTimer *animationTimer; ///< Timer for card animations
QSet<CardItem *> cardsToAnimate; ///< Cards currently animating
int playerRotation; ///< Rotation offset for player layout
/**
@ -184,24 +182,15 @@ public:
/** @brief Updates hovered card highlighting. */
void updateHoveredCard(CardItem *newCard);
/**
* @brief Registers an item for animation updates with the shared scene timer.
*
* The item must inherit QObject; it is unregistered automatically when it is
* destroyed, so it may be deleted mid-animation without a dangling pointer.
*/
void registerAnimationItem(IAnimatedItem *item);
/** @brief Registers a card for animation updates. */
void registerAnimationItem(AbstractCardItem *card);
/** @brief Unregisters an item from animation updates. */
void unregisterAnimationItem(IAnimatedItem *item);
/** @brief Unregisters a card from animation updates. */
void unregisterAnimationItem(AbstractCardItem *card);
void startRubberBand(const QPointF &selectionOrigin);
void resizeRubberBand(const QPointF &cursorPoint, int selectedCount);
void stopRubberBand();
private slots:
/** @brief Removes a destroyed item from the animation set. */
void removeAnimatedItem(QObject *item);
public slots:
void onCardSelectionChanged(AbstractCardItem *card, bool selected);
void onCardRightClicked(AbstractCardItem *card, QPoint screenPos);

View file

@ -13,7 +13,6 @@
#include <QDesktopServices>
#include <QMouseEvent>
#include <QScrollBar>
#include <QTimer>
#include <libcockatrice/card/database/card_database_manager.h>
#include <libcockatrice/network/server/remote/user_level.h>
#include <libcockatrice/settings/chat_settings.h>
@ -52,9 +51,6 @@ ChatView::ChatView(TabSupervisor *_tabSupervisor, AbstractGame *_game, bool _sho
setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
setOpenLinks(false);
connect(this, &ChatView::anchorClicked, this, &ChatView::openLink);
connect(verticalScrollBar(), &QScrollBar::rangeChanged, this, &ChatView::onScrollBarRangeChanged);
connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &ChatView::onScrollBarValueChanged);
}
void ChatView::adjustColorsToPalette()
@ -155,7 +151,7 @@ void ChatView::appendHtml(const QString &html)
bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum();
prepareBlock().insertHtml(html);
if (atBottom) {
scrollToBottom();
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
}
@ -173,7 +169,7 @@ void ChatView::appendHtmlServerMessage(const QString &html, bool optionalIsBold,
prepareBlock().insertHtml(htmlText);
if (atBottom) {
scrollToBottom();
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
}
@ -342,36 +338,11 @@ void ChatView::appendMessage(QString message,
}
}
// ChatHistory messages are only ever sent once per room, right after joining, before the user can
// interact with the view. Always scroll to the bottom so the whole history is visible on join.
if (atBottom || messageType.testFlag(Event_RoomSay::ChatHistory)) {
scrollToBottom();
}
}
void ChatView::scrollToBottom()
{
// The document layout, and therefore the scrollbar range, may be updated asynchronously (e.g. while
// the chat history is loaded into a view that has not been laid out yet). Setting the value once is
// not enough: keep stickToBottom set so any later range change scrolls to the new maximum as well.
stickToBottom = true;
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
void ChatView::onScrollBarRangeChanged()
{
if (stickToBottom) {
if (atBottom) {
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
}
void ChatView::onScrollBarValueChanged(int value)
{
if (value < verticalScrollBar()->maximum()) {
stickToBottom = false;
}
}
void ChatView::checkTag(QTextCursor &cursor, QString &message)
{
if (message.startsWith("[card]")) {

View file

@ -60,7 +60,6 @@ private:
QStringList highlightedWords;
bool evenNumber;
bool showTimestamps;
bool stickToBottom = false;
HoveredItemType hoveredItemType;
QString hoveredContent;
QAction *messageClicked;
@ -68,7 +67,6 @@ private:
[[nodiscard]] QTextFragment getFragmentUnderMouse(const QPoint &pos) const;
QTextCursor prepareBlock(bool same = false);
void scrollToBottom();
void appendCardTag(QTextCursor &cursor, const QString &cardName);
void appendUrlTag(QTextCursor &cursor, QString url);
static QColor getCustomMentionColor();
@ -90,8 +88,6 @@ private slots:
void actMessageClicked();
void adjustColorsToPalette();
void refreshBlockColors();
void onScrollBarRangeChanged();
void onScrollBarValueChanged(int value);
public:
ChatView(TabSupervisor *_tabSupervisor, AbstractGame *_game, bool _showTimestamps, QWidget *parent = nullptr);

View file

@ -116,13 +116,8 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage()
connect(&tapAnimationCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance().cardsDisplay(),
&CardsDisplaySettings::setTapAnimation);
connect(&enableAllAnimationsButton, &QPushButton::clicked, this, &UserInterfaceSettingsPage::enableAllAnimations);
connect(&disableAllAnimationsButton, &QPushButton::clicked, this, &UserInterfaceSettingsPage::disableAllAnimations);
auto *animationGrid = new QGridLayout;
animationGrid->addWidget(&enableAllAnimationsButton, 0, 0);
animationGrid->addWidget(&disableAllAnimationsButton, 0, 1);
animationGrid->addWidget(&tapAnimationCheckBox, 1, 0);
animationGrid->addWidget(&tapAnimationCheckBox, 0, 0);
animationGroupBox = new QGroupBox;
animationGroupBox->setLayout(animationGrid);
@ -273,16 +268,6 @@ void UserInterfaceSettingsPage::setNotificationEnabled(QT_STATE_CHANGED_T i)
}
}
void UserInterfaceSettingsPage::enableAllAnimations()
{
tapAnimationCheckBox.setChecked(true);
}
void UserInterfaceSettingsPage::disableAllAnimations()
{
tapAnimationCheckBox.setChecked(false);
}
void UserInterfaceSettingsPage::updateCommanderSpellbookUiState()
{
const int mode = SettingsCache::instance().deckEditor().getCommanderSpellbookIntegrationEnabled();
@ -325,8 +310,6 @@ void UserInterfaceSettingsPage::retranslateUi()
specNotificationsEnabledCheckBox.setText(tr("Notify in the taskbar for game events while you are spectating"));
buddyConnectNotificationsEnabledCheckBox.setText(tr("Notify in the taskbar when users in your buddy list connect"));
animationGroupBox->setTitle(tr("Animation settings"));
enableAllAnimationsButton.setText(tr("&Enable all animations"));
disableAllAnimationsButton.setText(tr("&Disable all animations"));
tapAnimationCheckBox.setText(tr("&Tap/untap animation"));
deckEditorGroupBox->setTitle(tr("Deck editor/storage settings"));
openDeckInNewTabCheckBox.setText(tr("Open deck in new tab by default"));

View file

@ -7,7 +7,6 @@
#include <QComboBox>
#include <QGroupBox>
#include <QLabel>
#include <QPushButton>
#include <QSpinBox>
#include <QToolButton>
#include <libcockatrice/settings/cards_display_settings.h>
@ -18,8 +17,6 @@ class UserInterfaceSettingsPage : public AbstractSettingsPage
Q_OBJECT
private slots:
void setNotificationEnabled(QT_STATE_CHANGED_T);
void enableAllAnimations();
void disableAllAnimations();
void updateCommanderSpellbookUiState();
private:
@ -37,8 +34,6 @@ private:
QCheckBox showTotalSelectionCountCheckBox;
QCheckBox useTearOffMenusCheckBox;
QCheckBox keepGameChatFocusCheckBox;
QPushButton enableAllAnimationsButton;
QPushButton disableAllAnimationsButton;
QCheckBox tapAnimationCheckBox;
QCheckBox openDeckInNewTabCheckBox;
QLabel visualDeckStoragePromptForConversionLabel;