@@ -159,7 +159,7 @@ void Engine::start()
159159 for (auto target : m_targets) {
160160 auto gfBlocks = target->greenFlagBlocks ();
161161 for (auto block : gfBlocks)
162- startScript (block, target);
162+ startScript (block, target. get () );
163163 }
164164
165165 m_eventLoopMutex.unlock ();
@@ -171,23 +171,27 @@ void Engine::stop()
171171 deleteClones ();
172172}
173173
174- void Engine::startScript (std::shared_ptr<Block> topLevelBlock, std::shared_ptr< Target> target)
174+ VirtualMachine * Engine::startScript (std::shared_ptr<Block> topLevelBlock, Target * target)
175175{
176176 if (!topLevelBlock) {
177177 std::cout << " warning: starting a script with a null top level block (nothing will happen)" << std::endl;
178- return ;
178+ return nullptr ;
179179 }
180180
181181 if (!target) {
182182 std::cout << " error: scripts must be started by a target" ;
183183 assert (false );
184- return ;
184+ return nullptr ;
185185 }
186186
187187 if (topLevelBlock->next ()) {
188188 auto script = m_scripts[topLevelBlock];
189- addRunningScript (script->start ());
189+ std::shared_ptr<VirtualMachine> vm = script->start (target);
190+ addRunningScript (vm);
191+ return vm.get ();
190192 }
193+
194+ return nullptr ;
191195}
192196
193197void Engine::broadcast (unsigned int index, VirtualMachine *sourceScript, bool wait)
@@ -201,61 +205,22 @@ void Engine::broadcast(unsigned int index, VirtualMachine *sourceScript, bool wa
201205void Engine::broadcastByPtr (Broadcast *broadcast, VirtualMachine *sourceScript, bool wait)
202206{
203207 const std::vector<Script *> &scripts = m_broadcastMap[broadcast];
208+ auto &runningBroadcasts = m_runningBroadcastMap[broadcast];
204209
205210 for (auto script : scripts) {
206- std::vector<VirtualMachine *> runningBroadcastScripts;
207-
208- for (const auto &[target, targetScripts] : m_runningScripts) {
209- for (auto vm : targetScripts) {
210- if (vm->script () == script) {
211- runningBroadcastScripts.push_back (vm.get ());
212- }
213- }
211+ for (auto &pair : runningBroadcasts) {
212+ if (pair.second ->script () == script)
213+ pair.first = sourceScript;
214214 }
215215
216- // Reset running scripts
217- for (VirtualMachine *vm : runningBroadcastScripts) {
218- vm->reset ();
219-
220- // Remove the script from scripts to remove because it's going to run again
221- m_scriptsToRemove.erase (std::remove (m_scriptsToRemove.begin (), m_scriptsToRemove.end (), vm), m_scriptsToRemove.end ());
222- assert (std::find (m_scriptsToRemove.begin (), m_scriptsToRemove.end (), vm) == m_scriptsToRemove.end ());
223-
224- auto &scripts = m_runningBroadcastMap[broadcast];
225-
226- for (auto &pair : scripts) {
227- if (pair.second ->script () == script)
228- pair.first = sourceScript;
229- }
230-
231- if (script == sourceScript->script ())
232- sourceScript->stop (false , !wait); // source script is the broadcast script
233- }
234-
235- // Start scripts which are not running
236- Target *root = script->target ();
237- std::vector<Target *> targets = { root };
238-
239- if (!root->isStage ()) {
240- Sprite *sprite = dynamic_cast <Sprite *>(root);
241- assert (sprite);
242- assert (!sprite->isClone ());
243- const auto &children = sprite->clones ();
244-
245- for (auto child : children)
246- targets.push_back (child.get ());
247- }
216+ if (script == sourceScript->script ())
217+ sourceScript->stop (false , !wait); // source script is the broadcast script
218+ }
248219
249- for (Target *target : targets) {
250- auto it = std::find_if (runningBroadcastScripts.begin (), runningBroadcastScripts.end (), [target](VirtualMachine *vm) { return vm->target () == target; });
220+ std::vector<VirtualMachine *> startedScripts = startHats (scripts);
251221
252- if (it == runningBroadcastScripts.end ()) {
253- auto vm = script->start (target);
254- addRunningScript (vm);
255- m_runningBroadcastMap[broadcast].push_back ({ sourceScript, vm.get () });
256- }
257- }
258- }
222+ for (VirtualMachine *vm : startedScripts)
223+ runningBroadcasts.push_back ({ sourceScript, vm });
259224}
260225
261226void Engine::stopScript (VirtualMachine *vm)
@@ -565,12 +530,12 @@ void Engine::setKeyState(const KeyEvent &event, bool pressed)
565530 auto it = m_whenKeyPressedScripts.find (event.name ());
566531
567532 if (it != m_whenKeyPressedScripts.cend ())
568- startWhenKeyPressedScripts (it->second );
533+ startHats (it->second );
569534
570535 it = m_whenKeyPressedScripts.find (" any" );
571536
572537 if (it != m_whenKeyPressedScripts.cend ())
573- startWhenKeyPressedScripts (it->second );
538+ startHats (it->second );
574539 }
575540}
576541
@@ -583,7 +548,7 @@ void Engine::setAnyKeyPressed(bool pressed)
583548 auto it = m_whenKeyPressedScripts.find (" any" );
584549
585550 if (it != m_whenKeyPressedScripts.cend ())
586- startWhenKeyPressedScripts (it->second );
551+ startHats (it->second );
587552 }
588553}
589554
@@ -1249,18 +1214,66 @@ void Engine::addRunningScript(std::shared_ptr<VirtualMachine> vm)
12491214 }
12501215}
12511216
1252- void Engine::startWhenKeyPressedScripts (const std::vector<Script *> &scripts)
1217+ std::vector<VirtualMachine *> Engine::startHats (const std::vector<Script *> &scripts)
12531218{
1219+ std::vector<VirtualMachine *> startedScripts;
1220+
12541221 for (auto script : scripts) {
1255- std::shared_ptr<Block> block = nullptr ;
1222+ std::vector<VirtualMachine *> runningScripts;
1223+
1224+ for (const auto &[target, targetScripts] : m_runningScripts) {
1225+ for (auto vm : targetScripts) {
1226+ if (vm->script () == script) {
1227+ runningScripts.push_back (vm.get ());
1228+ }
1229+ }
1230+ }
1231+
1232+ // Reset running scripts
1233+ for (VirtualMachine *vm : runningScripts) {
1234+ vm->reset ();
1235+
1236+ // Remove the script from scripts to remove because it's going to run again
1237+ m_scriptsToRemove.erase (std::remove (m_scriptsToRemove.begin (), m_scriptsToRemove.end (), vm), m_scriptsToRemove.end ());
1238+ assert (std::find (m_scriptsToRemove.begin (), m_scriptsToRemove.end (), vm) == m_scriptsToRemove.end ());
1239+ }
1240+
1241+ // Start scripts which are not running
1242+ Target *root = script->target ();
1243+ std::vector<Target *> targets = { root };
1244+
1245+ if (!root->isStage ()) {
1246+ Sprite *sprite = dynamic_cast <Sprite *>(root);
1247+ assert (sprite);
1248+ assert (!sprite->isClone ());
1249+ const auto &children = sprite->clones ();
12561250
1257- for (const auto &[b, s] : m_scripts) {
1258- if (s.get () == script)
1259- block = b;
1251+ for (auto child : children)
1252+ targets.push_back (child.get ());
12601253 }
12611254
1262- assert (block);
1263- assert (std::find_if (m_targets.begin (), m_targets.end (), [script](std::shared_ptr<Target> target) { return script->target () == target.get (); }) != m_targets.end ());
1264- startScript (block, *std::find_if (m_targets.begin (), m_targets.end (), [script](std::shared_ptr<Target> target) { return script->target () == target.get (); }));
1255+ for (Target *target : targets) {
1256+ std::shared_ptr<Block> block = nullptr ;
1257+
1258+ if (!runningScripts.empty ()) {
1259+ auto it = std::find_if (runningScripts.begin (), runningScripts.end (), [target, script](VirtualMachine *vm) { return (vm->target () == target) && (vm->script () == script); });
1260+
1261+ if (it != runningScripts.end ())
1262+ continue ; // skip the script because it was already running and was reset
1263+ }
1264+
1265+ for (const auto &[b, s] : m_scripts) {
1266+ if (s.get () == script) {
1267+ block = b;
1268+ break ;
1269+ }
1270+ }
1271+
1272+ assert (block);
1273+ assert (std::find_if (m_targets.begin (), m_targets.end (), [script](std::shared_ptr<Target> target) { return script->target () == target.get (); }) != m_targets.end ());
1274+ startedScripts.push_back (startScript (block, target));
1275+ }
12651276 }
1277+
1278+ return startedScripts;
12661279}
0 commit comments