Skip to content

Commit 0647e08

Browse files
authored
Merge pull request #402 from scratchcpp/engine_step_public
Add step() to IEngine
2 parents bf24e61 + d27e9e5 commit 0647e08

File tree

6 files changed

+49
-20
lines changed

6 files changed

+49
-20
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
/*! Automatically called from clones that are being deleted. */
8282
virtual void deinitClone(std::shared_ptr<Sprite> clone) = 0;
8383

84+
/*! Steps all currently running threads. Use this to implement a custom event loop. */
85+
virtual void step() = 0;
86+
8487
/*!
8588
* Calls and runs "when green flag clicked" blocks.
8689
* \note This function returns when all scripts finish.\n

src/engine/internal/engine.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,24 @@ void Engine::deinitClone(std::shared_ptr<Sprite> clone)
261261
m_executableTargets.erase(std::remove(m_executableTargets.begin(), m_executableTargets.end(), clone.get()), m_executableTargets.end());
262262
}
263263

264+
void Engine::step()
265+
{
266+
// https://github.com/scratchfoundation/scratch-vm/blob/f1aa92fad79af17d9dd1c41eeeadca099339a9f1/src/engine/runtime.js#L2087C6-L2155
267+
updateFrameDuration();
268+
269+
// Clean up threads that were told to stop during or since the last step
270+
m_threads.erase(std::remove_if(m_threads.begin(), m_threads.end(), [](std::shared_ptr<VirtualMachine> thread) { return thread->atEnd(); }), m_threads.end());
271+
272+
m_redrawRequested = false;
273+
274+
// Step threads
275+
stepThreads();
276+
277+
// Render
278+
if (m_redrawHandler)
279+
m_redrawHandler();
280+
}
281+
264282
void Engine::run()
265283
{
266284
start();
@@ -285,23 +303,6 @@ void Engine::setRedrawHandler(const std::function<void()> &handler)
285303
m_redrawHandler = handler;
286304
}
287305

288-
void Engine::step()
289-
{
290-
// https://github.com/scratchfoundation/scratch-vm/blob/f1aa92fad79af17d9dd1c41eeeadca099339a9f1/src/engine/runtime.js#L2087C6-L2155
291-
292-
// Clean up threads that were told to stop during or since the last step
293-
m_threads.erase(std::remove_if(m_threads.begin(), m_threads.end(), [](std::shared_ptr<VirtualMachine> thread) { return thread->atEnd(); }), m_threads.end());
294-
295-
m_redrawRequested = false;
296-
297-
// Step threads
298-
stepThreads();
299-
300-
// Render
301-
if (m_redrawHandler)
302-
m_redrawHandler();
303-
}
304-
305306
std::vector<std::shared_ptr<VirtualMachine>> Engine::stepThreads()
306307
{
307308
// https://github.com/scratchfoundation/scratch-vm/blob/develop/src/engine/sequencer.js#L70-L173
@@ -372,7 +373,6 @@ void Engine::stepThread(std::shared_ptr<VirtualMachine> thread)
372373

373374
void Engine::eventLoop(bool untilProjectStops)
374375
{
375-
updateFrameDuration();
376376
m_stopEventLoop = false;
377377

378378
while (true) {

src/engine/internal/engine.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class Engine : public IEngine
4242
void initClone(std::shared_ptr<Sprite> clone) override;
4343
void deinitClone(std::shared_ptr<Sprite> clone) override;
4444

45+
void step() override;
4546
void run() override;
4647
void runEventLoop() override;
4748
void stopEventLoop() override;
@@ -156,7 +157,6 @@ class Engine : public IEngine
156157
KeyOption
157158
};
158159

159-
void step();
160160
std::vector<std::shared_ptr<VirtualMachine>> stepThreads();
161161
void stepThread(std::shared_ptr<VirtualMachine> thread);
162162
void eventLoop(bool untilProjectStops = false);
@@ -216,7 +216,7 @@ class Engine : public IEngine
216216
std::unique_ptr<ITimer> m_defaultTimer;
217217
ITimer *m_timer = nullptr;
218218
double m_fps = 30; // default FPS
219-
std::chrono::milliseconds m_frameDuration; // will be computed in eventLoop()
219+
std::chrono::milliseconds m_frameDuration; // will be computed in step()
220220
bool m_turboModeEnabled = false;
221221
std::unordered_map<std::string, bool> m_keyMap; // holds key states
222222
bool m_anyKeyPressed = false;

test/engine/engine_test.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,31 @@ TEST(EngineTest, IsRunning)
7070
ASSERT_FALSE(engine.isRunning());
7171
}
7272

73+
TEST(EngineTest, Step)
74+
{
75+
Project p("step.sb3");
76+
ASSERT_TRUE(p.load());
77+
78+
p.start();
79+
80+
auto engine = p.engine();
81+
engine->setFps(250);
82+
Stage *stage = engine->stage();
83+
ASSERT_TRUE(stage);
84+
85+
ASSERT_VAR(stage, "test1");
86+
auto test1 = GET_VAR(stage, "test1");
87+
88+
ASSERT_VAR(stage, "test2");
89+
auto test2 = GET_VAR(stage, "test2");
90+
91+
for (int i = 1; i <= 3; i++) {
92+
engine->step();
93+
ASSERT_EQ(test1->value().toInt(), i);
94+
ASSERT_EQ(test2->value().toInt(), i > 1 ? 3 : 1);
95+
}
96+
}
97+
7398
TEST(EngineTest, EventLoop)
7499
{
75100
Engine engine;

test/mocks/enginemock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class EngineMock : public IEngine
2525
MOCK_METHOD(void, initClone, (std::shared_ptr<Sprite>), (override));
2626
MOCK_METHOD(void, deinitClone, (std::shared_ptr<Sprite>), (override));
2727

28+
MOCK_METHOD(void, step, (), (override));
2829
MOCK_METHOD(void, run, (), (override));
2930
MOCK_METHOD(void, runEventLoop, (), (override));
3031
MOCK_METHOD(void, stopEventLoop, (), (override));

test/step.sb3

1.6 KB
Binary file not shown.

0 commit comments

Comments
 (0)