Discuss Scratch
- Discussion Forums
- » Open Source Projects
- » I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
- Wowfunhappy
-
27 posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
Scratch has an “all at once” C-shaped block. https://scratch-mit-edu.ezproxyberklee.flo.org/projects/788226048. It doesn't do much of anything, and is hidden in the block palette. The source code in scratch-vm provides a pretty good description of why it exists:
https://github.com/LLK/scratch-vm/blob/f2781d3ea50d17e5088eec413935fd639cf3995b/src/blocks/scratch3_control.js#L195
I wanted to make the `all at once` block behave as it did in those early versions of Scratch 2.0, when the contained script would run without screen refresh.
I decided to try:
The results were… interesting.

I had effectively created the anti-all-at-once block: code outside this block was running all at once, while code inside the block ran normally! It was almost as if I had turned warp mode off at the start and on at the end…
…on a hunch, I decided to try doing just that:
This version seems to work perfectly! Code inside the all at once block runs without screen refresh, while code outside the block is unaffected!
This is great, but I'm totally weirded out! Clearly, I don't really understand what this code is doing, and I'm concerned that could lead to unintended side effects down the road.
Does anyone know why Scratch is seemingly executing this function bottom-to-top?
https://github.com/LLK/scratch-vm/blob/f2781d3ea50d17e5088eec413935fd639cf3995b/src/blocks/scratch3_control.js#L195
allAtOnce (args, util) { // Since the "all at once" block is implemented for compatiblity with // Scratch 2.0 projects, it behaves the same way it did in 2.0, which // is to simply run the contained script (like "if 1 = 1"). // (In early versions of Scratch 2.0, it would work the same way as // "run without screen refresh" custom blocks do now, but this was // removed before the release of 2.0.) util.startBranch(1, false); }
I wanted to make the `all at once` block behave as it did in those early versions of Scratch 2.0, when the contained script would run without screen refresh.
I decided to try:
allAtOnce (args, util) { util.thread.peekStackFrame().warpMode = true; util.startBranch(1, false); util.thread.peekStackFrame().warpMode = false; }
The results were… interesting.

I had effectively created the anti-all-at-once block: code outside this block was running all at once, while code inside the block ran normally! It was almost as if I had turned warp mode off at the start and on at the end…
…on a hunch, I decided to try doing just that:
allAtOnce (args, util) { util.thread.peekStackFrame().warpMode = false; util.startBranch(1, false); util.thread.peekStackFrame().warpMode = true; }
This version seems to work perfectly! Code inside the all at once block runs without screen refresh, while code outside the block is unaffected!
This is great, but I'm totally weirded out! Clearly, I don't really understand what this code is doing, and I'm concerned that could lead to unintended side effects down the road.
Does anyone know why Scratch is seemingly executing this function bottom-to-top?
Last edited by Wowfunhappy (Jan. 14, 2023 16:41:52)
- CST1229
-
1000+ posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
Scratch executes all block functions (that don't return a Promise) all at once (ha) - util.startBranch() doesn't execute the branch right when it is executed, it essentially schedules the branch to start after the function finishes running.
I don't know why that works - it seems like that would make the entire script run without screen refresh (including the blocks after it), or run the script INSIDE the c-slot with screen refresh and run the blocks after it WITHOUT screen refresh…
When I also did this, I handled it by adding an additional argument to the startBranch() function, which passes it to the sequencer's stepBranch() function (via another added argument), which passes it to the thread's pushStack() function (via ANOTHER added argument), which then finally passes the warp mode to the created stack frame.
I don't know why that works - it seems like that would make the entire script run without screen refresh (including the blocks after it), or run the script INSIDE the c-slot with screen refresh and run the blocks after it WITHOUT screen refresh…
When I also did this, I handled it by adding an additional argument to the startBranch() function, which passes it to the sequencer's stepBranch() function (via another added argument), which passes it to the thread's pushStack() function (via ANOTHER added argument), which then finally passes the warp mode to the created stack frame.
Last edited by CST1229 (Feb. 3, 2023 18:11:27)
- Wowfunhappy
-
27 posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
util.startBranch() doesn't execute the branch right when it is executed, it essentially schedules the branch to start after the function finishes running.Scratch executes all block functions (that don't return a Promise) all at once (ha) -
I don't know why that works - it seems like that would make the entire script run without screen refresh (including the blocks after it), or run the script INSIDE the c-slot with screen refresh and run the blocks after it WITHOUT screen refresh…
When I also did this, I handled it by adding an additional argument to the startBranch() function, which passes it to the sequencer's stepBranch() function (via another added argument), which passes it to the thread's pushStack() function (via ANOTHER added argument), which then finally passes the warp mode to the created stack frame.
Thank you!
- rdococ
-
1000+ posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
If `startBranch()` pushes another frame to the stack to represent the code in the C block, then the second call to `peekStackFrame()` returns the new stack frame and you're only setting that frame to warp.
Last edited by rdococ (April 14, 2023 18:37:25)
- imakegameslol88888
-
84 posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
because you coded it properly
- dynamicsofscratch
-
1000+ posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
deleted becuase my lemon brain just realized that I messed up the entire point of what you we're asking…
Last edited by dynamicsofscratch (April 22, 2023 05:43:05)
- Wowfunhappy
-
27 posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
If `startBranch()` pushes another frame to the stack to represent the code in the C block, then the second call to `peekStackFrame()` returns the new stack frame and you're only setting that frame to warp.
I'll admit I had to re-read this many times before I understood it, but—thank you! Combined with what @CST1229 said above about the branch not starting immediately, now the behavior makes complete sense!
- Mr_rudy
-
100+ posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
that isn't possible, it is a block in the VM, if you want to use it in turbowarp just use custom blocks Make IT as turbowarp extension.
- BigNate469
-
1000+ posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
Or you could just find a project that contains the block, download it, upload it to turbowarp, delete everything but the block in question, and you now should be able to use it in turbowarp, just copy and paste the block as necessary.
- EeveePro2756
-
4 posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
I'm not sure but try switching versions.
- julmik6478
-
500+ posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
Change project link to https://scratch-mit-edu.ezproxyberklee.flo.org/projects/401109316/
- TheCreatorOfUnTV
-
1000+ posts
I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...
It's because the warp Boolean, when true, slows down the script.
- Discussion Forums
- » Open Source Projects
-
» I made the `all at once` block actually run all at once. My code shouldn't work, I'd like to know why it does anyway...