jmoenig / Snap

a visual programming language inspired by Scratch
http://snap.berkeley.edu
GNU Affero General Public License v3.0
1.48k stars 739 forks source link

Invocations of custom blocks became "obsolete" after saving #167

Closed xtitter closed 10 years ago

xtitter commented 10 years ago

This project has a custom block "draw graph" which, now, has several bright red blocks that read "Obsolete". They didn't used to be obsolete -- rather, they were calls to the custom blocks "draw line" and "draw box", which appear to still be available -- but after a save, restart the browser, and load showed up that way.

This is a problem.

http://snap.berkeley.edu/snapsource/snap.html#present:Username=nate&ProjectName=grapher%20w%20custom%20blocks

I've shared this project, and it seems to be loading properly right now. However, it wasn't loading properly a few minutes ago (from the 'present' url) -- there was a javascript error in gui.js -- and I don't think I changed anything, although I was able to load it from within the cloud area in Snap.

jmoenig commented 10 years ago

I can reproduce this, Nate, here's what's the problem with this project, it's an issue of local vs. global block scope:

There is a sprite-local custom block for the Grapher sprite named DRAW LINE which is used inside the definition for the global custom block named DRAW GRAPH. Global block definitions cannot access local ones (because block definitions are compiled when you click "OK" or "APPLY" in the block editor and not "inlined" dynamically at runtime whenever Snap evaluates the block, and because sprite-local blocks cannot be used within another sprite).

Note, however, that you can use global custom blocks inside sprite-local custom block definitions.

I suggest that Snap scan the block definition for any out-of-scope block references whenever you click "OK" or "APPLY" and informs you about the problem. What do you think?

xtitter commented 10 years ago

The error-checking will help, but I'm not sure this is good behavior for our (eventual) OOP-liness. I'm not the best person to think about this, and I don't totally understand the problem. But, when we have OOP, we are going to want a child-sprite to run scripts local to the parent, or (more relevant?) have a child-sprite run a parent-local script that runs a child-local script (overloading a parent local script, says my Java hat, lol).

I'm assume there is a some sort of sprite-context that all blocks run with -- so, "move" knows which sprite is calling it and can move the right one. And, that context has to be passed on through all inner block calls -- can't this be used to find the sprite local blocks? My intuition is that is what should be happening, OOPly speaking, but maybe I'm simplifying (I guess you'd cascade up the inheritance chain really)

xtitter commented 10 years ago

Additionally, this problem may have showed up when I dragged a script from one sprite to another. You'll need to ensure thta your error check runs in that situation, and other situations where no block editor is ever opened.

jmoenig commented 10 years ago

You can (and should!) do OOP without directly invoking object's functions, instead sending messages which leave it up to the receiver how to behave. But anyway, the way to invoke other sprite's local blocks or scripts is for the other sprite to make them available by assigning a ringified instance to a (local or global) variable, and by the sender to CALL (or RUN or LAUNCH) that. Check out this example project (which is how it used to be done in BYOB, too):

http://snap.berkeley.edu/snapsource/snap.html#present:Username=jens&ProjectName=OOPish

And, you can't drag a local custom block from one sprite to another, it won't get copied. You know, local is local :-)

xtitter commented 10 years ago

( Wait, that is awesome... we have and always had "tell X to run its method Y"! It should be easy to include a high-level "tell" block, but unnecessary because of this? )

But, back to the OOP issue: I wasn't talking about a sprite sending a message to another (unrelated) sprite, but rather a sprite invoking its own block (that was defined in the parent). A custom script local to the parent should be available to the child, since the child "is" the parent