Blockly Mutators

230 views
Skip to first unread message

PilotTim136

unread,
Mar 26, 2024, 6:35:32 AM3/26/24
to Blockly
so, i want to make mutators for my project, but i don't understand how they work. I do have some uses for it, because i have a project for a project called "Scratch for JavascriptBot", discord bot, and it would be useful for this blockUnbenannt.png
and i want to show '(ID if other [])' only, if other is selected in the dropdown.
How can i do that?

(and please maybe add mutators to the blockly-block factory)

Mark Friedman

unread,
Mar 26, 2024, 6:00:58 PM3/26/24
to blo...@googlegroups.com
I'm happy to write about how mutators work in a separate post, but I would first suggest that maybe your block shouldn't be designed the way that you have pictured (and therefore that you wouldn't even need a mutator).  

I think that it would be clearer to the user to have two different blocks in your scenario: one for the "this" case and one for the "other" case.  That would remove the dropdown and the awkward "(ID if other ...)" text. Having two blocks would also make it clear in the toolbox that there are two kinds of message sends - something that otherwise would be obscured if the toolbox only had the one block with a dropdown to change the block.  

I know that as software developers we often want to create more general and abstract structures, but my feeling is that for the types of users that we create blocks-based interfaces for, being more concrete (like having two simpler blocks) is particularly important and useful. 

-Mark


--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/9abfb29e-7feb-4cc5-9b97-bced0da9a49an%40googlegroups.com.

PilotTim136

unread,
Mar 26, 2024, 6:35:24 PM3/26/24
to Blockly
what exactly do you mean? i didn't understand you clearly 😅

Mark Friedman

unread,
Mar 26, 2024, 6:53:26 PM3/26/24
to blo...@googlegroups.com
I mean having two blocks like the following (ignoring the renderer type):
Screenshot 2024-03-26 at 3.49.31 PM.png
and
Screenshot 2024-03-26 at 3.51.00 PM.png
Hope that helps.

-Mark


PilotTim136

unread,
Mar 27, 2024, 8:54:04 AM3/27/24
to Blockly
i know that, but what do you mean with 'a seperate post'? whats it called, so i can take a view on it

Mark Friedman

unread,
Mar 27, 2024, 1:49:42 PM3/27/24
to blo...@googlegroups.com
I just meant that I might post another message about mutators, which I have not yet done.

-Mark


PilotTim136

unread,
Mar 27, 2024, 7:00:55 PM3/27/24
to Blockly
Ohh, okay! Do you maybe know where this would be, or is this not really planned yet?

Mark Friedman

unread,
Mar 27, 2024, 7:10:13 PM3/27/24
to blo...@googlegroups.com
It's not written yet, but I'm curious whether my original reply might have changed your mind about needing mutators, at least for the block that you were originally talking about.

-Mark


PilotTim136

unread,
Mar 28, 2024, 3:46:39 PM3/28/24
to Blockly
but i would have purposes for it, for other blocks i have not made yet

Mark Friedman

unread,
Mar 28, 2024, 7:10:07 PM3/28/24
to blo...@googlegroups.com
Fair enough ;-)

So here is how I think about mutators.  Others might think of it differently, and I welcome their input!

One key thing to keep in mind is that there are a bunch of places in the Blockly code where it needs to copy a block. That includes explicitly copy/pasting a block, dragging a block, connecting it to other blocks, or creating a new one from the toolbox.  Blockly does that by looking at the type of the block, running the init method for that block type, and copying over the standard attributes of the block (e.g. its field's values). Unfortunately, that's not quite enough. Why? Because blocks sometimes morph (i.e. mutate) in non-standard ways (e.g. adding or removing inputs) based on user or programmatic actions. So, copying those mutated blocks requires more information than just their type.  That extra information is encoded in the "extra" state that is written and read by the saveExtraState and loadExtraState methods of blocks. 

The saveExtraState method allows you (the block definition writer) to encode whatever extra information you need to later recreate those mutations (i.e. changes) in your loadExtraState method in order to make a copied block match its source block.  Note that the saveExtraState and loadExtraState methods create and read the block's extra state as "Plain Old JavaScript Objects" (aka POJOs). That is, objects that are not instances of classes.

There is another major case where mutators (and their saveExtraState and loadExtraState methods) come into play and that's in the saving and loading of workspaces (or other sets of blocks), which is a common feature of many uses of Blockly.  Blockly does that through a process commonly called serialization.  During serialization, Blockly creates a state object for each block which contains the block's type, the values of its standard attributes and its extra state.  This larger block state object is also a POJO, which means that it can then be easily converted to a textual JSON string which can be externally saved.  The process of generating the JSON string which represents the workspace (or set of blocks) is serialization. Deserialization is just the reverse process of taking the JSON string and populating a workspace from it.

The call to Blockly.Extensions.registerMutator, takes a name for the mutator and what it calls a mixin object, which is an object which contains the extra state fields and your saveExtraState and loadExtraState field whose values are the functions mentioned above. You specify the name of the mutator in your block type definition. 

Note that there are other, optional, arguments to Blockly.Extensions.registerMutator, but I'm trying to keep things as simple as I can ;-). 

One potentially confusing thing is that Blockly sometimes (in its code and documentation) calls the process of creating the state POJO "serialization" and it sometimes refers to the type of the state object as "JSON".  Strictly speaking, the term "serialization" usually means the process of creating the external representation of an object (i.e. the JSON string), not the state object.  Also, strictly speaking" the type of the state object is just a JavaScript object (or POJO), i.e. not JSON.  JSON, properly speaking, is a textual format.

I hope that this helps clarify mutators and does not further confuse you!

-Mark


PilotTim136

unread,
Mar 28, 2024, 7:49:16 PM3/28/24
to Blockly
okay, i do get it a littlebit now, but how do i code them? because i didn't read anything about mutators on how to make them on the blockly developers site, or i didn't see the tab/mutators thing in the blocks.
what i mean by this:
for example, if i would want to make a switch case block, how would it kind of look in code? (the mutator code), because i don't quite understand how the code for them work.

Mark Friedman

unread,
Mar 29, 2024, 1:27:22 PM3/29/24
to blo...@googlegroups.com
Sorry, I thought that you had already read the documentation on mutators on the Blockly dev site.  That goes into more detail on the specifics of how to use them.

If you want to look at the implementation of the existing Blockly block types, you can find them here.  The If block code might be the closest to the Switch block that you want to implement, so that might be a good place to start.  Note that you won't need to implement the domToMutation or mutationToDom methods.  They are there in the Blockly code to support older, deprecated, cases.

-Mark


PilotTim136

unread,
Mar 30, 2024, 11:33:40 AM3/30/24
to Blockly
sorry to answer so late, but i will look into it! thank you :)
Reply all
Reply to author
Forward
0 new messages