@@ -126,8 +126,19 @@ void Engine::frame()
126126 do {
127127 script->run ();
128128 if (script->atEnd ()) {
129- for (auto &[key, value] : m_broadcastMap)
130- value.erase (std::remove (value.begin (), value.end (), script->script ()), value.end ());
129+ for (auto &[key, value] : m_runningBroadcastMap) {
130+ size_t index = 0 ;
131+
132+ for (const auto &pair : value) {
133+ if (pair.second == script.get ()) {
134+ value.erase (value.begin () + index);
135+ break ;
136+ }
137+
138+ index++;
139+ }
140+ }
141+
131142 m_scriptsToRemove.push_back (script.get ());
132143 }
133144 } while (!script->atEnd () && !m_breakFrame);
@@ -180,24 +191,48 @@ void Engine::startScript(std::shared_ptr<Block> topLevelBlock, std::shared_ptr<T
180191 }
181192}
182193
183- void libscratchcpp::Engine::broadcast (unsigned int index, VirtualMachine *sourceScript)
194+ void libscratchcpp::Engine::broadcast (unsigned int index, VirtualMachine *sourceScript, bool wait )
184195{
196+ bool previousSkipFrame = m_skipFrame;
197+ skipFrame ();
185198 const std::vector<Script *> &scripts = m_broadcastMap[index];
199+
186200 for (auto script : scripts) {
187- size_t index = -1 ;
188- for (size_t i = 0 ; i < m_runningScripts.size (); i++) {
201+ long scriptIndex = -1 ;
202+ for (long i = 0 ; i < m_runningScripts.size (); i++) {
189203 if (m_runningScripts[i]->script () == script) {
190- index = i;
204+ scriptIndex = i;
191205 break ;
192206 }
193207 }
194- if (index != -1 ) {
208+
209+ if (scriptIndex != -1 ) {
195210 // Reset the script if it's already running
196- m_runningScripts[index]->reset ();
197- if (script == sourceScript->script ())
211+ auto vm = m_runningScripts[scriptIndex];
212+ vm->reset ();
213+
214+ // Remove the script from scripts to remove because it's going to run again
215+ m_scriptsToRemove.erase (std::remove (m_scriptsToRemove.begin (), m_scriptsToRemove.end (), vm.get ()), m_scriptsToRemove.end ());
216+ assert (std::find (m_scriptsToRemove.begin (), m_scriptsToRemove.end (), m_runningScripts[scriptIndex].get ()) == m_scriptsToRemove.end ());
217+
218+ auto &scripts = m_runningBroadcastMap[index];
219+
220+ for (auto &pair : scripts) {
221+ if (pair.second ->script () == script)
222+ pair.first = sourceScript;
223+ }
224+
225+ if (script == sourceScript->script ()) {
198226 sourceScript->stop (false , true );
227+
228+ if (!previousSkipFrame && !wait)
229+ m_skipFrame = false ;
230+ } else
231+ sourceScript->stop (true , true );
199232 } else {
200- m_runningScripts.push_back (script->start ());
233+ auto vm = script->start ();
234+ m_runningScripts.push_back (vm);
235+ m_runningBroadcastMap[index].push_back ({ sourceScript, vm.get () });
201236 }
202237 }
203238}
@@ -251,9 +286,16 @@ void Engine::run()
251286 }
252287}
253288
254- bool Engine::broadcastRunning (unsigned int index)
289+ bool Engine::broadcastRunning (unsigned int index, VirtualMachine *sourceScript )
255290{
256- return !m_broadcastMap[index].empty ();
291+ const auto &scripts = m_runningBroadcastMap[index];
292+
293+ for (const auto &pair : scripts) {
294+ if (pair.first == sourceScript)
295+ return true ;
296+ }
297+
298+ return false ;
257299}
258300
259301void Engine::breakFrame ()
@@ -377,8 +419,13 @@ void libscratchcpp::Engine::addBroadcastScript(std::shared_ptr<Block> whenReceiv
377419 if (m_broadcastMap.count (id) == 1 ) {
378420 std::vector<Script *> &scripts = m_broadcastMap[id];
379421 scripts.push_back (m_scripts[whenReceivedBlock].get ());
380- } else
422+ } else {
381423 m_broadcastMap[id] = { m_scripts[whenReceivedBlock].get () };
424+
425+ // Create a vector of running scripts for this broadcast
426+ // so we don't need to check if it's there
427+ m_runningBroadcastMap[id] = {};
428+ }
382429}
383430
384431const std::vector<std::shared_ptr<Target>> &Engine::targets () const
0 commit comments