Skip to content
This repository has been archived by the owner on Dec 5, 2018. It is now read-only.

need a way to use loadImage with runtime-determined url - @pjs preload directive is no solution #145

Closed
teo1978 opened this issue Mar 5, 2015 · 16 comments

Comments

@teo1978
Copy link

teo1978 commented Mar 5, 2015

The @pjs preload directive may be an acceptable solution for loading images which url is static and known at compile time, but any Processing sketch that loads images whose urls are determined at runtime will miserably break in Processing js and this cannot be solved with a @pjs preload directive.

I'm pretty sure there's a way to fix this. Basically by building into processing some of the hacky workarounds that people use in their sketches to have our sketches work in Processing.js.

I understand the downsides of having such workarounds bult-in (one that comes to my mind is to use a while loop to block execution until the image is really loaded, and that may trigger the unresponsive script warning), so perhaps another @pjs may be introduced to turn on or off "synchronous image loading" or "full Processing loadImage compatibility" mode or whatever you'd like to call it

@GoToLoop
Copy link
Contributor

GoToLoop commented Mar 6, 2015

@teo1978
Copy link
Author

teo1978 commented Mar 6, 2015

That's kind of the other way around: allowing to write code that will work in the same way (async) in Java and Javascript mode. Thanks GoToLoop.

Anyway that doesn't solve the problem of working Processing sketches (using loadImage) that just break in ProcessingJS

@GoToLoop
Copy link
Contributor

GoToLoop commented Mar 6, 2015

  • loadImage() much probably won't be able to return a successfully loaded image in time.
  • That's why @pjs exists in order to preload everything before sketch starts!
  • Non-preloaded images should rely on requestImage() I'm afraid!

@pjs
Copy link

pjs commented Mar 6, 2015

Don't tell me why I exist! ;)

On Thu, Mar 5, 2015 at 6:17 PM GoToLoop notifications@github.com wrote:

  • loadImage() much probably won't be able to return a successfully
    loaded image in time.
  • That's why @pjs https://github.com/pjs exists in order to preload
    everything before sketch starts!
  • Non-preloaded images should rely on requestImage() I'm afraid!


Reply to this email directly or view it on GitHub
#145 (comment)
.

@Pomax
Copy link
Member

Pomax commented Mar 6, 2015

if you can't preload, use requestImage and the techniques that Processing explains to use for dynamic images. Synchronous requests on the web are (not so slowly) getting locked down and being deprecated, so in the near future everything's going to be a "request now, then do other things while the resource is being loaded for you". This isn't a thing Processing.js can fix, and is in fact such a pickle that Processing itself is currently working on adding async resource loading to the language.

@Pomax Pomax closed this as completed Mar 6, 2015
@teo1978
Copy link
Author

teo1978 commented Mar 6, 2015

You're right, indeed I'm myself an advocate of asynchronous loading. I was pissed off by sketches breaking on something so basic as loadImage (especially given its contraddiction with the parity-at-all-costs philosophy of ProcessingJS) but I didn't know about requestImage.

Note by the way that requestImage only half implements asynchronous loading, in that it doesn't even provide a callback. Having to check whether an image is loaded in draw() is pathetic. But that's Processing's fault. The sloppy design of their API is so irritating.

Funnily (nay, sadly), I've just found out that back in 2013 there was a request for a callback from requestImage(). The answer was:

For 2.0 we'll be deprecating requestImage() in favor of better asynchronous loading support methods.

Two years have passed, we are at version 2.2.1 and neither has requestImage() been deprecated, nor any "better asynchronous loading support methods" implemented. And of course requestImage() still lacks a callback.

@GoToLoop
Copy link
Contributor

GoToLoop commented Mar 7, 2015

It's easy to include an optional callback parameter to requestImage(), no matter whether "daddy" Java Mode's API adopt it or not.
Problem is that @Pomax himself is adamantly against providing PJS w/ more features & flexibility than Processing got! =(

@Pomax
Copy link
Member

Pomax commented Mar 7, 2015

mostly because you don't need it to. Just write it in JS and tie plain JS and your sketch together.

@GoToLoop
Copy link
Contributor

GoToLoop commented Mar 7, 2015

Do you really expect regular Processing's intended audience to do that???
Why can't PJS shine on its own? It was even removed from Processing's site!
The official trio is P5, P5*JS & Processing.py now!

@Pomax
Copy link
Member

Pomax commented Mar 7, 2015

I honestly have no idea why you're so upset here. If you want Processing.js to shine on its own, then write the extension code to make it do that and then we can bundle it in and everyone wins. Like I mentioned before in the conclusion of #140, I'm not against additional functionality, I'm all for it, and it can all be done by offering users of Pjs extensions they can load alongside Processing.js -- it's just not going into the core library. Because the core library is purely for parity with Processing (with the exception of code necessary to overcome differences between JS and Java where reasonably possible)

@GoToLoop
Copy link
Contributor

GoToLoop commented Mar 7, 2015

  1. Would that extension option allow to cleanly override requestImage() w/ an extra parameter?
  2. Would an extension option be as easy to activate as issueing an import extension;?
  3. Would an extension option show up in the Add Library for easy download?

@teo1978
Copy link
Author

teo1978 commented Mar 7, 2015

As a corollary of question 2 by GoToLoop, a question I'm particularly interested in is:

Is it possible to write a Java library for Processing and a JavaScript library for Processing.js, and deliver them in some conventional way (like you do with Processing libraries, which just need to be placed in a given subfolder of the sketchbook and imported and they'll work), so that, if the Java and JavaScript versions of the library have the same API, a user would be able to install the "2-platform" library and use in his sketch and have the sketch work seamlessly both in Processing and ProcessingJS (i.e. switch between Java and JavaScript mode seamlessly)?

I'm now realizing I'm basically rephrasing GoToLoop's questions.
If the answer is no, then that's something PJS definitely needs, because if you expect users to use libraries (and developers to provide them), it must be as painless as it is in P5.

@teo1978
Copy link
Author

teo1978 commented Mar 7, 2015

@GoToLoop (sorry everybody else for asking here but there doesn't seem to be a way to send a private message to a user in GitHub), OMG I didn't know about p5*js. Have you tried it thoroughly? Is it mature enough? (by "enough" I mean enough to be used seriously, to be a replacement for Processing[.js], and to be used for teaching&learning programming from scratch as is Processing)

@GoToLoop
Copy link
Contributor

GoToLoop commented Mar 7, 2015

@GoToLoop
Copy link
Contributor

GoToLoop commented Mar 7, 2015

There are some rare Java-JS cross-mode API libraries. Only 1s I know about is:

@Pomax
Copy link
Member

Pomax commented Mar 7, 2015

Those are good questions, so to answer each of those:

(1) yes: since it's just JavaScript, we can write a bit of JS that takes the sketch prototype as defined in Processing.js, and replace it with a wrapping function that adds in the callback handling.

2 + 3: that sounds like you're asking about something the PDE would have to do, which we've never been involved with. The "javascript mode" was a thing that one of the Processing devs put in as an exploration, and it simply landed in release mode (we never collaborated on that). So, if you wanted to implement these things:

(2) on the web it makes more sense to strip the imports entirely, and simply load the JS library that will provide the imported API.

(3) This is a thing you'd have to petition the Processing people for, or even write a PR for so that they can simply land it for you. It'd probably be a thing where you convert import ..... into <script src="......"></script>, but getting import rewriting "right" is a thing that can very quickly turn into a long discussion on exactly how precise to do imports, and whether everything should be single files or split, etc. etc. so I'd simply not bother and rely on how JavaScript already works and simply load an API implementing library alongside Pjs so that things just work.

A concrete example of using more-than-Pjs code

The idea so far has been if you write a dual technology library, then you write your code against the java version as you'd do already, and then simply include the javascript version as an on-page <script> for your page, and things should just work. The processing.js parser filters out import calls, so that wouldn't load it, but you'd write your JS version of the library in a way that exposes the API on script load.

Say we use import minim in a sketch, and we want that to work on the web. We can pretty easily write a shim for the API we need, such as the one on https://github.com/Pomax/Pjs-2D-Game-Engine/blob/master/minim.js, and then we load that:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>...</title>
  </head>
  <body>
    <canvas data-processing-sources="file1.pde file2.pde ..."></canvas>
    <script src="processing.js"></script>
    <script src="minim.js"></script>
  </body>
</html>

This gives the global JavaScript scope a new object Minim, with the same API that we use in our sketch, and because our sketch too is just plain JavaScript, calls in your sketch code to new Minim() just work out of the box, no additional work required.

The same goes for when your sketch (for some reason) relies on underlying Java constructs rather than purely the Processing API, such as tapping into the Long object for MAX_VALUE or the like. You just write a bit of JS that models that object, with the API you need:

var Long = {
  // technically lossy in JavaScript, which can only faithfully do numbers up to 2^53-1
  "MAX_VALUE": Math.pow(2,63)-1,

  // JavaScript has no int/long, all numbers are either 32 bit ints, or doubles
  parseLong: function(v) {
    return parseInt(v,10);
  }
}

And then as long as you load it before your sketch gets interpreted, any calls to Long.MAX_VALUE and Long.parseLong() in your sketch will just work without needing to change a single thing about how Processing.js already works.

Extending Pjs

If you're interested in extending parts of Pjs beyond what it should do in the core library, open a new ticket for the thing you want to add, and we can work on making that happen there. We've sidetracked this issue a lot at this point, and it makes far more sense if I take the information from this answer, plus the information from #140 and compile that into a file that explains how to contribute what things where, so we can refer to that in the future.

I'm going to hit the lock button for this issue simply because it's become this side-tracked, but feel free to open a new issue for either extending requireImage specifically, or adding something else to Pjs without putting it in the core library. I've opened #148 as documentation-creation-issue.

@processing-js processing-js locked and limited conversation to collaborators Mar 7, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants