Skip to content

Commit 0c2560a

Browse files
committed
Add clone support to MouseEventHandler
1 parent 48839af commit 0c2560a

File tree

3 files changed

+69
-17
lines changed

3 files changed

+69
-17
lines changed

src/mouseeventhandler.cpp

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ ProjectLoader *MouseEventHandler::projectLoader() const
3333
void MouseEventHandler::setProjectLoader(ProjectLoader *newProjectLoader)
3434
{
3535
m_projectLoader = newProjectLoader;
36+
37+
if (m_projectLoader) {
38+
connect(m_projectLoader, &ProjectLoader::spritesChanged, this, &MouseEventHandler::getSprites);
39+
connect(m_projectLoader, &ProjectLoader::cloneCreated, this, &MouseEventHandler::addClone);
40+
connect(m_projectLoader, &ProjectLoader::cloneDeleted, this, &MouseEventHandler::removeClone);
41+
}
3642
}
3743

3844
bool MouseEventHandler::eventFilter(QObject *obj, QEvent *event)
@@ -78,34 +84,64 @@ bool MouseEventHandler::eventFilter(QObject *obj, QEvent *event)
7884
return QObject::eventFilter(obj, event);
7985
}
8086

81-
void MouseEventHandler::forwardPointEvent(QSinglePointEvent *event, QQuickItem *oldClickedItem)
87+
void scratchcpprender::MouseEventHandler::getSprites()
8288
{
8389
Q_ASSERT(m_projectLoader);
8490

8591
if (!m_projectLoader)
8692
return;
8793

88-
// Create list of sprites
94+
m_sprites.clear();
8995
const auto &spriteModels = m_projectLoader->spriteList();
90-
std::vector<IRenderedTarget *> sprites;
91-
auto count = spriteModels.size();
92-
sprites.reserve(count);
9396

94-
for (int i = 0; i < count; i++) {
95-
Q_ASSERT(spriteModels[i]);
96-
IRenderedTarget *sprite = spriteModels[i]->renderedTarget();
97+
for (SpriteModel *model : spriteModels) {
98+
Q_ASSERT(model);
99+
IRenderedTarget *sprite = model->renderedTarget();
97100
Q_ASSERT(sprite);
98101
Q_ASSERT(sprite->scratchTarget());
99-
sprites.push_back(sprite);
102+
m_sprites.push_back(sprite);
100103
}
104+
}
105+
106+
void scratchcpprender::MouseEventHandler::addClone(SpriteModel *model)
107+
{
108+
Q_ASSERT(model);
109+
IRenderedTarget *sprite = model->renderedTarget();
110+
Q_ASSERT(sprite);
111+
Q_ASSERT(std::find_if(m_sprites.begin(), m_sprites.end(), [sprite](IRenderedTarget *renderedTarget) { return renderedTarget == sprite; }) == m_sprites.end());
112+
m_sprites.push_back(sprite);
113+
}
114+
115+
void scratchcpprender::MouseEventHandler::removeClone(SpriteModel *model)
116+
{
117+
Q_ASSERT(model);
118+
IRenderedTarget *sprite = model->renderedTarget();
119+
Q_ASSERT(sprite);
120+
m_sprites.erase(std::remove_if(m_sprites.begin(), m_sprites.end(), [sprite](IRenderedTarget *renderedTarget) { return renderedTarget == sprite; }), m_sprites.end());
121+
Q_ASSERT(std::find_if(m_sprites.begin(), m_sprites.end(), [sprite](IRenderedTarget *renderedTarget) { return renderedTarget == sprite; }) == m_sprites.end());
122+
123+
// Make sure the pointer is never used again after it becomes "dangling"
124+
if (m_clickedItem == sprite)
125+
m_clickedItem = nullptr;
126+
127+
if (m_hoveredItem == sprite)
128+
m_hoveredItem = nullptr;
129+
}
130+
131+
void MouseEventHandler::forwardPointEvent(QSinglePointEvent *event, QQuickItem *oldClickedItem)
132+
{
133+
Q_ASSERT(m_projectLoader);
134+
135+
if (!m_projectLoader)
136+
return;
101137

102-
// Sort the list by layer order
103-
std::sort(sprites.begin(), sprites.end(), [](IRenderedTarget *t1, IRenderedTarget *t2) { return t1->scratchTarget()->layerOrder() > t2->scratchTarget()->layerOrder(); });
138+
// Sort sprite list by layer order
139+
std::sort(m_sprites.begin(), m_sprites.end(), [](IRenderedTarget *t1, IRenderedTarget *t2) { return t1->scratchTarget()->layerOrder() > t2->scratchTarget()->layerOrder(); });
104140

105141
// Find hovered sprite
106142
QQuickItem *hoveredItem = nullptr;
107143

108-
for (IRenderedTarget *sprite : sprites) {
144+
for (IRenderedTarget *sprite : m_sprites) {
109145
// contains() expects position in the item's coordinate system
110146
QPointF localPos = sprite->mapFromScene(event->scenePosition());
111147

src/mouseeventhandler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ namespace scratchcpprender
1414

1515
class IRenderedTarget;
1616
class ProjectLoader;
17+
class SpriteModel;
1718

1819
class MouseEventHandler : public QObject
1920
{
@@ -35,11 +36,15 @@ class MouseEventHandler : public QObject
3536
void mouseReleased();
3637

3738
private:
39+
void getSprites();
40+
void addClone(SpriteModel *model);
41+
void removeClone(SpriteModel *model);
3842
void forwardPointEvent(QSinglePointEvent *event, QQuickItem *oldClickedItem = nullptr);
3943
void sendPointEventToItem(QSinglePointEvent *event, QQuickItem *item);
4044
void sendHoverEventToItem(QHoverEvent *originalEvent, QEvent::Type newType, QQuickItem *item);
4145

4246
IRenderedTarget *m_stage = nullptr;
47+
std::vector<IRenderedTarget *> m_sprites;
4348
QQuickItem *m_hoveredItem = nullptr;
4449
QQuickItem *m_clickedItem = nullptr;
4550
ProjectLoader *m_projectLoader = nullptr;

test/mouseeventhandler/mouseeventhandler_test.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,20 @@ TEST(MouseEventHandlerTest, ProjectLoader)
4545
TEST(MouseEventHandlerTest, HoverEnterLeaveEvent)
4646
{
4747
MouseEventHandler handler;
48-
RenderedTargetMock stage, renderedTarget1, renderedTarget2, renderedTarget3;
49-
SpriteModel model1, model2, model3;
48+
RenderedTargetMock stage, renderedTarget1, renderedTarget2, renderedTarget3, renderedTarget4;
49+
SpriteModel model1, model2, model3, model4;
5050
model1.setRenderedTarget(&renderedTarget1);
5151
model2.setRenderedTarget(&renderedTarget2);
5252
model3.setRenderedTarget(&renderedTarget3);
53-
Sprite sprite1, sprite2, sprite3;
53+
model4.setRenderedTarget(&renderedTarget4);
54+
Sprite sprite1, sprite2, sprite3, sprite4; // sprite1, sprite3 and sprite4 are clones here
5455
sprite1.setLayerOrder(2);
5556
sprite2.setLayerOrder(1);
5657
sprite3.setLayerOrder(3);
58+
sprite4.setLayerOrder(4);
5759
ProjectLoader loader;
5860
auto sprites = loader.sprites();
59-
sprites.append(&sprites, &model1);
6061
sprites.append(&sprites, &model2);
61-
sprites.append(&sprites, &model3);
6262
handler.setStage(&stage);
6363
handler.setProjectLoader(&loader);
6464
QPointingDevice dev;
@@ -68,6 +68,14 @@ TEST(MouseEventHandlerTest, HoverEnterLeaveEvent)
6868
static const QPointF globalPos(11.5, 5.9);
6969
static const QPointF oldPos(9.5, 3.9);
7070

71+
EXPECT_CALL(renderedTarget2, scratchTarget()).WillOnce(Return(&sprite2));
72+
emit loader.spritesChanged();
73+
74+
emit loader.cloneCreated(&model1);
75+
emit loader.cloneCreated(&model3);
76+
emit loader.cloneCreated(&model4);
77+
emit loader.cloneDeleted(&model4); // sprite4 was deleted
78+
7179
EXPECT_CALL(renderedTarget1, scratchTarget()).WillRepeatedly(Return(&sprite1));
7280
EXPECT_CALL(renderedTarget2, scratchTarget()).WillRepeatedly(Return(&sprite2));
7381
EXPECT_CALL(renderedTarget3, scratchTarget()).WillRepeatedly(Return(&sprite3));
@@ -139,6 +147,7 @@ TEST(MouseEventHandlerTest, HoverMoveEvent)
139147
EXPECT_CALL(renderedTarget1, scratchTarget()).WillRepeatedly(Return(&sprite1));
140148
EXPECT_CALL(renderedTarget2, scratchTarget()).WillRepeatedly(Return(&sprite2));
141149
EXPECT_CALL(renderedTarget3, scratchTarget()).WillRepeatedly(Return(&sprite3));
150+
emit loader.spritesChanged();
142151

143152
EXPECT_CALL(renderedTarget1, mapFromScene(scenePos)).WillRepeatedly(Return(localPos));
144153
EXPECT_CALL(renderedTarget2, mapFromScene(scenePos)).WillRepeatedly(Return(localPos));
@@ -230,6 +239,7 @@ TEST(MouseEventHandlerTest, MouseMoveEvent)
230239
EXPECT_CALL(renderedTarget1, scratchTarget()).WillRepeatedly(Return(&sprite1));
231240
EXPECT_CALL(renderedTarget2, scratchTarget()).WillRepeatedly(Return(&sprite2));
232241
EXPECT_CALL(renderedTarget3, scratchTarget()).WillRepeatedly(Return(&sprite3));
242+
emit loader.spritesChanged();
233243

234244
EXPECT_CALL(renderedTarget1, mapFromScene(scenePos)).WillRepeatedly(Return(localPos));
235245
EXPECT_CALL(renderedTarget2, mapFromScene(scenePos)).WillRepeatedly(Return(localPos));
@@ -297,6 +307,7 @@ TEST(MouseEventHandlerTest, MousePressReleaseEvent)
297307
EXPECT_CALL(renderedTarget1, scratchTarget()).WillRepeatedly(Return(&sprite1));
298308
EXPECT_CALL(renderedTarget2, scratchTarget()).WillRepeatedly(Return(&sprite2));
299309
EXPECT_CALL(renderedTarget3, scratchTarget()).WillRepeatedly(Return(&sprite3));
310+
emit loader.spritesChanged();
300311

301312
EXPECT_CALL(renderedTarget1, mapFromScene(scenePos)).WillRepeatedly(Return(localPos));
302313
EXPECT_CALL(renderedTarget2, mapFromScene(scenePos)).WillRepeatedly(Return(localPos));

0 commit comments

Comments
 (0)