Hello, I'm customizing the blockly if block, but when I press the configuration button to set the block and then turn it off and on again, the existing block disappears. In compose, nextConnection is coming out as null, what could be the problem?

42 views
Skip to first unread message

박태욱

unread,
May 10, 2024, 5:31:19 AM5/10/24
to Blockly
import Blockly from 'blockly';
import { connection } from 'mongoose';
import { ScriptGenerator } from '../generator';

export const logic_block = {
    "script_logic_if": {
        init: function () {
            this.appendDummyInput()
                .appendField(new Blockly.FieldTextInput("default_text"), "input_text");
            this.setOutput(true, "String");
            this.setColour(230);
            this.setTooltip("");
            this.setHelpUrl("");
        }
    },
    "script_logic_text": {
        init: function () {
            this.appendDummyInput()
                .appendField(new Blockly.FieldTextInput("default_text"), "input_text");
            this.setOutput(true, "String");
            this.setColour(230);
            this.setTooltip("");
            this.setHelpUrl("");
        }
    },
    "script_logic_if_test": {
        init: function () {
            this.appendValueInput("IF")
                .setCheck(null)
                .appendField("if");
            this.appendStatementInput("DO").appendField("do");
            this.setPreviousStatement(true, null);
            this.setNextStatement(true, null);
            this.setMutator(new Blockly.icons.MutatorIcon(['logic_elseif', 'logic_else'], this));
            this.itemCount_ = 0;
            this.logic_elseifCount_ = 0;
            this.logic_elseCount_ = 0;
        },

        // 블럭 저장되거나 불러 올 떄 사용하는 XML 형태의 mutation 요소 생성하고 반환
        mutationToDom: function () {
            var container = Blockly.utils.xml.createElement('mutation');
            if (this.logic_elseifCount_) { container.setAttribute('logic_elseif', this.logic_elseifCount_); }
            if (this.logic_elseCount_) { container.setAttribute('logic_else', 1); }

            return container;
        },

        //xml요소에서 block 상태 정보를 불러옴
        domToMutation: function (xmlElement) {
            console.log("domToMutation");
            this.logic_elseifCount_ = parseInt(xmlElement.getAttribute('logic_elseif'), 10);
            this.logic_elseCount_ = parseInt(xmlElement.getAttribute('logic_else'), 10);
            this.updateShape_();
        },

        //block 구조 업데이트
        updateShape_: function () {
            //시작 할 때 기존에 존재할 수 있는 부분 제거
            for (let i = 1; i <= this.logic_elseifCount_; i++) {
                if (this.getInput('COND' + i)) {
                    this.removeInput('COND' + i);
                    this.removeInput('DO' + i);
                }
            }

            if (this.getInput('ADD_ELSE')) {
                this.removeInput('ADD_ELSE');
            }

            // itemcount가 증가하면, Add+i이름 새로운 블럭 추가
            for (let i = 1; i <= this.logic_elseifCount_; i++) {
                this.appendValueInput('COND' + i)
                    .setCheck(null)
                    .appendField("else if");
                this.appendStatementInput('DO' + i)
                    .setCheck(null)
                    .appendField("do");
            }

            if (this.logic_elseCount_) {
                this.appendStatementInput('ADD_ELSE')
                    .setCheck(null)
                    .appendField("else");
            }
        },

        //workspace.newBlock()은 새로운 블록을 생성하고 참조 반환.
        decompose: function (workspace) {
            console.log("decompose");
            var topBlock = workspace.newBlock('controls_if_if'); // 설정 눌렀을 때 처음 블럭
            topBlock.initSvg();

            var currentBlock = topBlock;
            currentBlock = currentBlock.nextConnection;
            console.log(currentBlock);
            for (var i = 1; i <= this.logic_elseifCount_; i++) {
                var logic_elseif_block = workspace.newBlock('logic_elseif');
                logic_elseif_block.initSvg();
                currentBlock.connect(logic_elseif_block.previousConnection);
                currentBlock = logic_elseif_block.previousConnection;
            }
            if (this.logic_elseCount_) {
                var logic_else_block = workspace.newBlock('logic_else');
                logic_else_block.initSvg();
                currentBlock.connect(logic_else_block.previousConnection);
            }
            return topBlock;
        },

        compose: function (topBlock) {
            var itemBlock = topBlock.nextConnection.targetBlock();
            this.logic_elseifCount_ = 0;
            this.logic_elseCount_ = 0;

            console.log(itemBlock);

            var statementConnections = [];
            var elseStatementConnection = null;

            while (itemBlock) {
                switch (itemBlock.type) {
                    case "logic_elseif":
                        this.logic_elseifCount_++;
                        statementConnections.push(itemBlock.valueConnection_);
                        break;
                    case 'logic_else':
                        this.logic_elseCount_++;
                        elseStatementConnection = itemBlock.statementConnection_;
                        break;
                }
                console.log(itemBlock)
                itemBlock = itemBlock.nextConnection && itemBlock.nextConnection.targetBlock();
            }

            this.itemCount_ = statementConnections.length;
            this.updateShape_();

            for (var i = 0; i < this.itemCount_; i++) {
                //statementConnections[i].reconnect(this, 'ADD' + i);
            }
        },
    },
    "controls_if_if": {
        init: function () {
            this.setColour(120);
            this.setNextStatement(true);
            this.appendDummyInput().appendField("if");
            this.contextMenu = false;
        }
    },
    "logic_elseif": {
        init: function () {
            this.setPreviousStatement(true);
            this.setNextStatement(true);
            this.setColour(120);
            this.appendDummyInput().appendField("else if");
            this.contextMenu = false;
        }
    },
    "logic_else": {
        init: function () {
            this.setPreviousStatement(true);
            this.setColour(210);
            this.appendDummyInput().appendField("else");
            this.contextMenu = false;
        }
    }

};

export const logic_contents = {
    'kind': 'category',
    'name': 'Logic',
    'colour': '#C5186A',
    'contents': Object.entries(logic_block).map(([item]) => { return { 'kind': 'block', 'type': item } })
};

Beka Westberg

unread,
May 10, 2024, 11:36:10 AM5/10/24
to Blockly
Hello! Thanks for your question :D

This may not be the only issue, but I think there's a problem with your `decompose` method. In some places `currentBlock` is a block, which doesn't have a `connect` method. And in some places `currentBlock` a connection, which does have a `connect` method. In places where `currentBlock` a block, your logic breaks.


```
decompose: function (workspace) {

            var topBlock = workspace.newBlock('controls_if_if'); // 설정 눌렀을 때 처음 블럭
            topBlock.initSvg();

            // Here you assign a block to currentBlock.
            var currentBlock = topBlock;
            currentBlock = currentBlock.nextConnection;
            console.log(currentBlock);
            for (var i = 1; i <= this.logic_elseifCount_; i++) {
                var logic_elseif_block = workspace.newBlock('logic_elseif');
                logic_elseif_block.initSvg();
                // Here you call connect on `currentBlock`. But if `currentBlock` is a block, you
                // should call `currentBlock.nextConnection.connect`
                currentBlock.connect(logic_elseif_block.previousConnection);
                // Here you assign a connection to `currentBlock`, not a block.
                currentBlock = logic_elseif_block.previousConnection;
            }
            if (this.logic_elseCount_) {
                var logic_else_block = workspace.newBlock('logic_else');
                logic_else_block.initSvg();
                currentBlock.connect(logic_else_block.previousConnection);
            }
            return topBlock;
        },
```

I hope that helps! If you have any further questions please reply =)
--Beka



Reply all
Reply to author
Forward
0 new messages