Skip to content

Commit 1d455ea

Browse files
committed
Automatically delete clones when the project stops
1 parent 284c097 commit 1d455ea

File tree

5 files changed

+66
-4
lines changed

5 files changed

+66
-4
lines changed

include/scratchcpp/iengine.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ class LIBSCRATCHCPP_EXPORT IEngine
8181
/*! Calls the "when I start as a clone" blocks of the given sprite. */
8282
virtual void initClone(Sprite *clone) = 0;
8383

84+
/*! Automatically called from clones that are being deleted. */
85+
virtual void deinitClone(Sprite *clone) = 0;
86+
8487
/*!
8588
* Runs the event loop and calls "when green flag clicked" blocks.
8689
* \note This function returns when all scripts finish.\n

src/engine/internal/engine.cpp

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,17 @@ Engine::Engine() :
3232
{
3333
}
3434

35+
Engine::~Engine()
36+
{
37+
m_clones.clear();
38+
}
39+
3540
void Engine::clear()
3641
{
3742
m_sections.clear();
3843
m_targets.clear();
3944
m_broadcasts.clear();
45+
m_clones.clear();
4046
}
4147

4248
// Resolves ID references and sets pointers of entities.
@@ -172,6 +178,11 @@ void Engine::frame()
172178

173179
void Engine::start()
174180
{
181+
if (m_running)
182+
finalize();
183+
184+
deleteClones();
185+
175186
m_timer->reset();
176187
m_running = true;
177188

@@ -184,9 +195,8 @@ void Engine::start()
184195

185196
void Engine::stop()
186197
{
187-
m_runningScripts.clear();
188-
m_scriptsToRemove.clear();
189-
m_running = false;
198+
finalize();
199+
deleteClones();
190200
}
191201

192202
void Engine::startScript(std::shared_ptr<Block> topLevelBlock, std::shared_ptr<Target> target)
@@ -328,6 +338,14 @@ void Engine::initClone(Sprite *clone)
328338
m_runningScripts.push_back(vm);
329339
}
330340
}
341+
342+
assert(std::find(m_clones.begin(), m_clones.end(), clone) == m_clones.end());
343+
m_clones.push_back(clone);
344+
}
345+
346+
void Engine::deinitClone(Sprite *clone)
347+
{
348+
m_clones.erase(std::remove(m_clones.begin(), m_clones.end(), clone), m_clones.end());
331349
}
332350

333351
void Engine::run()
@@ -360,7 +378,7 @@ void Engine::run()
360378
lastFrameTime = currentTime;
361379
}
362380

363-
stop();
381+
finalize();
364382
}
365383

366384
bool Engine::isRunning() const
@@ -879,6 +897,31 @@ BlockSectionContainer *Engine::blockSectionContainer(IBlockSection *section) con
879897
return nullptr;
880898
}
881899

900+
void Engine::finalize()
901+
{
902+
m_runningScripts.clear();
903+
m_scriptsToRemove.clear();
904+
m_running = false;
905+
}
906+
907+
void Engine::deleteClones()
908+
{
909+
m_clones.clear();
910+
911+
for (auto target : m_targets) {
912+
Sprite *sprite = dynamic_cast<Sprite *>(target.get());
913+
914+
if (sprite) {
915+
std::vector<std::shared_ptr<Sprite>> clones = sprite->children();
916+
917+
for (auto clone : clones) {
918+
assert(clone);
919+
clone->~Sprite();
920+
}
921+
}
922+
}
923+
}
924+
882925
void Engine::updateFrameDuration()
883926
{
884927
m_frameDuration = std::chrono::milliseconds(static_cast<long>(1000 / m_fps));

src/engine/internal/engine.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class Engine : public IEngine
2121
public:
2222
Engine();
2323
Engine(const Engine &) = delete;
24+
~Engine();
2425

2526
void clear() override;
2627
void resolveIds();
@@ -35,6 +36,7 @@ class Engine : public IEngine
3536
void stopScript(VirtualMachine *vm) override;
3637
void stopTarget(Target *target, VirtualMachine *exceptScript) override;
3738
void initClone(libscratchcpp::Sprite *clone) override;
39+
void deinitClone(libscratchcpp::Sprite *clone) override;
3840
void run() override;
3941

4042
bool isRunning() const override;
@@ -109,6 +111,8 @@ class Engine : public IEngine
109111
BlockSectionContainer *blockSectionContainer(IBlockSection *section) const;
110112

111113
private:
114+
void finalize();
115+
void deleteClones();
112116
std::shared_ptr<Block> getBlock(const std::string &id);
113117
std::shared_ptr<Variable> getVariable(const std::string &id);
114118
std::shared_ptr<List> getList(const std::string &id);
@@ -142,6 +146,7 @@ class Engine : public IEngine
142146
bool m_mousePressed = false;
143147
unsigned int m_stageWidth = 480;
144148
unsigned int m_stageHeight = 360;
149+
std::vector<Sprite *> m_clones;
145150

146151
bool m_running = false;
147152
bool m_breakFrame = false;

src/scratch/sprite.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ Sprite::Sprite() :
2323
Sprite::~Sprite()
2424
{
2525
if (isClone()) {
26+
IEngine *eng = engine();
27+
28+
if (eng) {
29+
eng->deinitClone(this);
30+
31+
auto children = allChildren();
32+
for (auto child : children)
33+
eng->deinitClone(child.get());
34+
}
35+
2636
assert(impl->cloneParent);
2737
impl->cloneParent->impl->removeClone(this);
2838
}

test/mocks/enginemock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class EngineMock : public IEngine
2323
MOCK_METHOD(void, stopScript, (VirtualMachine *), (override));
2424
MOCK_METHOD(void, stopTarget, (Target *, VirtualMachine *), (override));
2525
MOCK_METHOD(void, initClone, (Sprite *), (override));
26+
MOCK_METHOD(void, deinitClone, (Sprite *), (override));
2627
MOCK_METHOD(void, run, (), (override));
2728

2829
MOCK_METHOD(bool, isRunning, (), (const, override));

0 commit comments

Comments
 (0)