Skip to content

Commit 55f6e95

Browse files
committed
Add clone limit
1 parent 1d455ea commit 55f6e95

File tree

6 files changed

+76
-1
lines changed

6 files changed

+76
-1
lines changed

include/scratchcpp/iengine.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ class LIBSCRATCHCPP_EXPORT IEngine
140140
/*! Sets the stage height. */
141141
virtual void setStageHeight(unsigned int height) = 0;
142142

143+
/*! Returns the maximum number of clones (or -1 if the limit is disabled). */
144+
virtual int cloneLimit() const = 0;
145+
146+
/*! Sets the maximum number of clones (use -1 or any negative number to disable the limit). */
147+
virtual void setCloneLimit(int limit) = 0;
148+
143149
/*! Returns true if there are any running script of the broadcast with the given index. */
144150
virtual bool broadcastRunning(unsigned int index, VirtualMachine *sourceScript) = 0;
145151

src/engine/internal/engine.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ void Engine::stopTarget(Target *target, VirtualMachine *exceptScript)
311311

312312
void Engine::initClone(Sprite *clone)
313313
{
314-
if (!clone)
314+
if (!clone || ((m_cloneLimit >= 0) && (m_clones.size() >= m_cloneLimit)))
315315
return;
316316

317317
Sprite *source = clone->cloneParent();
@@ -481,6 +481,16 @@ void Engine::setStageHeight(unsigned int height)
481481
m_stageHeight = height;
482482
}
483483

484+
int Engine::cloneLimit() const
485+
{
486+
return m_cloneLimit;
487+
}
488+
489+
void Engine::setCloneLimit(int limit)
490+
{
491+
m_cloneLimit = limit < 0 ? -1 : limit;
492+
}
493+
484494
bool Engine::broadcastRunning(unsigned int index, VirtualMachine *sourceScript)
485495
{
486496
if (index < 0 || index >= m_broadcasts.size())

src/engine/internal/engine.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class Engine : public IEngine
6363
unsigned int stageHeight() const override;
6464
void setStageHeight(unsigned int height) override;
6565

66+
int cloneLimit() const override;
67+
void setCloneLimit(int limit) override;
68+
6669
bool broadcastRunning(unsigned int index, VirtualMachine *sourceScript) override;
6770
bool broadcastByPtrRunning(Broadcast *broadcast, VirtualMachine *sourceScript) override;
6871

@@ -146,6 +149,7 @@ class Engine : public IEngine
146149
bool m_mousePressed = false;
147150
unsigned int m_stageWidth = 480;
148151
unsigned int m_stageHeight = 360;
152+
int m_cloneLimit = 300;
149153
std::vector<Sprite *> m_clones;
150154

151155
bool m_running = false;

test/clone_limit.sb3

2.31 KB
Binary file not shown.

test/engine/engine_test.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,58 @@ TEST(EngineTest, Clones)
547547
}
548548
}
549549

550+
TEST(EngineTest, CloneLimit)
551+
{
552+
Project p("clone_limit.sb3");
553+
ASSERT_TRUE(p.load());
554+
auto engine = p.engine();
555+
ASSERT_EQ(engine->cloneLimit(), 300);
556+
557+
// TODO: Set "infinite" FPS and remove this (#254)
558+
engine->setFps(100000);
559+
560+
Stage *stage = engine->stage();
561+
ASSERT_TRUE(stage);
562+
563+
p.run();
564+
ASSERT_VAR(stage, "count");
565+
ASSERT_EQ(GET_VAR(stage, "count")->value().toInt(), 300);
566+
ASSERT_VAR(stage, "delete_passed");
567+
ASSERT_TRUE(GET_VAR(stage, "delete_passed")->value().toBool());
568+
569+
engine->setCloneLimit(475);
570+
ASSERT_EQ(engine->cloneLimit(), 475);
571+
p.run();
572+
ASSERT_VAR(stage, "count");
573+
ASSERT_EQ(GET_VAR(stage, "count")->value().toInt(), 475);
574+
ASSERT_VAR(stage, "delete_passed");
575+
ASSERT_TRUE(GET_VAR(stage, "delete_passed")->value().toBool());
576+
577+
engine->setCloneLimit(0);
578+
ASSERT_EQ(engine->cloneLimit(), 0);
579+
p.run();
580+
ASSERT_VAR(stage, "count");
581+
ASSERT_EQ(GET_VAR(stage, "count")->value().toInt(), 0);
582+
ASSERT_VAR(stage, "delete_passed");
583+
ASSERT_TRUE(GET_VAR(stage, "delete_passed")->value().toBool());
584+
585+
engine->setCloneLimit(-1);
586+
ASSERT_EQ(engine->cloneLimit(), -1);
587+
p.run();
588+
ASSERT_VAR(stage, "count");
589+
ASSERT_GT(GET_VAR(stage, "count")->value().toInt(), 500);
590+
ASSERT_VAR(stage, "delete_passed");
591+
ASSERT_TRUE(GET_VAR(stage, "delete_passed")->value().toBool());
592+
593+
engine->setCloneLimit(-5);
594+
ASSERT_EQ(engine->cloneLimit(), -1);
595+
p.run();
596+
ASSERT_VAR(stage, "count");
597+
ASSERT_GT(GET_VAR(stage, "count")->value().toInt(), 500);
598+
ASSERT_VAR(stage, "delete_passed");
599+
ASSERT_TRUE(GET_VAR(stage, "delete_passed")->value().toBool());
600+
}
601+
550602
// TODO: Uncomment this after fixing #256 and #257
551603
/*TEST(EngineTest, BackdropBroadcasts)
552604
{

test/mocks/enginemock.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ class EngineMock : public IEngine
5050
MOCK_METHOD(unsigned int, stageHeight, (), (const, override));
5151
MOCK_METHOD(void, setStageHeight, (unsigned int), (override));
5252

53+
MOCK_METHOD(int, cloneLimit, (), (const, override));
54+
MOCK_METHOD(void, setCloneLimit, (int), (override));
55+
5356
MOCK_METHOD(bool, broadcastRunning, (unsigned int, VirtualMachine *), (override));
5457
MOCK_METHOD(bool, broadcastByPtrRunning, (Broadcast *, VirtualMachine *), (override));
5558

0 commit comments

Comments
 (0)