scratchfoundation / scratch-blocks

Scratch Blocks is a library for building creative computing interfaces.
https://scratch.mit.edu/developers
Apache License 2.0
2.6k stars 1.39k forks source link

Whether a variable is "for this sprite only" or not should be obviously visible #1379

Open towerofnix opened 6 years ago

towerofnix commented 6 years ago

Apologies for the essay!!!!

Expected Behavior

There should be some way to easily tell whether a variable block is local to a specific sprite ("for this sprite only") or not, ideally without any further interaction.

Actual Behavior

Currently the only way to tell if an existing variable is sprite-local is to show the variable on the stage (the monitor will display "[Sprite Name]: my variable" instead of "my variable") or to switch to the stage and then back to the sprite (if the variable is local to that sprite, it definitely won't show up in the stage's variable palette, since the stage can't have any sprite-local variables.)

Steps to Reproduce

Make a variable which is local to a sprite by checking the "for this sprite only" checkbox when creating it. (This checkbox doesn't exist in Scratch 3.0 yet -- you'll have to make the variable in Scratch 2.0, then load that project in the 3.0 editor.)

Operating System and Browser

(Platform-independent.)


Thoughts on how this should be implemented? Neither of the current methods are really satisfactory, mainly because they require interaction. The interactions they need are significant, too -- switching between sprite and stage takes a relatively long time, because of the block workspace reloading, and showing a variable requires navigating to the variables palette, which means losing whatever palette you were previously scrolled to.

One idea is to prefix the variable name, e.g. "Sprite1: hp":

A variable block whose label is "Sprite1: hp"

This would make the variable be explicitly different from a global variable, whose name would just be "hp", as well as from any local variable "hp" of another sprite, where the display would be "Sprite3: hp", for example.

Renaming the sprite would obviously change the label of the block. But what if the block is duplicated into a different sprite? That is, by being dragged over the icon of the sprite in the sprite list, or by being added into the backpack and then dropped in the other block. I believe the functionality of this should be that the new block which appears in the other sprite should be that own sprite's local variable "hp", i.e. "Other Sprite: hp", but it might be confusing to have the block's label change. ("Where did the block go?")

Another edge case: What if the block is duplicated into a sprite where that local variable does not exist, or the stage? In order to match the functionality of Scratch, this would have to display as a local variable on sprites and a global variable on the stage (since variables "local to the stage" are really just global variables, and since when a variable does not exist and its value is requested from a sprite, a sprite-local variable with that name is created).

Having sprite-local variable blocks be labeled with their owner sprite's name would prevent conflicts with variable names. One edge case this would resolve is when you select a sprite, create a sprite-local variable, then select another sprite (or the stage), and create a global variable with the same name. Currently, whether a variable block is referencing the global variable or the sprite-local variable is entirely unclear. The only way to be certain is to change the global variable's value (switch to the stage, then change the value of the variable), and then check if the variable block's value has changed. If the variable block were explicitly labeled "Sprite1: my variable", it would be obvious that the variable belongs to that sprite and is not global.

However, it introduces a comparable edge case, again related to duplicating blocks: What if the sprite-local variable block is duplicated into another sprite which does not have a sprite-local variable of that same name, and a global variable with the same name does exist? Should the new variable block in the other sprite display as "Other Sprite: variable", or should it display as "variable" (in reference to the global variable)?

For reference, here is a short description of how variable creation works in Scratch 2.0. (I haven't tested this in Scratch 3.0, and I'm not sure it works the same in 3.0, since 3.0 uses variable IDs instead of variable names as the identifying property, and I'm not sure how variable IDs are generated. But the general implementation looks to be the same in 3.0; see Target.lookupOrCreateVariable.)

As far as Scratch 2.0 is concerned, the only identifying property of a variable block is its name. Whether a variable block belongs to a global sprite is only knowable at runtime: if a sprite owns a variable with the same name, then that is the variable that the block refers to. Otherwise, if the stage owns a variable with the same name, then that is the variable that the block refers to. If neither the stage nor the sprite own a variable of the name, then a variable that belongs to the sprite is created, and that is the variable that the block refers to.

mrjacobbloom commented 6 years ago

I really like this idea, but I'm worried scripts with a lot of nested reporters would get too long. An icon wouldn't take as much horizontal space and would parallel the cloud icon, but also wouldn't give as much information (though which sprite the variable belongs to would be obvious from context since you can only view one workspace at once). Maybe a "visibility eye" or a lock icon? Or even a thumbnail of the sprite it belongs to?

towerofnix commented 6 years ago

Or even a thumbnail of the sprite it belongs to?

I like this idea! (Edit: this has the same issues as displaying the sprite name, of course, so still worth thinking about those edge cases I mentioned.)

A lock icon would make it look like the variable is limited from being edited at all, I think, which isn't the idea we want.

AmazingMech2418 commented 6 years ago

@towerofnix I've seen a mod that uses this format: <name>[local].

zephyrr commented 6 years ago

Rather than a lock icon etc, how about using just a prefix colon for local names, as a visual hint/shorthand; the spritename:varname usage would still be used where needed for ambiguity resolution? (Or make this abbreviated visual form configurable).

rachel-fenichel commented 6 years ago

I can guarantee someone would make a global variable named "spritename:varname" just to make life difficult.

kyleplo commented 6 years ago

What about an icon, like cloud variables?

joker314 commented 6 years ago

I think to resolve the issue of an icon not containing enough information to be useful, the same icon could be placed in the dialogue box for creating variables. The checkbox which makes a certain variable "for this sprite only" could either have whatever icon we choose to represent the check mark; or the label associated with the checkbox could be prefixed with the icon.

I've seen suggestions on the Scratch forums which put forward the unicode House Emoji (🏠), for the variable is sort of local to its own residence, rather than the public streets.

TheLogFather commented 6 years ago

Maybe an extra identification icon could be added to global vars instead? The cloudvars already have such a 'badge' to identify they are in cloud, so perhaps it make sense for global vars to be the ones that are identified with a badge, rather than local? (Quite what that badge should be, though... I mean, a 'globe' badge seems a bit inappropriate, despite the description using the word 'global'... such a var is really only 'project-wide', not 'world-wide' -that feels as though it's a more fitting description for a cloudvar. [Not quite sure what happens when Scratch is available on Mars, though... ;) ] )

joker314 commented 6 years ago

@TheLogFather That might be cool. But I think your point about the globe not being a good fit actually applies to any icon. The icon needs to convey that many things can access the variable; and given you can't specify which things can access it, every global variable could be misinterpreted as a cloud variable.