From e9f5a5fdacbca156e0dc2e1a71838da27d8ed2c1 Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Wed, 18 Jan 2023 00:43:31 +0800 Subject: [PATCH] pyglet sync --- libs/pyglet/font/freetype.py | 1 - libs/pyglet/gl/gl.py | 27 ++++++- libs/pyglet/gl/gl_compat.py | 27 ++++++- libs/pyglet/graphics/__init__.py | 86 +++++++------------- libs/pyglet/gui/widgets.py | 2 + libs/pyglet/input/darwin_hid.py | 6 +- libs/pyglet/libs/win32/__init__.py | 91 ++++++++++----------- libs/pyglet/math.py | 4 + libs/pyglet/shapes.py | 117 ++++++++++++++++++++++++--- libs/pyglet/window/win32/__init__.py | 18 ++--- 10 files changed, 246 insertions(+), 133 deletions(-) diff --git a/libs/pyglet/font/freetype.py b/libs/pyglet/font/freetype.py index 117d019..2a41849 100644 --- a/libs/pyglet/font/freetype.py +++ b/libs/pyglet/font/freetype.py @@ -215,7 +215,6 @@ class FreeTypeFont(base.Font): if not match: raise base.FontException(f"Could not match font '{self._name}'") self.filename = match.file - print(match) self.face = FreeTypeFace.from_fontconfig(match) @classmethod diff --git a/libs/pyglet/gl/gl.py b/libs/pyglet/gl/gl.py index 4c98a8f..ae25665 100644 --- a/libs/pyglet/gl/gl.py +++ b/libs/pyglet/gl/gl.py @@ -1,7 +1,7 @@ # ---------------------------------------------------------------------------- # pyglet # Copyright (c) 2006-2008 Alex Holkner -# Copyright (c) 2008-2022 pyglet contributors +# Copyright (c) 2008-2023 pyglet contributors # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -42,6 +42,13 @@ from ctypes import * from pyglet.gl.lib import link_GL as _link_function from pyglet.gl.lib import c_ptrdiff_t +class struct___GLsync(Structure): + __slots__ = [ + ] +struct___GLsync._fields_ = [ + ('_opaque_struct', c_int) +] + # END OF gl.template # GL type definitions @@ -66,6 +73,8 @@ GLintptr = c_ptrdiff_t GLsizeiptr = c_ptrdiff_t GLint64 = c_int64 GLuint64 = c_uint64 +GLsync = POINTER(struct___GLsync) +GLDEBUGPROC = CFUNCTYPE(None, GLenum, GLenum, GLuint, GLenum, GLsizei, POINTER(GLchar), POINTER(GLvoid)) # GL enumerant (token) definitions GL_FALSE = 0 @@ -1582,6 +1591,7 @@ glClearNamedFramebufferuiv = _link_function('glClearNamedFramebufferuiv', None, glClearStencil = _link_function('glClearStencil', None, [GLint], requires='OpenGL 1.0') glClearTexImage = _link_function('glClearTexImage', None, [GLuint, GLint, GLenum, GLenum, POINTER(GLvoid)], requires='OpenGL 4.4') glClearTexSubImage = _link_function('glClearTexSubImage', None, [GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, POINTER(GLvoid)], requires='OpenGL 4.4') +glClientWaitSync = _link_function('glClientWaitSync', GLenum, [GLsync, GLbitfield, GLuint64], requires='OpenGL 3.2') glClipControl = _link_function('glClipControl', None, [GLenum, GLenum], requires='OpenGL 4.5') glColorMask = _link_function('glColorMask', None, [GLboolean, GLboolean, GLboolean, GLboolean], requires='OpenGL 1.0') glColorMaski = _link_function('glColorMaski', None, [GLuint, GLboolean, GLboolean, GLboolean, GLboolean], requires='OpenGL 3.0') @@ -1623,6 +1633,7 @@ glCreateTextures = _link_function('glCreateTextures', None, [GLenum, GLsizei, PO glCreateTransformFeedbacks = _link_function('glCreateTransformFeedbacks', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 4.5') glCreateVertexArrays = _link_function('glCreateVertexArrays', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 4.5') glCullFace = _link_function('glCullFace', None, [GLenum], requires='OpenGL 1.0') +glDebugMessageCallback = _link_function('glDebugMessageCallback', None, [GLDEBUGPROC, POINTER(GLvoid)], requires='OpenGL 4.3') glDebugMessageControl = _link_function('glDebugMessageControl', None, [GLenum, GLenum, GLenum, GLsizei, POINTER(GLuint), GLboolean], requires='OpenGL 4.3') glDebugMessageInsert = _link_function('glDebugMessageInsert', None, [GLenum, GLenum, GLuint, GLenum, GLsizei, POINTER(GLchar)], requires='OpenGL 4.3') glDeleteBuffers = _link_function('glDeleteBuffers', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 1.5') @@ -1635,6 +1646,7 @@ glDeleteRenderbuffers = _link_function('glDeleteRenderbuffers', None, [GLsizei, glDeleteRenderbuffersEXT = _link_function('glDeleteRenderbuffersEXT', None, [GLsizei, POINTER(GLuint)], requires='None') glDeleteSamplers = _link_function('glDeleteSamplers', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 3.3') glDeleteShader = _link_function('glDeleteShader', None, [GLuint], requires='OpenGL 2.0') +glDeleteSync = _link_function('glDeleteSync', None, [GLsync], requires='OpenGL 3.2') glDeleteTextures = _link_function('glDeleteTextures', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 1.1') glDeleteTransformFeedbacks = _link_function('glDeleteTransformFeedbacks', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 4.0') glDeleteVertexArrays = _link_function('glDeleteVertexArrays', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 3.0') @@ -1678,6 +1690,7 @@ glEndConditionalRender = _link_function('glEndConditionalRender', None, [], requ glEndQuery = _link_function('glEndQuery', None, [GLenum], requires='OpenGL 1.5') glEndQueryIndexed = _link_function('glEndQueryIndexed', None, [GLenum, GLuint], requires='OpenGL 4.0') glEndTransformFeedback = _link_function('glEndTransformFeedback', None, [], requires='OpenGL 3.0') +glFenceSync = _link_function('glFenceSync', GLsync, [GLenum, GLbitfield], requires='OpenGL 3.2') glFinish = _link_function('glFinish', None, [], requires='OpenGL 1.0') glFlush = _link_function('glFlush', None, [], requires='OpenGL 1.0') glFlushMappedBufferRange = _link_function('glFlushMappedBufferRange', None, [GLenum, GLintptr, GLsizeiptr], requires='OpenGL 3.0') @@ -1794,6 +1807,7 @@ glGetString = _link_function('glGetString', POINTER(GLubyte), [GLenum], requires glGetStringi = _link_function('glGetStringi', POINTER(GLubyte), [GLenum, GLuint], requires='OpenGL 3.0') glGetSubroutineIndex = _link_function('glGetSubroutineIndex', GLuint, [GLuint, GLenum, POINTER(GLchar)], requires='OpenGL 4.0') glGetSubroutineUniformLocation = _link_function('glGetSubroutineUniformLocation', GLint, [GLuint, GLenum, POINTER(GLchar)], requires='OpenGL 4.0') +glGetSynciv = _link_function('glGetSynciv', None, [GLsync, GLenum, GLsizei, POINTER(GLsizei), POINTER(GLint)], requires='OpenGL 3.2') glGetTexImage = _link_function('glGetTexImage', None, [GLenum, GLint, GLenum, GLenum, POINTER(GLvoid)], requires='OpenGL 1.0') glGetTexLevelParameterfv = _link_function('glGetTexLevelParameterfv', None, [GLenum, GLint, GLenum, POINTER(GLfloat)], requires='OpenGL 1.0') glGetTexLevelParameteriv = _link_function('glGetTexLevelParameteriv', None, [GLenum, GLint, GLenum, POINTER(GLint)], requires='OpenGL 1.0') @@ -1870,6 +1884,7 @@ glIsRenderbuffer = _link_function('glIsRenderbuffer', GLboolean, [GLuint], requi glIsRenderbufferEXT = _link_function('glIsRenderbufferEXT', GLboolean, [GLuint], requires='None') glIsSampler = _link_function('glIsSampler', GLboolean, [GLuint], requires='OpenGL 3.3') glIsShader = _link_function('glIsShader', GLboolean, [GLuint], requires='OpenGL 2.0') +glIsSync = _link_function('glIsSync', GLboolean, [GLsync], requires='OpenGL 3.2') glIsTexture = _link_function('glIsTexture', GLboolean, [GLuint], requires='OpenGL 1.1') glIsTransformFeedback = _link_function('glIsTransformFeedback', GLboolean, [GLuint], requires='OpenGL 4.0') glIsVertexArray = _link_function('glIsVertexArray', GLboolean, [GLuint], requires='OpenGL 3.0') @@ -2224,6 +2239,7 @@ glViewport = _link_function('glViewport', None, [GLint, GLint, GLsizei, GLsizei] glViewportArrayv = _link_function('glViewportArrayv', None, [GLuint, GLsizei, POINTER(GLfloat)], requires='OpenGL 4.1') glViewportIndexedf = _link_function('glViewportIndexedf', None, [GLuint, GLfloat, GLfloat, GLfloat, GLfloat], requires='OpenGL 4.1') glViewportIndexedfv = _link_function('glViewportIndexedfv', None, [GLuint, POINTER(GLfloat)], requires='OpenGL 4.1') +glWaitSync = _link_function('glWaitSync', None, [GLsync, GLbitfield, GLuint64], requires='OpenGL 3.2') __all__ = [ @@ -2248,6 +2264,8 @@ __all__ = [ 'GLsizeiptr', 'GLint64', 'GLuint64', + 'GLsync', + 'GLDEBUGPROC', 'GL_DEPTH_BUFFER_BIT', 'GL_STENCIL_BUFFER_BIT', 'GL_COLOR_BUFFER_BIT', @@ -3760,6 +3778,7 @@ __all__ = [ 'glClearStencil', 'glClearTexImage', 'glClearTexSubImage', + 'glClientWaitSync', 'glClipControl', 'glColorMask', 'glColorMaski', @@ -3801,6 +3820,7 @@ __all__ = [ 'glCreateTransformFeedbacks', 'glCreateVertexArrays', 'glCullFace', + 'glDebugMessageCallback', 'glDebugMessageControl', 'glDebugMessageInsert', 'glDeleteBuffers', @@ -3813,6 +3833,7 @@ __all__ = [ 'glDeleteRenderbuffersEXT', 'glDeleteSamplers', 'glDeleteShader', + 'glDeleteSync', 'glDeleteTextures', 'glDeleteTransformFeedbacks', 'glDeleteVertexArrays', @@ -3856,6 +3877,7 @@ __all__ = [ 'glEndQuery', 'glEndQueryIndexed', 'glEndTransformFeedback', + 'glFenceSync', 'glFinish', 'glFlush', 'glFlushMappedBufferRange', @@ -3972,6 +3994,7 @@ __all__ = [ 'glGetStringi', 'glGetSubroutineIndex', 'glGetSubroutineUniformLocation', + 'glGetSynciv', 'glGetTexImage', 'glGetTexLevelParameterfv', 'glGetTexLevelParameteriv', @@ -4048,6 +4071,7 @@ __all__ = [ 'glIsRenderbufferEXT', 'glIsSampler', 'glIsShader', + 'glIsSync', 'glIsTexture', 'glIsTransformFeedback', 'glIsVertexArray', @@ -4402,4 +4426,5 @@ __all__ = [ 'glViewportArrayv', 'glViewportIndexedf', 'glViewportIndexedfv', + 'glWaitSync', ] diff --git a/libs/pyglet/gl/gl_compat.py b/libs/pyglet/gl/gl_compat.py index e76fc5c..ba647cb 100644 --- a/libs/pyglet/gl/gl_compat.py +++ b/libs/pyglet/gl/gl_compat.py @@ -1,7 +1,7 @@ # ---------------------------------------------------------------------------- # pyglet # Copyright (c) 2006-2008 Alex Holkner -# Copyright (c) 2008-2022 pyglet contributors +# Copyright (c) 2008-2023 pyglet contributors # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -42,6 +42,13 @@ from ctypes import * from pyglet.gl.lib import link_GL as _link_function from pyglet.gl.lib import c_ptrdiff_t +class struct___GLsync(Structure): + __slots__ = [ + ] +struct___GLsync._fields_ = [ + ('_opaque_struct', c_int) +] + # END OF gl.template # GL type definitions @@ -66,6 +73,8 @@ GLintptr = c_ptrdiff_t GLsizeiptr = c_ptrdiff_t GLint64 = c_int64 GLuint64 = c_uint64 +GLsync = POINTER(struct___GLsync) +GLDEBUGPROC = CFUNCTYPE(None, GLenum, GLenum, GLuint, GLenum, GLsizei, POINTER(GLchar), POINTER(GLvoid)) # GL enumerant (token) definitions GL_FALSE = 0 @@ -2021,6 +2030,7 @@ glClearStencil = _link_function('glClearStencil', None, [GLint], requires='OpenG glClearTexImage = _link_function('glClearTexImage', None, [GLuint, GLint, GLenum, GLenum, POINTER(GLvoid)], requires='OpenGL 4.4') glClearTexSubImage = _link_function('glClearTexSubImage', None, [GLuint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, POINTER(GLvoid)], requires='OpenGL 4.4') glClientActiveTexture = _link_function('glClientActiveTexture', None, [GLenum], requires='OpenGL 1.3') +glClientWaitSync = _link_function('glClientWaitSync', GLenum, [GLsync, GLbitfield, GLuint64], requires='OpenGL 3.2') glClipControl = _link_function('glClipControl', None, [GLenum, GLenum], requires='OpenGL 4.5') glClipPlane = _link_function('glClipPlane', None, [GLenum, POINTER(GLdouble)], requires='OpenGL 1.0') glColor3b = _link_function('glColor3b', None, [GLbyte, GLbyte, GLbyte], requires='OpenGL 1.0') @@ -2098,6 +2108,7 @@ glCreateTextures = _link_function('glCreateTextures', None, [GLenum, GLsizei, PO glCreateTransformFeedbacks = _link_function('glCreateTransformFeedbacks', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 4.5') glCreateVertexArrays = _link_function('glCreateVertexArrays', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 4.5') glCullFace = _link_function('glCullFace', None, [GLenum], requires='OpenGL 1.0') +glDebugMessageCallback = _link_function('glDebugMessageCallback', None, [GLDEBUGPROC, POINTER(GLvoid)], requires='OpenGL 4.3') glDebugMessageControl = _link_function('glDebugMessageControl', None, [GLenum, GLenum, GLenum, GLsizei, POINTER(GLuint), GLboolean], requires='OpenGL 4.3') glDebugMessageInsert = _link_function('glDebugMessageInsert', None, [GLenum, GLenum, GLuint, GLenum, GLsizei, POINTER(GLchar)], requires='OpenGL 4.3') glDeleteBuffers = _link_function('glDeleteBuffers', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 1.5') @@ -2111,6 +2122,7 @@ glDeleteRenderbuffers = _link_function('glDeleteRenderbuffers', None, [GLsizei, glDeleteRenderbuffersEXT = _link_function('glDeleteRenderbuffersEXT', None, [GLsizei, POINTER(GLuint)], requires='None') glDeleteSamplers = _link_function('glDeleteSamplers', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 3.3') glDeleteShader = _link_function('glDeleteShader', None, [GLuint], requires='OpenGL 2.0') +glDeleteSync = _link_function('glDeleteSync', None, [GLsync], requires='OpenGL 3.2') glDeleteTextures = _link_function('glDeleteTextures', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 1.1') glDeleteTransformFeedbacks = _link_function('glDeleteTransformFeedbacks', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 4.0') glDeleteVertexArrays = _link_function('glDeleteVertexArrays', None, [GLsizei, POINTER(GLuint)], requires='OpenGL 3.0') @@ -2175,6 +2187,7 @@ glEvalMesh2 = _link_function('glEvalMesh2', None, [GLenum, GLint, GLint, GLint, glEvalPoint1 = _link_function('glEvalPoint1', None, [GLint], requires='OpenGL 1.0') glEvalPoint2 = _link_function('glEvalPoint2', None, [GLint, GLint], requires='OpenGL 1.0') glFeedbackBuffer = _link_function('glFeedbackBuffer', None, [GLsizei, GLenum, POINTER(GLfloat)], requires='OpenGL 1.0') +glFenceSync = _link_function('glFenceSync', GLsync, [GLenum, GLbitfield], requires='OpenGL 3.2') glFinish = _link_function('glFinish', None, [], requires='OpenGL 1.0') glFlush = _link_function('glFlush', None, [], requires='OpenGL 1.0') glFlushMappedBufferRange = _link_function('glFlushMappedBufferRange', None, [GLenum, GLintptr, GLsizeiptr], requires='OpenGL 3.0') @@ -2314,6 +2327,7 @@ glGetString = _link_function('glGetString', POINTER(GLubyte), [GLenum], requires glGetStringi = _link_function('glGetStringi', POINTER(GLubyte), [GLenum, GLuint], requires='OpenGL 3.0') glGetSubroutineIndex = _link_function('glGetSubroutineIndex', GLuint, [GLuint, GLenum, POINTER(GLchar)], requires='OpenGL 4.0') glGetSubroutineUniformLocation = _link_function('glGetSubroutineUniformLocation', GLint, [GLuint, GLenum, POINTER(GLchar)], requires='OpenGL 4.0') +glGetSynciv = _link_function('glGetSynciv', None, [GLsync, GLenum, GLsizei, POINTER(GLsizei), POINTER(GLint)], requires='OpenGL 3.2') glGetTexEnvfv = _link_function('glGetTexEnvfv', None, [GLenum, GLenum, POINTER(GLfloat)], requires='OpenGL 1.0') glGetTexEnviv = _link_function('glGetTexEnviv', None, [GLenum, GLenum, POINTER(GLint)], requires='OpenGL 1.0') glGetTexGendv = _link_function('glGetTexGendv', None, [GLenum, GLenum, POINTER(GLdouble)], requires='OpenGL 1.0') @@ -2410,6 +2424,7 @@ glIsRenderbuffer = _link_function('glIsRenderbuffer', GLboolean, [GLuint], requi glIsRenderbufferEXT = _link_function('glIsRenderbufferEXT', GLboolean, [GLuint], requires='None') glIsSampler = _link_function('glIsSampler', GLboolean, [GLuint], requires='OpenGL 3.3') glIsShader = _link_function('glIsShader', GLboolean, [GLuint], requires='OpenGL 2.0') +glIsSync = _link_function('glIsSync', GLboolean, [GLsync], requires='OpenGL 3.2') glIsTexture = _link_function('glIsTexture', GLboolean, [GLuint], requires='OpenGL 1.1') glIsTransformFeedback = _link_function('glIsTransformFeedback', GLboolean, [GLuint], requires='OpenGL 4.0') glIsVertexArray = _link_function('glIsVertexArray', GLboolean, [GLuint], requires='OpenGL 3.0') @@ -2985,6 +3000,7 @@ glViewport = _link_function('glViewport', None, [GLint, GLint, GLsizei, GLsizei] glViewportArrayv = _link_function('glViewportArrayv', None, [GLuint, GLsizei, POINTER(GLfloat)], requires='OpenGL 4.1') glViewportIndexedf = _link_function('glViewportIndexedf', None, [GLuint, GLfloat, GLfloat, GLfloat, GLfloat], requires='OpenGL 4.1') glViewportIndexedfv = _link_function('glViewportIndexedfv', None, [GLuint, POINTER(GLfloat)], requires='OpenGL 4.1') +glWaitSync = _link_function('glWaitSync', None, [GLsync, GLbitfield, GLuint64], requires='OpenGL 3.2') glWindowPos2d = _link_function('glWindowPos2d', None, [GLdouble, GLdouble], requires='OpenGL 1.4') glWindowPos2dv = _link_function('glWindowPos2dv', None, [POINTER(GLdouble)], requires='OpenGL 1.4') glWindowPos2f = _link_function('glWindowPos2f', None, [GLfloat, GLfloat], requires='OpenGL 1.4') @@ -3025,6 +3041,8 @@ __all__ = [ 'GLsizeiptr', 'GLint64', 'GLuint64', + 'GLsync', + 'GLDEBUGPROC', 'GL_DEPTH_BUFFER_BIT', 'GL_STENCIL_BUFFER_BIT', 'GL_COLOR_BUFFER_BIT', @@ -4976,6 +4994,7 @@ __all__ = [ 'glClearTexImage', 'glClearTexSubImage', 'glClientActiveTexture', + 'glClientWaitSync', 'glClipControl', 'glClipPlane', 'glColor3b', @@ -5053,6 +5072,7 @@ __all__ = [ 'glCreateTransformFeedbacks', 'glCreateVertexArrays', 'glCullFace', + 'glDebugMessageCallback', 'glDebugMessageControl', 'glDebugMessageInsert', 'glDeleteBuffers', @@ -5066,6 +5086,7 @@ __all__ = [ 'glDeleteRenderbuffersEXT', 'glDeleteSamplers', 'glDeleteShader', + 'glDeleteSync', 'glDeleteTextures', 'glDeleteTransformFeedbacks', 'glDeleteVertexArrays', @@ -5130,6 +5151,7 @@ __all__ = [ 'glEvalPoint1', 'glEvalPoint2', 'glFeedbackBuffer', + 'glFenceSync', 'glFinish', 'glFlush', 'glFlushMappedBufferRange', @@ -5269,6 +5291,7 @@ __all__ = [ 'glGetStringi', 'glGetSubroutineIndex', 'glGetSubroutineUniformLocation', + 'glGetSynciv', 'glGetTexEnvfv', 'glGetTexEnviv', 'glGetTexGendv', @@ -5365,6 +5388,7 @@ __all__ = [ 'glIsRenderbufferEXT', 'glIsSampler', 'glIsShader', + 'glIsSync', 'glIsTexture', 'glIsTransformFeedback', 'glIsVertexArray', @@ -5940,6 +5964,7 @@ __all__ = [ 'glViewportArrayv', 'glViewportIndexedf', 'glViewportIndexedfv', + 'glWaitSync', 'glWindowPos2d', 'glWindowPos2dv', 'glWindowPos2f', diff --git a/libs/pyglet/graphics/__init__.py b/libs/pyglet/graphics/__init__.py index 506bb62..21359a7 100644 --- a/libs/pyglet/graphics/__init__.py +++ b/libs/pyglet/graphics/__init__.py @@ -33,27 +33,26 @@ # POSSIBILITY OF SUCH DAMAGE. # ---------------------------------------------------------------------------- -"""Low-level graphics rendering. +"""Low-level graphics rendering and abstractions. -This module provides an efficient low-level abstraction over OpenGL. It gives -very good performance for rendering OpenGL primitives. The module is used -internally by other areas of pyglet. +This module provides efficient abstractions over OpenGL objects, such as +Shaders and Buffers. It also provides classes for highly performant batched +rendering and grouping. See the :ref:`guide_graphics` for details on how to use this graphics API. Batches and groups ================== -Without even needing to understand the details on how to draw primitives with -the graphics API, developers can make use of :py:class:`~pyglet.graphics.Batch` -and :py:class:`~pyglet.graphics.Group` objects to improve performance of sprite -and text rendering. +Developers can make use of :py:class:`~pyglet.graphics.Batch` and +:py:class:`~pyglet.graphics.Group` objects to improve performance when +rendering a large number of objects. -The :py:class:`~pyglet.sprite.Sprite`, :py:func:`~pyglet.text.Label` and -:py:func:`~pyglet.text.layout.TextLayout` classes all accept a ``batch`` and -``group`` parameter in their constructors. A batch manages a set of objects -that will be drawn all at once, and a group describes the manner in which an -object is drawn. +The :py:class:`~pyglet.sprite.Sprite`, :py:func:`~pyglet.text.Label`, +:py:func:`~pyglet.text.layout.TextLayout`, and other classes all accept a +``batch`` and ``group`` parameter in their constructors. A Batch manages +a set of objects that will be drawn all at once, and a Group can be used +to set OpenGL state and further sort the draw operation. The following example creates a batch, adds two sprites to the batch, and then draws the entire batch:: @@ -65,64 +64,29 @@ draws the entire batch:: def on_draw() batch.draw() -Drawing a complete batch is much faster than drawing the items in the batch +Drawing a complete Batch is much faster than drawing the items in the batch individually, especially when those items belong to a common group. -Groups describe the OpenGL state required for an item. This is for the most -part managed by the sprite and text classes, however you can also use custom -groups to ensure items are drawn in a particular order. For example, the +Groups describe the OpenGL state required for an item. This is for the most +part managed by the sprite, text, and other classes, however you can also use +custom groups to ensure items are drawn in a particular order. For example, the following example adds a background sprite which is guaranteed to be drawn before the car and the boat:: batch = pyglet.graphics.Batch() - background = pyglet.sprite.SpriteGroup(0) - foreground = pyglet.sprite.SpriteGroup(1) + background = pyglet.graphics.Group(order=0) + foreground = pyglet.graphics.Group(order=1) - background = pyglet.sprite.Sprite(background_image, - batch=batch, group=background) + background = pyglet.sprite.Sprite(background_image, batch=batch, group=background) car = pyglet.sprite.Sprite(car_image, batch=batch, group=foreground) boat = pyglet.sprite.Sprite(boat_image, batch=batch, group=foreground) def on_draw() batch.draw() -It's preferable to manage sprites and text objects within as few batches as -possible. If the drawing of sprites or text objects need to be interleaved -with other drawing that does not use the graphics API, multiple batches will -be required. - -Drawing modes -============= - -Methods in this module that accept a ``mode`` parameter will accept any value -in the OpenGL drawing mode enumeration: ``GL_POINTS``, ``GL_LINE_STRIP``, -``GL_LINE_LOOP``, ``GL_LINES``, ``GL_TRIANGLE_STRIP``, ``GL_TRIANGLE_FAN``, -``GL_TRIANGLES``, and ``GL_POLYGON``. - -:: - - pyglet.graphics.draw(1, GL_POINTS, ('v2i',(10,20))) - -However, because of the way the graphics API renders multiple primitives with -shared state, ``GL_POLYGON``, ``GL_LINE_LOOP`` and ``GL_TRIANGLE_FAN`` cannot -be used --- the results are undefined. - -When using ``GL_LINE_STRIP`` or ``GL_TRIANGLE_STRIP``, care must be taken to -insert degenerate vertices at the beginning and end of each -vertex list. For example, given the vertex list:: - - A, B, C, D - -the correct vertex list to provide the vertex list is:: - - A, A, B, C, D, D - -Alternatively, the ``NV_primitive_restart`` extension can be used if it is -present. This also permits use of ``GL_POLYGON``, ``GL_LINE_LOOP`` and -``GL_TRIANGLE_FAN``. Unfortunately the extension is not provided by older -video drivers, and requires indexed vertex lists. - -.. versionadded:: 1.1 +It's preferable to manage pyglet objects within as few batches as possible. If +the drawing of sprites or text objects need to be interleaved with other +drawing that does not use the graphics API, multiple batches will be required. """ import ctypes @@ -140,6 +104,9 @@ _debug_graphics_batch = pyglet.options['debug_graphics_batch'] def draw(size, mode, **data): """Draw a primitive immediately. + :warning: This function is deprecated as of 2.0.4, and will be removed + in the next release. + :Parameters: `size` : int Number of vertices given @@ -189,6 +156,9 @@ def draw(size, mode, **data): def draw_indexed(size, mode, indices, **data): """Draw a primitive with indexed vertices immediately. + :warning: This function is deprecated as of 2.0.4, and will be removed + in the next release. + :Parameters: `size` : int Number of vertices given diff --git a/libs/pyglet/gui/widgets.py b/libs/pyglet/gui/widgets.py index 392f4f8..19a5562 100644 --- a/libs/pyglet/gui/widgets.py +++ b/libs/pyglet/gui/widgets.py @@ -494,6 +494,8 @@ class TextEntry(WidgetBase): if self._check_hit(x, y): self._set_focus(True) self._caret.on_mouse_press(x, y, buttons, modifiers) + else: + self._set_focus(False) def on_text(self, text): if not self.enabled: diff --git a/libs/pyglet/input/darwin_hid.py b/libs/pyglet/input/darwin_hid.py index d1f3620..2390714 100644 --- a/libs/pyglet/input/darwin_hid.py +++ b/libs/pyglet/input/darwin_hid.py @@ -316,7 +316,7 @@ class HIDDevice: def get_guid(self): """Generate an SDL2 style GUID from the product guid.""" - if self.transport == 'USB': + if self.transport.upper() == 'USB': bustype = 0x03 vendor = self.vendorID or 0 product = self.productID or 0 @@ -328,7 +328,7 @@ class HIDDevice: version = ((version << 8) | (version >> 8)) & 0xFFFF return "{:04x}0000{:04x}0000{:04x}0000{:04x}0000".format(bustype, vendor, product, version) - elif self.transport == 'BLUETOOTH': + elif self.transport.upper() == 'BLUETOOTH': bustype = 0x05 # Byte swap (ABCD --> CDAB): bustype = ((bustype << 8) | (bustype >> 8)) & 0xFFFF @@ -726,7 +726,7 @@ def get_apple_remote(display=None): def _create_controller(device, display): - if device.transport in ('USB', 'BLUETOOTH'): + if device.transport.upper() in ('USB', 'BLUETOOTH'): mapping = get_mapping(device.get_guid()) if not mapping: return diff --git a/libs/pyglet/libs/win32/__init__.py b/libs/pyglet/libs/win32/__init__.py index bdf5183..b52681d 100644 --- a/libs/pyglet/libs/win32/__init__.py +++ b/libs/pyglet/libs/win32/__init__.py @@ -46,56 +46,15 @@ IS64 = struct.calcsize("P") == 8 _debug_win32 = pyglet.options['debug_win32'] -if _debug_win32: - import traceback +DebugLibrary = lambda lib: ctypes.WinDLL(lib, use_last_error=True if _debug_win32 else False) - _GetLastError = windll.kernel32.GetLastError - _SetLastError = windll.kernel32.SetLastError - _FormatMessageA = windll.kernel32.FormatMessageA - - _log_win32 = open('debug_win32.log', 'w') - - - def format_error(err): - msg = create_string_buffer(256) - _FormatMessageA(constants.FORMAT_MESSAGE_FROM_SYSTEM, - c_void_p(), - err, - 0, - msg, - len(msg), - c_void_p()) - return msg.value - - - class DebugLibrary: - def __init__(self, lib): - self.lib = lib - - def __getattr__(self, name): - fn = getattr(self.lib, name) - - def f(*args): - _SetLastError(0) - result = fn(*args) - err = _GetLastError() - if err != 0: - for entry in traceback.format_list(traceback.extract_stack()[:-1]): - _log_win32.write(entry) - print(format_error(err), file=_log_win32) - return result - - return f -else: - DebugLibrary = lambda lib: lib - -_gdi32 = DebugLibrary(windll.gdi32) -_kernel32 = DebugLibrary(windll.kernel32) -_user32 = DebugLibrary(windll.user32) -_dwmapi = DebugLibrary(windll.dwmapi) -_shell32 = DebugLibrary(windll.shell32) -_ole32 = DebugLibrary(windll.ole32) -_oleaut32 = DebugLibrary(windll.oleaut32) +_gdi32 = DebugLibrary('gdi32') +_kernel32 = DebugLibrary('kernel32') +_user32 = DebugLibrary('user32') +_dwmapi = DebugLibrary('dwmapi') +_shell32 = DebugLibrary('shell32') +_ole32 = DebugLibrary('ole32') +_oleaut32 = DebugLibrary('oleaut32') # _gdi32 _gdi32.AddFontMemResourceEx.restype = HANDLE @@ -216,6 +175,8 @@ _user32.LoadCursorW.restype = HCURSOR _user32.LoadCursorW.argtypes = [HINSTANCE, c_wchar_p] _user32.LoadIconW.restype = HICON _user32.LoadIconW.argtypes = [HINSTANCE, c_wchar_p] +_user32.LoadImageW.restype = HICON +_user32.LoadImageW.argtypes = [HINSTANCE, LPCWSTR, UINT, c_int, c_int, UINT] _user32.MapVirtualKeyW.restype = UINT _user32.MapVirtualKeyW.argtypes = [UINT, UINT] _user32.MapWindowPoints.restype = c_int @@ -319,6 +280,37 @@ _oleaut32.VariantInit.argtypes = [c_void_p] _oleaut32.VariantClear.restype = HRESULT _oleaut32.VariantClear.argtypes = [c_void_p] +if _debug_win32: + import traceback + + _log_win32 = open('debug_win32.log', 'w') + + + def win32_errcheck(result, func, args): + last_err = ctypes.get_last_error() + if last_err != 0: # If the result is not success and last error is invalid. + for entry in traceback.format_list(traceback.extract_stack()[:-1]): + _log_win32.write(entry) + print(f"[Result {result}] Error #{last_err} - {ctypes.FormatError(last_err)}", file=_log_win32) + return args + + + def set_errchecks(lib): + """Set errcheck hook on all functions we have defined.""" + for key in lib.__dict__: + if key.startswith('_'): # Ignore builtins. + continue + lib.__dict__[key].errcheck = win32_errcheck + + + set_errchecks(_gdi32) + set_errchecks(_kernel32) + set_errchecks(_user32) + set_errchecks(_dwmapi) + set_errchecks(_shell32) + set_errchecks(_ole32) + set_errchecks(_oleaut32) + # Initialize COM in MTA mode. Required for: WIC (DirectWrite), WMF, and XInput try: _ole32.CoInitializeEx(None, constants.COINIT_MULTITHREADED) @@ -332,4 +324,5 @@ def _uninitialize(): except OSError: pass + atexit.register(_uninitialize) diff --git a/libs/pyglet/math.py b/libs/pyglet/math.py index 7f36f66..9bdf708 100644 --- a/libs/pyglet/math.py +++ b/libs/pyglet/math.py @@ -230,6 +230,10 @@ class Vec2: return Vec2(self.x + (alpha * (other.x - self.x)), self.y + (alpha * (other.y - self.y))) + def reflect(self, normal: Vec2) -> Vec2: + """Create a new Vec2 reflected (ricochet) from the given normal.""" + return self - normal * 2 * normal.dot(self) + def rotate(self, angle: float) -> Vec2: """Create a new Vector rotated by the angle. The magnitude remains unchanged. diff --git a/libs/pyglet/shapes.py b/libs/pyglet/shapes.py index 9767c1b..b8c40a1 100644 --- a/libs/pyglet/shapes.py +++ b/libs/pyglet/shapes.py @@ -112,7 +112,7 @@ vertex_source = """#version 150 core { m_translate[3][0] = translation.x; m_translate[3][1] = translation.y; - m_rotation[0][0] = cos(-radians(rotation)); + m_rotation[0][0] = cos(-radians(rotation)); m_rotation[0][1] = sin(-radians(rotation)); m_rotation[1][0] = -sin(-radians(rotation)); m_rotation[1][1] = cos(-radians(rotation)); @@ -599,6 +599,111 @@ class Arc(ShapeBase): self._vertex_list.draw(self._draw_mode) +class BezierCurve(ShapeBase): + _draw_mode = GL_LINES + + def __init__(self, *points, t=1.0, segments=100, color=(255, 255, 255, 255), batch=None, group=None): + """Create a Bézier curve. + + The curve's anchor point (x, y) defaults to its first control point. + + :Parameters: + `points` : List[[int, int]] + Control points of the curve. + `t` : float + Draw `100*t` percent of the curve. 0.5 means the curve + is half drawn and 1.0 means draw the whole curve. + `segments` : int + You can optionally specify how many line segments the + curve should be made from. + `color` : (int, int, int, int) + The RGB or RGBA color of the curve, specified as a + tuple of 3 or 4 ints in the range of 0-255. RGB colors + will be treated as having an opacity of 255. + `batch` : `~pyglet.graphics.Batch` + Optional batch to add the curve to. + `group` : `~pyglet.graphics.Group` + Optional parent group of the curve. + """ + self._points = list(points) + self._t = t + self._segments = segments + self._num_verts = self._segments * 2 + r, g, b, *a = color + self._rgba = r, g, b, a[0] if a else 255 + + program = get_default_shader() + self._batch = batch or Batch() + self._group = _ShapeGroup(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, program, group) + + self._create_vertex_list() + self._update_vertices() + + def _make_curve(self, t): + n = len(self._points) - 1 + p = [0, 0] + for i in range(n + 1): + m = math.comb(n, i) * (1 - t) ** (n - i) * t ** i + p[0] += m * self._points[i][0] + p[1] += m * self._points[i][1] + return p + + def _create_vertex_list(self): + self._vertex_list = self._group.program.vertex_list( + self._num_verts, self._draw_mode, self._batch, self._group, + colors=('Bn', self._rgba * self._num_verts), + translation=('f', (self._points[0]) * self._num_verts)) + + def _update_vertices(self): + if not self._visible: + vertices = (0,) * self._segments * 4 + else: + x = -self._anchor_x + y = -self._anchor_y + + # Calculate the points of the curve: + points = [(x + self._make_curve(self._t * t / self._segments)[0], + y + self._make_curve(self._t * t / self._segments)[1]) for t in range(self._segments + 1)] + trans_x, trans_y = points[0] + trans_x += self._anchor_x + trans_y += self._anchor_y + coords = [[x - trans_x, y - trans_y] for x, y in points] + + # Create a list of doubled-up points from the points: + vertices = [] + for i in range(len(coords) - 1): + line_points = *coords[i], *coords[i + 1] + vertices.extend(line_points) + + self._vertex_list.vertices[:] = vertices + + @property + def points(self): + """Control points of the curve. + + :type: List[[int, int]] + """ + return self._points + + @points.setter + def points(self, value): + self._points = value + self._update_vertices() + + @property + def t(self): + """Draw `100*t` percent of the curve. + + :type: float + """ + return self._t + + @t.setter + def t(self, value): + self._t = value + self._update_vertices() + + class Circle(ShapeBase): def __init__(self, x, y, radius, segments=None, color=(255, 255, 255, 255), batch=None, group=None): @@ -799,14 +904,6 @@ class Ellipse(ShapeBase): self._rotation = rotation self._vertex_list.rotation[:] = (rotation,) * self._num_verts - def draw(self): - """Draw the shape at its current position. - - Using this method is not recommended. Instead, add the - shape to a `pyglet.graphics.Batch` for efficient rendering. - """ - self._vertex_list.draw(self._draw_mode) - class Sector(ShapeBase): def __init__(self, x, y, radius, segments=None, angle=math.tau, start_angle=0, @@ -1677,4 +1774,4 @@ class Polygon(ShapeBase): self._vertex_list.rotation[:] = (rotation,) * self._num_verts -__all__ = 'Arc', 'Circle', 'Ellipse', 'Line', 'Rectangle', 'BorderedRectangle', 'Triangle', 'Star', 'Polygon', 'Sector' +__all__ = 'Arc', 'BezierCurve', 'Circle', 'Ellipse', 'Line', 'Rectangle', 'BorderedRectangle', 'Triangle', 'Star', 'Polygon', 'Sector' diff --git a/libs/pyglet/window/win32/__init__.py b/libs/pyglet/window/win32/__init__.py index a6bfc9d..3bb715a 100644 --- a/libs/pyglet/window/win32/__init__.py +++ b/libs/pyglet/window/win32/__init__.py @@ -185,7 +185,8 @@ class Win32Window(BaseWindow): self._get_window_proc(self._event_handlers)) self._window_class.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC self._window_class.hInstance = 0 - self._window_class.hIcon = _user32.LoadIconW(module, MAKEINTRESOURCE(1)) + self._window_class.hIcon = _user32.LoadImageW(module, MAKEINTRESOURCE(1), IMAGE_ICON, + 0, 0, LR_DEFAULTSIZE | LR_SHARED) self._window_class.hbrBackground = black self._window_class.lpszMenuName = None self._window_class.cbClsExtra = 0 @@ -233,10 +234,6 @@ class Win32Window(BaseWindow): self._view_window_class.hInstance, 0) - if not self._view_hwnd: - last_error = _kernel32.GetLastError() - raise Exception("Failed to create handle", self, last_error, self._view_hwnd, self._hwnd) - self._dc = _user32.GetDC(self._view_hwnd) # Only allow files being dropped if specified. @@ -295,9 +292,9 @@ class Win32Window(BaseWindow): self.context.attach(self.canvas) self._wgl_context = self.context._context - self.set_caption(self._caption) - self.switch_to() + + self.set_caption(self._caption) self.set_vsync(self._vsync) if self._visible: @@ -320,6 +317,8 @@ class Win32Window(BaseWindow): super(Win32Window, self).close() return + self.set_mouse_platform_visible(True) + _user32.DestroyWindow(self._hwnd) _user32.UnregisterClassW(self._view_window_class.lpszClassName, 0) _user32.UnregisterClassW(self._window_class.lpszClassName, 0) @@ -328,7 +327,6 @@ class Win32Window(BaseWindow): self._view_window_class = None self._view_event_handlers.clear() self._event_handlers.clear() - self.set_mouse_platform_visible(True) self._hwnd = None self._dc = None self._wgl_context = None @@ -464,7 +462,7 @@ class Win32Window(BaseWindow): else: cursor = self._create_cursor_from_image(self._mouse_cursor) - _user32.SetClassLongW(self._view_hwnd, GCL_HCURSOR, cursor) + _user32.SetClassLongPtrW(self._view_hwnd, GCL_HCURSOR, cursor) _user32.SetCursor(cursor) if platform_visible == self._mouse_platform_visible: @@ -546,7 +544,7 @@ class Win32Window(BaseWindow): if exclusive and self._has_focus: _user32.RegisterHotKey(self._hwnd, 0, WIN32_MOD_ALT, VK_TAB) - else: + elif self._exclusive_keyboard and not exclusive: _user32.UnregisterHotKey(self._hwnd, 0) self._exclusive_keyboard = exclusive