Spaces:
Runtime error
Runtime error
| const formatMessage = require('format-message'); | |
| const BlockType = require('../../extension-support/block-type'); | |
| const ArgumentType = require('../../extension-support/argument-type'); | |
| // const Cast = require('../../util/cast'); | |
| /** | |
| * Class for CloneTool blocks | |
| * @constructor | |
| */ | |
| class JgCloneToolBlocks { | |
| constructor(runtime) { | |
| /** | |
| * The runtime instantiating this block package. | |
| * @type {Runtime} | |
| */ | |
| this.runtime = runtime; | |
| } | |
| /** | |
| * @returns {object} metadata for this extension and its blocks. | |
| */ | |
| getInfo() { | |
| return { | |
| id: 'jgClones', | |
| name: 'Clone Communication', | |
| color1: '#FFAB19', | |
| color2: '#EC9C13', | |
| blocks: [ | |
| { | |
| blockType: BlockType.LABEL, | |
| text: "Main Sprite Communication" | |
| }, | |
| { | |
| opcode: 'getCloneWithVariableSetTo', | |
| text: formatMessage({ | |
| id: 'jgClones.blocks.getCloneWithVariableSetTo', | |
| default: 'get [DATA] of clone with [VAR] set to [VALUE]', | |
| description: 'Block that returns the value of the item picked within a clone with a variable set to a certain value.' | |
| }), | |
| disableMonitor: true, | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| DATA: { type: ArgumentType.STRING, menu: 'spriteData' }, | |
| VAR: { type: ArgumentType.STRING, menu: 'spriteVariables' }, | |
| VALUE: { type: ArgumentType.STRING, defaultValue: '0' }, | |
| } | |
| }, | |
| { | |
| opcode: 'getCloneVariableWithVariableSetTo', | |
| text: formatMessage({ | |
| id: 'jgClones.blocks.getCloneVariableWithVariableSetTo', | |
| default: 'get [VAR1] of clone with [VAR2] set to [VALUE]', | |
| description: 'Block that returns the value of the variable picked within a clone with a variable set to a certain value.' | |
| }), | |
| disableMonitor: true, | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| VAR1: { type: ArgumentType.STRING, menu: 'spriteVariables' }, | |
| VAR2: { type: ArgumentType.STRING, menu: 'spriteVariables' }, | |
| VALUE: { type: ArgumentType.STRING, defaultValue: '0' }, | |
| } | |
| }, | |
| // { | |
| // opcode: 'setValueOnCloneWithVariableSetTo', | |
| // text: formatMessage({ | |
| // id: 'jgClones.blocks.setValueOnCloneWithVariableSetTo', | |
| // default: 'set [DATA] to [VALUE1] on clone with [VAR] set to [VALUE2]', | |
| // description: 'Block that sets the value of the item picked within a clone with a variable set to a certain value.' | |
| // }), | |
| // blockType: BlockType.COMMAND, | |
| // arguments: { | |
| // DATA: { type: ArgumentType.STRING, menu: 'spriteData' }, | |
| // VALUE1: { type: ArgumentType.STRING, defaultValue: '0' }, | |
| // VAR: { type: ArgumentType.STRING, menu: 'spriteVariables' }, | |
| // VALUE2: { type: ArgumentType.STRING, defaultValue: '0' }, | |
| // } | |
| // }, | |
| { | |
| opcode: 'setVariableOnCloneWithVariableSetTo', | |
| text: formatMessage({ | |
| id: 'jgClones.blocks.setVariableOnCloneWithVariableSetTo', | |
| default: 'set [VAR1] to [VALUE1] on clone with [VAR2] set to [VALUE2]', | |
| description: 'Block that sets a variable within a clone with a variable set to a certain value.' | |
| }), | |
| blockType: BlockType.COMMAND, | |
| arguments: { | |
| VAR1: { type: ArgumentType.STRING, menu: 'spriteVariables' }, | |
| VALUE1: { type: ArgumentType.STRING, defaultValue: '0' }, | |
| VAR2: { type: ArgumentType.STRING, menu: 'spriteVariables' }, | |
| VALUE2: { type: ArgumentType.STRING, defaultValue: '0' }, | |
| } | |
| }, | |
| "---", | |
| "---", | |
| { | |
| blockType: BlockType.LABEL, | |
| text: "Clone Communication" | |
| }, | |
| { | |
| opcode: 'getMainSpriteData', | |
| text: formatMessage({ | |
| id: 'jgClones.blocks.getMainSpriteData', | |
| default: 'get [DATA] of main sprite', | |
| description: 'Block that returns the value of the item picked on the main sprite.' | |
| }), | |
| disableMonitor: true, | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| DATA: { type: ArgumentType.STRING, menu: 'spriteData' } | |
| } | |
| }, | |
| { | |
| opcode: 'getVariableOnMainSprite', | |
| text: formatMessage({ | |
| id: 'jgClones.blocks.getVariableOnMainSprite', | |
| default: 'get [VAR] of main sprite', | |
| description: 'Block that returns the value of the variable picked on the main sprite.' | |
| }), | |
| disableMonitor: true, | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| VAR: { type: ArgumentType.STRING, menu: 'spriteVariables' }, | |
| } | |
| }, | |
| // { | |
| // opcode: 'setValueOnMainSprite', | |
| // text: formatMessage({ | |
| // id: 'jgClones.blocks.setValueOnMainSprite', | |
| // default: 'set [DATA] to [VALUE] on main sprite', | |
| // description: 'Block that sets the value of the item picked within the main sprite.' | |
| // }), | |
| // blockType: BlockType.COMMAND, | |
| // arguments: { | |
| // DATA: { type: ArgumentType.STRING, menu: 'spriteData' }, | |
| // VALUE: { type: ArgumentType.STRING, defaultValue: '0' } | |
| // } | |
| // }, | |
| { | |
| opcode: 'setVariableOnMainSprite', | |
| text: formatMessage({ | |
| id: 'jgClones.blocks.setVariableOnMainSprite', | |
| default: 'set [VAR] to [VALUE] on main sprite', | |
| description: 'Block that sets a variable within the main sprite.' | |
| }), | |
| blockType: BlockType.COMMAND, | |
| arguments: { | |
| VAR: { type: ArgumentType.STRING, menu: 'spriteVariables' }, | |
| VALUE: { type: ArgumentType.STRING, defaultValue: '0' } | |
| } | |
| }, | |
| "---", | |
| "---", | |
| { | |
| blockType: BlockType.LABEL, | |
| text: "Other" | |
| }, | |
| { | |
| opcode: 'getIsClone', | |
| text: formatMessage({ | |
| id: 'jgClones.blocks.getIsClone', | |
| default: 'is clone?', | |
| description: 'Block that returns whether the current sprite is a clone or not.' | |
| }), | |
| disableMonitor: true, | |
| blockType: BlockType.BOOLEAN | |
| }, | |
| { | |
| opcode: 'clonesInSprite', | |
| text: formatMessage({ | |
| id: 'jgClones.blocks.clonesInSprite', | |
| default: 'clone count of [SPRITE]', | |
| description: 'Block that returns the amount of clones of this sprite that currently exist.' | |
| }), | |
| disableMonitor: true, | |
| blockType: BlockType.REPORTER, | |
| arguments: { | |
| SPRITE: { type: ArgumentType.STRING, menu: 'sprites' }, | |
| } | |
| } | |
| ], | |
| menus: { | |
| sprites: "getSpriteMenu", | |
| spriteVariables: "getSpriteVariablesMenu", | |
| spriteData: { | |
| acceptReporters: true, | |
| items: [ | |
| // motion | |
| "x position", | |
| "y position", | |
| "direction", | |
| "rotation style", | |
| // looks (excluding effects) | |
| "visible", | |
| "costume number", | |
| "costume name", | |
| "size", | |
| "x stretch", | |
| "y stretch", | |
| // sound | |
| "volume", | |
| // sensing | |
| "draggable", | |
| // music (doesnt seem to work) | |
| // "tempo", | |
| // effects | |
| "color effect", | |
| "fisheye effect", | |
| "whirl effect", | |
| "pixelate effect", | |
| "mosaic effect", | |
| "brightness effect", | |
| "ghost effect", | |
| "saturation effect", | |
| "red effect", | |
| "green effect", | |
| "blue effect", | |
| "opaque effect", | |
| ].map(item => ({ text: item, value: item })) | |
| } | |
| } | |
| }; | |
| } | |
| // utilities | |
| getClones (sprite) { | |
| // i call this the stair step null check | |
| if (!sprite.clones) return []; | |
| const clones = sprite.clones | |
| return clones.filter(clone => clone.isOriginal === false); | |
| } | |
| getTargetBySpriteName (name) { | |
| const targets = this.runtime.targets; | |
| const sprites = targets.filter(target => target.isOriginal).filter(target => target.sprite.name == name); | |
| return sprites[0]; | |
| } | |
| getTargetClonesByVariableSetToValue (target, variableName, value) { | |
| const clones = this.getClones(target.sprite); | |
| const cloneList = clones.filter(clone => { | |
| const variables = Object.getOwnPropertyNames(clone.variables).map(variableId => { | |
| return clone.variables[variableId]; | |
| }); | |
| const variable = variables.filter(variable => variable.name == variableName)[0]; | |
| if (!variable) return false; | |
| if (String(variable.value) != String(value)) return false; | |
| return true; | |
| }); | |
| return cloneList; | |
| } | |
| getTargetCloneByVariableSetToValue (target, variableName, value) { | |
| const clones = this.getTargetClonesByVariableSetToValue(target, variableName, value); | |
| if (!clones) return; | |
| return clones[0]; | |
| } | |
| menuOptionToTargetProperty (option) { | |
| switch (option) { | |
| case "x position": | |
| return "x"; | |
| case "y position": | |
| return "y"; | |
| case "x stretch": | |
| return "xStretch"; | |
| case "y stretch": | |
| return "yStretch"; | |
| case "rotation style": | |
| return "rotationStyle"; | |
| case "costume number": | |
| return "currentCostume"; | |
| case "costume name": | |
| return "costumeName"; | |
| default: | |
| return option; | |
| } | |
| } | |
| getMainSprite (target) { | |
| if (!target.sprite) return; | |
| const clones = target.sprite.clones; | |
| const mainSprites = clones.filter(clone => clone.isOriginal); | |
| return mainSprites[0]; | |
| } | |
| // menus | |
| getSpriteMenu () { | |
| const targets = this.runtime.targets; | |
| const emptyMenu = [{ text: "", value: "" }]; | |
| if (!targets) return emptyMenu; | |
| const menu = targets.filter(target => target.isOriginal && (!target.isStage)).map(target => ({ text: target.sprite.name, value: target.sprite.name })); | |
| return (menu.length > 0) ? menu : emptyMenu; | |
| } | |
| getSpriteVariablesMenu () { | |
| const target = vm.editingTarget; | |
| const emptyMenu = [{ text: "", value: "" }]; | |
| if (!target) return emptyMenu; | |
| if (!target.variables) return emptyMenu; | |
| const menu = Object.getOwnPropertyNames(target.variables).map(variableId => { | |
| const variable = target.variables[variableId] | |
| return { | |
| text: variable.name, | |
| value: variable.name, | |
| } | |
| }); | |
| // check if menu has 0 items because pm throws an error if theres no items | |
| return (menu.length > 0) ? menu : emptyMenu; | |
| } | |
| // blocks | |
| // other blocks | |
| getIsClone (_, util) { | |
| return !util.target.isOriginal; | |
| } | |
| clonesInSprite (args) { | |
| const target = this.getTargetBySpriteName(args.SPRITE); | |
| if (!target) return 0; | |
| const clones = this.getClones(target.sprite); | |
| return clones.length; | |
| } | |
| // main sprite communication | |
| getCloneWithVariableSetTo (args, util) { | |
| const target = util.target; | |
| const clone = this.getTargetCloneByVariableSetToValue(target, args.VAR, String(args.VALUE)); | |
| if (!clone) return ""; | |
| const property = this.menuOptionToTargetProperty(args.DATA); | |
| switch (property) { | |
| case "currentCostume": | |
| return clone.currentCostume + 1; | |
| case "costumeName": | |
| return clone.sprite.costumes_[clone.currentCostume].name; | |
| case "xStretch": | |
| return clone.stretch[0]; | |
| case "yStretch": | |
| return clone.stretch[1]; | |
| case "color effect": | |
| return clone.effects.color; | |
| case "fisheye effect": | |
| return clone.effects.fisheye; | |
| case "whirl effect": | |
| return clone.effects.whirl; | |
| case "pixelate effect": | |
| return clone.effects.pixelate; | |
| case "mosaic effect": | |
| return clone.effects.mosaic; | |
| case "brightness effect": | |
| return clone.effects.brightness; | |
| case "ghost effect": | |
| return clone.effects.ghost; | |
| case "red effect": | |
| return clone.effects.red; | |
| case "green effect": | |
| return clone.effects.green; | |
| case "blue effect": | |
| return clone.effects.blue; | |
| case "opaque effect": | |
| return clone.effects.opaque; | |
| case "saturation effect": | |
| return clone.effects.saturation; | |
| default: | |
| return clone[property]; | |
| } | |
| } | |
| getCloneVariableWithVariableSetTo (args, util) { | |
| const target = util.target; | |
| const clone = this.getTargetCloneByVariableSetToValue(target, args.VAR2, String(args.VALUE)); | |
| if (!clone) return ""; | |
| const variables = {}; | |
| Object.getOwnPropertyNames(clone.variables).forEach(id => { | |
| variables[clone.variables[id].name] = clone.variables[id].value; | |
| }); | |
| return variables[args.VAR1]; | |
| } | |
| setVariableOnCloneWithVariableSetTo (args, util) { | |
| const target = util.target; | |
| const clones = this.getTargetClonesByVariableSetToValue(target, args.VAR2, String(args.VALUE2)); | |
| clones.forEach(clone => { | |
| Object.getOwnPropertyNames(clone.variables).forEach(variableId => { | |
| const variable = clone.variables[variableId]; | |
| if (variable.name !== args.VAR1) return; | |
| const value = isNaN(Number(args.VALUE1)) ? String(args.VALUE1) : Number(args.VALUE1); | |
| variable.value = value; | |
| }); | |
| }); | |
| } | |
| // clone communication | |
| getMainSpriteData (args, util) { | |
| const target = util.target; | |
| const mainSprite = this.getMainSprite(target); | |
| if (!mainSprite) return ""; | |
| const property = this.menuOptionToTargetProperty(args.DATA); | |
| switch (property) { | |
| case "currentCostume": | |
| return mainSprite.currentCostume + 1; | |
| case "costumeName": | |
| return mainSprite.sprite.costumes_[mainSprite.currentCostume].name; | |
| case "xStretch": | |
| return mainSprite.stretch[0]; | |
| case "yStretch": | |
| return mainSprite.stretch[1]; | |
| case "color effect": | |
| return mainSprite.effects.color; | |
| case "fisheye effect": | |
| return mainSprite.effects.fisheye; | |
| case "whirl effect": | |
| return mainSprite.effects.whirl; | |
| case "pixelate effect": | |
| return mainSprite.effects.pixelate; | |
| case "mosaic effect": | |
| return mainSprite.effects.mosaic; | |
| case "brightness effect": | |
| return mainSprite.effects.brightness; | |
| case "ghost effect": | |
| return mainSprite.effects.ghost; | |
| case "red effect": | |
| return mainSprite.effects.red; | |
| case "green effect": | |
| return mainSprite.effects.green; | |
| case "blue effect": | |
| return mainSprite.effects.blue; | |
| case "opaque effect": | |
| return mainSprite.effects.opaque; | |
| case "saturation effect": | |
| return mainSprite.effects.saturation; | |
| default: | |
| return mainSprite[property]; | |
| } | |
| } | |
| getVariableOnMainSprite(args, util) { | |
| const target = util.target; | |
| const mainSprite = this.getMainSprite(target); | |
| if (!mainSprite) return ""; | |
| const variables = {}; | |
| Object.getOwnPropertyNames(mainSprite.variables).forEach(id => { | |
| variables[mainSprite.variables[id].name] = mainSprite.variables[id].value; | |
| }); | |
| return variables[args.VAR]; | |
| } | |
| setVariableOnMainSprite (args, util) { | |
| const target = util.target; | |
| const mainSprite = this.getMainSprite(target); | |
| Object.getOwnPropertyNames(mainSprite.variables).forEach(variableId => { | |
| const variable = mainSprite.variables[variableId]; | |
| if (variable.name !== args.VAR) return; | |
| const value = isNaN(Number(args.VALUE)) ? String(args.VALUE) : Number(args.VALUE); | |
| variable.value = value; | |
| }); | |
| } | |
| } | |
| module.exports = JgCloneToolBlocks; | |