How to adapt a library for Instance Mode (P5JS)

  • Yes, there is a way to do it. But not when using the keyword new.
  • And guess what: p5js keeps a secret property when global mode is active → p5.instance.
  • You can write your classes’ constructor to request a p5 object, but fallback to p5.instance in case your library’s user decided not to pass it.
  • Something like this: this.p = p instanceof p5 && p || p5.instance;
  • I’ve refactored your classes Object3D & Word3D’s constructors to do just that:
"use strict";

class Object3D {
  constructor({ p, depth=1, size=1, resolution=1,
                bevelled=false, threshold=60 }) {
    this.p = p instanceof p5 && p || p5.instance;

    this.depth = +depth;
    this.size = +size;
    this.resX = this.resY = +resolution;
    this.bevelled = bevelled;
    this.threshold = +threshold;

    this.edges = Int32Array.of(resolution, 0);
  }
}

class Word3D extends Object3D {
  constructor({ p, string='', depth, size, resolution, bevelled=true, 
                font='Times New Roman', style='bold' }) {
    super({ p, depth, size, resolution, bevelled, threshold: 160 });

    this.string = string.split('').join(String.fromCharCode(8202));
    this.stringLength = string.length;

    this.font = font;
    this.style = style;
  }
}
  • Another trick is that some p5js classes secretly store the sketch’s p5 object!
  • For example: class p5.Element has hidden property _pInst.
  • While class p5.Vector has hidden property p5.
  • Possibly, other p5js classes may do the same, but I didn’t fully research them all yet.
  • Your class Canvas3D happens to require a p5.Graphics object as parameter canvas.
  • The p5.Graphics is a subclass of p5.Element.
  • Therefore, it’s got the hidden property p5.Element::_pInst too!
  • So we can rewrite Canvas3D::constructor() to grab a p5 via a p5.Graphics object like this:
class Canvas3D extends Object3D {
  constructor({ canvas, depth, size, resolution, bevelled }) {
    super({ p: canvas._pInst, depth, size, resolution, bevelled });
    this.canvas = canvas;
  }
}
1 Like