wow thats a lot of changes
This commit is contained in:
@@ -117,7 +117,7 @@ Blockly.Blocks["every_seconds"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput()
|
||||
.appendField("every")
|
||||
.appendField(new Blockly.FieldNumber(2, 0.1), "SECONDS")
|
||||
.appendField(new Blockly.FieldNumber(2, 0.01), "SECONDS")
|
||||
.appendField("seconds");
|
||||
this.appendStatementInput("DO").setCheck("default");
|
||||
this.setStyle("events_blocks");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as Blockly from "blockly";
|
||||
import * as BlocklyJS from "blockly/javascript";
|
||||
import {FieldColourHsvSliders} from '@blockly/field-colour-hsv-sliders';
|
||||
|
||||
function getAvailableCostumes() {
|
||||
if (window.projectCostumes && window.projectCostumes.length > 0) {
|
||||
@@ -216,3 +217,95 @@ BlocklyJS.javascriptGenerator.forBlock["switch_backdrop"] = function (block) {
|
||||
const name = block.getFieldValue("BACKDROP_NAME");
|
||||
return `setBackdropByName('${name}');\n`;
|
||||
};
|
||||
|
||||
// Color/Tint effect block - with HSV color picker
|
||||
Blockly.Blocks["set_color_effect"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput()
|
||||
.appendField("set color effect to")
|
||||
.appendField(new FieldColourHsvSliders("#ff0000"), "COLOR");
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setInputsInline(true);
|
||||
this.setStyle("looks_blocks");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["set_color_effect"] = function (block, generator) {
|
||||
const color = block.getFieldValue("COLOR") || "#000000";
|
||||
return `setSpriteEffect('tint', '${color}');\n`;
|
||||
};
|
||||
|
||||
// Set effect by amount
|
||||
Blockly.Blocks["set_effect"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput()
|
||||
.appendField("set")
|
||||
.appendField(new Blockly.FieldDropdown([
|
||||
["color", "color"],
|
||||
["brightness", "brightness"],
|
||||
["ghost", "ghost"],
|
||||
["pixelate", "pixelate"],
|
||||
["mosaic (WIP)", "mosaic"],
|
||||
["whirl", "whirl"],
|
||||
["fisheye", "fisheye"],
|
||||
]), "EFFECT")
|
||||
.appendField("effect to");
|
||||
this.appendValueInput("VALUE")
|
||||
.setCheck("Number");
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setInputsInline(true);
|
||||
this.setStyle("looks_blocks");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["set_effect"] = function (block, generator) {
|
||||
const effect = block.getFieldValue("EFFECT");
|
||||
const value = generator.valueToCode(block, "VALUE", BlocklyJS.Order.ATOMIC) || "0";
|
||||
return `setSpriteEffect('${effect}', ${value});\n`;
|
||||
};
|
||||
|
||||
// Change effect by amount
|
||||
Blockly.Blocks["change_effect"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput()
|
||||
.appendField("change")
|
||||
.appendField(new Blockly.FieldDropdown([
|
||||
["color", "color"],
|
||||
["brightness", "brightness"],
|
||||
["ghost", "ghost"],
|
||||
["pixelate", "pixelate"],
|
||||
["mosaic (WIP)", "mosaic"],
|
||||
["whirl", "whirl"],
|
||||
["fisheye", "fisheye"],
|
||||
]), "EFFECT")
|
||||
.appendField("effect by");
|
||||
this.appendValueInput("VALUE")
|
||||
.setCheck("Number");
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setInputsInline(true);
|
||||
this.setStyle("looks_blocks");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["change_effect"] = function (block, generator) {
|
||||
const effect = block.getFieldValue("EFFECT");
|
||||
const value = generator.valueToCode(block, "VALUE", BlocklyJS.Order.ATOMIC) || "0";
|
||||
return `changeSpriteEffect('${effect}', ${value});\n`;
|
||||
};
|
||||
|
||||
// Clear all effects
|
||||
Blockly.Blocks["clear_effects"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput().appendField("clear graphic effects");
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setStyle("looks_blocks");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["clear_effects"] = function () {
|
||||
return `clearSpriteEffects();\n`;
|
||||
};
|
||||
90
src/blocks/monitors.js
Normal file
90
src/blocks/monitors.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import * as Blockly from "blockly";
|
||||
import * as BlocklyJS from "blockly/javascript";
|
||||
|
||||
Blockly.Blocks["show_variable"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput()
|
||||
.appendField("show variable")
|
||||
.appendField(new Blockly.FieldDropdown(this.getVariables), "VAR");
|
||||
this.appendDummyInput()
|
||||
.appendField("at x:")
|
||||
.appendField(new Blockly.FieldNumber(10), "X")
|
||||
.appendField("y:")
|
||||
.appendField(new Blockly.FieldNumber(10), "Y");
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setColour("#FF8C1A");
|
||||
this.setInputsInline(true);
|
||||
},
|
||||
getVariables: function() {
|
||||
const variables = window.projectVariables || {};
|
||||
const varNames = Object.keys(variables);
|
||||
if (varNames.length === 0) {
|
||||
return [["no variables", ""]];
|
||||
}
|
||||
return varNames.map(name => [name, name]);
|
||||
}
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["show_variable"] = function (block) {
|
||||
const varName = block.getFieldValue("VAR");
|
||||
const x = block.getFieldValue("X") || 10;
|
||||
const y = block.getFieldValue("Y") || 10;
|
||||
return `showVariableMonitor("${varName}", ${x}, ${y});\n`;
|
||||
};
|
||||
|
||||
Blockly.Blocks["hide_variable"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput()
|
||||
.appendField("hide variable")
|
||||
.appendField(new Blockly.FieldDropdown(this.getVariables), "VAR");
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setColour("#FF8C1A");
|
||||
},
|
||||
getVariables: function() {
|
||||
const variables = window.projectVariables || {};
|
||||
const varNames = Object.keys(variables);
|
||||
if (varNames.length === 0) {
|
||||
return [["no variables", ""]];
|
||||
}
|
||||
return varNames.map(name => [name, name]);
|
||||
}
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["hide_variable"] = function (block) {
|
||||
const varName = block.getFieldValue("VAR");
|
||||
return `hideVariableMonitor("${varName}");\n`;
|
||||
};
|
||||
|
||||
// Block to MOVE the variable monitor to a position
|
||||
Blockly.Blocks["move_variable_to"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput()
|
||||
.appendField("move variable")
|
||||
.appendField(new Blockly.FieldDropdown(this.getVariables), "VAR")
|
||||
.appendField("to x:")
|
||||
.appendField(new Blockly.FieldNumber(10), "X")
|
||||
.appendField("y:")
|
||||
.appendField(new Blockly.FieldNumber(10), "Y");
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setColour("#FF8C1A");
|
||||
},
|
||||
getVariables: function() {
|
||||
const variables = window.projectVariables || {};
|
||||
const varNames = Object.keys(variables);
|
||||
if (varNames.length === 0) {
|
||||
return [["no variables", ""]];
|
||||
}
|
||||
return varNames.map(name => [name, name]);
|
||||
}
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["move_variable_to"] = function (block) {
|
||||
const varName = block.getFieldValue("VAR");
|
||||
const x = block.getFieldValue("X") || 10;
|
||||
const y = block.getFieldValue("Y") || 10;
|
||||
console.log('Generating move_variable_to code:', varName, x, y);
|
||||
return `moveVariableMonitor("${varName}", ${x}, ${y});\n`;
|
||||
};
|
||||
278
src/blocks/sensing.js
Normal file
278
src/blocks/sensing.js
Normal file
@@ -0,0 +1,278 @@
|
||||
import * as Blockly from "blockly";
|
||||
import * as BlocklyJS from "blockly/javascript";
|
||||
import {FieldColourHsvSliders} from '@blockly/field-colour-hsv-sliders';
|
||||
|
||||
// Function to get available sprites for dropdown
|
||||
function getAvailableSprites() {
|
||||
if (window.sprites && window.sprites.length > 0) {
|
||||
return window.sprites.map(sprite => [sprite.id, sprite.id]);
|
||||
}
|
||||
return [["no sprites", ""]];
|
||||
}
|
||||
|
||||
// Touching block
|
||||
Blockly.Blocks["touching"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput("MAIN")
|
||||
.appendField("touching")
|
||||
.appendField(
|
||||
new Blockly.FieldDropdown([
|
||||
["mouse pointer", "mouse"],
|
||||
["edge", "edge"],
|
||||
["sprite", "sprite"],
|
||||
]),
|
||||
"TARGET"
|
||||
);
|
||||
this.setOutput(true, "Boolean");
|
||||
this.setColour("#4CBFE6");
|
||||
this.setTooltip("Check if sprite is touching something");
|
||||
},
|
||||
onchange: function(e) {
|
||||
if (e.type === Blockly.Events.BLOCK_FIELD_INTERMEDIATE_CHANGE) return;
|
||||
if (!this.workspace) return;
|
||||
|
||||
const target = this.getFieldValue('TARGET');
|
||||
const spriteDropdown = this.getField('SPRITE_ID');
|
||||
const mainInput = this.getInput('MAIN');
|
||||
|
||||
if (target === 'sprite') {
|
||||
if (!spriteDropdown) {
|
||||
mainInput.appendField("named");
|
||||
mainInput.appendField(new Blockly.FieldDropdown(
|
||||
function() {
|
||||
return getAvailableSprites();
|
||||
}
|
||||
), "SPRITE_ID");
|
||||
}
|
||||
} else {
|
||||
if (spriteDropdown) {
|
||||
// Remove the dropdown first
|
||||
mainInput.removeField('SPRITE_ID');
|
||||
|
||||
// Find and remove the "named" label
|
||||
const fields = mainInput.fieldRow;
|
||||
for (let i = fields.length - 1; i >= 0; i--) {
|
||||
const field = fields[i];
|
||||
if (field.getText && field.getText() === "named") {
|
||||
mainInput.removeField(fields[i].name, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["touching"] = function (block, generator) {
|
||||
const target = block.getFieldValue("TARGET");
|
||||
|
||||
if (target === "mouse") {
|
||||
return [`isTouchingMouse()`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
} else if (target === "edge") {
|
||||
return [`isTouchingEdge()`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
} else if (target === "sprite") {
|
||||
const spriteId = block.getFieldValue("SPRITE_ID") || "";
|
||||
return [`isTouchingSprite("${spriteId}")`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
}
|
||||
|
||||
return ["false", BlocklyJS.Order.ATOMIC];
|
||||
};
|
||||
|
||||
// Mouse down block
|
||||
Blockly.Blocks["mouse_down"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput().appendField("mouse down?");
|
||||
this.setOutput(true, "Boolean");
|
||||
this.setColour("#4CBFE6");
|
||||
this.setTooltip("Check if mouse button is pressed");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["mouse_down"] = function () {
|
||||
return [`isMouseDown()`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
};
|
||||
|
||||
// Touching color block with full slider control
|
||||
Blockly.Blocks["touching_color"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput()
|
||||
.appendField("touching color")
|
||||
.appendField(new FieldColourHsvSliders("#ff0000"), "COLOR");
|
||||
this.setOutput(true, "Boolean");
|
||||
this.setColour("#4CBFE6");
|
||||
this.setTooltip("Check if sprite is touching a specific color");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["touching_color"] = function (block) {
|
||||
const color = block.getFieldValue("COLOR");
|
||||
return [`isTouchingColor("${color}")`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
};
|
||||
|
||||
// Distance to block - FIXED VERSION
|
||||
Blockly.Blocks["distance_to"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput("MAIN")
|
||||
.appendField("distance to")
|
||||
.appendField(
|
||||
new Blockly.FieldDropdown([
|
||||
["mouse pointer", "mouse"],
|
||||
["sprite", "sprite"],
|
||||
]),
|
||||
"TARGET"
|
||||
);
|
||||
this.setOutput(true, "Number");
|
||||
this.setColour("#4CBFE6");
|
||||
this.setTooltip("Get distance to target");
|
||||
},
|
||||
onchange: function(e) {
|
||||
if (e.type === Blockly.Events.BLOCK_FIELD_INTERMEDIATE_CHANGE) return;
|
||||
if (!this.workspace) return;
|
||||
|
||||
const target = this.getFieldValue('TARGET');
|
||||
const spriteDropdown = this.getField('SPRITE_ID');
|
||||
const mainInput = this.getInput('MAIN');
|
||||
|
||||
if (target === 'sprite') {
|
||||
if (!spriteDropdown) {
|
||||
mainInput.appendField("named");
|
||||
mainInput.appendField(new Blockly.FieldDropdown(
|
||||
function() {
|
||||
return getAvailableSprites();
|
||||
}
|
||||
), "SPRITE_ID");
|
||||
}
|
||||
} else {
|
||||
if (spriteDropdown) {
|
||||
// Remove the dropdown first
|
||||
mainInput.removeField('SPRITE_ID');
|
||||
|
||||
// Find and remove the "named" label
|
||||
const fields = mainInput.fieldRow;
|
||||
for (let i = fields.length - 1; i >= 0; i--) {
|
||||
const field = fields[i];
|
||||
if (field.getText && field.getText() === "named") {
|
||||
mainInput.removeField(fields[i].name, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["distance_to"] = function (block, generator) {
|
||||
const target = block.getFieldValue("TARGET");
|
||||
|
||||
if (target === "mouse") {
|
||||
return [`distanceToMouse()`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
} else if (target === "sprite") {
|
||||
const spriteId = block.getFieldValue("SPRITE_ID") || "";
|
||||
return [`distanceToSprite("${spriteId}")`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
}
|
||||
|
||||
return ["0", BlocklyJS.Order.ATOMIC];
|
||||
};
|
||||
|
||||
// Answer (for ask and wait)
|
||||
Blockly.Blocks["answer"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput().appendField("answer");
|
||||
this.setOutput(true, "String");
|
||||
this.setColour("#4CBFE6");
|
||||
this.setTooltip("The answer from the last 'ask and wait' prompt");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["answer"] = function () {
|
||||
return [`getAnswer()`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
};
|
||||
|
||||
// Ask and wait
|
||||
Blockly.Blocks["ask_and_wait"] = {
|
||||
init: function () {
|
||||
this.appendValueInput("QUESTION")
|
||||
.setCheck("String")
|
||||
.appendField("ask")
|
||||
.appendField("and wait");
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setColour("#4CBFE6");
|
||||
this.setTooltip("Ask a question and wait for user input");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["ask_and_wait"] = function (block, generator) {
|
||||
const question = generator.valueToCode(block, "QUESTION", BlocklyJS.Order.ATOMIC) || '"What\'s your name?"';
|
||||
return `await askAndWait(${question});\n`;
|
||||
};
|
||||
|
||||
// Username
|
||||
Blockly.Blocks["username"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput().appendField("username");
|
||||
this.setOutput(true, "String");
|
||||
this.setColour("#4CBFE6");
|
||||
this.setTooltip("Get the current username");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["username"] = function () {
|
||||
return [`getUsername()`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
};
|
||||
|
||||
// Loudness
|
||||
Blockly.Blocks["loudness"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput().appendField("loudness");
|
||||
this.setOutput(true, "Number");
|
||||
this.setColour("#4CBFE6");
|
||||
this.setTooltip("Microphone loudness (0-100)");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["loudness"] = function () {
|
||||
return [`getLoudness()`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
};
|
||||
|
||||
// Current date/time
|
||||
Blockly.Blocks["current"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput()
|
||||
.appendField("current")
|
||||
.appendField(
|
||||
new Blockly.FieldDropdown([
|
||||
["year", "year"],
|
||||
["month", "month"],
|
||||
["date", "date"],
|
||||
["day of week", "dayofweek"],
|
||||
["hour", "hour"],
|
||||
["minute", "minute"],
|
||||
["second", "second"],
|
||||
]),
|
||||
"UNIT"
|
||||
);
|
||||
this.setOutput(true, "Number");
|
||||
this.setColour("#4CBFE6");
|
||||
this.setTooltip("Get current date/time value");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["current"] = function (block) {
|
||||
const unit = block.getFieldValue("UNIT");
|
||||
return [`getCurrent("${unit}")`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
};
|
||||
|
||||
// Days since 2000
|
||||
Blockly.Blocks["days_since_2000"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput().appendField("days since 2000");
|
||||
this.setOutput(true, "Number");
|
||||
this.setColour("#4CBFE6");
|
||||
this.setTooltip("Number of days since January 1, 2000");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["days_since_2000"] = function () {
|
||||
return [`getDaysSince2000()`, BlocklyJS.Order.FUNCTION_CALL];
|
||||
};
|
||||
77
src/blocks/text_rendering.js
Normal file
77
src/blocks/text_rendering.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import * as Blockly from "blockly";
|
||||
import * as BlocklyJS from "blockly/javascript";
|
||||
|
||||
Blockly.Blocks["display_text_as_sprite"] = {
|
||||
init: function () {
|
||||
this.appendValueInput("TEXT")
|
||||
.setCheck("String")
|
||||
.appendField("display text");
|
||||
this.appendDummyInput()
|
||||
.appendField("font size")
|
||||
.appendField(new Blockly.FieldNumber(32, 1, 500), "SIZE");
|
||||
this.appendDummyInput()
|
||||
.appendField("color")
|
||||
.appendField(new Blockly.FieldTextInput("#ffffff"), "COLOR"); // CHANGED: Use FieldTextInput instead
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setStyle("looks_blocks");
|
||||
this.setTooltip("Display text as the sprite");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["display_text_as_sprite"] = function (
|
||||
block,
|
||||
generator
|
||||
) {
|
||||
const text = generator.valueToCode(block, "TEXT", BlocklyJS.Order.ATOMIC) || '""';
|
||||
const size = block.getFieldValue("SIZE");
|
||||
const color = block.getFieldValue("COLOR");
|
||||
|
||||
return `displayTextAsSprite(${text}, ${size}, "${color}");\n`;
|
||||
};
|
||||
|
||||
Blockly.Blocks["clear_text_sprite"] = {
|
||||
init: function () {
|
||||
this.appendDummyInput().appendField("clear text sprite");
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setStyle("looks_blocks");
|
||||
this.setTooltip("Remove text and restore original sprite");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["clear_text_sprite"] = function () {
|
||||
return `clearTextSprite();\n`;
|
||||
};
|
||||
|
||||
Blockly.Blocks["set_text_property"] = {
|
||||
init: function () {
|
||||
this.appendValueInput("VALUE")
|
||||
.appendField("set text")
|
||||
.appendField(
|
||||
new Blockly.FieldDropdown([
|
||||
["font", "font"],
|
||||
["alignment", "align"],
|
||||
["bold", "bold"],
|
||||
["italic", "italic"],
|
||||
["outline color", "stroke"],
|
||||
["outline thickness", "strokeThickness"],
|
||||
]),
|
||||
"PROPERTY"
|
||||
)
|
||||
.appendField("to");
|
||||
this.setPreviousStatement(true, "default");
|
||||
this.setNextStatement(true, "default");
|
||||
this.setStyle("looks_blocks");
|
||||
},
|
||||
};
|
||||
|
||||
BlocklyJS.javascriptGenerator.forBlock["set_text_property"] = function (
|
||||
block,
|
||||
generator
|
||||
) {
|
||||
const property = block.getFieldValue("PROPERTY");
|
||||
const value = generator.valueToCode(block, "VALUE", BlocklyJS.Order.ATOMIC) || '""';
|
||||
|
||||
return `setTextProperty("${property}", ${value});\n`;
|
||||
};
|
||||
Reference in New Issue
Block a user