mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-01-25 17:09:50 -05:00
commit
6c118cf8e0
5 changed files with 63 additions and 29 deletions
|
@ -263,6 +263,7 @@ class Blocks {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const stage = optRuntime.getTargetForStage();
|
const stage = optRuntime.getTargetForStage();
|
||||||
|
const editingTarget = optRuntime.getEditingTarget();
|
||||||
|
|
||||||
// UI event: clicked scripts toggle in the runtime.
|
// UI event: clicked scripts toggle in the runtime.
|
||||||
if (e.element === 'stackclick') {
|
if (e.element === 'stackclick') {
|
||||||
|
@ -330,25 +331,39 @@ class Blocks {
|
||||||
this.deleteBlock(e.blockId);
|
this.deleteBlock(e.blockId);
|
||||||
break;
|
break;
|
||||||
case 'var_create':
|
case 'var_create':
|
||||||
// New variables being created by the user are all global.
|
// Check if the variable being created is global or local
|
||||||
// Check if this variable exists on the current target or stage.
|
// If local, create a local var on the current editing target, as long
|
||||||
// If not, create it on the stage.
|
// as there are no conflicts, and the current target is actually a sprite
|
||||||
// TODO create global and local variables when UI provides a way.
|
// If global or if the editing target is not present or we somehow got
|
||||||
if (optRuntime.getEditingTarget()) {
|
// into a state where a local var was requested for the stage,
|
||||||
if (!optRuntime.getEditingTarget().lookupVariableById(e.varId)) {
|
// create a stage (global) var after checking for name conflicts
|
||||||
stage.createVariable(e.varId, e.varName, e.varType);
|
// on all the sprites.
|
||||||
|
if (e.isLocal && editingTarget && !editingTarget.isStage) {
|
||||||
|
if (!editingTarget.lookupVariableById(e.varId)) {
|
||||||
|
editingTarget.createVariable(e.varId, e.varName, e.varType);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Check for name conflicts in all of the targets
|
||||||
|
const allTargets = optRuntime.targets.filter(t => t.isOriginal);
|
||||||
|
for (const target of allTargets) {
|
||||||
|
if (target.lookupVariableByNameAndType(e.varName, e.varType, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (!stage.lookupVariableById(e.varId)) {
|
|
||||||
// Since getEditingTarget returned null, we now need to
|
|
||||||
// explicitly check if the stage has the variable, and
|
|
||||||
// create one if not.
|
|
||||||
stage.createVariable(e.varId, e.varName, e.varType);
|
stage.createVariable(e.varId, e.varName, e.varType);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'var_rename':
|
case 'var_rename':
|
||||||
stage.renameVariable(e.varId, e.newName);
|
if (editingTarget && editingTarget.hasOwnProperty(e.varId)) {
|
||||||
// Update all the blocks that use the renamed variable.
|
// This is a local variable, rename on the current target
|
||||||
if (optRuntime) {
|
editingTarget.renameVariable(e.varId, e.newName);
|
||||||
|
// Update all the blocks on the current target that use
|
||||||
|
// this variable
|
||||||
|
editingTarget.blocks.updateBlocksAfterVarRename(e.varId, e.newName);
|
||||||
|
} else {
|
||||||
|
// This is a global variable
|
||||||
|
stage.renameVariable(e.varId, e.newName);
|
||||||
|
// Update all blocks on all targets that use the renamed variable
|
||||||
const targets = optRuntime.targets;
|
const targets = optRuntime.targets;
|
||||||
for (let i = 0; i < targets.length; i++) {
|
for (let i = 0; i < targets.length; i++) {
|
||||||
const currTarget = targets[i];
|
const currTarget = targets[i];
|
||||||
|
@ -356,9 +371,12 @@ class Blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'var_delete':
|
case 'var_delete': {
|
||||||
stage.deleteVariable(e.varId);
|
const target = (editingTarget && editingTarget.hasOwnProperty(e.varId)) ?
|
||||||
|
editingTarget : stage;
|
||||||
|
target.deleteVariable(e.varId);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 'comment_create':
|
case 'comment_create':
|
||||||
if (optRuntime && optRuntime.getEditingTarget()) {
|
if (optRuntime && optRuntime.getEditingTarget()) {
|
||||||
const currTarget = optRuntime.getEditingTarget();
|
const currTarget = optRuntime.getEditingTarget();
|
||||||
|
|
|
@ -1715,6 +1715,15 @@ class Runtime extends EventEmitter {
|
||||||
return this._editingTarget;
|
return this._editingTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAllVarNamesOfType (varType) {
|
||||||
|
let varNames = [];
|
||||||
|
for (const target of this.targets) {
|
||||||
|
const targetVarNames = target.getAllVariableNamesInScopeByType(varType, true);
|
||||||
|
varNames = varNames.concat(targetVarNames);
|
||||||
|
}
|
||||||
|
return varNames;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the runtime to request a redraw.
|
* Tell the runtime to request a redraw.
|
||||||
* Use after a clone/sprite has completed some visible operation on the stage.
|
* Use after a clone/sprite has completed some visible operation on the stage.
|
||||||
|
|
|
@ -83,17 +83,19 @@ class Target extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* Get the names of all the variables of the given type that are in scope for this target.
|
* Get the names of all the variables of the given type that are in scope for this target.
|
||||||
* For targets that are not the stage, this includes any target-specific
|
* For targets that are not the stage, this includes any target-specific
|
||||||
* variables as well as any stage variables.
|
* variables as well as any stage variables unless the skipStage flag is true.
|
||||||
* For the stage, this is all stage variables.
|
* For the stage, this is all stage variables.
|
||||||
* @param {string} type The variable type to search for; defaults to Variable.SCALAR_TYPE
|
* @param {string} type The variable type to search for; defaults to Variable.SCALAR_TYPE
|
||||||
|
* @param {?bool} skipStage Optional flag to skip the stage.
|
||||||
* @return {Array<string>} A list of variable names
|
* @return {Array<string>} A list of variable names
|
||||||
*/
|
*/
|
||||||
getAllVariableNamesInScopeByType (type) {
|
getAllVariableNamesInScopeByType (type, skipStage) {
|
||||||
if (typeof type !== 'string') type = Variable.SCALAR_TYPE;
|
if (typeof type !== 'string') type = Variable.SCALAR_TYPE;
|
||||||
|
skipStage = skipStage || false;
|
||||||
const targetVariables = Object.values(this.variables)
|
const targetVariables = Object.values(this.variables)
|
||||||
.filter(v => v.type === type)
|
.filter(v => v.type === type)
|
||||||
.map(variable => variable.name);
|
.map(variable => variable.name);
|
||||||
if (this.isStage || !this.runtime) {
|
if (skipStage || this.isStage || !this.runtime) {
|
||||||
return targetVariables;
|
return targetVariables;
|
||||||
}
|
}
|
||||||
const stage = this.runtime.getTargetForStage();
|
const stage = this.runtime.getTargetForStage();
|
||||||
|
@ -194,11 +196,13 @@ class Target extends EventEmitter {
|
||||||
* was not found.
|
* was not found.
|
||||||
* @param {string} name Name of the variable.
|
* @param {string} name Name of the variable.
|
||||||
* @param {string} type Type of the variable. Defaults to Variable.SCALAR_TYPE.
|
* @param {string} type Type of the variable. Defaults to Variable.SCALAR_TYPE.
|
||||||
|
* @param {?bool} skipStage Optional flag to skip checking the stage
|
||||||
* @return {?Variable} Variable object if found, or null if not.
|
* @return {?Variable} Variable object if found, or null if not.
|
||||||
*/
|
*/
|
||||||
lookupVariableByNameAndType (name, type) {
|
lookupVariableByNameAndType (name, type, skipStage) {
|
||||||
if (typeof name !== 'string') return;
|
if (typeof name !== 'string') return;
|
||||||
if (typeof type !== 'string') type = Variable.SCALAR_TYPE;
|
if (typeof type !== 'string') type = Variable.SCALAR_TYPE;
|
||||||
|
skipStage = skipStage || false;
|
||||||
|
|
||||||
for (const varId in this.variables) {
|
for (const varId in this.variables) {
|
||||||
const currVar = this.variables[varId];
|
const currVar = this.variables[varId];
|
||||||
|
@ -207,7 +211,7 @@ class Target extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.runtime && !this.isStage) {
|
if (!skipStage && this.runtime && !this.isStage) {
|
||||||
const stage = this.runtime.getTargetForStage();
|
const stage = this.runtime.getTargetForStage();
|
||||||
if (stage) {
|
if (stage) {
|
||||||
for (const varId in stage.variables) {
|
for (const varId in stage.variables) {
|
||||||
|
|
|
@ -33,8 +33,9 @@ class Variable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toXML () {
|
toXML (isLocal) {
|
||||||
return `<variable type="${this.type}" id="${this.id}">${this.name}</variable>`;
|
isLocal = (isLocal === true);
|
||||||
|
return `<variable type="${this.type}" id="${this.id}" islocal="${isLocal}">${this.name}</variable>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1074,19 +1074,21 @@ class VirtualMachine extends EventEmitter {
|
||||||
const id = messageIds[i];
|
const id = messageIds[i];
|
||||||
delete this.runtime.getTargetForStage().variables[id];
|
delete this.runtime.getTargetForStage().variables[id];
|
||||||
}
|
}
|
||||||
const variableMap = Object.assign({},
|
const globalVarMap = Object.assign({}, this.runtime.getTargetForStage().variables);
|
||||||
this.runtime.getTargetForStage().variables,
|
const localVarMap = this.editingTarget.isStage ?
|
||||||
this.editingTarget.variables
|
Object.create(null) :
|
||||||
);
|
Object.assign({}, this.editingTarget.variables);
|
||||||
|
|
||||||
const variables = Object.keys(variableMap).map(k => variableMap[k]);
|
const globalVariables = Object.keys(globalVarMap).map(k => globalVarMap[k]);
|
||||||
|
const localVariables = Object.keys(localVarMap).map(k => localVarMap[k]);
|
||||||
const workspaceComments = Object.keys(this.editingTarget.comments)
|
const workspaceComments = Object.keys(this.editingTarget.comments)
|
||||||
.map(k => this.editingTarget.comments[k])
|
.map(k => this.editingTarget.comments[k])
|
||||||
.filter(c => c.blockId === null);
|
.filter(c => c.blockId === null);
|
||||||
|
|
||||||
const xmlString = `<xml xmlns="http://www.w3.org/1999/xhtml">
|
const xmlString = `<xml xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<variables>
|
<variables>
|
||||||
${variables.map(v => v.toXML()).join()}
|
${globalVariables.map(v => v.toXML()).join()}
|
||||||
|
${localVariables.map(v => v.toXML(true)).join()}
|
||||||
</variables>
|
</variables>
|
||||||
${workspaceComments.map(c => c.toXML()).join()}
|
${workspaceComments.map(c => c.toXML()).join()}
|
||||||
${this.editingTarget.blocks.toXML(this.editingTarget.comments)}
|
${this.editingTarget.blocks.toXML(this.editingTarget.comments)}
|
||||||
|
|
Loading…
Reference in a new issue