I am trying to make a simple pyglet app (with Python 3.7) where I can draw a grid, some tiles, color them etc. While also being able to pan, zoom around, so I followed this question :
How to pan and zoom properly in 2D?
However the on_resize()
event of the MyWindow
subclass
seems to be called repeatedly after run()
is called, even if I don't touch the window, and the script crashes with a max recursion depth, except when I comment out its self.width = width
and self.height = height
lines.
But then resizing the window squishes the objects I'm drawing...
I would like resizing to just show more of the map, keeping the aspect ratio and size of drawn objects.
I have added some print()
calls to check what happens, but I'm truly at a loss with what's happening here.
import pyglet
from pyglet.gl import *
from algorithm.priorityqueue import PriorityQueue
from algorithm.squaregrid import heuristic, SquareGrid
ZOOM_IN_FACTOR = 1.2
ZOOM_OUT_FACTOR = 1/ZOOM_IN_FACTOR
class Triangle:
def __init__(self, color):
self.color = color
self.vertices = pyglet.graphics.vertex_list(3, ('v3f', [0,0,0, 1000,0,0, 1000,1000,0]),
('c4B', self.color*3))
def draw(self, x, y, z):
glTranslatef(x, y, z)
self.vertices.draw(GL_TRIANGLES)
glTranslatef(-x, -y, -z)
class Tile:
def __init__(self, size, color):
self.size = size
self.color = color
self.vertices = pyglet.graphics.vertex_list(
4, ('v3f', [0,0,0, 0+self.size,0,0,
0+self.size,0+self.size,0, 0,0+self.size,0]),
('c4B', self.color*4))
def draw(self, x, y, z):
glTranslatef(x, y, z)
self.vertices.draw(GL_QUADS)
glTranslatef(-x, -y, -z)
class Line:
def __init__(self, start, end, color, stroke):
self.color = color
self.stroke = stroke
self.sx, self.sy = start
self.ex, self.ey = end
self.vertices = pyglet.graphics.vertex_list(
2, ('v3f', [self.sx,self.sy,0, self.ex,self.ey,0]),
('c4B', self.color*2))
def draw(self):
glLineWidth(self.stroke)
self.vertices.draw(GL_LINES)
class MyWindow(pyglet.window.Window):
def __init__(self, width, height, *args, **kwargs):
conf = Config(sample_buffers=1,
samples=4,
depth_size=16,
double_buffer=True)
super().__init__(width, height, config=conf, *args, **kwargs)
#self.set_minimum_size(960, 540)
#glClearColor(0.8, 0.8, 0.8, 1.0)
#glOrtho(0, self.width, 0, self.height, -10, 10) # setup orthogonal projection
self.left = 0
self.right = width
self.bottom = 0
self.top = height
self.zoom_level = 1
self.zoomed_width = width
self.zoomed_height = height
print("init finished")
def init_gl(self, width, height):
print("init_gl started")
# Clear color
glClearColor(255/255, 255/255, 255/255, 255/255)
# Antialiasing
glEnable(GL_LINE_SMOOTH)
glEnable(GL_POLYGON_SMOOTH)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
# Alpha Blending
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
# Viewport
glViewport(0, 0, width, height)
def drawstuff(self):
print("drawstuff called")
self.triangle = Triangle((255, 0, 0, 255))
self.square = Tile(10, (255,0,255,255))
self.gridlines = []
for j in range(0,25):
self.gridlines.append(Line((0, 40*j),(1000, 40*j),(50,50,50,255), 2))
for i in range(0,25):
self.gridlines.append(Line((40*i, 0),(40*i, 1000),(50,50,50,255), 2))
def on_resize(self, width, height):
print("on_resize called")
# It crashes here!
self.width = width
print(width)
self.height = height
print(height)
self.init_gl(width, height)
def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
# Move camera
self.left -= dx*self.zoom_level
self.right -= dx*self.zoom_level
self.bottom -= dy*self.zoom_level
self.top -= dy*self.zoom_level
def on_mouse_scroll(self, x, y, dx, dy):
# Scale factor
f = ZOOM_IN_FACTOR if dy<0 else ZOOM_OUT_FACTOR if dy>0 else 1
# If in proper range
if .2 < self.zoom_level*f < 5:
self.zoom_level *= f
print(self.width, self.height)
mouse_x = x/self.width
mouse_y = y/self.height
mouse_x_in_world = self.left + mouse_x * self.zoomed_width
mouse_y_in_world = self.bottom + mouse_y * self.zoomed_height
self.zoomed_width *= f
self.zoomed_height *= f
self.left = mouse_x_in_world - mouse_x * self.zoomed_width
self.right = mouse_x_in_world + (1 - mouse_x) * self.zoomed_width
self.bottom = mouse_y_in_world - mouse_y * self.zoomed_height
self.top = mouse_y_in_world + (1 - mouse_y) * self.zoomed_height
def on_draw(self):
print("draw called")
# Init projection matrix
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
# Init Modelview matrix
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
# Save default modelview matrix
glPushMatrix()
# Clear window with ClearColor
glClear(GL_COLOR_BUFFER_BIT)
# Set Orthographic projection matrix
glOrtho(self.left, self.right, self.bottom, self.top, 1, -1)
#self.draw_background()
self.triangle.draw(0, 0, 0)
self.square.draw(-100, -100, 0)
for line in self.gridlines:
line.draw()
# Remove default modelview matrix
glPopMatrix()
def run(self):
print("run called")
pyglet.app.run()
print("run finished")
if __name__ == "__main__":
App = MyWindow(800, 500, resizable=True)
App.drawstuff()
App.run()
And the console shows :
$ python3 environments/testapp.py
init finished
drawstuff called
run called
on_resize called
on_resize called
on_resize called
on_resize called
on_resize called
etc. with at some point :
on_resize called
on_resize called
Traceback (most recent call last):
File "environments/testapp.py", line 185, in <module>
App.run()
File "environments/testapp.py", line 177, in run
pyglet.app.run()
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/app/__init__.py", line 107, in run
event_loop.run()
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/app/base.py", line 159, in run
self._legacy_setup()
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/app/base.py", line 182, in _legacy_setup
window.dispatch_pending_events()
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/window/xlib/__init__.py", line 914, in dispatch_pending_events
EventDispatcher.dispatch_event(self, *self._event_queue.pop(0))
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/event.py", line 415, in dispatch_event
if getattr(self, event_type)(*args):
File "environments/testapp.py", line 110, in on_resize
self.width = width
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/window/__init__.py", line 964, in width
self.set_size(new_width, self.height)
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/window/xlib/__init__.py", line 574, in set_size
self.dispatch_event('on_resize', width, height)
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/window/__init__.py", line 1323, in dispatch_event
if EventDispatcher.dispatch_event(self, *args) != False:
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/event.py", line 415, in dispatch_event
if getattr(self, event_type)(*args):
File "environments/testapp.py", line 110, in on_resize
self.width = width
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/window/__init__.py", line 964, in width
self.set_size(new_width, self.height)
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/window/xlib/__init__.py", line 574, in set_size
self.dispatch_event('on_resize', width, height)
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/window/__init__.py", line 1323, in dispatch_event
if EventDispatcher.dispatch_event(self, *args) != False:
With the last 10 lines repeating for a while, and at the end :
if EventDispatcher.dispatch_event(self, *args) != False:
File "/home/admin/.local/lib/python3.7/site-packages/pyglet/event.py", line 415, in dispatch_event
if getattr(self, event_type)(*args):
File "environments/testapp.py", line 108, in on_resize
print("on_resize called")
RecursionError: maximum recursion depth exceeded while calling a Python object
I find it weird that run()
is calling on_resize()
on its own, and I really have no clue as to why reassigning the attributes self.width and self.height is entering a recursion.
It also crashes when the value assigned is not width or height, but any constant number as well, and also whether the Window instance is passed resizable = True
or = False
as argument