Instance mode over multiple files

Hi,

I'm writing some sketches in p5 using instance mode. Some of them are getting pretty big, so I was wondering if there was any way to move some of the functionality into multiple files. My initial attempt was to move all the mouse event functions into another file, then import it into the main sketch file and call a function to register them:

test.js:

import registerFunctions from './mouseHandler.js';
let sketch = function(p5) {

  var a = 5;

  p5.setup = function() {
    ...
    registerFunctions(p5);
  };

  p5.draw = function() {...};
};

let p5Sketch = new p5(sketch , 'canvas-holder');

mouseHandler.js:

function _mousePressed() {
  console.log(a); // Obviously wont work
}

export default function registerInputFunctions(p5) {

    p5.mousePressed = _mousePressed;
}

My obvious issue is that I can't access the inner variables from test.js, so this method wont be very useful. So is there any way I can split the sketch into multiple files and somehow access the variables in the sketch from each of the other files?

Thanks in advance :)>-

Answers

  • edited July 2017 Answer ✓
    • Your variable a was declared in function sketch().
    • Therefore, only its inner functions setup() & draw() can access var a as a closure.
    • So, given _mousePressed() isn't an inner function of sketch(), the former can't access the latter's var a closure. :(
    • However, you can workaround that by assigning your var a as a property of p5 as well, just like setup() & draw() already are; effectively exporting them all: :ar!
    • Then you can access it via this within your imported mousePressed(). *-:)

    http://Bl.ocks.org/GoSubRoutine/ce702dbf832b11732ddae6b7c7d49f9d

    index.html:

    <script defer src=http://CDN.JSDelivr.net/npm/p5></script>
    <script defer src=mouseHandler.js></script>
    <script defer src=sketch.js></script>
    

    mouseHandler.js:

    "use strict";
    
    var imports;
    
    void function (imports) {
      function mousePressed() {
        const inc = this.mouseButton === this.LEFT && -1 || 1;
        this.a = this.constrain(this.a + inc, -1, 100);
        console.log(this.a);
        this.redraw();
      }
    
      imports.mousePressed = mousePressed;
    }(imports || (imports = {}));
    

    sketch.js:

    /**
     * Instance Mode Multi-Files (v1.7.1)
     * GoToLoop (2017-Jul-26)
     *
     * Forum.Processing.org/two/discussion/23580/
     * instance-mode-over-multiple-files#Item_1
     *
     * Bl.ocks.org/GoSubRoutine/ce702dbf832b11732ddae6b7c7d49f9d
     */
    
    "use strict";
    
    void function () {
      const s = new p5(p => {
        let a = ~~p.random(100);
        Object.defineProperty(p, 'a', {
          get() { return a; }, set(n) { a = n; },
          enumerable: true, configurable: false
        });
    
        p.setup = function () {
          this.createCanvas(300, 200);
          this.noLoop();
          this.colorMode(this.RGB).blendMode(this.BLEND);
          this.fill('yellow').stroke('red').strokeWeight(2.5);
          this.textAlign(this.CENTER, this.CENTER).textSize(0o200);
        };
    
        function draw() {
          this.background('#' + this.hex(~~this.random(0x1000), 3));
          this.text(a, this.width>>1, this.height>>1);
        }
        p.draw = draw.bind(p);
      }, 'canvas-holder');
    
      s.mousePressed = imports.mousePressed;
    }();
    
  • @GoToLoop Can you comment in the difference between p.draw = draw.bind(p); and p.draw = function () { .... }. Do I need to use bind here in this case?

    Kf

  • edited August 2017 Answer ✓
    • In JS, by default, current this inside a function refers to the object which had invoked it. ~O)
    • Within p5.js library, functions setup(), mousePressed(), etc., are called back by the p5's instance object itself. B-)
    • Therefore, if we use this inside those callbacks, that this is an instance of class p5 of the current sketch. :>
    • However, callback draw() seems like an exception; some ugly inconsistent glitch there! @-)
    • Somehow, whatever object is calling back draw(), isn't an instance of class p5! 8-}
    • That's why I had to use bind() in order to permanently force draw()'s this to refer to current p5's instance object, represented by closured parameter p. :ar!
    • Either bind() it or rewrite draw() to use parameter p in place of this: :-@

    p.draw = function () {
      p.background('#' + p.hex(~~p.random(0x1000), 3));
      p.text(a, p.width>>1, p.height>>1);
    };
    
  • Thxs @GoToLoop for your comments.

    kf

Sign In or Register to comment.