I've been doing some work trying to build my own +- mutator block to allow longer boolean checks (i.e. if one of a list evals to true, or if all of the list evals to true)
i've taken Beka's implementation and kind of butchered her list create function (sorry) as it looked close to what i wanted.
Because i'm evaling booleans i put a check on each input to check if they were booleans and the functionality is working but as the gif below shows the last one i add (that goes over the initialisation of 2 in the list) is rounded rather than diamond shaped which might confuse the end user.
I've added the full code below as i'm unable to figure out where the error is that might be causing this. Has anyone had similar issues? or know how i might solve it?
p.s. if there is a way to include code that formats it better let me know and i'll reupload it with a better formatting so its easier to read
p.p.s the changes i made are in the naming, so type, mutator name, adding in the check at the end of the value inputs and changing the remove minus to remove when it gets to one option so you can't enter something with nothing.
Blockly.defineBlocksWithJsonArray([
{
"type": "oneOf",
"message0": "one of these are true %1",
"args0": [
{
"type": "input_dummy",
"name": "EMPTY",
},
],
"output": "Boolean",
"style": "logic_blocks",
"mutator": "oneOf_mutator",
},
]);
/* eslint-enable quotes */
const listCreateMutator = {
/**
* Number of item inputs the block has.
* @type {number}
*/
itemCount_: 0,
/**
* Creates XML to represent number of text inputs.
* @return {!Element} XML storage element.
* @this {Blockly.Block}
*/
mutationToDom: function() {
const container = Blockly.utils.xml.createElement('mutation');
container.setAttribute('items', this.itemCount_);
return container;
},
/**
* Parses XML to restore the text inputs.
* @param {!Element} xmlElement XML storage element.
* @this {Blockly.Block}
*/
domToMutation: function(xmlElement) {
const targetCount = parseInt(xmlElement.getAttribute('items'), 10);
this.updateShape_(targetCount);
},
/**
* Adds inputs to the block until it reaches the target number of inputs.
* @param {number} targetCount The target number of inputs for the block.
* @this {Blockly.Block}
* @private
*/
updateShape_: function(targetCount) {
while (this.itemCount_ < targetCount) {
this.addPart_();
}
while (this.itemCount_ > targetCount) {
this.removePart_();
}
this.updateMinus_();
},
/**
* Callback for the plus image. Adds an input to the end of the block and
* updates the state of the minus.
*/
plus: function() {
this.addPart_();
this.updateMinus_();
},
/**
* Callback for the minus image. Removes an input from the end of the block
* and updates the state of the minus.
*/
minus: function() {
if (this.itemCount_ == 0) {
return;
}
this.removePart_();
this.updateMinus_();
},
// To properly keep track of indices we have to increment before/after adding
// the inputs, and decrement the opposite.
// Because we want our first input to be ADD0 (not ADD1) we increment after.
/**
* Adds an input to the end of the block. If the block currently has no
* inputs it updates the top 'EMPTY' input to receive a block.
* @this {Blockly.Block}
* @private
*/
addPart_: function() {
console.log(this.itemCount_);
if (this.itemCount_ == 0) {
this.removeInput('EMPTY');
this.topInput_ = this.appendValueInput('ADD' + this.itemCount_).setCheck('Boolean')
.appendField(createPlusField(), 'PLUS')
.appendField("one of these are true ");
} else {
this.appendValueInput('ADD' + this.itemCount_).setCheck('Boolean');
}
this.itemCount_++;
},
/**
* Removes an input from the end of the block. If we are removing the last
* input this updates the block to have an 'EMPTY' top input.
* @this {Blockly.Block}
* @private
*/
removePart_: function() {
console.log(this.itemCount_);
this.itemCount_--;
this.removeInput('ADD' + this.itemCount_);
if (this.itemCount_ == 0) {
this.topInput_ = this.appendDummyInput('EMPTY').setCheck('Boolean')
.appendField(createPlusField(), 'PLUS')
.appendField("Please add an option to check");
}
},
/**
* Makes it so the minus is visible iff there is an input available to remove.
* @private
*/
updateMinus_: function() {
const minusField = this.getField('MINUS');
if (!minusField && this.itemCount_ > 0) {
this.topInput_.insertFieldAt(1, createMinusField(), 'MINUS');
} else if (minusField && this.itemCount_ < 2) {
this.topInput_.removeField('MINUS');
}
},
};
/**
* Updates the shape of the block to have 3 inputs if no mutation is provided.
* @this {Blockly.Block}
*/
const listCreateHelper = function() {
this.getInput('EMPTY').insertFieldAt(0, createPlusField(), 'PLUS');
this.updateShape_(2);
};
Blockly.Extensions.registerMutator('oneOf_mutator',
listCreateMutator, listCreateHelper);