From 3c499d528bea663ee3ddfeedb101fca505e7e4d6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 24 Mar 2021 13:56:15 +0100 Subject: Brush up the hellogl2 example - Use snake case - Use Argument parser - Fix the transparent option to work - Port away from string-based signal/slot connections Task-number: PYSIDE-1112 Change-Id: I104363b35db59fc9e4626d85ebae886c73abfd8a Reviewed-by: Christian Tismer --- examples/opengl/hellogl2/hellogl2.py | 264 ++++++++++++++++++----------------- 1 file changed, 137 insertions(+), 127 deletions(-) (limited to 'examples/opengl/hellogl2/hellogl2.py') diff --git a/examples/opengl/hellogl2/hellogl2.py b/examples/opengl/hellogl2/hellogl2.py index 56301e047..c4e6d64c4 100644 --- a/examples/opengl/hellogl2/hellogl2.py +++ b/examples/opengl/hellogl2/hellogl2.py @@ -2,7 +2,7 @@ ############################################################################ ## ## Copyright (C) 2013 Riverbank Computing Limited. -## Copyright (C) 2018 The Qt Company Ltd. +## Copyright (C) 2021 The Qt Company Ltd. ## Contact: http://www.qt.io/licensing/ ## ## This file is part of the Qt for Python examples of the Qt Toolkit. @@ -42,10 +42,11 @@ """PySide6 port of the opengl/hellogl2 example from Qt v5.x""" -import sys +from argparse import ArgumentParser, RawTextHelpFormatter +import ctypes import math import numpy -import ctypes +import sys from PySide6.QtCore import QCoreApplication, Signal, SIGNAL, SLOT, Qt, QSize, QPointF from PySide6.QtGui import (QVector3D, QOpenGLFunctions, QMatrix4x4, QOpenGLContext, QSurfaceFormat) @@ -61,41 +62,50 @@ try: from OpenGL import GL except ImportError: app = QApplication(sys.argv) - messageBox = QMessageBox(QMessageBox.Critical, "OpenGL hellogl", + message_box = QMessageBox(QMessageBox.Critical, "OpenGL hellogl", "PyOpenGL must be installed to run this example.", QMessageBox.Close) - messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate") - messageBox.exec_() + message_box.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate") + message_box.exec_() sys.exit(1) class Window(QWidget): - def __init__(self, parent=None): + def __init__(self, transparent, parent=None): QWidget.__init__(self, parent) - self.glWidget = GLWidget() + if transparent: + self.setAttribute(Qt.WA_TranslucentBackground) + self.setAttribute(Qt.WA_NoSystemBackground, False) + + self._gl_widget = GLWidget(transparent) + + self._x_slider = self.create_slider() + self._x_slider.valueChanged.connect(self._gl_widget.set_xrotation) + self._gl_widget.x_rotation_changed.connect(self._x_slider.setValue) - self.xSlider = self.createSlider(SIGNAL("xRotationChanged(int)"), - self.glWidget.setXRotation) - self.ySlider = self.createSlider(SIGNAL("yRotationChanged(int)"), - self.glWidget.setYRotation) - self.zSlider = self.createSlider(SIGNAL("zRotationChanged(int)"), - self.glWidget.setZRotation) + self._y_slider = self.create_slider() + self._y_slider.valueChanged.connect(self._gl_widget.set_yrotation) + self._gl_widget.y_rotation_changed.connect(self._y_slider.setValue) - mainLayout = QHBoxLayout() - mainLayout.addWidget(self.glWidget) - mainLayout.addWidget(self.xSlider) - mainLayout.addWidget(self.ySlider) - mainLayout.addWidget(self.zSlider) - self.setLayout(mainLayout) + self._z_slider = self.create_slider() + self._z_slider.valueChanged.connect(self._gl_widget.set_zrotation) + self._gl_widget.z_rotation_changed.connect(self._z_slider.setValue) - self.xSlider.setValue(15 * 16) - self.ySlider.setValue(345 * 16) - self.zSlider.setValue(0 * 16) + main_layout = QHBoxLayout() + main_layout.addWidget(self._gl_widget) + main_layout.addWidget(self._x_slider) + main_layout.addWidget(self._y_slider) + main_layout.addWidget(self._z_slider) + self.setLayout(main_layout) + + self._x_slider.setValue(15 * 16) + self._y_slider.setValue(345 * 16) + self._z_slider.setValue(0 * 16) self.setWindowTitle(self.tr("Hello GL")) - def createSlider(self, changedSignal, setterSlot): + def create_slider(self): slider = QSlider(Qt.Vertical) slider.setRange(0, 360 * 16) @@ -103,10 +113,6 @@ class Window(QWidget): slider.setPageStep(15 * 16) slider.setTickInterval(15 * 16) slider.setTickPosition(QSlider.TicksRight) - - self.glWidget.connect(slider, SIGNAL("valueChanged(int)"), setterSlot) - self.connect(self.glWidget, changedSignal, slider, SLOT("setValue(int)")) - return slider def keyPressEvent(self, event): @@ -141,17 +147,16 @@ class Logo(): self.extrude(x4, y4, y4, x4) self.extrude(y4, x4, y3, x3) - Pi = 3.14159265358979323846 - NumSectors = 100 + NUM_SECTORS = 100 - for i in range(NumSectors): - angle = (i * 2 * Pi) / NumSectors + for i in range(NUM_SECTORS): + angle = (i * 2 * math.pi) / NUM_SECTORS x5 = 0.30 * math.sin(angle) y5 = 0.30 * math.cos(angle) x6 = 0.20 * math.sin(angle) y6 = 0.20 * math.cos(angle) - angle = ((i + 1) * 2 * Pi) / NumSectors + angle = ((i + 1) * 2 * math.pi) / NUM_SECTORS x7 = 0.20 * math.sin(angle) y7 = 0.20 * math.cos(angle) x8 = 0.30 * math.sin(angle) @@ -162,13 +167,13 @@ class Logo(): self.extrude(x6, y6, x7, y7) self.extrude(x8, y8, x5, y5) - def constData(self): + def const_data(self): return self.m_data.tobytes() def count(self): return self.m_count - def vertexCount(self): + def vertex_count(self): return self.m_count / 6 def quad(self, x1, y1, x2, y2, x3, y3, x4, y4): @@ -219,44 +224,45 @@ class Logo(): self.m_count += 6 class GLWidget(QOpenGLWidget, QOpenGLFunctions): - xRotationChanged = Signal(int) - yRotationChanged = Signal(int) - zRotationChanged = Signal(int) + x_rotation_changed = Signal(int) + y_rotation_changed = Signal(int) + z_rotation_changed = Signal(int) - def __init__(self, parent=None): + def __init__(self, transparent, parent=None): QOpenGLWidget.__init__(self, parent) QOpenGLFunctions.__init__(self) - self.core = "--coreprofile" in QCoreApplication.arguments() - self.xRot = 0 - self.yRot = 0 - self.zRot = 0 - self.lastPos = QPointF() + self._transparent = transparent + self._core = QSurfaceFormat.defaultFormat().profile() == QSurfaceFormat.CoreProfile + + self._x_rot = 0 + self._y_rot = 0 + self._z_rot = 0 + self._last_pos = QPointF() self.logo = Logo() self.vao = QOpenGLVertexArrayObject() - self.logoVbo = QOpenGLBuffer() + self._logo_vbo = QOpenGLBuffer() self.program = QOpenGLShaderProgram() - self.projMatrixLoc = 0 - self.mvMatrixLoc = 0 - self.normalMatrixLoc = 0 - self.lightPosLoc = 0 + self._proj_matrix_loc = 0 + self._mv_matrix_loc = 0 + self._normal_matrix_loc = 0 + self._light_pos_loc = 0 self.proj = QMatrix4x4() self.camera = QMatrix4x4() self.world = QMatrix4x4() - self.transparent = "--transparent" in QCoreApplication.arguments() - if self.transparent: + if transparent: fmt = self.format() fmt.setAlphaBufferSize(8) self.setFormat(fmt) - def xRotation(self): - return self.xRot + def x_rotation(self): + return self._x_rot - def yRotation(self): - return self.yRot + def y_rotation(self): + return self._y_rot - def zRotation(self): - return self.zRot + def z_rotation(self): + return self._z_rot def minimumSizeHint(self): return QSize(50, 50) @@ -264,42 +270,42 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions): def sizeHint(self): return QSize(400, 400) - def normalizeAngle(self, angle): + def normalize_angle(self, angle): while angle < 0: angle += 360 * 16 while angle > 360 * 16: angle -= 360 * 16 return angle - def setXRotation(self, angle): - angle = self.normalizeAngle(angle) - if angle != self.xRot: - self.xRot = angle - self.emit(SIGNAL("xRotationChanged(int)"), angle) + def set_xrotation(self, angle): + angle = self.normalize_angle(angle) + if angle != self._x_rot: + self._x_rot = angle + self.x_rotation_changed.emit(angle) self.update() - def setYRotation(self, angle): - angle = self.normalizeAngle(angle) - if angle != self.yRot: - self.yRot = angle - self.emit(SIGNAL("yRotationChanged(int)"), angle) + def set_yrotation(self, angle): + angle = self.normalize_angle(angle) + if angle != self._y_rot: + self._y_rot = angle + self.y_rotation_changed.emit(angle) self.update() - def setZRotation(self, angle): - angle = self.normalizeAngle(angle) - if angle != self.zRot: - self.zRot = angle - self.emit(SIGNAL("zRotationChanged(int)"), angle) + def set_zrotation(self, angle): + angle = self.normalize_angle(angle) + if angle != self._z_rot: + self._z_rot = angle + self.z_rotation_changed.emit(angle) self.update() def cleanup(self): self.makeCurrent() - self.logoVbo.destroy() + self._logo_vbo.destroy() del self.program self.program = None self.doneCurrent() - def vertexShaderSourceCore(self): + def vertex_shader_source_core(self): return """#version 150 in vec4 vertex; in vec3 normal; @@ -314,7 +320,7 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions): gl_Position = projMatrix * mvMatrix * vertex; }""" - def fragmentShaderSourceCore(self): + def fragment_shader_source_core(self): return """#version 150 in highp vec3 vert; in highp vec3 vertNormal; @@ -329,7 +335,7 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions): }""" - def vertexShaderSource(self): + def vertex_shader_source(self): return """attribute vec4 vertex; attribute vec3 normal; varying vec3 vert; @@ -343,7 +349,7 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions): gl_Position = projMatrix * mvMatrix * vertex; }""" - def fragmentShaderSource(self): + def fragment_shader_source(self): return """varying highp vec3 vert; varying highp vec3 vertNormal; uniform highp vec3 lightPos; @@ -358,48 +364,48 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions): def initializeGL(self): self.context().aboutToBeDestroyed.connect(self.cleanup) self.initializeOpenGLFunctions() - self.glClearColor(0, 0, 0, 1) + self.glClearColor(0, 0, 0, 0 if self._transparent else 1) self.program = QOpenGLShaderProgram() - if self.core: - self.vertexShader = self.vertexShaderSourceCore() - self.fragmentShader = self.fragmentShaderSourceCore() + if self._core: + self._vertex_shader = self.vertex_shader_source_core() + self._fragment_shader = self.fragment_shader_source_core() else: - self.vertexShader = self.vertexShaderSource() - self.fragmentShader = self.fragmentShaderSource() + self._vertex_shader = self.vertex_shader_source() + self._fragment_shader = self.fragment_shader_source() - self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, self.vertexShader) - self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, self.fragmentShader) + self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, self._vertex_shader) + self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, self._fragment_shader) self.program.bindAttributeLocation("vertex", 0) self.program.bindAttributeLocation("normal", 1) self.program.link() self.program.bind() - self.projMatrixLoc = self.program.uniformLocation("projMatrix") - self.mvMatrixLoc = self.program.uniformLocation("mvMatrix") - self.normalMatrixLoc = self.program.uniformLocation("normalMatrix") - self.lightPosLoc = self.program.uniformLocation("lightPos") + self._proj_matrix_loc = self.program.uniformLocation("projMatrix") + self._mv_matrix_loc = self.program.uniformLocation("mvMatrix") + self._normal_matrix_loc = self.program.uniformLocation("normalMatrix") + self._light_pos_loc = self.program.uniformLocation("lightPos") self.vao.create() - vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao) + vao_binder = QOpenGLVertexArrayObject.Binder(self.vao) - self.logoVbo.create() - self.logoVbo.bind() + self._logo_vbo.create() + self._logo_vbo.bind() float_size = ctypes.sizeof(ctypes.c_float) - self.logoVbo.allocate(self.logo.constData(), self.logo.count() * float_size) + self._logo_vbo.allocate(self.logo.const_data(), self.logo.count() * float_size) - self.setupVertexAttribs() + self.setup_vertex_attribs() self.camera.setToIdentity() self.camera.translate(0, 0, -1) - self.program.setUniformValue(self.lightPosLoc, QVector3D(0, 0, 70)) + self.program.setUniformValue(self._light_pos_loc, QVector3D(0, 0, 70)) self.program.release() - vaoBinder = None + vao_binder = None - def setupVertexAttribs(self): - self.logoVbo.bind() + def setup_vertex_attribs(self): + self._logo_vbo.bind() f = QOpenGLContext.currentContext().functions() f.glEnableVertexAttribArray(0) f.glEnableVertexAttribArray(1) @@ -409,7 +415,7 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions): pointer = VoidPtr(3 * float_size) f.glVertexAttribPointer(0, 3, int(GL.GL_FLOAT), int(GL.GL_FALSE), 6 * float_size, null) f.glVertexAttribPointer(1, 3, int(GL.GL_FLOAT), int(GL.GL_FALSE), 6 * float_size, pointer) - self.logoVbo.release() + self._logo_vbo.release() def paintGL(self): self.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) @@ -417,61 +423,65 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions): self.glEnable(GL.GL_CULL_FACE) self.world.setToIdentity() - self.world.rotate(180 - (self.xRot / 16), 1, 0, 0) - self.world.rotate(self.yRot / 16, 0, 1, 0) - self.world.rotate(self.zRot / 16, 0, 0, 1) + self.world.rotate(180 - (self._x_rot / 16), 1, 0, 0) + self.world.rotate(self._y_rot / 16, 0, 1, 0) + self.world.rotate(self._z_rot / 16, 0, 0, 1) - vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao) + vao_binder = QOpenGLVertexArrayObject.Binder(self.vao) self.program.bind() - self.program.setUniformValue(self.projMatrixLoc, self.proj) - self.program.setUniformValue(self.mvMatrixLoc, self.camera * self.world) - normalMatrix = self.world.normalMatrix() - self.program.setUniformValue(self.normalMatrixLoc, normalMatrix) + self.program.setUniformValue(self._proj_matrix_loc, self.proj) + self.program.setUniformValue(self._mv_matrix_loc, self.camera * self.world) + normal_matrix = self.world.normalMatrix() + self.program.setUniformValue(self._normal_matrix_loc, normal_matrix) - self.glDrawArrays(GL.GL_TRIANGLES, 0, self.logo.vertexCount()) + self.glDrawArrays(GL.GL_TRIANGLES, 0, self.logo.vertex_count()) self.program.release() - vaoBinder = None + vao_binder = None def resizeGL(self, width, height): self.proj.setToIdentity() self.proj.perspective(45, width / height, 0.01, 100) def mousePressEvent(self, event): - self.lastPos = event.position() + self._last_pos = event.position() def mouseMoveEvent(self, event): pos = event.position() - dx = pos.x() - self.lastPos.x() - dy = pos.y() - self.lastPos.y() + dx = pos.x() - self._last_pos.x() + dy = pos.y() - self._last_pos.y() if event.buttons() & Qt.LeftButton: - self.setXRotation(self.xRot + 8 * dy) - self.setYRotation(self.yRot + 8 * dx) + self.set_xrotation(self._x_rot + 8 * dy) + self.set_yrotation(self._y_rot + 8 * dx) elif event.buttons() & Qt.RightButton: - self.setXRotation(self.xRot + 8 * dy) - self.setZRotation(self.zRot + 8 * dx) + self.set_xrotation(self._x_rot + 8 * dy) + self.set_zrotation(self._z_rot + 8 * dx) - self.lastPos = pos + self._last_pos = pos if __name__ == '__main__': app = QApplication(sys.argv) + parser = ArgumentParser(description="hellogl2", formatter_class=RawTextHelpFormatter) + parser.add_argument('--multisample', '-m', action='store_true', + help='Use Multisampling') + parser.add_argument('--coreprofile', '-c', action='store_true', + help='Use Core Profile') + parser.add_argument('--transparent', '-t', action='store_true', + help='Transparent Windows') + options = parser.parse_args() fmt = QSurfaceFormat() fmt.setDepthBufferSize(24) - if "--multisample" in QCoreApplication.arguments(): + if options.multisample: fmt.setSamples(4) - if "--coreprofile" in QCoreApplication.arguments(): + if options.coreprofile: fmt.setVersion(3, 2) fmt.setProfile(QSurfaceFormat.CoreProfile) QSurfaceFormat.setDefaultFormat(fmt) - mainWindow = Window() - if "--transparent" in QCoreApplication.arguments(): - mainWindow.setAttribute(Qt.WA_TranslucentBackground) - mainWindow.setAttribute(Qt.WA_NoSystemBackground, False) - - mainWindow.resize(mainWindow.sizeHint()) - mainWindow.show() + main_window = Window(options.transparent) + main_window.resize(main_window.sizeHint()) + main_window.show() res = app.exec_() sys.exit(res) -- cgit v1.2.3