Я пытаюсь создать простое приложение pyglet (с Python 3.7), где я могу нарисовать сетку, несколько плиток, раскрасить их и т. Д. c. Также имея возможность панорамирования, увеличивать масштаб, я следовал за этим вопросом:
Как правильно панорамировать и масштабировать в 2D?
Однако событие on_resize()
подкласс MyWindow
, кажется, вызывается повторно после вызова run()
, даже если я не касаюсь окна, и сценарий падает с максимальной глубиной рекурсии , за исключением случаев, когда я закомментирую его self.width = width
и self.height = height
строки. Но затем изменение размера окна приводит к сжатию объектов, которые я рисую ...
Я бы хотел изменить размеры, чтобы просто показать больше карты, сохраняя соотношение сторон и размер нарисованных объектов.
I Я добавил print()
вызовов, чтобы проверить, что происходит, но я действительно в растерянности, что происходит здесь.
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()
И консоль показывает:
$ 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
et c. с каким-то моментом:
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:
С последними 10 строками, повторяющимися некоторое время, и в конце:
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
Я нахожу странным, что run()
вызывает on_resize()
сам по себе, и я действительно понятия не имею, почему переназначение атрибутов self.width и self.height входит в рекурсию.
Также происходит сбой, когда назначенное значение не ширина или высота, а любое постоянное число, а также передается ли экземпляр Window resizable = True
или = False
в качестве аргумента