Issue with using PShapes in py5

Hello everyone!
I have started to use py5, and I love it, especially the way it’s a python library and the way to handle vectors. Good job and thank you to everyone here who created or contributed to this project.

I have an issue when trying to use the equivalent of pshapes. I tried the examples in the documentation, but encounter the same issue.

def setup():
    global s  # the Py5Shape object
    # creating the Py5Shape as a square. the
    # numeric arguments are similar to rect().
    s = py5.create_shape(py5.RECT, 0, 0, 50, 50)
    s.set_fill("#0000FF")
    s.set_stroke(False)


def draw():
    py5.shape(s, 25, 25)

This example works fine. The problem appears when I try to use create_shape() without an argument, like in the following example.

    s = py5.create_shape()
    s.begin_shape(py5.TRIANGLE_STRIP)
    s.vertex(30, 75)
    s.vertex(40, 20)
    s.vertex(50, 75)
    s.vertex(60, 20)
    s.vertex(70, 75)
    s.vertex(80, 20)
    s.vertex(90, 75)
    s.end_shape()

I get the error that s is not defined, when it’s exactly the same code as the first example.

When I try to declare the shape outside of setup, I get this one:

Traceback (most recent call last):
File “PApplet.java”, line 11139, in processing.core.PApplet.createShape
Exception: Java Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File “F:/xxx/test_pshape.py”, line 29, in
s = py5.create_shape()
File “C:\Users\xxx\anaconda3\envs\py5coding\lib\site-packages\py5_init_.py”, line 5688, in create_shape
return py5sketch.create_shape(*args)
File “C:\Users\xxx\anaconda3\envs\py5coding\lib\site-packages\py5\shape.py”, line 45, in decorated
result = f(self
, *args)
File “C:\Users\xxx\anaconda3\envs\py5coding\lib\site-packages\py5\sketch.py”, line 7130, in create_shape
return self._instance.createShape(*args)
java.lang.NullPointerException: java.lang.NullPointerException

Process finished with exit code 1

Could anyone help me? I’m using anaconda and used the command described on the documentation to install an environment.

Info : conda 4.11.0
python 3.9.7
openjdk version “11.0.8” 2020-07-14 LTS
OpenJDK Runtime Environment Zulu11.41+23-CA (build 11.0.8+10-LTS)
OpenJDK 64-Bit Server VM Zulu11.41+23-CA (build 11.0.8+10-LTS, mixed mode)
Windows 10

2 Likes

Cheers @Setsuna !

I have tried first without the TRIANGLE_STRIP argument and then adding it and it still worked for me :frowning:

See if you can see any difference in my code. Otherwise we could open an issue at the py5 repo!


image

import py5

def setup():
    global s
    py5.size(200, 200)
    s = py5.create_shape()
    s.begin_shape(py5.TRIANGLE_STRIP)
    s.fill(0, 0, 255)
    s.vertex(0, 0)
    s.vertex(0, 100)
    s.vertex(50, 0)
    s.vertex(50, 100)
    s.end_shape(py5.CLOSE)


def draw():
    py5.shape(s, 25, 25)

py5.run_sketch()
2 Likes

Yes, your code does work and it’s been making me crazy until I realized the issue. It’s just that in the documentation example that I pasted, the “global s” declaration is not the first line of the function.

def setup():
    py5.size(100, 100, py5.P2D)
    global s
    s = py5.create_shape()
    s.begin_shape(py5.TRIANGLE_STRIP)
    s.vertex(30, 75)
    s.vertex(40, 20)
    s.vertex(50, 75)
    s.vertex(60, 20)
    s.vertex(70, 75)
    s.vertex(80, 20)
    s.vertex(90, 75)
    s.end_shape()


def draw():
    py5.shape(s, 0, 0)

I’m going to suggest an edit in the doc. Thank you for taking the time @villares

2 Likes

Oh! This is a bug in py5 that is going to be fixed soon!

It has to do with some magic done under the hood to create a settings() function containing the size() invocation. The Processing IDE does the same thing for Processing Python mode, and I think it is a good thing for making code simpler to beginners… I’m sorry this almost drove you crazy :frowning:

I’m happy you could make it work! :smiley:

2 Likes

Oh nice find!
I already noticed the settings/setup and size gave weird results sometimes.
And it’s always good to have something that makes you think, even when it makes you a bit crazy.

However there still is something I don’t get. Why doesn’t the code work if I put the whole create shape thing outside of setup?

import py5

s = py5.create_shape()
s.begin_shape()
s.vertex(30, 75)
s.vertex(40, 20)
s.vertex(50, 75)
s.vertex(60, 20)
s.vertex(70, 75)
s.vertex(80, 20)
s.vertex(90, 75)
s.end_shape()

def settings():
    py5.size(100, 100)

def draw():
    py5.shape(s, 0, 0)

py5.run_sketch()

1 Like

Could you just use imported mode? And drop the draw() function (because there’s no animation) –

size(100, 100)

s = create_shape()
s.begin_shape()
s.vertex(30, 75)
s.vertex(40, 20)
s.vertex(50, 75)
s.vertex(60, 20)
s.vertex(70, 75)
s.vertex(80, 20)
s.vertex(90, 75)
s.end_shape()

shape(s, 0, 0)

This runs fine for me using the run_sketch command line tool / thonny-py5mode plugin.

1 Like

Yes of course I could use that, this was a simplified example to pinpoint the problem.
I have a more complicated project where I tried to use pshape in a class, and I initiated the classes outside of setup, which led to the same bug. When I put this part in setup, it works. I just don’t understand whether I’m doing something wrong or if it’s a bug.

1 Like

I’m not sure why, but I think it makes some intuitive sense for me, let me try to put it this way:
Many many things in Processing do not work before the environment is “properly set” after size() has been called setting the proper renderer (the default one, or P2D or P3D). So after some years using Python mode I “kind of learned” not to invoke any major Processing feature outside/before setup(), as things usually don’t work well. Last time I got burned (multiple times, by the way) was the function that tells you the sketch path…

2 Likes

To @villares’ point, this wouldn’t work in Processing.py either, so not really a bug or something wrong. The following produces an error (NullPointerException at …) using Python Mode:

s = createShape()
s.beginShape()
s.vertex(30, 75)
...
s.endShape()

def setup():
    size(100, 100)

def draw():
    shape(s, 0, 0)

Glad to hear you’re loving py5 :smiley:

2 Likes

Thank you @villares and @tabreturn, this makes sense!

1 Like