-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[p5.js 2.0] WebGL module syntax #7296
[p5.js 2.0] WebGL module syntax #7296
Conversation
Sounds good, I guess technically we can set arbitrary properties on functions, right? If we want something like multiple exports, we could maybe attach the classes to the module function itself, e.g.: function texture(p5, fn) {
p5.Texture = texture.Texture;
p5.MipmapTexture = texture.MipmapTexture;
// ...
}
texture.Texture = class Texture { /* ... */ };
texture.MipmapTexture = class MipmapTexture extends texture.Texture { /* ... */ };
export default texture; ...but yeah we might need |
Setting the class definition on the function as a property probably still won't work as it is also effectively defining the class outside of the library syntax. ie. texture.Texture = class Texture { /* ... */ }; within Conventional multiple exports will work fine even when there are default export, but the scope is more of an issue here. For attaching new renderers, the syntax is as follows: function newRenderer(p5, fn) {
p5.renderers["new-renderer"] = NewRendererClass;
} where function setup(){
createCanvas(400, 400, "new-renderer"); // Matching the property key used to attach the renderer class
} However, if there is a need again to have both the class definition available for things like |
ahh I see. One option could be to go with a dependency injection sort of approach, where classes that need p5 expect to have it injected as their first parameter. Something like, if you define your class like this: class Texture {
constructor(p5, arg1, arg2) {
this.p5 = p5
}
} then expose a p5-style function texture(p5, fn) {
fn.createTexture = function(arg1, arg2) {
return new Texture(p5, arg1, arg2)
}
} I think that would let us make classes extend other classes without immediately having the p5 instance, e.g.: class MipmapTexture extends Texture {
constructor(p5, arg1, arg2) {
super(p5, arg1, arg2)
}
}
// ...
fn.createMipmapTexture = function(arg1, arg2) {
return new MipmapTexture(p5, arg1, arg2)
} We'd lose out on some simplicity though, and it would make the |
A solution that seems to work but I'm still not sure I like it is this: let MipmapTextureBinding;
function texture(p5, fn){
p5.Texture = class Texture {}
MipmapTextureBinding = class MipmapTexture extends p5.Texture {}
}
export {
MipmapTextureBinding as MipmapTexture
};
export default texture; |
Right, I guess that comes with the implicit understanding that you'll call |
Ah no, this is the library syntax file, the |
I guess to summarize a bit, there are three possible solutions (all written below with
function texture(p5, fn){
p5.Texture = class Texture { /* ... */ }
p5.MipmapTexture = class MipmapTexture extends p5.Texture { /* ... */ }
}
export default texture;
class Texture {
constructor(p5, arg1, arg2) {
this.p5 = p5
}
}
class MipmapTexture extends Texture {
constructor(p5, arg1, arg2) {
super(p5, arg1, arg2)
}
}
function texture(p5, fn){
fn.createTexture = function(arg1, arg2) {
return new Texture(p5, arg1, arg2)
}
fn.createMipmapTexture = function(arg1, arg2) {
return new MipmapTexture(p5, arg1, arg2)
}
}
export default texture;
export { Texture, MipmapTexture }; // For use with `instanceof`
let MipmapTextureBinding;
function texture(p5, fn){
p5.Texture = class Texture {}
MipmapTextureBinding = class MipmapTexture extends p5.Texture {}
}
export {
MipmapTextureBinding as MipmapTexture
};
export default texture; Each have their tradeoffs,
@davepagurek Not sure if there is still another option but do you have a preference otherwise? |
I've come up with an adjusted version of solution 3 that can partially address its problem: let MipmapTextureBinding = new Proxy(function(){}, {
construct(){
console.error('You are trying to access an export value before it is initialized. Please initialize the library file using `p5.registerAddon` before using this export value.');
return undefined;
}
});
function texture(p5, fn){
p5.Texture = class Texture {}
MipmapTextureBinding = class MipmapTexture extends p5.Texture {}
}
export {
MipmapTextureBinding as MipmapTexture
};
export default texture; This instead of creating confusion in case someone try to use the exported @davepagurek If you have a moment can you see if you have any preference around these? I can implement it then merge it in before I continue work on the p5.Graphics stuff. |
Sorry I missed your earlier comment! I don't have a super strong preference either way, but I think I generally prefer the first two options for how much easier to understand they are -- scope of variables, especially changing or reassignment of those variables, is a pretty confusing part of JavaScript for newcomers, and it feels like that + a fallback proxy adds a lot of cognitive overhead for making a class. The downside of options 1 and 2 is that they're not really private. I think this is maybe not the worst thing, since we don't document it, and it lets interested advanced users do custom things if they're interested, similar to how a lot of people still access |
I think in this case I would prefer option 1 for consistency sake as it puts it in the same ballpark as |
@davepagurek Most of the files are converted to use the new syntax but there are a few snagging issues remaining:
p5.DataArray
seems largely internal, although they do have a public documentation, are they public API? If not they can have the same treatment as theGeometryBuilder
class as a standalone class without being attached top5
.MipmapTexture
class have a compatibility issue with the new system. Atexport
time, there is notp5
available forMipmapTexture
to be able to extendp5.Texture
, we can move theclass Texture
into the file scope (ie. not in the new library syntaxfunction(p5, fn){...
) but theTexture
class itself needs a reference top5
at definition which is only available in the new library syntax function. We also cannot exportMipmapTexture
from the library syntax function since export need to be at root. I'm not sure what would be the best way to handle this so if you have some ideas that would be great.p5.RendererGL
class might needp5.Texture
to be solved first and I think you were mentioning wanting to refactor this part. I'll defer this one for now as I also have not convertedp5.Renderer2D
so there's no rush to do it just yet.