How to convert string to a line of code

RazRaz
edited April 2017 in How To...

(In Processing) Can I convert a string to a code? For example: The user write on a text box "rect(100,100,20,50)". And the computer convert it to a line of code and on the screen the rect will be drawn. How can I do that?

Answers

  • GoToLoop Thank you! But I dont need boolean statement, I need a line of code! And methods :)

  • edited February 2016

    as I discussed with gotoloop in the other thread: gotoloop thinks put can do rectangles too

    and he's right - see below

  • edited February 2016
    // based on the QSCript example QSCriptIDE
    // now used to eval java directly
    // thanks to gotoloop / forum 
    
    /**
     <h1>QScript algorithm editor</h1>
     <p>There are 3 predefined scripts demonstrating solutions to simple math 
     algorithms. To execute one of these scripts click on one of the green 
     buttons, then click on the Init button, this will parse and tokenise 
     the script. </p>
    
     <p>In the event of a syntax error it will be highlighted in red and a 
     description will appear in the pink status bar. </p>
    
     <p>It is not possible to run the script until it has been successfully 
     tokenised. At that time you can click on the start button, slect whether you 
     want to trace the progress of the evaluation and if tracing the speed of 
     evaluation.</p>
    
     <p>To run your own scripts simply type them into the script editor and then
     initialise and run them.</p>
    
     <p>For detailed information about how to use this library 
     please visit the 
     <a href="http://www.lagers.org.uk/qscript/">website</a></p>
    
     created 2014 by Peter Lager
     */
    
    import g4p_controls.*;
    
    import org.qscript.eventsonfire.*;
    import org.qscript.events.*;
    import org.qscript.editor.*;
    import org.qscript.*;
    import org.qscript.operator.*;
    import org.qscript.errors.*;
    
    import java.awt.Font;
    import java.util.*;
    
    
    
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    
    final int EDIT = 1;
    final int RUNNING = 3;
    
    int currMode;
    
    Script script;
    String code[];
    boolean codeChanged = false;
    TreeMap<String, String> store = new TreeMap<String, String>();
    LinkedList<ScriptEvent> event_queue = new LinkedList<ScriptEvent>();
    
    StringBuilder output = new StringBuilder();
    
    ScriptEngine se_Global1;
    
    public void setup() {
      size(1400, 570, JAVA2D);
      createGUI();
      customGUI();
      // Set the script to start with
      script = new Script("");
      setScript(1);
      // Set the script trace and trace delays based on initial GUI settings
      script.traceDelay(sdrDelay.getValueI());
      setTraceMode(cbxTrace.isSelected());
    
      // Scripting events are to be sent to this object
      script.addListener(this);
    
      goToMode(EDIT);
      registerMethod("pre", this);
    
    
    
      se_Global1 = new ScriptEngineManager().getEngineByName("js");
      //
    }
    
    
    
    
    static final void evalJS(PApplet pa, ScriptEngine js, String expression) {
      js.put("p", pa);
    
      try {
        js.eval("p." + expression);
      }
    
      catch (ScriptException cause) {
        throw new RuntimeException(cause);
      }
    }
    
    
    
    // Switch IDE between running and editing modes
    public void goToMode(int mode) {
      switch(mode) {
      case EDIT:
        currMode = mode;
        btnStart.setAlpha(255);
        btnStop.setAlpha(120);
        break;
      case RUNNING:
        currMode = mode;
        btnStart.setAlpha(120);
        btnStop.setAlpha(255);
        break;
      }
    }  
    
    
    // Clear the data store of all variables
    public void clearVars() {
      store.clear();
      txaVars.setText("");
      if (script != null)
        script.clearVariables();
    }
    
    // Hide/show trace controls depending on whether the
    // trace is switched on or off.
    public void setTraceMode(boolean traceOn) {
      if (script != null) {
        if (traceOn) {
          lblDelayTitle.setVisible(true);
          sdrDelay.setVisible(true);
          btnPause.setVisible(true);
          btnPause.setAlpha(255);
          btnResume.setVisible(true);
          btnResume.setAlpha(120);
          script.traceModeOn();
        } else {
          lblDelayTitle.setVisible(false);
          sdrDelay.setVisible(false);
          btnPause.setVisible(false);
          btnPause.setAlpha(255);
          btnResume.setVisible(false);
          btnResume.setAlpha(120);
          script.traceModeOff();
          script.resume();
          txaScript.clearStyles();
        }
      }
    }
    
    /**
     * Since events are fired asynchronously this method might be called whilst G4P
     * is drawing its controls causing the program to crash. To avoid this we will
     * add the event to a queue and process it during Processing's event loop.
     */
    @ EventHandler
      public void onScriptEvent(ScriptEvent event) {
      if (event instanceof HaltExecutionEvent && event.etype == ErrorType.STOPPED_BY_USER)
        event_queue.addFirst(event);
      else
        event_queue.addLast(event);
    }
    
    /**
     * This method has been registered with Processing so will be called just 
     * before the draw method. It will process a maximum of 20 events in the FIFO
     * queue, then allow the draw method to execute.
     * Since the script can generate hundreds of events per frame we have to
     * cap the number processed if we want the GUI to be responsive.
     */
    public void pre() {
      int count = 0;
      while (!event_queue.isEmpty () && count++ < 20)
        performEventAction(event_queue.removeFirst());
    }
    
    /**
     * This method performs the actions needed by any particular type of script 
     * event. 
     */
    public void performEventAction(ScriptEvent event) {
      if (event instanceof TraceEvent && cbxTrace.isSelected()) {
        txaScript.clearStyles();
        txaScript.addStyle(G4P.BACKGROUND, 0xFF0000CC, event.lineNo, event.pos, event.pos + event.width);
        txaScript.addStyle(G4P.FOREGROUND, 0xFFFFFF00, event.lineNo, event.pos, event.pos + event.width);
        txaScript.moveCaretTo(event.lineNo, event.pos);
      } else if (event instanceof SyntaxErrorEvent || event instanceof EvaluationErrorEvent) {
        lblStatus.setText(event.getMessage());
        txaScript.clearStyles();
        txaScript.addStyle(G4P.BACKGROUND, 0xFFFF0000, event.lineNo, event.pos, event.pos + event.width);
        txaScript.addStyle(G4P.FOREGROUND, 0xFFFFFFFF, event.lineNo, event.pos, event.pos + event.width);
        txaScript.addStyle(G4P.WEIGHT, 4, event.lineNo, event.pos, event.pos + event.width);
        txaScript.moveCaretTo(event.lineNo, event.pos);
        goToMode(EDIT);
      } else if (event instanceof HaltExecutionEvent) {
        lblStatus.setText(event.getMessage());
        event_queue.clear();
        txaScript.clearStyles();
        txaScript.addStyle(G4P.BACKGROUND, 0xFFFF0000, event.lineNo, event.pos, event.pos + event.width);
        txaScript.addStyle(G4P.FOREGROUND, 0xFFFFFFFF, event.lineNo, event.pos, event.pos + event.width);
        txaScript.addStyle(G4P.WEIGHT, 4, event.lineNo, event.pos, event.pos + event.width);
        goToMode(EDIT);
      } else if (event instanceof ScriptFinishedEvent) {
        lblStatus.setText(event.getMessage());
        event_queue.clear();
        txaScript.clearStyles();
        goToMode(EDIT);
      } else if (event instanceof OutputEvent) {
        output.append(event.extra[0]);      
        txaOutput.setText(output.toString(), 2000);
      } else if (event instanceof StoreUpdateEvent) {
        Variable var = (Variable) event.extra[0];
        store.put(var.getIdentifier(), var.toString());
        StringBuilder s = new StringBuilder();
        for (String id : store.keySet ()) {
          if (id.length() > 12) {
            s.append(id.substring(0, 9));
            s.append("...   ");
          } else {
            s.append(id);
            s.append("               ".substring(0, 15 - id.length()));
          }
          s.append(store.get(id));
          s.append("\n");
        }
        txaVars.setText(s.toString());
      } else if (event instanceof WaitEvent) {
        Argument arg = (Argument) event.extra[0];
        int time = arg.toInteger();
        if (time == 0)
          lblStatus.setText("Waiting for you to resume ... ");
        else
          lblStatus.setText("Waiting for " + time + " milliseconds");
      }
    }
    
    public void draw() {
      // background(230, 230, 255);
      fill(230, 230, 255);
    
      rect(0, 0, 600, height);
    }
    
    // Use this method to add additional statements
    // to customise the GUI controls
    public void customGUI() {
      //  lblStatus.setTextAlign(GAlign.LEFT, null);
      txaVars.setFont(new Font("Monospaced", Font.PLAIN, 11));
      txaOutput.setFont(new Font("Dialog", Font.PLAIN, 11));
      txaScript.setFont(new Font("Monospaced", Font.PLAIN, 12));
      txaVars.setTextEditEnabled(false);
      txaOutput.setTextEditEnabled(false);
    }
    
    
    public void setScript(int sn) {
      String fname = null;
      StringList codeLines = new StringList();
      String desc = "";
      switch(sn) {
      case 1:
        fname = "quadratic.txt";
        break;
      case 2:
        fname = "fibonacci.txt";
        break;
      case 3:
        fname = "primes.txt";
        break;
      }
      if (fname == null)
        return;
    
      // String[] lines = loadStrings(fname);
      String[] lines = new String[1];
    
      lines[0] = "rect(710,20,33,44);" ;
      codeLines.append(lines[0]);
    
    
      //int ln = 0;
      //while (ln < lines.length) {
      //  if (lines[ln].startsWith("##Desc")) {
      //    ln++;
      //    while (!lines[ln].startsWith ("##") && ln <lines.length)
      //      desc += lines[ln++] + " ";
      //  }
      //  if (lines[ln].startsWith("##Code")) {
      //    ln++;
      //    while (!lines[ln].startsWith ("##") && ln <lines.length)
      //      codeLines.append(lines[ln++]);
      //  }
      //  ln++;
      //}
    
    
      code = codeLines.array();
      script.setCode(code);
      txaScript.setText(code);
      txaOutput.setText(desc, 240);
      txaVars.setText("");
      lblStatus.setText("");
      codeChanged = true;
      goToMode(EDIT);
    }
    
    /// ------------------------------------
    
    // GUI tab
    public void script_change(GTextArea source, GEvent event) {
      if (event == GEvent.CHANGED) {
        txaOutput.setText("");
        lblStatus.setText("");
        txaScript.clearStyles();
        codeChanged = true;
      }
    }
    
    public void delay_change(GCustomSlider source, GEvent event) {
      if (script != null) {
        script.traceDelay(source.getValueI());
      }
    }
    
    public void start_click(GButton source, GEvent event) {
      goToMode(RUNNING);
      txaScript.clearStyles();
      if (codeChanged) {
        script.setCode(txaScript.getTextAsArray());
        code=txaScript.getTextAsArray();
        codeChanged = false;
      }
      lblStatus.setText("");
      output = new StringBuilder();
      setTraceMode(cbxTrace.isSelected());
      txaOutput.setText("");
      clearVars();
      //  Solver$.evaluate(script);
    
      background(0); 
      stroke(0);
    
      String joinString="";
      for (int i=0; i<code.length; i++) 
        evalJS(this, se_Global1, code[i]);
    
      // println(code[0]);
    
      goToMode(EDIT);
      //
    }
    
    public void stop_click(GButton source, GEvent event) {
      script.stop();
    }
    
    public void pause_click(GButton source, GEvent event) {
      script.waitFor(0);
      source.setAlpha(120);
      btnResume.setAlpha(255);
    }
    
    public void resume_click(GButton source, GEvent event) {
      script.resume();
      source.setAlpha(120);
      btnPause.setAlpha(255);
    }
    
    public void trace_click(GCheckbox source, GEvent event) {
      setTraceMode(source.isSelected());
    }
    
    public void script1_click(GButton source, GEvent event) {
      if (currMode != RUNNING)
        setScript(1);
    }
    
    public void script2_click(GButton source, GEvent event) {
      if (currMode != RUNNING)
        setScript(2);
    }
    
    public void script3_click(GButton source, GEvent event) {
      if (currMode != RUNNING)
        setScript(3);
    }
    
    // Create all the GUI controls. 
    public void createGUI() {
      G4P.messagesEnabled(false);
      G4P.setGlobalColorScheme(GCScheme.BLUE_SCHEME);
      G4P.setCursor(ARROW);
      if (frame != null)
        frame.setTitle("Sketch Window");
      txaScript = new GTextArea(this, 0, 20, 350, 450, G4P.SCROLLBARS_BOTH);
      txaScript.setPromptText("Enter your script");
      txaScript.setOpaque(true);
      txaScript.addEventHandler(this, "script_change");
      txaVars = new GTextArea(this, 350, 20, 250, 210, G4P.SCROLLBARS_BOTH);
      txaVars.setOpaque(true);
      txaOutput = new GTextArea(this, 350, 250, 250, 220, G4P.SCROLLBARS_BOTH);
      txaOutput.setLocalColorScheme(GCScheme.GREEN_SCHEME);
      txaOutput.setOpaque(false);
      lblScriptTitle = new GLabel(this, 0, 0, 350, 20);
      lblScriptTitle.setText("QScript editor");
      lblScriptTitle.setTextBold();
      lblScriptTitle.setOpaque(true);
      lblOutputTitle = new GLabel(this, 350, 230, 250, 20);
      lblOutputTitle.setText("Output");
      lblOutputTitle.setTextBold();
      lblOutputTitle.setLocalColorScheme(GCScheme.GREEN_SCHEME);
      lblOutputTitle.setOpaque(true);
      lblVariablesTitle = new GLabel(this, 350, 0, 250, 20);
      lblVariablesTitle.setText("Variables");
      lblVariablesTitle.setTextBold();
      lblVariablesTitle.setOpaque(true);
      lblStatusTitle = new GLabel(this, 10, 500, 70, 20);
      lblStatusTitle.setText("Status:");
      lblStatusTitle.setTextBold();
      lblStatusTitle.setLocalColorScheme(GCScheme.RED_SCHEME);
      lblStatusTitle.setOpaque(true);
      lblStatus = new GLabel(this, 80, 500, 510, 20);
      lblStatus.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
      lblStatus.setText(" ");
      lblStatus.setTextBold();
      lblStatus.setTextItalic();
      lblStatus.setLocalColorScheme(GCScheme.RED_SCHEME);
      lblStatus.setOpaque(true);
      sdrDelay = new GCustomSlider(this, 250, 470, 200, 20, "grey_blue");
      sdrDelay.setLimits(50.0f, 0.0f, 500.0f);
      sdrDelay.setEasing(10.0f);
      sdrDelay.setNumberFormat(G4P.INTEGER, 0);
      sdrDelay.setOpaque(true);
      sdrDelay.addEventHandler(this, "delay_change");
      btnStart = new GButton(this, 10, 470, 50, 20);
      btnStart.setText("Start");
      btnStart.setTextBold();
      btnStart.addEventHandler(this, "start_click");
      btnStop = new GButton(this, 70, 470, 50, 20);
      btnStop.setText("Stop");
      btnStop.setTextBold();
      btnStop.addEventHandler(this, "stop_click");
    
      btnPause = new GButton(this, 460, 470, 60, 20);
      btnPause.setText("Pause");
      btnPause.setTextBold();
      btnPause.addEventHandler(this, "pause_click");
    
      btnResume = new GButton(this, 530, 470, 60, 20);
      btnResume.setText("Resume");
      btnResume.setTextBold();
      btnResume.addEventHandler(this, "resume_click");
    
      cbxTrace = new GCheckbox(this, 130, 470, 70, 20);
      cbxTrace.setIconAlign(GAlign.RIGHT, GAlign.MIDDLE);
      cbxTrace.setText("Trace");
      cbxTrace.setTextBold();
      cbxTrace.setOpaque(true);
      cbxTrace.addEventHandler(this, "trace_click");
      lblDelayTitle = new GLabel(this, 210, 470, 50, 20);
      lblDelayTitle.setText("Delay");
      lblDelayTitle.setTextBold();
      lblDelayTitle.setOpaque(true);
      btnScript1 = new GButton(this, 10, 530, 180, 30);
      btnScript1.setText("Solve Quadratic Equation");
      btnScript1.setTextBold();
      btnScript1.setLocalColorScheme(GCScheme.ORANGE_SCHEME);
      btnScript1.addEventHandler(this, "script1_click");
      btnScript2 = new GButton(this, 210, 530, 180, 30);
      btnScript2.setText("Fibonacci Series");
      btnScript2.setTextBold();
      btnScript2.setLocalColorScheme(GCScheme.ORANGE_SCHEME);
      btnScript2.addEventHandler(this, "script2_click");
      btnScript3 = new GButton(this, 410, 530, 180, 30);
      btnScript3.setText("Prime Number Sieve");
      btnScript3.setTextBold();
      btnScript3.setLocalColorScheme(GCScheme.ORANGE_SCHEME);
      btnScript3.addEventHandler(this, "script3_click");
    }
    
    // Variable declarations 
    GTextArea txaScript; 
    GTextArea txaVars; 
    GTextArea txaOutput; 
    GLabel lblScriptTitle; 
    GLabel lblOutputTitle; 
    GLabel lblVariablesTitle; 
    GLabel lblStatusTitle; 
    GLabel lblStatus; 
    GCustomSlider sdrDelay; 
    GButton btnStart; 
    GButton btnStop; 
    GButton btnPause; 
    GButton btnResume; 
    GCheckbox cbxTrace; 
    GLabel lblDelayTitle; 
    GButton btnScript1; 
    GButton btnScript2; 
    GButton btnScript3;
    
    // 
    
  • edited February 2016

    I posted an example based on the QScript example QSCriptIDE by @quark

    the whole java / put is by @gotoloop

    I killed most of the functionality of the QScript

    but you can press "start" to get an rectangle or whatever

    you can edit the sketch

    you can write e.g.

    rect(710,20,33,44);
    

    OR with 2 lines

    rect(710,20,33,144);
    rect(710,220,33,44);
    

    OR

    rect(710,20,33,44);
    stroke(255); 
    line(710,320,733,344); 
    

    and hit "start"

    Lines

    the important lines are 90 to 100

    279 to 282

    342 to 355

    and I added line 334

    remark

    • you have to strip it of all QScript stuff and of the other gui-elements that you don't need

    I am not sure though how to make a separate window where the rectangles are actually drawn

  • edited February 2016

    I would be happier if I could pass a String array (my array code) to

    static final void evalJS(PApplet pa, ScriptEngine js, String expression) {
    
  • edited February 2016

    @Chrisir, don't you think your code was a lil' too big for @Raz? :-\"
    Anyways, here's my own attempt w/ lotsa tricks I've learnt today about Nashorn JS + P5: :-bd

    /**
     * Processing Nashorn JS Integration (v1.04)
     * GoToLoop (2016-Feb-28)
     *
     * forum.Processing.org/two/discussion/15151/
     * how-to-convert-string-to-a-line-of-code
     *
     * forum.Processing.org/two/discussion/7147/
     * some-simple-pulse-equations-using-trig
     */
    
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    final ScriptEngine js = new ScriptEngineManager().getEngineByName("js");
    
    static final String[] SENTENCES = {
      "Nashorn JS is cool!", 
      "We can draw on the canvas inside JS too!", 
      "Let's program is JS now!!!"
    };
    
    void setup() {
      size(400, 150);
      smooth(4);
      frameRate(.5);
    
      js.put("p", this); // puts sketch's PApplet as p into JS.
    
      js.put("w", width);  // puts width's  current value as w into JS.
      js.put("h", height); // puts height's current value as h into JS.
    
      js.put("SENTENCES", SENTENCES); // puts String[] SENTENCES.
      js.put("idx", 0); // creates global variable idx into JS.
    
      evalJS(js, // transfers all PConstants to JS global scope.
        "var PConstants = Java.type('processing.core.PConstants')", 
        "for each (var f in PConstants.class.getFields()) {", 
        "  var field = f.getName()", 
        "  this[field] = PConstants[field] }");
    
      evalJS(js, // transfers all JS' Math methods to global scope.
        "for each (var prop in Object.getOwnPropertyNames(Math))"
        + "this[prop] = Math[prop]");
    
      evalP5(js, // calls P5's canvas API from JS.
        "textFont(p.createFont('DejaVu Sans', 18))", 
        "textAlign(CENTER, BASELINE)", 
        "stroke(0), p.strokeWeight(1.5), p.fill(~~0xffFFFF00)");
    }
    
    void draw() {
      println(evalP5(js, // calls P5's canvas API from JS.
        "background(~~p.random(0x1000000))", 
        "text(SENTENCES[idx = (idx+1) % SENTENCES.length], w>>1, h>>1)", 
        "frame.setTitle('Idx: ' + idx + '   Frame: ' + p.frameCount)"), ENTER);
    }
    
    static final String evalP5(final ScriptEngine js, final String... phrases) {
      for (int i = 0; i < phrases.length; phrases[i] = "p." + phrases[i++]);
      return evalJS(js, phrases);
    }
    
    static final String evalJS(final ScriptEngine js, final String... phrases) {
      final String expression = join(phrases, ENTER);
    
      try {
        js.eval(expression);
      }
      catch (final ScriptException cause) {
        System.err.println(expression);
        throw new RuntimeException(cause);
      }
    
      return expression;
    }
    
  • edited January 2018

    Now's a more advanced version which includes CompiledScript for better script performance: ;;)

    http://docs.Oracle.com/javase/8/docs/api/javax/script/Compilable.html
    http://docs.Oracle.com/javase/8/docs/api/javax/script/CompiledScript.html

    /**
     * Processing Nashorn JS Integration (v4.0)
     * GoToLoop (2016-Feb-28)
     *
     * Forum.Processing.org/two/discussion/15151/how-to-convert-string-to-a-line-of-code
     * Forum.Processing.org/two/discussion/7147/some-simple-pulse-equations-using-trig
     */
    
    final ScriptEngine js = new ScriptEngineManager().getEngineByName("Nashorn");
    
    final CompiledScript compiledJS = compileJS(js, // compiles P5's canvas API calls.
      "background(~~random(0x1000000))", 
      "text(SENTENCES[idx = (idx+1) % SENTENCES.length], w>>1, h>>1)", 
      "surf.setTitle('Idx: ' + idx + '   Frame: ' + frameCount)");
    
    static final String[] SENTENCES = {
      "Nashorn JS is cool!", 
      "We can draw on the canvas inside JS too!", 
      "Let's program is JS now!!!"
    };
    
    void setup() {
      size(400, 150);
      smooth(4);
      frameRate(.5);
    
      initJSProcessingEnv(js, this);
    
      js.put("SENTENCES", SENTENCES); // puts String[] SENTENCES.
      js.put("idx", 0); // creates global variable idx into JS.
    
      evalJS(js, "surf = surface || frame"); // assigns either surface or frame.
    
      println(evalJS(js, // calls P5's canvas API from JS.
        "textFont(createFont('DejaVu Sans', 18))", 
        "textAlign(CENTER, BASELINE)", 
        "fill(~~0xffFFFF00), stroke(0), strokeWeight(1.5)"));
    }
    
    void draw() {
      runJS(compiledJS);
    }
    
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    import javax.script.Invocable;
    import javax.script.Compilable;
    import javax.script.CompiledScript;
    
    static final void initJSProcessingEnv
      (final ScriptEngine js, final PApplet pa) {
      js.put("p", pa); // injects sketch's PApplet as p into JS.
    
      js.put("w", pa.width);  // injects width's  current value as w into JS.
      js.put("h", pa.height); // injects height's current value as h into JS.
    
      evalJS(js, // imports Processing's packages.
        "var processing = {", 
        "  core:   JavaImporter(Packages.processing.core),", 
        "  data:   JavaImporter(Packages.processing.data),", 
        "  event:  JavaImporter(Packages.processing.event),", 
        "  awt:    JavaImporter(Packages.processing.awt),", 
        "  javafx: JavaImporter(Packages.processing.javafx),", 
        "  opengl: JavaImporter(Packages.processing.opengl)", 
        "}");
    
      evalJS(js, // imports Processing's core classes.
        "var PApplet         = Java.type('processing.core.PApplet'),", 
        "    PConstants      = Java.type('processing.core.PConstants'),", 
        "    PFont           = Packages.processing.core.PFont,", 
        "    PGraphics       = Packages.processing.core.PGraphics,", 
        "    PImage          = Packages.processing.core.PImage,", 
        "    PMatrix         = Packages.processing.core.PMatrix,", 
        "    PMatrix2D       = Packages.processing.core.PMatrix2D,", 
        "    PMatrix3D       = Packages.processing.core.PMatrix3D,", 
        "    PShape          = Packages.processing.core.PShape,", 
        "    PShapeOBJ       = Packages.processing.core.PShapeOBJ,", 
        "    PShapeSVG       = Packages.processing.core.PShapeSVG,", 
        "    PStyle          = Packages.processing.core.PStyle,", 
        "    PSurface        = Packages.processing.core.PSurface,", 
        "    PSurfaceNone    = Packages.processing.core.PSurfaceNone,", 
        "    PVector         = Packages.processing.core.PVector,", 
        "    ThinkDifferent  = Packages.processing.core.ThinkDifferent");
    
      evalJS(js, // imports Processing's data classes.
        "var FloatDict       = Packages.processing.data.FloatDict,", 
        "    FloatList       = Packages.processing.data.FloatList,", 
        "    IntDict         = Packages.processing.data.IntDict,", 
        "    IntList         = Packages.processing.data.IntList,", 
        "    JSONArray       = Packages.processing.data.JSONArray,", 
        "    JSONObject      = Packages.processing.data.JSONObject,", 
        "    JSONTokener     = Packages.processing.data.JSONTokener,", 
        "    Sort            = Packages.processing.data.Sort,", 
        "    StringDict      = Packages.processing.data.StringDict,", 
        "    StringList      = Packages.processing.data.StringList,", 
        "    Table           = Packages.processing.data.Table,", 
        "    TableRow        = Packages.processing.data.TableRow,", 
        "    XML             = Packages.processing.data.XML");
    
      evalJS(js, // imports Processing's event classes.
        "var Event           = Packages.processing.event.Event,", 
        "    KeyEvent        = Packages.processing.event.KeyEvent,", 
        "    MouseEvent      = Packages.processing.event.MouseEvent,", 
        "    TouchEvent      = Packages.processing.event.TouchEvent");
    
      evalJS(js, // imports Processing's awt classes.
        "var PGraphicsJava2D = Packages.processing.awt.PGraphicsJava2D,", 
        "    PShapeJava2D    = Packages.processing.awt.PShapeJava2D,", 
        "    PSurfaceAWT     = Packages.processing.awt.PSurfaceAWT");
    
      evalJS(js, // imports Processing's javafx classes.
        "var PGraphicsFX2D   = Packages.processing.javafx.PGraphicsFX2D,", 
        "    PSurfaceFX      = Packages.processing.javafx.PSurfaceFX");
    
      evalJS(js, // imports Processing's opengl classes.
        "var FontTexture     = Packages.processing.opengl.FontTexture,", 
        "    FrameBuffer     = Packages.processing.opengl.FrameBuffer,", 
        "    LinePath        = Packages.processing.opengl.LinePath,", 
        "    LineStroker     = Packages.processing.opengl.LineStroker,", 
        "    PGL             = Packages.processing.opengl.PGL,", 
        "    PGraphics2D     = Packages.processing.opengl.PGraphics2D,", 
        "    PGraphics3D     = Packages.processing.opengl.PGraphics3D,", 
        "    PGraphicsOpenGL = Packages.processing.opengl.PGraphicsOpenGL,", 
        "    PJOGL           = Packages.processing.opengl.PJOGL,", 
        "    PShader         = Packages.processing.opengl.PShader,", 
        "    PShapeOpenGL    = Packages.processing.opengl.PShapeOpenGL,", 
        "    PSurfaceJOGL    = Packages.processing.opengl.PSurfaceJOGL,", 
        "    Texture         = Packages.processing.opengl.Texture,", 
        "    VertexBuffer    = Packages.processing.opengl.VertexBuffer");
    
      evalJS(js, // imports some useful Java classes.
        "var ArrayList       = java.util.ArrayList,", 
        "    LinkedList      = java.util.LinkedList,", 
        "    ArrayDeque      = java.util.ArrayDeque,", 
        "    HashMap         = java.util.HashMap,", 
        "    WeakHashMap     = java.util.WeakHashMap,", 
        "    HashSet         = java.util.HashSet,", 
        "    LinkedHashSet   = java.util.LinkedHashSet,", 
        "    TreeSet         = java.util.TreeSet,", 
        "    Collections     = java.util.Collections,", 
        "    Arrays          = java.util.Arrays,", 
        "    Objects         = java.util.Objects,", 
        "    Optional        = java.util.Optional,", 
        "    Comparator      = java.util.Comparator,", 
        "    Timer           = java.util.Timer",
        "    TimerTask       = java.util.TimerTask",
        "    Scanner         = java.util.Scanner",
        "    File            = java.io.File,", 
        "    FileFilter      = java.io.FileFilter,", 
        "    FilenameFilter  = java.io.FilenameFilter,", 
        "    BufferedReader  = java.io.BufferedReader,", 
        "    FileReader      = java.io.FileReader,", 
        "    PrintWriter     = java.io.PrintWriter,", 
        "    InputStream     = java.io.InputStream,", 
        "    OutputStream    = java.io.OutputStream,", 
        "    IOException     = java.io.IOException,",
        "    StringBuilder   = java.lang.StringBuilder,",
        "    System          = java.lang.System,",
        "    Cloneable       = java.lang.Cloneable",
        "    Comparable      = java.lang.Comparable",
        "    Iterable        = java.lang.Iterable",
        "    Runnable        = java.lang.Runnable",
        "    Thread          = java.lang.Thread",
        "    ThreadGroup     = java.lang.ThreadGroup",
        "    ThreadLocal     = java.lang.ThreadLocal",
        "    Character       = java.lang.Character",
        "    Byte            = java.lang.Byte",
        "    Short           = java.lang.Short",
        "    Integer         = java.lang.Integer",
        "    Long            = java.lang.Long",
        "    Float           = java.lang.Float",
        "    Double          = java.lang.Double",
        "    Random          = java.lang.Random",
        "    StrictMath      = java.lang.StrictMath");
    
      evalJS(js, // transfers all PConstants' to JS global scope.
        "void function () {", 
        "  for each (var f in PConstants.class.getFields()) {", 
        "    var name = f.getName(), field = PConstants[name]", 
        "    if (!this[name])  this[name] = field", 
        "  }", 
        "} ()");
    
      evalJS(js, // transfers all PApplet's static fields to JS global scope.
        "void function () {", 
        "  for each (var f in PApplet.class.getFields()) {", 
        "    var name = f.getName(), field = PApplet[name]", 
        "    if (field && !this[name])  this[name] = field", 
        "  }", 
        "} ()");
    
      evalJS(js, // transfers all PApplet's static methods to JS global scope.
        "void function () {", 
        "  for each (var m in PApplet.class.getDeclaredMethods()) {", 
        "    var name = m.getName(), method = PApplet[name]", 
        "    if (method && !this[name])  this[name] = method", 
        "  }", 
        "} ()");
    
      // Injects PApplet's non-static members to JS global scope:
      evalJS(js, "Object.bindProperties(this, p)");
    
      evalJS(js, // transfers JS' Math static properties to global scope.
        "void function () {", 
        "  for each (var prop in Object.getOwnPropertyNames(Math))", 
        "    if (!this[prop])  this[prop] = Math[prop]", 
        "} ()");
    }
    
    @SafeVarargs static final String evalJS
      (final ScriptEngine js, final String... statements) {
      if (statements == null)  return "";
    
      final String expression = PApplet.join(statements, PConstants.ENTER);
    
      try {
        js.eval(expression);
      }
      catch (final ScriptException cause) {
        PApplet.println(cause);
        System.err.println(expression);
        throw new RuntimeException(cause);
      }
    
      return expression;
    }
    
    @SafeVarargs static final CompiledScript compileJS
      (final ScriptEngine js, final String... statements) {
      final String expression = statements != null?
        PApplet.join(statements, PConstants.ENTER) : "";
    
      try {
        return ((Compilable) js).compile(expression);
      }
      catch (final ScriptException cause) {
        PApplet.println(cause);
        System.err.println(expression);
        throw new RuntimeException(cause);
      }
    }
    
    static final Object runJS
      (final CompiledScript compiled) {
      try {
        return compiled.eval();
      }
      catch (final ScriptException cause) {
        PApplet.println(cause);
        throw new RuntimeException(cause);
      }
    }
    
    @SafeVarargs static final Object invokeJS
      (final ScriptEngine js, final String funct, final Object... args) {
      try {
        return ((Invocable) js).invokeFunction(funct, args);
      }
      catch (final Exception cause) {
        PApplet.println(cause);
        System.err.println(funct);
        PApplet.printArray(args);
        throw new RuntimeException(cause);
      }
    }
    
Sign In or Register to comment.