Creating Custom block with mutator in playground

274 views
Skip to first unread message

Him

unread,
Aug 15, 2022, 5:14:10 PM8/15/22
to Blockly
Hi, I have been using the advanced playground and following the code generator code lab. There was an example on creating your own block and thats fine, but I want to build one with a mutator. Its going to be very similar to the list block but with some extra information. I tried copy pasting code from the list.js block definition and changing some code without much luck. Does anyone know how i can achieve this?

Thanks

Beka Westberg

unread,
Aug 15, 2022, 5:29:41 PM8/15/22
to blo...@googlegroups.com
Hello!

Thank you for your question =) Could you provide a bit more information about where you got stuck? E.g. did the block show up in your toolbox, and just not work correctly? Or did it not show up at all?

If you could post your source code, that would be super helpful for debugging!

Hopefully with a bit more info we can figure out what the issue is =)

Best wishes,
--Beka

On Mon, Aug 15, 2022 at 2:14 PM Him <fatai....@gmail.com> wrote:
Hi, I have been using the advanced playground and following the code generator code lab. There was an example on creating your own block and thats fine, but I want to build one with a mutator. Its going to be very similar to the list block but with some extra information. I tried copy pasting code from the list.js block definition and changing some code without much luck. Does anyone know how i can achieve this?

Thanks

--
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/253abbe2-690d-4487-b51f-f4f087d141ben%40googlegroups.com.

Him

unread,
Aug 15, 2022, 5:55:04 PM8/15/22
to Blockly
Hi, so in the attached image i defined the block. The definitions for "list_create_with_item" and "list_create_with_containter" are copy/pasted from the list.js block definition. The same thing with the list_create_with_item, i just renamed it to "utils_concurrent2". At best the block only shows up if the 3 block defnitions are commented out, and even if it does, it doesnt have the wheel to add more itemsMicrosoftTeams-image (2).png

Beka Westberg

unread,
Aug 16, 2022, 11:19:44 AM8/16/22
to blo...@googlegroups.com
Hello again,

Thanks for posting your source code =) But I think the issue (if there is one) is probably inside your blocks['utils_current2'] assignment, which is currently collapsed. If you could copy-paste the *text* of that block definition, that would be very helpful =)

Best Wishes,
--Beka

Him

unread,
Aug 16, 2022, 12:29:56 PM8/16/22
to Blockly
I would attach the file here if thats acceptable since its a lot of code. But all I did was copy paste the code for list but give it a new name
blocks['utils_concurrent2'] = {
    /**
     * Block for creating a list with any number of elements of any type.
     * @this {Block}
     */
    init: function() {
      this.setHelpUrl(Msg['LISTS_CREATE_WITH_HELPURL']);
      this.setStyle('list_blocks');
      this.itemCount_ = 3;
      this.updateShape_();
      this.setOutput(true, 'Array');
      this.setMutator(new Mutator(['lists_create_with_item']));
      this.setTooltip(Msg['LISTS_CREATE_WITH_TOOLTIP']);
    },
    /**
     * Create XML to represent list inputs.
     * Backwards compatible serialization implementation.
     * @return {!Element} XML storage element.
     * @this {Block}
     */
    mutationToDom: function() {
      const container = xmlUtils.createElement('mutation');
      container.setAttribute('items', this.itemCount_);
      return container;
    },
    /**
     * Parse XML to restore the list inputs.
     * Backwards compatible serialization implementation.
     * @param {!Element} xmlElement XML storage element.
     * @this {Block}
     */
    domToMutation: function(xmlElement) {
      this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10);
      this.updateShape_();
    },
    /**
     * Returns the state of this block as a JSON serializable object.
     * @return {{itemCount: number}} The state of this block, ie the item count.
     */
    saveExtraState: function() {
      return {
        'itemCount': this.itemCount_,
      };
    },
    /**
     * Applies the given state to this block.
     * @param {*} state The state to apply to this block, ie the item count.
     */
    loadExtraState: function(state) {
      this.itemCount_ = state['itemCount'];
      this.updateShape_();
    },
    /**
     * Populate the mutator's dialog with this block's components.
     * @param {!Workspace} workspace Mutator's workspace.
     * @return {!Block} Root block in mutator.
     * @this {Block}
     */
    decompose: function(workspace) {
      const containerBlock = workspace.newBlock('lists_create_with_container');
      containerBlock.initSvg();
      let connection = containerBlock.getInput('STACK').connection;
      for (let i = 0; i < this.itemCount_; i++) {
        const itemBlock = workspace.newBlock('lists_create_with_item');
        itemBlock.initSvg();
        connection.connect(itemBlock.previousConnection);
        connection = itemBlock.nextConnection;
      }
      return containerBlock;
    },
    /**
     * Reconfigure this block based on the mutator dialog's components.
     * @param {!Block} containerBlock Root block in mutator.
     * @this {Block}
     */
    compose: function(containerBlock) {
      let itemBlock = containerBlock.getInputTargetBlock('STACK');
      // Count number of inputs.
      const connections = [];
      while (itemBlock && !itemBlock.isInsertionMarker()) {
        connections.push(itemBlock.valueConnection_);
        itemBlock =
            itemBlock.nextConnection && itemBlock.nextConnection.targetBlock();
      }
      // Disconnect any children that don't belong.
      for (let i = 0; i < this.itemCount_; i++) {
        const connection = this.getInput('ADD' + i).connection.targetConnection;
        if (connection && connections.indexOf(connection) === -1) {
          connection.disconnect();
        }
      }
      this.itemCount_ = connections.length;
      this.updateShape_();
      // Reconnect any child blocks.
      for (let i = 0; i < this.itemCount_; i++) {
        Mutator.reconnect(connections[i], this, 'ADD' + i);
      }
    },
    /**
     * Store pointers to any connected child blocks.
     * @param {!Block} containerBlock Root block in mutator.
     * @this {Block}
     */
    saveConnections: function(containerBlock) {
      let itemBlock = containerBlock.getInputTargetBlock('STACK');
      let i = 0;
      while (itemBlock) {
        const input = this.getInput('ADD' + i);
        itemBlock.valueConnection_ = input && input.connection.targetConnection;
        itemBlock =
            itemBlock.nextConnection && itemBlock.nextConnection.targetBlock();
        i++;
      }
    },
    /**
     * Modify this block to have the correct number of inputs.
     * @private
     * @this {Block}
     */
    updateShape_: function() {
      if (this.itemCount_ && this.getInput('EMPTY')) {
        this.removeInput('EMPTY');
      } else if (!this.itemCount_ && !this.getInput('EMPTY')) {
        this.appendDummyInput('EMPTY').appendField(
            Msg['LISTS_CREATE_EMPTY_TITLE']);
      }
      // Add new inputs.
      for (let i = 0; i < this.itemCount_; i++) {
        if (!this.getInput('ADD' + i)) {
          const input = this.appendValueInput('ADD' + i).setAlign(Align.RIGHT);
          if (i === 0) {
            input.appendField(Msg['LISTS_CREATE_WITH_INPUT_WITH']);
          }
        }
      }
      // Remove deleted inputs.
      for (let i = this.itemCount_; this.getInput('ADD' + i); i++) {
        this.removeInput('ADD' + i);
      }
    },
  };

Beka Westberg

unread,
Aug 16, 2022, 6:18:46 PM8/16/22
to blo...@googlegroups.com
Hmmm, well looking at it, nothing immediately jumps out to me as wrong, so that's good! Are you getting any errors in the browser console when the block definitions are uncommented?

Best,
--Beka

Him

unread,
Aug 16, 2022, 8:10:20 PM8/16/22
to Blockly
Thanks for the tip about the console logs. I just wasnt importing the libraries properly

Beka Westberg

unread,
Aug 17, 2022, 11:54:31 AM8/17/22
to blo...@googlegroups.com
Yay I'm glad you found the solution to your problem =)

Best of luck with your project!
--Beka

Reply all
Reply to author
Forward
0 new messages