# How to adapt a library for Instance Mode (P5JS)

**URL:** <https://discourse.processing.org/t/how-to-adapt-a-library-for-instance-mode-p5js/11775>\
**Category:** Development\
**Created:** [June 2, 2019, 12:50pm UTC](https://discourse.processing.org/t/how-to-adapt-a-library-for-instance-mode-p5js/11775 "2019-06-02T12:50:11Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![FreddieRa](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/freddiera/32/4078_2.png) [@FreddieRa](https://discourse.processing.org/u/FreddieRa)\
**Post date:** [June 2, 2019, 12:50pm UTC](https://discourse.processing.org/t/how-to-adapt-a-library-for-instance-mode-p5js/11775/1 "2019-06-02T12:50:11Z")

</div>

Hi there,

I have already written the [p5.3D](https://github.com/FreddieRa/p5.3D) library, for adding 3D text and images into WebGL, but currently this only works for Global Mode.

I’m not sure exactly what needs to be done, or how it needs to be reformatted, to make it work for Instance Mode. Has anyone else on here already converted a library to do this, or understands what is required?

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [June 2, 2019, 1:35pm UTC](https://discourse.processing.org/t/how-to-adapt-a-library-for-instance-mode-p5js/11775/2 "2019-06-02T13:35:35Z")

</div>

> [@FreddieRa](#):
>
> Has anyone else on here already converted a library to do this, or understands what is required?

Not some library, but separate class files, which request the sketch’s p5 instance reference as their 1st argument:  
[https://github.com/GoSubRoutine/Ball-in-the-Chamber/tree/master/instance/classes](https://github.com/GoSubRoutine/Ball-in-the-Chamber/tree/master/instance/classes)

Both classes Ball & Chamber store the sketch’s reference in their property _p_:  
[https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/classes/ball.js#L2-L10](https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/classes/ball.js#L2-L10)  
[https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/classes/chamber.js#L2-L8](https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/classes/chamber.js#L2-L8)

And then, access p5js’ API via that property _p_:  
[https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/classes/ball.js#L31-L34](https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/classes/ball.js#L31-L34)  
[https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/classes/chamber.js#L9-L12](https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/classes/chamber.js#L9-L12)

See that instance mode sketch in action at the link below:  
[GoSubRoutine.GitHub.io/Ball-in-the-Chamber/instance/](http://GoSubRoutine.GitHub.io/Ball-in-the-Chamber/instance/)

---

<div class="post-metadata">

**Author:** ![FreddieRa](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/freddiera/32/4078_2.png) [@FreddieRa](https://discourse.processing.org/u/FreddieRa)\
**Post date:** [June 2, 2019, 1:46pm UTC](https://discourse.processing.org/t/how-to-adapt-a-library-for-instance-mode-p5js/11775/3 "2019-06-02T13:46:25Z")

</div>

Right okay, but that means that in the instance mode, you’re calling the function and passing in the instance. In other libraries, the function can be called by the instance i.e.

> `var sketch = p5(function(p){p.setup(){...}; p.draw(){p.function(){}}})`

as opposed to

> `var sketch = p5(function(p){p.setup(){...}; p.draw(){function(p){}}})`

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [June 2, 2019, 7:47pm UTC](https://discourse.processing.org/t/how-to-adapt-a-library-for-instance-mode-p5js/11775/4 "2019-06-02T19:47:28Z")

</div>

> [@FreddieRa](#):
>
> , but that means that in the instance mode, you’re calling the function and passing in the instance.

- Not sure if I understood your example above. 😕
- Anyways, a p5js library needs to work whether a sketch is using global or instance mode. 👷‍♂️
- And a sure way to accomplish such flexibility is for the library to request the sketch’s p5 reference from its user. 📚
- As an example, take a look at how I instantiate classes Ball & Chamber: 🙈

[https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/sketch/sketch.js#L30-L31](https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/sketch/sketch.js#L30-L31)  
[https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/sketch/sketch.js#L33-L40](https://github.com/GoSubRoutine/Ball-in-the-Chamber/blob/2.0.5/instance/sketch/sketch.js#L33-L40)

- Even though the “sketch.js” above is using instance mode, if I decide to convert it to global mode, the 2 code blocks above would be exactly the same! 😳
- That is, classes Ball & Chamber work regardless the current mode a sketch is using, b/c they request the sketch’s reference as their 1st parameter! 🥳

---

<div class="post-metadata">

**Author:** ![FreddieRa](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/freddiera/32/4078_2.png) [@FreddieRa](https://discourse.processing.org/u/FreddieRa)\
**Post date:** [June 2, 2019, 8:06pm UTC](https://discourse.processing.org/t/how-to-adapt-a-library-for-instance-mode-p5js/11775/5 "2019-06-02T20:06:06Z")

</div>

I understand how you achieved that, though thank you for explaining, my previous comment was just saying that I don’t want to have to pass in the sketch’s references, and I know there are other ways to do it from what I have seen other libraries use. It is these methods that I want to implement.

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [June 3, 2019, 1:08am UTC](https://discourse.processing.org/t/how-to-adapt-a-library-for-instance-mode-p5js/11775/6 "2019-06-03T01:08:31Z")

</div>

> [@FreddieRa](#):
>
> , and I know there are other ways to do it from what I have seen other libraries use.

- 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:

```auto
"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:

```auto
class Canvas3D extends Object3D {
  constructor({ canvas, depth, size, resolution, bevelled }) {
    super({ p: canvas._pInst, depth, size, resolution, bevelled });
    this.canvas = canvas;
  }
}

```

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [June 3, 2019, 1:48am UTC](https://discourse.processing.org/t/how-to-adapt-a-library-for-instance-mode-p5js/11775/7 "2019-06-03T01:48:54Z")

</div>

- Now the solution you’re looking for: Not request the p5 object from your library’s user!
- You already know by now that directly instantiating classes using the keyword `new` can’t consistently get a sketch’s p5 object, unless they require it as their **constructor()**'s parameter.
- There are some workarounds though like p5._instance_, p5.Element:: **_pInst_** , p5.Vector::_p5_, etc.
- However, they’re all circumstantial and don’t work for all cases.
- What you need to do instead is adding an instantiator method in the class p5’s _prototype{}_ object.
- B/c it’s a p5 method, it automatically receives the p5’s object via the keyword `this` every time it’s invoked!
- That’s exactly how p5 methods like **createVector()**, **createCanvas()**, **createGraphics()**, **createElement()**, etc. work!
- They all instantiate a class in our place passing the p5’s `this` as 1 of the arguments behind-the-scenes.
- You’d only need to advice your library’s users to prefer those **createXXX()** methods rather than directly instantiating a class via `new`:

```javascript
p5.prototype.createWord3D(string, depth, size, resolution, bevelled, font, style) {
  return new Word3D({ p: this, string, depth, size, resolution, bevelled, font, style });
}

```

---

<div class="post-metadata">

**Author:** ![FreddieRa](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/freddiera/32/4078_2.png) [@FreddieRa](https://discourse.processing.org/u/FreddieRa)\
**Post date:** [June 3, 2019, 9:23pm UTC](https://discourse.processing.org/t/how-to-adapt-a-library-for-instance-mode-p5js/11775/8 "2019-06-03T21:23:12Z")

</div>

That’s awesome, thank you very much for your help on this. It now works exactly as intended, and the “create” syntax is nicer anyway since it’s closer to what already exists.

It can be found here: [https://github.com/FreddieRa/p5.3D](https://github.com/FreddieRa/p5.3D)
