diff --git a/cockatrice/src/game_graphics/animated_item.h b/cockatrice/src/game_graphics/animated_item.h deleted file mode 100644 index 700e0f62d..000000000 --- a/cockatrice/src/game_graphics/animated_item.h +++ /dev/null @@ -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 diff --git a/cockatrice/src/game_graphics/board/abstract_card_item.cpp b/cockatrice/src/game_graphics/board/abstract_card_item.cpp index 1410d0c80..e0029ee2d 100644 --- a/cockatrice/src/game_graphics/board/abstract_card_item.cpp +++ b/cockatrice/src/game_graphics/board/abstract_card_item.cpp @@ -305,11 +305,6 @@ void AbstractCardItem::setTapped(bool _tapped, bool canAnimate) } } -bool AbstractCardItem::animationEvent() -{ - return false; -} - void AbstractCardItem::setFaceDown(bool _facedown) { facedown = _facedown; diff --git a/cockatrice/src/game_graphics/board/abstract_card_item.h b/cockatrice/src/game_graphics/board/abstract_card_item.h index 8cbe95282..bdb5f7cf1 100644 --- a/cockatrice/src/game_graphics/board/abstract_card_item.h +++ b/cockatrice/src/game_graphics/board/abstract_card_item.h @@ -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; diff --git a/cockatrice/src/game_graphics/board/card_item.h b/cockatrice/src/game_graphics/board/card_item.h index 2ba43d03d..37f3bab50 100644 --- a/cockatrice/src/game_graphics/board/card_item.h +++ b/cockatrice/src/game_graphics/board/card_item.h @@ -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); diff --git a/cockatrice/src/game_graphics/game_scene.cpp b/cockatrice/src/game_graphics/game_scene.cpp index 25c5fbcf0..db2088104 100644 --- a/cockatrice/src/game_graphics/game_scene.cpp +++ b/cockatrice/src/game_graphics/game_scene.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -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 i(animatedItems); + QMutableSetIterator 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(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(card)); + if (!animationTimer->isActive()) { animationTimer->start(10, this); } } -void GameScene::unregisterAnimationItem(IAnimatedItem *item) +void GameScene::unregisterAnimationItem(AbstractCardItem *card) { - animatedItems.remove(dynamic_cast(item)); - if (animationTimer && animatedItems.isEmpty()) { - animationTimer->stop(); - } -} - -void GameScene::removeAnimatedItem(QObject *item) -{ - animatedItems.remove(item); - if (animationTimer && animatedItems.isEmpty()) { + cardsToAnimate.remove(static_cast(card)); + if (cardsToAnimate.isEmpty()) { animationTimer->stop(); } } diff --git a/cockatrice/src/game_graphics/game_scene.h b/cockatrice/src/game_graphics/game_scene.h index 7f01bf1f5..74e979556 100644 --- a/cockatrice/src/game_graphics/game_scene.h +++ b/cockatrice/src/game_graphics/game_scene.h @@ -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 -#include #include #include #include +#include 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 zoneViews; ///< Active zone view widgets QSize viewSize; ///< Current view size QPointer hoveredCard; ///< Currently hovered card - QBasicTimer *animationTimer; ///< Timer for scene animations - QHash animatedItems; ///< Items currently animating + QBasicTimer *animationTimer; ///< Timer for card animations + QSet 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); diff --git a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp index 869df4cf3..e97d25e64 100644 --- a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp +++ b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -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]")) { diff --git a/cockatrice/src/interface/widgets/server/chat_view/chat_view.h b/cockatrice/src/interface/widgets/server/chat_view/chat_view.h index 646aa6a80..8d5894613 100644 --- a/cockatrice/src/interface/widgets/server/chat_view/chat_view.h +++ b/cockatrice/src/interface/widgets/server/chat_view/chat_view.h @@ -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); diff --git a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp index fa6de81c2..634df0b15 100644 --- a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp @@ -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")); diff --git a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h index f98e723b8..9e6fada69 100644 --- a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h +++ b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -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;