Skip to content

Commit 9ee5bde

Browse files
authored
Merge pull request #312 from scratchcpp/request_redraw_from_sprite
Request redraw when visual properties change
2 parents 344175a + 06ff1e8 commit 9ee5bde

File tree

7 files changed

+163
-2
lines changed

7 files changed

+163
-2
lines changed

src/engine/internal/engine.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ void Engine::clear()
4444
m_targets.clear();
4545
m_broadcasts.clear();
4646
m_clones.clear();
47+
48+
m_running = false;
49+
m_breakFrame = false;
50+
m_skipFrame = false;
51+
m_lockFrame = false;
4752
}
4853

4954
// Resolves ID references and sets pointers of entities.
@@ -945,6 +950,9 @@ void Engine::finalize()
945950
m_runningScripts.clear();
946951
m_scriptsToRemove.clear();
947952
m_running = false;
953+
m_breakFrame = false;
954+
m_skipFrame = false;
955+
m_lockFrame = false;
948956
}
949957

950958
void Engine::deleteClones()

src/scratch/sprite.cpp

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ std::shared_ptr<Sprite> Sprite::clone()
7979
clone->setCostumeIndex(costumeIndex());
8080
clone->setLayerOrder(layerOrder());
8181
clone->setVolume(volume());
82-
clone->setEngine(engine());
8382

8483
clone->impl->visible = impl->visible;
8584
clone->impl->x = impl->x;
@@ -89,9 +88,14 @@ std::shared_ptr<Sprite> Sprite::clone()
8988
clone->impl->draggable = impl->draggable;
9089
clone->impl->rotationStyle = impl->rotationStyle;
9190

91+
clone->setEngine(engine());
92+
9293
// Call "when I start as clone" scripts
9394
eng->initClone(clone.get());
9495

96+
if (impl->visible)
97+
eng->breakFrame();
98+
9599
if (impl->iface)
96100
impl->iface->onCloned(clone.get());
97101

@@ -149,6 +153,14 @@ bool Sprite::visible() const
149153
void Sprite::setVisible(bool newVisible)
150154
{
151155
impl->visible = newVisible;
156+
157+
if (impl->visible) {
158+
IEngine *eng = engine();
159+
160+
if (eng)
161+
eng->breakFrame();
162+
}
163+
152164
if (impl->iface)
153165
impl->iface->onVisibleChanged(impl->visible);
154166
}
@@ -193,6 +205,14 @@ double Sprite::size() const
193205
void Sprite::setSize(double newSize)
194206
{
195207
impl->size = newSize;
208+
209+
if (impl->visible) {
210+
IEngine *eng = engine();
211+
212+
if (eng)
213+
eng->breakFrame();
214+
}
215+
196216
if (impl->iface)
197217
impl->iface->onSizeChanged(impl->size);
198218

@@ -215,6 +235,13 @@ void Sprite::setCostumeIndex(int newCostumeIndex)
215235
costume->setGraphicsEffectValue(effect, value);
216236
}
217237

238+
if (impl->visible) {
239+
IEngine *eng = engine();
240+
241+
if (eng)
242+
eng->breakFrame();
243+
}
244+
218245
Target::setCostumeIndex(newCostumeIndex);
219246
}
220247

@@ -234,6 +261,13 @@ void Sprite::setDirection(double newDirection)
234261
else
235262
impl->direction = std::fmod(newDirection + 180, 360) - 180;
236263

264+
if (impl->visible) {
265+
IEngine *eng = engine();
266+
267+
if (eng)
268+
eng->breakFrame();
269+
}
270+
237271
if (impl->iface)
238272
impl->iface->onDirectionChanged(impl->direction);
239273
}
@@ -279,6 +313,13 @@ void Sprite::setRotationStyle(RotationStyle newRotationStyle)
279313
if (costume)
280314
costume->setMirrorHorizontally(newRotationStyle == RotationStyle::LeftRight);
281315

316+
if (impl->visible) {
317+
IEngine *eng = engine();
318+
319+
if (eng)
320+
eng->breakFrame();
321+
}
322+
282323
if (impl->iface)
283324
impl->iface->onRotationStyleChanged(impl->rotationStyle);
284325
}
@@ -329,6 +370,13 @@ void Sprite::setGraphicsEffectValue(IGraphicsEffect *effect, double value)
329370

330371
if (costume)
331372
costume->setGraphicsEffectValue(effect, value);
373+
374+
if (impl->visible) {
375+
IEngine *eng = engine();
376+
377+
if (eng)
378+
eng->breakFrame();
379+
}
332380
}
333381

334382
/*! Sets the value of all graphics effects to 0 (clears them). */
@@ -340,6 +388,13 @@ void Sprite::clearGraphicsEffects()
340388

341389
if (costume)
342390
costume->clearGraphicsEffects();
391+
392+
if (impl->visible) {
393+
IEngine *eng = engine();
394+
395+
if (eng)
396+
eng->breakFrame();
397+
}
343398
}
344399

345400
Target *Sprite::dataSource() const
@@ -356,4 +411,11 @@ void Sprite::setXY(double x, double y)
356411
impl->y = y;
357412
} else
358413
impl->getFencedPosition(x, y, &impl->x, &impl->y);
414+
415+
if (impl->visible) {
416+
IEngine *eng = engine();
417+
418+
if (eng)
419+
eng->breakFrame();
420+
}
359421
}

src/scratch/target.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <scratchcpp/variable.h>
55
#include <scratchcpp/list.h>
66
#include <scratchcpp/block.h>
7+
#include <scratchcpp/iengine.h>
78

89
#include "target_p.h"
910

@@ -209,6 +210,11 @@ void Target::setCostumeIndex(int newCostumeIndex)
209210
{
210211
if (newCostumeIndex >= 0 && newCostumeIndex < costumes().size())
211212
impl->costumeIndex = newCostumeIndex;
213+
214+
if (isStage()) {
215+
if (impl->engine)
216+
impl->engine->breakFrame();
217+
}
212218
}
213219

214220
/*! Returns the currently set costume. */

test/engine/engine_test.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ TEST(EngineTest, IsRunning)
6060
engine.start();
6161
engine.run();
6262
ASSERT_FALSE(engine.isRunning());
63+
64+
engine.breakFrame();
65+
66+
engine.start();
67+
ASSERT_TRUE(engine.isRunning());
68+
ASSERT_TRUE(engine.breakingCurrentFrame());
69+
70+
engine.stop();
71+
ASSERT_FALSE(engine.isRunning());
72+
ASSERT_FALSE(engine.breakingCurrentFrame());
6373
}
6474

6575
TEST(EngineTest, Fps)

test/scratch_classes/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ add_executable(
5151
target_link_libraries(
5252
stage_test
5353
GTest::gtest_main
54+
GTest::gmock_main
5455
scratchcpp
56+
scratchcpp_mocks
5557
)
5658

5759
gtest_discover_tests(stage_test)

test/scratch_classes/sprite_test.cpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,15 @@ TEST(SpriteTest, Visible)
2929
{
3030
Sprite sprite;
3131
ASSERT_TRUE(sprite.visible());
32+
EngineMock engine;
33+
sprite.setEngine(&engine);
34+
3235
sprite.setVisible(false);
3336
ASSERT_FALSE(sprite.visible());
37+
38+
EXPECT_CALL(engine, breakFrame());
39+
sprite.setVisible(true);
40+
ASSERT_TRUE(sprite.visible());
3441
}
3542

3643
TEST(SpriteTest, Clone)
@@ -116,6 +123,7 @@ TEST(SpriteTest, Clone)
116123

117124
EngineMock engine;
118125
sprite->setEngine(&engine);
126+
EXPECT_CALL(engine, breakFrame()).Times(2);
119127

120128
Sprite *clone1;
121129
EXPECT_CALL(engine, initClone(_)).WillOnce(SaveArg<0>(&clone1));
@@ -145,6 +153,8 @@ TEST(SpriteTest, Clone)
145153

146154
checkCloneData(clone2);
147155

156+
sprite->setVisible(true);
157+
148158
Sprite *clone3;
149159
EXPECT_CALL(engine, initClone(_)).WillOnce(SaveArg<0>(&clone3));
150160
ASSERT_EQ(clone1->clone().get(), clone3);
@@ -215,6 +225,11 @@ TEST(SpriteTest, XY)
215225
ASSERT_EQ(sprite.x(), 0);
216226
ASSERT_EQ(sprite.y(), 0);
217227

228+
EngineMock engine;
229+
sprite.setEngine(&engine);
230+
EXPECT_CALL(engine, breakFrame()).Times(18);
231+
EXPECT_CALL(engine, spriteFencingEnabled()).Times(4).WillRepeatedly(Return(false));
232+
218233
sprite.setX(-53.25);
219234
ASSERT_EQ(sprite.x(), -53.25);
220235

@@ -260,7 +275,6 @@ TEST(SpriteTest, XY)
260275
EXPECT_CALL(*imageFormat, colorAt(3, 2, 1)).WillOnce(Return(rgba(0, 0, 0, 0)));
261276
costume->setData(5, data);
262277

263-
EngineMock engine;
264278
sprite.setEngine(&engine);
265279
sprite.setDirection(34.45);
266280

@@ -384,6 +398,10 @@ TEST(SpriteTest, Size)
384398

385399
ASSERT_EQ(c1->scale(), 1);
386400

401+
EngineMock engine;
402+
sprite.setEngine(&engine);
403+
EXPECT_CALL(engine, breakFrame()).Times(4);
404+
387405
sprite.setSize(63.724);
388406
ASSERT_EQ(sprite.size(), 63.724);
389407
ASSERT_EQ(std::round(c1->scale() * 100000) / 100000, 0.63724);
@@ -399,11 +417,34 @@ TEST(SpriteTest, Size)
399417
ASSERT_EQ(std::round(c1->scale() * 10000) / 10000, 1.8684);
400418
}
401419

420+
TEST(SpriteTest, CostumeIndex)
421+
{
422+
Sprite sprite;
423+
EngineMock engine;
424+
sprite.setEngine(&engine);
425+
EXPECT_CALL(engine, breakFrame()).Times(2);
426+
427+
auto c1 = std::make_shared<Costume>("", "", "");
428+
auto c2 = std::make_shared<Costume>("", "", "");
429+
sprite.addCostume(c1);
430+
sprite.addCostume(c2);
431+
432+
sprite.setCostumeIndex(0);
433+
ASSERT_EQ(sprite.costumeIndex(), 0);
434+
435+
sprite.setCostumeIndex(1);
436+
ASSERT_EQ(sprite.costumeIndex(), 1);
437+
}
438+
402439
TEST(SpriteTest, Direction)
403440
{
404441
Sprite sprite;
405442
ASSERT_EQ(sprite.direction(), 90);
406443

444+
EngineMock engine;
445+
sprite.setEngine(&engine);
446+
EXPECT_CALL(engine, breakFrame()).Times(10);
447+
407448
sprite.setDirection(-42.75);
408449
ASSERT_EQ(sprite.direction(), -42.75);
409450

@@ -457,6 +498,10 @@ TEST(SpriteTest, RotationStyle)
457498

458499
ASSERT_EQ(c1->mirrorHorizontally(), false);
459500

501+
EngineMock engine;
502+
sprite.setEngine(&engine);
503+
EXPECT_CALL(engine, breakFrame()).Times(8);
504+
460505
sprite.setRotationStyle(Sprite::RotationStyle::DoNotRotate);
461506
ASSERT_EQ(sprite.rotationStyle(), Sprite::RotationStyle::DoNotRotate);
462507
ASSERT_EQ(sprite.rotationStyleStr(), "don't rotate");
@@ -486,6 +531,8 @@ TEST(SpriteTest, RotationStyle)
486531
sprite.setCostumeIndex(1);
487532
ASSERT_EQ(c2->mirrorHorizontally(), false);
488533

534+
sprite.setVisible(false);
535+
489536
sprite.setRotationStyle("don't rotate");
490537
ASSERT_EQ(sprite.rotationStyle(), Sprite::RotationStyle::DoNotRotate);
491538
ASSERT_EQ(sprite.rotationStyleStr(), "don't rotate");
@@ -624,6 +671,11 @@ TEST(SpriteTest, GraphicsEffects)
624671
auto c2 = std::make_shared<Costume>("", "", "");
625672

626673
Sprite sprite;
674+
675+
EngineMock engine;
676+
sprite.setEngine(&engine);
677+
EXPECT_CALL(engine, breakFrame()).Times(6);
678+
627679
sprite.addCostume(c1);
628680
sprite.addCostume(c2);
629681
sprite.setCostumeIndex(0);

test/scratch_classes/stage_test.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#include <scratchcpp/stage.h>
2+
#include <scratchcpp/costume.h>
3+
#include <enginemock.h>
24

35
#include "../common.h"
46

@@ -10,6 +12,25 @@ TEST(StageTest, IsStage)
1012
ASSERT_TRUE(stage.isStage());
1113
}
1214

15+
TEST(SpriteTest, CostumeIndex)
16+
{
17+
Stage stage;
18+
EngineMock engine;
19+
stage.setEngine(&engine);
20+
EXPECT_CALL(engine, breakFrame()).Times(2);
21+
22+
auto c1 = std::make_shared<Costume>("", "", "");
23+
auto c2 = std::make_shared<Costume>("", "", "");
24+
stage.addCostume(c1);
25+
stage.addCostume(c2);
26+
27+
stage.setCostumeIndex(0);
28+
ASSERT_EQ(stage.costumeIndex(), 0);
29+
30+
stage.setCostumeIndex(1);
31+
ASSERT_EQ(stage.costumeIndex(), 1);
32+
}
33+
1334
TEST(StageTest, Tempo)
1435
{
1536
Stage stage;

0 commit comments

Comments
 (0)