batch drawing problem with resizable frame

82 views
Skip to first unread message

Jens Neumann

unread,
Dec 8, 2019, 6:04:52 PM12/8/19
to pyglet-users
Hello everyone,

I'm new to python and pyglet in general. Right now I'm trying to build a very simple GUI and I came accross an issue with batch drawing.

I want to draw a menu bar at the top of a pyglet window and i want to use batch drawing. Below is a code sample for you to reproduce my issue. A rectangle and a line will be drawn. The problem accures when I resize this window, the width and height of this rectangle and line will be updated, but also its former position will be visible.

import pyglet
from pyglet.gl import *

batch = pyglet.graphics.Batch()
background = pyglet.graphics.OrderedGroup(0)
foreground = pyglet.graphics.OrderedGroup(1)

class Edit_Window(pyglet.window.Window):
def __init__(self,*args,**kwargs):
super().__init__(*args, **kwargs)
self.menu_bar_height = 40
glClearColor(1.0, 1.0, 1.0, 1.0)

def menu_bar(self):
self.indices = [0, 1, 2, 2, 3, 1]
self.vertex = [0,self.height,
0,(self.height - self.menu_bar_height),
self.width,self.height,
self.width,(self.height-self.menu_bar_height)]
self.color = [0.8, 0.8, 0.8,
0.8, 0.8, 0.8,
0.8, 0.8, 0.8,
0.8, 0.8, 0.8]
self.line_vertex = [0,(self.height-self.menu_bar_height), self.width,(self.height-self.menu_bar_height)]
self.vertices = batch.add_indexed(4, GL_TRIANGLES, background, self.indices, ('v2f', self.vertex), ('c3f', self.color))
self.line_vertices = batch.add_indexed(2, GL_LINES, background, [0,1], ('v2f', self.line_vertex) ,('c3f', (0.5,0.5,0.5, 0.5,0.5,0.5)))


def on_draw(self):
self.clear()
self.menu_bar()
batch.draw()

if __name__ == '__main__':
edit_window = Edit_Window(resizable=True)
pyglet.app.run()


It works as intended, when I dont use batch drawing, i.e. when i replace the lines:
        self.vertices = batch.add_indexed(4, GL_TRIANGLES, background, self.indices, ('v2f', self.vertex), ('c3f', self.color))
self.line_vertices = batch.add_indexed(2, GL_LINES, background, [0,1], ('v2f', self.line_vertex) ,('c3f', (0.5,0.5,0.5, 0.5,0.5,0.5)))

with:
        self.line_vertices = pyglet.graphics.vertex_list_indexed(2, [0,1], ('v2f', self.line_vertex) ,('c3f', (0.5,0.5,0.5, 0.5,0.5,0.5)))
self.line_vertices.draw(GL_LINES)
self.vertices = pyglet.graphics.vertex_list_indexed(4, self.indices, ('v2f', self.vertex) ,('c3f', self.color))
self.vertices.draw(GL_TRIANGLES)


With this replacement everything is resized correctly. Is there a way to get this behaviour while using batch drawing?  Am I using batch drawing wrong? ( I mainly want to use batch drawing to make use of it's groups)


Regards,
Jens

Benjamin Moran

unread,
Dec 8, 2019, 8:45:47 PM12/8/19
to pyglet-users
You're almost there. What you were doing wrong is re-adding new objects to the Batch each time, causing overlapping duplicate vertex lists. Instead, you want to store the VertexLists returned from Batch.add, and just update them when the window is resized. Here is a working example: 

import pyglet
from pyglet.gl import *

batch = pyglet.graphics.Batch()
background = pyglet.graphics.OrderedGroup(0)
foreground = pyglet.graphics.OrderedGroup(1)


class Edit_Window(pyglet.window.Window):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.menu_bar_height = 40
glClearColor(1.0, 1.0, 1.0, 1.0)

        ##########################
# Create box at the start:
##########################
        self.indices = [0, 1, 2, 2, 3, 1]
        box_color = [0.8] * 12     # Just to simplify the example
box_vertices = [0, self.height,
0, (self.height - self.menu_bar_height),
self.width, self.height,
self.width, (self.height - self.menu_bar_height)]

line_vertices = [0, (self.height - self.menu_bar_height), self.width, (self.height - self.menu_bar_height)]

# Store the VertexList instances that are return from Batch.add:
self.box_vertex_list = batch.add_indexed(4, GL_TRIANGLES, background, self.indices,
('v2f', box_vertices), ('c3f', box_color))
self.line_vertex_list = batch.add_indexed(2, GL_LINES, background, [0, 1],
('v2f', line_vertices), ('c3f', (0.5, 0.5, 0.5, 0.5, 0.5, 0.5)))

def on_resize(self, width, height):
# When the window is resized, update the EXISTING VertexLists,
# instead of re-creating them each time.
line_vertices = [0, (height - self.menu_bar_height), width, (height - self.menu_bar_height)]
box_vertices = [0, height,
0, (height - self.menu_bar_height),
width, height,
width, (height - self.menu_bar_height)]
self.line_vertex_list.vertices[:] = line_vertices
self.box_vertex_list.vertices[:] = box_vertices

# Since we're overriding the origional Window.on_resize method, make
# sure to call the origional one here. This is necessary because
# the origional method sets the Window projection and viewport
super().on_resize(width, height)

def on_draw(self):
self.clear()

batch.draw()


if __name__ == '__main__':
edit_window = Edit_Window(resizable=True)
pyglet.app.run()

Jens Neumann

unread,
Dec 9, 2019, 9:16:34 AM12/9/19
to pyglet-users
Thank you very much! This works perfectly :)
Reply all
Reply to author
Forward
0 new messages