Smart pic, now obsolete

Hi again @dardoro! I'm working on getting the read-back of script-pics to Snap! and I had a quick question: within the morphic.js file of the source code, do you know how I can access the IDE attribute of the GUI? I've been experimenting with different calls from the different files, since the ide = this.morphAtPointer()?.parentThatIsA( IDE_Morph) that you provided in your example is erroring.

return this.parentThatIsA(IDE_Morph);

I've checked the slightly modified version

HandMorph.prototype.processDrop = function (ev) {
 if( ev.shiftKey){ 
  let
    ide = this.morphAtPointer()?.parentThatIsA( IDE_Morph) 
    ,url = ev.dataTransfer?.getData( "text/uri-list")
    ,file = ev.dataTransfer?.files?.[0];

console.log( this, this.morphAtPointer?.(), ide);

And saw that every object has a proper value.
So this works in the scope of HandMorph and image dropped onto scripting area.

If You use this in other scopes or drop the image outside of the scripting area, an absolute reference to an IDE will be better
let ide = world.children[0]

I modified the project ( ide and arr2Str definition).

BTW: @bh, sorry to bother You. Can you split this thread starting with the first jvillalobos2002 post to Advanced>Development?

I've added minimal, shallow, export of custom block definition with the picture of its body.

@dardoro thanks for the new updates to the code! I included them into the local version of Snap! that I have, but when it processes the dropped image, the file and url fields come out to be null, and the file has no name attribute. Might you have any idea why this is happening? Here are some screenshots:

The code that I have:

The errors I get after dropping an image onto Snap!:

I'll keep messing around with it myself, but if you have any fixes, they're appreciated :slight_smile:

That's the problem with async functions and event handlers.
The ev.dataTransfer is volatile and vanishes outside of the event handler sequential scope.
So the

let 
url ...
,file ...

must be set before asynchronous
pic.onload=...

BTW: arr2str() is prone to error for bigger files. Better
function arr2Str( arr){ return arr.map( b => String.fromCharCode(b)).join("")}
or
function arr2Str( arr){ return arr.reduce((acc, b)=>acc+String.fromCharCode( b), "")};

@dardoro We have made very good progress! I meant to share this with you earlier, but midterms have been a pain. Now we have Snap! automatically embedding XML scripts within each script pic, and accepting them back on drop. We have also added a neat menu for users to indicate whether they'd like to interpret the XML in an image or upload the image itself, only if the XML exists within the image. If it doesn't, then images will simply be sent to the costume window.

The problem we're having right now is with custom blocks. Their scripts are properly embedded within the PNG script pics, but they are not processing entirely correctly after being dropped back on the script window. If you have any guidance on that, that would be amazing.

I'd share videos, but the forum doesn't allow for them :") So here are some screen shots:

I've tested the included pictures with my base project
undefined (11)
test2 (1)
without problem, in two separate steps.

I'm not sure if it was already clear. Despite its image, the custom block should be exported from the palette, NOT from the script editor.
During a block editing session, editor content is wrongly serialized as a script:

<script>
  <block s=""><script><custom-block s="test2"></custom-block></script></block>
  <block s="doForEach"><l>item</l><l/> <script></script></block>
</script>

Custom block exported from the palette has a proper form.


<blocks app="Snap! 6, https://snap.berkeley.edu" version="1">
  <block-definition s="test2" type="command" category="other">
    <header></header><code></code><translations></translations><inputs></inputs>
    <script><block s="doForEach"><l>item</l><l/><script></script></block></script>
  </block-definition>
</blocks>

The crucial parts responsible for the custom block, from the palette, handling

BlockMorph.prototype.userMenu = function(){
...
   ,top = this.definition || this.topBlock() 
...
 if( !this.isTemplate || this.definition){//for scripts & custom blocks only
...
     "script pic & XML"
     ,()=>{
       let xml = unescape( encodeURIComponent( ide.serializer.serialize( top)));
       if(this.isTemplate){ xml = "<blocks>" + xml + "</blocks>"};
       let pic = top.scriptsPicture?.() || top.scriptPic?.();

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.