Using background and size in setup would not set the background to the specified color
tushar5526 opened this issue · 11 comments
Each size
calls creates a new surface and a new canvas. Any path drawn on the old canvas would be lost.
from p5 import *
def setup():
size(600,340)
background(220)
def draw():
circle(mouse_x, mouse_y, 50)
run(renderer='skia')
Background not set to 220
in former sketch
from p5 import *
def setup():
# size(600,340) -> removed size, no new surface and canvas created so it would work as expected
background(220)
def draw():
circle(mouse_x, mouse_y, 50)
run(renderer='skia')
Users can use the workaround for now like this, by the time it gets fixed.
def draw():
if frame_count == 1:
background(220)
Hey @tushar5526 ,
What I found was, the issue is not just with size()
and background()
being together in setup()
but with any 2D Primitive
when called after size() in setup(), are not visible (probably covered).
The following code will also not work as it is supposed to:
from p5 import *
def setup():
size(512,512)
circle(100,100,50)
run() # Also with run(renderer="skia")
This is quite different from from p5.js , is this something peculiar for p5py and I am missing a reference or there is an issue with size()
here?
Yes, as p5py is in its beta version there are a lot of bugs like this to be fixed. You can start an issue and start working on it. For 2D renderers I would prefer that you also try skia renderer and priortize that for fixes related to 2D renderer.
run(renderer='skia')
@tushar5526 really sorry for the late response, was a little occupied. I have created a new issue for the same and would love to work on it. Should I go ahead?
yes
Hello!
I've investigated this a bit, and when size()
is called in setup()
, the reason why background()
or ellipse()
or any function that would draw to the screen doesn't work is that:
- It actually does work. Initially, these functions do take effect on the window and you'd see the result (only momentarily, though).
- Then, right after the
setup()
function returns, thepoll_events()
method is called (here: https://github.com/p5py/p5/blob/master/p5/sketch/Skia2DRenderer/base.py#L162), which then eventually triggers theframe_buffer_resize_callback_handler()
callback. This is because we set a new size insetup()
- This callback makes a call to the
create_surface()
method (here: https://github.com/p5py/p5/blob/master/p5/sketch/Skia2DRenderer/base.py#L215), which in turn callsp5.renderer.initialize_renderer()
, which in turn calls theSkiaRenderer2D.clear()
method. This method clears the window and makes it completely black. So no graphics drawn onto it previously would survive.
Possible solution:
The reason the window is getting cleared is because poll_events()
is being called after all the graphics in setup()
were drawn to the screen. What if we call poll_events()
right after the size()
method is called (and before any other function is called in setup()
by the user)?
I tried calling p5.sketch.poll_events()
at the end of the size()
function (here: https://github.com/p5py/p5/blob/master/p5/sketch/userspace.py#L247), and it works! Somewhat...
One caveat is that you must call size()
before any function that draws to the window in setup()
.
Another one is that the same problem occurs if the user manually resizes the window. In this case, it is inevitable for the window resize event to get triggered and the window will get cleared.
I feel like this behavior might be acceptable? I'd very much like to hear your views on this @tushar5526.
This solution works very well for cases where the user doesn't want to create a dynamic sketch, and if the user calls background()
in draw()
every frame, then this issue wouldn't persist anyway.
Let me know your thoughts on this "fix"! I could totally write a comment and create a pull request with the fix described above.
Or if you feel like this isn't satisfactory enough, that's cool too! Let's brainstorm this further 🙂
Hey @procub3r thanks for the detailed explanation.
What if we call poll_events() right after the size() method is called (and before any other function is called in setup() by the user)?
Processing focuses a lot on abstracting out implementation details, I think we should not assume that users who come from p5.js will find it easy to wrap their heads around it.
One caveat is that you must call size() before any function that draws to the window in setup().
We are taking p5.js as our benchmark performance and functionality to reach in the future. p5.js does not restrict calling size at a certain position.
There is a PR in progress for this issue, I would like your review on #420 and think of edge cases to the solution.
Looks like p5.js also works in a similar way. When you call either createCanvas()
or resizeCanvas()
after drawing to the screen in setup()
, none of the graphics drawn are displayed on the window.
It works when you call these functions in setup()
before drawing any graphics though.
Of course there is no restriction as to where you can call resizeCanvas()
. It's just that any graphics currently drawn to the canvas will be cleared.
This is the same behavior that my proposed solution provides.
I may be missing something here. Could you please look into this? @tushar5526
This is what I mean:
p5jsdemo.mov
Processing focuses a lot on abstracting out implementation details, I think we should not assume that users who come from p5.js will find it easy to wrap their heads around it.
The user code will remain unchanged of course. The call to poll_events()
will take place in the implementation of the size()
function.
Fixed by #446