Skip to content

Commit fda3e02

Browse files
committed
Engine: Add support for sending broadcasts by pointer
1 parent 441ccc6 commit fda3e02

File tree

4 files changed

+46
-6
lines changed

4 files changed

+46
-6
lines changed

include/scratchcpp/iengine.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ class LIBSCRATCHCPP_EXPORT IEngine
6565
/*! Starts the script of the broadcast with the given index. */
6666
virtual void broadcast(unsigned int index, VirtualMachine *sourceScript, bool wait = false) = 0;
6767

68+
/*! Starts the script of the given broadcast. */
69+
virtual void broadcastByPtr(Broadcast *broadcast, VirtualMachine *sourceScript, bool wait = false) = 0;
70+
6871
/*! Stops the given script. */
6972
virtual void stopScript(VirtualMachine *vm) = 0;
7073

@@ -122,6 +125,9 @@ class LIBSCRATCHCPP_EXPORT IEngine
122125
/*! Returns true if there are any running script of the broadcast with the given index. */
123126
virtual bool broadcastRunning(unsigned int index, VirtualMachine *sourceScript) = 0;
124127

128+
/*! Returns true if there are any running script of the given broadcast. */
129+
virtual bool broadcastByPtrRunning(Broadcast *broadcast, VirtualMachine *sourceScript) = 0;
130+
125131
/*!
126132
* Call this from a block implementation to force a "screen refresh".
127133
* \note This has no effect in "run without screen refresh" custom blocks.

src/engine/internal/engine.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <scratchcpp/block.h>
1414
#include <scratchcpp/variable.h>
1515
#include <scratchcpp/list.h>
16+
#include <scratchcpp/costume.h>
1617
#include <cassert>
1718
#include <iostream>
1819
#include <thread>
@@ -208,9 +209,13 @@ void Engine::startScript(std::shared_ptr<Block> topLevelBlock, std::shared_ptr<T
208209

209210
void Engine::broadcast(unsigned int index, VirtualMachine *sourceScript, bool wait)
210211
{
212+
if (index < 0 || index >= m_broadcasts.size())
213+
return;
214+
211215
bool previousSkipFrame = m_skipFrame;
212216
skipFrame();
213217
const std::vector<Script *> &scripts = m_broadcastMap[index];
218+
auto broadcast = m_broadcasts[index];
214219

215220
for (auto script : scripts) {
216221
std::vector<VirtualMachine *> runningBroadcastScripts;
@@ -229,7 +234,7 @@ void Engine::broadcast(unsigned int index, VirtualMachine *sourceScript, bool wa
229234
m_scriptsToRemove.erase(std::remove(m_scriptsToRemove.begin(), m_scriptsToRemove.end(), vm), m_scriptsToRemove.end());
230235
assert(std::find(m_scriptsToRemove.begin(), m_scriptsToRemove.end(), vm) == m_scriptsToRemove.end());
231236

232-
auto &scripts = m_runningBroadcastMap[index];
237+
auto &scripts = m_runningBroadcastMap[broadcast.get()];
233238

234239
for (auto &pair : scripts) {
235240
if (pair.second->script() == script)
@@ -264,12 +269,20 @@ void Engine::broadcast(unsigned int index, VirtualMachine *sourceScript, bool wa
264269
if (it == runningBroadcastScripts.end()) {
265270
auto vm = script->start(target);
266271
m_runningScripts.push_back(vm);
267-
m_runningBroadcastMap[index].push_back({ sourceScript, vm.get() });
272+
m_runningBroadcastMap[broadcast.get()].push_back({ sourceScript, vm.get() });
268273
}
269274
}
270275
}
271276
}
272277

278+
void Engine::broadcastByPtr(Broadcast *broadcast, VirtualMachine *sourceScript, bool wait)
279+
{
280+
auto it = std::find_if(m_broadcasts.begin(), m_broadcasts.end(), [broadcast](std::shared_ptr<Broadcast> b) { return b.get() == broadcast; });
281+
282+
if (it != m_broadcasts.end())
283+
this->broadcast(it - m_broadcasts.begin(), sourceScript, wait);
284+
}
285+
273286
void Engine::stopScript(VirtualMachine *vm)
274287
{
275288
assert(vm);
@@ -411,7 +424,20 @@ void Engine::setStageHeight(unsigned int height)
411424

412425
bool Engine::broadcastRunning(unsigned int index, VirtualMachine *sourceScript)
413426
{
414-
const auto &scripts = m_runningBroadcastMap[index];
427+
if (index < 0 || index >= m_broadcasts.size())
428+
return false;
429+
430+
return broadcastByPtrRunning(m_broadcasts[index].get(), sourceScript);
431+
}
432+
433+
bool Engine::broadcastByPtrRunning(Broadcast *broadcast, VirtualMachine *sourceScript)
434+
{
435+
auto it = m_runningBroadcastMap.find(broadcast);
436+
437+
if (it == m_runningBroadcastMap.cend())
438+
return false;
439+
440+
const auto &scripts = it->second;
415441

416442
for (const auto &pair : scripts) {
417443
if (pair.first == sourceScript)
@@ -570,6 +596,10 @@ int Engine::findBroadcastById(const std::string &broadcastId) const
570596
void Engine::addBroadcastScript(std::shared_ptr<Block> whenReceivedBlock, std::shared_ptr<Broadcast> broadcast)
571597
{
572598
auto id = findBroadcast(broadcast->name());
599+
600+
if (id == -1)
601+
return;
602+
573603
if (m_broadcastMap.count(id) == 1) {
574604
std::vector<Script *> &scripts = m_broadcastMap[id];
575605
// TODO: Do not allow adding existing scripts
@@ -579,7 +609,7 @@ void Engine::addBroadcastScript(std::shared_ptr<Block> whenReceivedBlock, std::s
579609

580610
// Create a vector of running scripts for this broadcast
581611
// so we don't need to check if it's there
582-
m_runningBroadcastMap[id] = {};
612+
m_runningBroadcastMap[m_broadcasts[id].get()] = {};
583613
}
584614
}
585615

src/engine/internal/engine.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class Engine : public IEngine
3131
void stop() override;
3232
void startScript(std::shared_ptr<Block> topLevelBlock, std::shared_ptr<Target> target) override;
3333
void broadcast(unsigned int index, VirtualMachine *sourceScript, bool wait = false) override;
34+
void broadcastByPtr(Broadcast *broadcast, VirtualMachine *sourceScript, bool wait = false) override;
3435
void stopScript(VirtualMachine *vm) override;
3536
void stopTarget(Target *target, VirtualMachine *exceptScript) override;
3637
void initClone(libscratchcpp::Sprite *clone) override;
@@ -54,6 +55,7 @@ class Engine : public IEngine
5455
void setStageHeight(unsigned int height) override;
5556

5657
bool broadcastRunning(unsigned int index, VirtualMachine *sourceScript) override;
58+
bool broadcastByPtrRunning(Broadcast *broadcast, VirtualMachine *sourceScript) override;
5759

5860
void breakFrame() override;
5961
bool breakingCurrentFrame() override;
@@ -116,8 +118,8 @@ class Engine : public IEngine
116118
std::vector<std::shared_ptr<Target>> m_targets;
117119
std::vector<std::shared_ptr<Broadcast>> m_broadcasts;
118120
std::unordered_map<unsigned int, std::vector<Script *>> m_broadcastMap;
119-
std::unordered_map<unsigned int, std::vector<std::pair<VirtualMachine *, VirtualMachine *>>> m_runningBroadcastMap; // source script, "when received" script
120-
std::unordered_map<Target *, std::vector<Script *>> m_cloneInitScriptsMap; // target (no clones), "when I start as a clone" scripts
121+
std::unordered_map<Broadcast *, std::vector<std::pair<VirtualMachine *, VirtualMachine *>>> m_runningBroadcastMap; // source script, "when received" script
122+
std::unordered_map<Target *, std::vector<Script *>> m_cloneInitScriptsMap; // target (no clones), "when I start as a clone" scripts
121123
std::vector<std::string> m_extensions;
122124
std::vector<std::shared_ptr<VirtualMachine>> m_runningScripts;
123125
std::vector<VirtualMachine *> m_scriptsToRemove;

test/mocks/enginemock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class EngineMock : public IEngine
1919
MOCK_METHOD(void, stop, (), (override));
2020
MOCK_METHOD(void, startScript, (std::shared_ptr<Block>, std::shared_ptr<Target>), (override));
2121
MOCK_METHOD(void, broadcast, (unsigned int, VirtualMachine *, bool), (override));
22+
MOCK_METHOD(void, broadcastByPtr, (Broadcast *, VirtualMachine *, bool), (override));
2223
MOCK_METHOD(void, stopScript, (VirtualMachine *), (override));
2324
MOCK_METHOD(void, stopTarget, (Target *, VirtualMachine *), (override));
2425
MOCK_METHOD(void, initClone, (Sprite *), (override));
@@ -42,6 +43,7 @@ class EngineMock : public IEngine
4243
MOCK_METHOD(void, setStageHeight, (unsigned int), (override));
4344

4445
MOCK_METHOD(bool, broadcastRunning, (unsigned int, VirtualMachine *), (override));
46+
MOCK_METHOD(bool, broadcastByPtrRunning, (Broadcast *, VirtualMachine *), (override));
4547

4648
MOCK_METHOD(void, breakFrame, (), (override));
4749
MOCK_METHOD(bool, breakingCurrentFrame, (), (override));

0 commit comments

Comments
 (0)