Loading External PDE

edited September 2017 in How To...

Hi guys, I have written an application using processing and I'd like to enable it to read PDE files that a user copies in the sketch folder. I've read some threads on using the Java classloader and also nested classes. The problem with classloader is that the user needs to compile a java or jar file and from what I understand a nested class doesn't quite work for this purpose since the nested sketch needs to be defined in the main application. Wanted to see if my understanding is correct and which thread is the latest and most suitable for this problem?

Cheers!

Answers

  • I'd like to enable it to read PDE files that a user copies in the sketch folder

    What do you do with the PDE files? Do you want to load them and display them by your application or do you want to be part of your sketch? Any pde file within your sketch folder will be loaded in separate tabs and all these pde files will be treated as a single pde file by the Processing IDE.

    Maybe this next link could be relevant: http://forum.happycoding.io/t/how-to-make-a-processing-showcase/83/5

    Kf

  • Nice recommendation @kfrajer -- I hadn't seen that before.

    In addition, here are some related approaches that chain apps and/or use a launcher script to create a showcase or gallery:

  • I want to load a compiled and exported PDE into another compiled and exported PDE. So I have an exported main sketch that's designed to scan the folder for other exported PDEs and load them as part of the sketch. Sort of like how you would load a preset for a VST if you are familiar with that.

  • I suspect that your specific requirement that the second sketch also be exported as an application means that what you are trying to do will not work.

    Are VST presets stand-alone applications that run without the VST?

  • Well, the second sketch is exported as an application in this example if I understand correctly? http://happycoding.io/examples/java/processing-in-java/processing-showcase

  • That's right, the individual sketches for the gallery/showcase can be exported from PDE in that example.

    However, in that example the main showcase program is Java -- the class ProcessingShowcase isn't a processing sketch, and indeed it has a main instead of a setup()/draw() etc.

    I could be wrong -- maybe you can use List<PApplet> inside a master sketch as shown there. I'm just not sure how.

  • Ok, so I think that'll work. The only thing left is reading the names of the sketch classes from the folder and adding them which is possible as well. I'll do a few experiments and post my results here. Thank you guys for your help.

  • edited August 2017

    Interesting. That looks much easier than what I had in mind lol.

    So I did some research and found out about reflection. Instead of loading say 10 sketches and stopping then hiding them one by one as I switch to the next, I thought it might be easier to have a simple class with one method in there and then call that method using reflection. This way, I'd have one sketch running. But for some reason this doesn't work, not sure why.

    Anyone have a clue?

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Type;
    
    
    import processing.core.PApplet;
    
    int index;
    List<Object> presets;
    
    Method method;
    Object t;
    
    void setup()
    {
      //Wil use these later to make a list of presets
      //index = 0;
      //presets = new ArrayList<Object>();
    
      size(200,200);
    
      try
      {
        Class<?> c = Class.forName("Test");
        t = c.newInstance();
    
        //presets.add(t);
    
        method = t.getClass().getMethod("doTing");
    
      }
      catch(Exception e)
      {
      }
    }
    
    void draw()
    {
      background(0);
      fill(255);
      try
      { 
      method.invoke(t);
      }
      catch(Exception e)
      {
      }
    }
    
    public class Test {
    
      public Test()
      {
      }
    
      public void doTing(){
        ellipse(50,50, 20, 20);
      }
    }`
    
  • Looking at this thread:

    https://forum.processing.org/two/discussion/7036/multiple-screens#latest

    What is the easiest way to modify each of the PApplet sketches after the whole code is exported? Do they have to be .jar files?

  • Actually on second thought I don't want to open separate sketches. I want to call different methods from withing a sketch. But I'm looking for a way to allow the user to modify these methods. It looks like I'll need beanshell or some type of code interpreter.

  • Ok, so you import processing classes to javascript and then have JS evaluate processing code? Do I need P5 as well? Can I do the same with beanshell?

  • edited September 2017

    Do I need P5 as well?

    • By P5 you mean Processing's Java Mode, right? :-/
    • If then, there's no need. Nashorn is a JVM language bundled in Java already. :)>-
    • So you can use Java directly or some other JVM flavor to access Nashorn. \m/
  • edited September 2017

    Can I do the same with BeanShell?

    • Never used JVM flavor BeanShell before: https://en.Wikipedia.org/wiki/BeanShell
    • But AFAIK, any programming languages w/ bundled functions like eval() or commands like exec are capable of running dynamic scripts.
    • As an example, Python got those features builtin.
    • And so you can code in Processing's Python Mode instead in order to use such functionality! *-:)
  • edited September 2017
  • Hmm. Pretty cool stuff. Thanks a lot for laying out all the different options! :) I had no idea what P5 was actually. It sounds like either JS or Python should work for what I want to do.

  • If you opt for Java Mode + Nashorn JS approach, take a look at this example about pulse equation expressions evaluated via ScriptEngine::eval(): :ar!

    1. https://Forum.Processing.org/two/discussion/7147/some-simple-pulse-equations-using-trig-#Item_8
    2. http://Docs.Oracle.com/javase/8/docs/api/javax/script/AbstractScriptEngine.html#eval-java.lang.String-
  • edited September 2017

    There's also a corresponding p5.js online version which calls JS' eval() and uses lib dat.GUI: O:-)

    1. http://Bl.ocks.org/GoSubRoutine/f9a0a94dcfee23a037b35f308b256d98
    2. https://Developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

    index.html:

    <script async src=http://CDN.JSDelivr.net/npm/p5></script>
    <script defer src=http://CDN.JSDelivr.net/gh/dataarts/dat.gui/build/dat.gui.min.js></script>
    <script defer src=sketch.js></script>
    

    sketch.js:

    /**
     * Pulsing Equations (v3.0.2)
     * by _vk (2014/Sep)
     * mod GoToLoop (2017/Sep/21)
     *
     * Forum.Processing.org/two/discussion/7147/
     * some-simple-pulse-equations-using-trig-#Item_10
     *
     * Forum.Processing.org/two/discussion/23468/loading-external-pde#Item_20
     *
     * Bl.ocks.org/GoSubRoutine/f9a0a94dcfee23a037b35f308b256d98
     */
    
    "use strict";
    
    const EQUATIONS = Object.freeze([
      "sin(t)", 
      "cos(t)", 
      "cos(t)*sin(t)", 
      "sin(t)*sin(t*1.5)", 
      "sin(tan(cos(t)*1.2))", 
      "sin(tan(t)*.05)", 
      "cos(sin(t*3.0))*sin(t*.2)", 
      "sin(pow(8.0, sin(t)))", 
      "sin(exp(cos(t*.8))*2.0)", 
      "sin(t - PI*tan(t)*.01)", 
      "pow(sin(t*PI), 12.0)", 
      "cos(sin(t)*tan(t*PI)*PI/8.0)", 
      "sin(tan(t)*pow(sin(t), 10.0))", 
      "cos(sin(t*3.0) + t*3.0)", 
      "pow(abs(sin(t*2.0))*.6, sin(t*2.0)) * .6"
    ]);
    
    const TXT = 'Press any button for next equation',
          FNT = 'DejaVu Sans',
          FPS = 60, OFFSET = 20, OPACITY = 50,
          vals = { size: 200, step: .5, spd: .15, amp: 5 };
    
    let idx = 0, equation = EQUATIONS[idx], x = 0, txtW;
    
    function setup() {
      createCanvas(500, 500).mouseClicked(keyTyped);
    
      colorMode(RGB).blendMode(BLEND);
      rectMode(CORNERS).ellipseMode(CENTER).angleMode(RADIANS);
      strokeCap(ROUND).frameRate(FPS).background(0);
    
      textFont(FNT).textAlign(LEFT).textSize(15);
      txtW = OFFSET + textWidth(TXT);
    
      createGUI();
    }
    
    function draw() {
      fill(0, OPACITY).noStroke();
      rect(0, 0, width, height - 150);
    
      fill(0).rect(0, height - 50, width, height);
      fill(220).ellipse(35, height - 37, 20);
    
      fill(0).textSize(14);
      text(nf(idx+1, 2), 26, height - 32);
    
      fill(150).textSize(15);
      text(TXT, width - txtW, height - 12);
    
      fill(200).textSize(20);
      text(equation, 54, height - 32);
    
      const diam = evalEquation(equation, millis()*vals.spd, vals.size);
      fill(0xff).ellipse(width>>1, (height>>1) - 100, diam);
    
      stroke(0xd0, 0, 0).point(x, height - 100 + diam/vals.amp);
      stroke(80, 0, 0).line(0, height - 100, width, height - 100);
    
      if ((x += vals.step) > width || x < 0) {
        x = x > width? 0 : width
        fill(0).noStroke();
        rect(0, height - 150, width, height);
      }
    }
    
    function keyTyped() {
      fill(x = 0).noStroke();
      rect(0, height - 250, width, height);
      equation = EQUATIONS[idx = (idx+1) % EQUATIONS.length];
    }
    
    function evalEquation(expression, theta, mult) {
      const t = theta * DEG_TO_RAD;
      return mult * eval(expression);
    }
    
    function createGUI() {
      const gui = new dat.GUI;
      gui.add(vals, 'size', height>>2, height>>1, 1); // 200
      gui.add(vals, 'step', -3, 3, .01); // .5
      gui.add(vals, 'spd', -2, 2, .01);  // .15
      gui.add(vals, 'amp', -20, 20, .1); // 5
    }
    
  • edited September 2017

    So turns out processing 3.0a5 doesn't support python mode? ~X( I'm gonna play around with JS a little more. Going back to beanshell, does anyone have experience using it? This is my code so far and it just doesn't recognize any processing code. Do I need to import anything in my script?

    import bsh.*;   
    
    Interpreter i;
    
    void setup()
    {
      size(100,100);
      i = new Interpreter();
    }
    
    void draw()
    {
      background(255);
      fill(0);
      try
      {
        i.eval("ellipse(50,50,50,50);"); //doesnt work :(
        i.source("doTing.bsh"); //doesnt work :(
      }
      catch(EvalError e)
      {
        println( e.getErrorLineNumber() );
        println( e.getErrorText());
        println( e.getTarget());
      }
      catch(Exception e)
      {
      }
    } 
    

    this is the script:

    import processing.core.*;
    import processing.data.*;
    import processing.event.*;
    import processing.awt.*;
    import processing.javafx.*;
    import processing.opengl.*;
    
    ellipse(50,50,50,50); 
    System.out.println("FACKKKKKKKKK"); //this works
    
  • Re:

    processing 3.0a5 doesn't support python mode?

    Is there a specific reason you are using 3.0a5 instead of 3.3.6?

  • Processing 3.0a5 is essentially version 2.2.1. :-j
    Anything compatible w/ 2.2.1 should be compatible w/ 3.0a5 as well. :>

  • I tried porting my code over to the latest version had some nasty errors so decided to finish this project in 3.0a5. I don't see python mode in the list when I try to add it.

  • edited September 2017
    • My advice is to give up on 3.0a5 and use 2.2.1 instead! =;
    • The reason why is that even though 3.0a5 is compatible w/ 2.2.1, it uses P3's "sketchbook.path.three=" instead of P2's "sketchbook.path=" sketchbook path in the "preferences.txt" file! :-&
    • Thus it clashes w/ all of Processing 3's libraries, modes & tools! :-SS
    • I've tried to force 3.0a5 to use the same sketchbook path as P2's by changing its "defaults.txt" file in its subfolder "lib/". :ar!
    • However, 3.0a5 has completely ignored that change in "defaults.txt" and continued to use "sketchbook.path.three=" from "preferences.txt"! :(
  • that explains why I can't add the beanshell library no matter what I do. Right now I have it in my code folder. ~X( Ok, I'll downgrade to 2.2.1 and see what happens [-O<

  • edited September 2017
    • Even so, I'd still recommend Nashorn instead of BeanShell for the simple fact it is already bundled in Java's library. :)>-
    • Another factor to consider is JS' syntax is already very similar to Java's. ~O)
    • And I've already made helper functions which integrate Nashorn JS environment w/ Processing's API. :>
  • I went down to 2.2.1, JS and python modes both installed but the rest of my code doesn't work anymore :( Can I copy the files for these modes into my old 3.0a5 folder? Where would they be stored?

  • edited September 2017

    As I've mentioned, 3.0a5 recognizes P3's sketchbook's path.
    However, P2's Python Mode isn't compatible w/ P3, only 3.0a5 and less.
    But you should instead use latest P3 version rather than older versions.

Sign In or Register to comment.