mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-07 18:43:26 -08:00
Holding or spamming the draw-arrow shortcut fires the action again before the previous local arrow has been placed. Every new arrow takes the mouse grab from the previous one, so the previous arrow never receives the release that deletes it. If the cursor had passed over a card meanwhile, the orphan stayed visible on the board. Track the in-progress arrow on the CardItem that started it and cancel it, together with any child arrows, before starting a new one. The attach-arrow shortcut (Ctrl+Alt+A) uses the same path, so it no longer leaks arrows either. Fixes #4329. Co-authored-by: mb <mbaecker@unforce.de>
148 lines
3.7 KiB
C++
148 lines
3.7 KiB
C++
#ifndef ARROWITEM_H
|
|
#define ARROWITEM_H
|
|
|
|
#include "../animated_item.h"
|
|
#include "arrow_target.h"
|
|
#include "graphics_item_type.h"
|
|
|
|
#include <QColor>
|
|
#include <QElapsedTimer>
|
|
#include <QGraphicsItem>
|
|
#include <QList>
|
|
#include <QMetaObject>
|
|
#include <QObject>
|
|
#include <QPainterPath>
|
|
#include <QPointF>
|
|
#include <QPointer>
|
|
#include <QRectF>
|
|
#include <QSharedPointer>
|
|
#include <QtGlobal>
|
|
#include <libcockatrice/game/board/arrow_data.h>
|
|
#include <qtmetamacros.h>
|
|
|
|
class CardItem;
|
|
class PlayerLogic;
|
|
template <class T> class QSharedPointer;
|
|
|
|
class ArrowItem : public QObject, public QGraphicsItem, public IAnimatedItem
|
|
{
|
|
Q_OBJECT
|
|
Q_INTERFACES(QGraphicsItem)
|
|
signals:
|
|
void requestDeletion(int creatorId, int id);
|
|
|
|
private:
|
|
QPainterPath path;
|
|
QPainterPath bodyPath;
|
|
QPainterPath headPath;
|
|
QPainterPath shaftOutlinePath;
|
|
QPainterPath centerLine;
|
|
qreal headBaseFraction = 1.0;
|
|
QElapsedTimer animationClock;
|
|
qreal strokeDurationMs = 0;
|
|
qreal glowFadeDurationMs = 0;
|
|
qreal drawProgress = 1.0;
|
|
qreal glowAlpha = 0.0;
|
|
bool animationStarted = false;
|
|
|
|
static constexpr qreal glowExtent = 12.0;
|
|
|
|
protected:
|
|
QSharedPointer<const ArrowData> data;
|
|
QPointer<ArrowTarget> startItem;
|
|
QPointer<ArrowTarget> targetItem;
|
|
bool targetLocked = false;
|
|
bool fullColor = true;
|
|
|
|
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
|
|
|
public:
|
|
enum
|
|
{
|
|
Type = typeArrow
|
|
};
|
|
[[nodiscard]] int type() const override
|
|
{
|
|
return Type;
|
|
}
|
|
ArrowItem(QSharedPointer<const ArrowData> _data, ArrowTarget *_startItem, ArrowTarget *_targetItem);
|
|
~ArrowItem() override;
|
|
|
|
void onTargetDestroyed();
|
|
void delArrow();
|
|
/// Abandons an in-progress drag arrow, discarding any child arrows with it.
|
|
virtual void cancel();
|
|
void updatePath();
|
|
void updatePath(const QPointF &endPoint);
|
|
void startDrawAnimation();
|
|
bool animationEvent() override;
|
|
|
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
|
[[nodiscard]] QRectF boundingRect() const override
|
|
{
|
|
return path.boundingRect().adjusted(-glowExtent, -glowExtent, glowExtent, glowExtent);
|
|
}
|
|
[[nodiscard]] QPainterPath shape() const override
|
|
{
|
|
return path;
|
|
}
|
|
[[nodiscard]] int getId() const
|
|
{
|
|
return data->id;
|
|
}
|
|
[[nodiscard]] int getCreatorId() const
|
|
{
|
|
return data->creatorId;
|
|
}
|
|
[[nodiscard]] ArrowTarget *getStartItem() const
|
|
{
|
|
return startItem;
|
|
}
|
|
[[nodiscard]] ArrowTarget *getTargetItem() const
|
|
{
|
|
return targetItem;
|
|
}
|
|
void setTargetLocked(bool _targetLocked)
|
|
{
|
|
targetLocked = _targetLocked;
|
|
}
|
|
};
|
|
|
|
class ArrowDragItem : public ArrowItem
|
|
{
|
|
Q_OBJECT
|
|
private:
|
|
PlayerLogic *player;
|
|
int deleteInPhase;
|
|
QList<QPointer<ArrowDragItem>> childArrows;
|
|
QMetaObject::Connection positionConnection;
|
|
|
|
public:
|
|
ArrowDragItem(PlayerLogic *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase);
|
|
void addChildArrow(ArrowDragItem *child);
|
|
void cancel() override;
|
|
|
|
protected:
|
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
|
};
|
|
|
|
class ArrowAttachItem : public ArrowItem
|
|
{
|
|
Q_OBJECT
|
|
private:
|
|
PlayerLogic *player;
|
|
QList<QPointer<ArrowAttachItem>> childArrows;
|
|
QMetaObject::Connection positionConnection;
|
|
|
|
public:
|
|
explicit ArrowAttachItem(ArrowTarget *_startItem);
|
|
void addChildArrow(ArrowAttachItem *child);
|
|
void cancel() override;
|
|
|
|
protected:
|
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
|
};
|
|
|
|
#endif
|