-
-
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] State machines and renderer refactoring #7270
Conversation
@davepagurek Following on what we discussed regarding the renderer, I've set up an implementation of the renderer state machine here. For 2D most of the things are working since it is relatively simple, for WebGL however it seems there are some states not being tracked correctly, causing tests to fail. |
oops I resolved the merge conflicts with the dev-2.0 updates, but that also brought in some more bits that I need to convert to use states. I'll push another commit soon |
Some properties and methods of p5 instance still need to be taken cared of. Remove references to DOM in constructor.
This need to be refactored out eventually as many don't make sense being on p5.Graphics
@davepagurek I don't want to change too much of WebGL at the moment seeing that you and others are also working on it so I can't fix all the WebGL tests. The main failure is likely linked to p5.Framebuffer and possibly also the WebGL filters. The overall code is still a bit too spaghetti, I'll try to get things a bit more streamlined but have a busy period coming up so I'll see how much I can complete. I've added some notes below regarding things that eventually should be implemented, let me know if they don't make sense. Let me know if discussing over a call is easier as well.
|
I just thought of a possible idea for p5.Graphics, perhaps I can leverage the new module API where it is a function taking in the signature of |
Move "push()" and "pop()" functions to core/transform module
Also WebGL methods are not attached to p5.Graphics yet as they need to use the new module syntax, @davepagurek do you have an idea of around when would be a good point to do that conversion for WebGL? Probably need to align with other things going on so we don't convert in the middle of someone's work. Another thing is that not everything make sense to attach to p5.Graphics, with a general guideline being only renderer related stuff should be attached, other environment related stuff should use the p5 instance version (eg. constants, framerates, data loading, interactions, objects such as p5.Color so probably also p5.Texture etc as well). |
@limzykenneth Luke's project should be wrapping up this week, so that could potentially be a good point to start? But also if we're mostly renaming properties and maybe moving where they're defined, I can resolve any conflicts that come up with Luke's and Garima's projects if this is in the way of more refactor work. |
took a while to find the cause of the masking bugs, but the cause of that one was the ordering of It turned out to not be the underlying cause, but I also refactored |
I don't think |
Sounds good, I've moved it earlier so I'll just keep it there. What do you think about having a separate |
From what I can see in the implementation, |
Right now it acts kind of like an interface that anything that supports loadPixels conforms to to be able to share a 2D loadPixels implementation. So right now it's kind of like this: interface SupportsPixels {
pixelsState: {
_pixelDensity: number
width: number
height: number
drawingContext: CanvasRenderingContext2D
pixels: Uint8ClampedArray
imageData?: ImageData // Cached image data after loadPixels called
}
} And then things that have this reuse the 2D renderer's Lines 457 to 460 in 60dbf86
So if we want to keep using that pattern, p5.js/src/core/p5.Renderer2D.js Lines 21 to 28 in 60dbf86
...but now, I think Since graphics and the main canvas both have a |
The For p5.Image it has most of the For p5 instance, it won't need to implement |
I think one thing we'll need is a way for the renderer to "reach out" to the thing that owns it to set its I've added that, and caught a few cases where the renderer had a property with the same name as a main instance function (e.g. There are a few tests still failing that have to do with |
Actually, this approach works for now but it means a lot more things are now leaked into the global scope that probably shouldn't be, e.g. I'm going to just make it expose |
I don't know how much of the renderer we need to expose to the instance beyond Basically what I think would be nice is that global variables like I believe |
this.push(); | ||
this.resetMatrix(); | ||
this.clear(); | ||
this.states.imageMode = constants.CORNER; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out the updatePixels problems were because setting the imageMode to CENTER does nothing when calling this.image
as opposed to the user-exposed image()
. I think that's fine, and actually probably for the best that our internal implementations depend less on state, but we should watch out for more cases like this left over from before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically we also don't need this line since it'll use corner mode regardless. Might be worth keeping for clarity, although then it's misleading because it looks like something that you can change when you actually can't. Maybe I should remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that should be removed if it's doing nothing, I kept it around because I didn't know if it was actually needed or not and I just translated from what was before.
Ok last webgl test was because it was accessing a constant from a graphic, which is now undefined. Tests are all green on my end now! |
Do you think there would be a case where a new renderer, e.g. SVG, would want to add new state visible to the end user? If so, it might make sense to make a way for the renderer itself to define what gets exposed (could be as simple as doing |
Two failed on my end that looks like single pixel and off by one error
If you can do a rebase and push it should run here on CI then we can check here. |
That could be a thing but probably need to be a slightly more elaborate API as the renderer implementer might want to set both the getter and setter. |
Rebasing now |
@davepagurek All tests passed in CI! Shall we merge this in then you can start working on additional WebGL refactoring while I work on some more details stuff to make internal API clearer? |
Awesome! Sounds good, thanks for doing that rebase! |
Renderer state machine
The base
p5.Renderer
class will provide astates
property that will keep track of all states within the renderer that are affected bypush()
andpop()
. The base version looks like the following:Each renderer that extends
p5.Renderer
should add any additional states to thestates
properties when it should be affected bypush()
andpop()
, eg.this.states.someState = 'someValue'
. The base implementation ofpush()
andpop()
will keep track of the states withpush()
pushing a copy of the current state into an array thenpop()
restores the last saved state in the array to the renderer's current state. (See line comments for a bit more details below)The individual renderer should call
super.push()
andsuper.pop()
in their own implementation ofpush()
andpop()
in addition to acting on the necessary changes in states.OOP hierachy
The previous hierachy has
p5.Element
as the base class whichp5.Renderer
extends andp5.Renderer2D/GL
again extends. This means all renderer are assumed to have ap5.Element
backing. Part of the changes made here is to remove this assumption sop5.Renderer
can be extended into renderers that does not render to a HTML element.Eventually, the individual renderers
p5.Renderer2D
andp5.RendererGL
will have their own reference top5.Element
that they can operate through.Overall event handling is still something that needs to be think through for this case though.
Global mode
_setProperty()
is no longer used. Global variables will now all be using getters that refers to the value in the p5 instance.Pending global functions to be attached in the same way.