pyglet 2.1.13__py3-none-any.whl → 3.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyglet/__init__.py +67 -61
- pyglet/__init__.pyi +15 -8
- pyglet/app/__init__.py +22 -13
- pyglet/app/async_app.py +212 -0
- pyglet/app/base.py +2 -1
- pyglet/app/{xlib.py → linux.py} +3 -3
- pyglet/config/__init__.py +101 -0
- pyglet/config/gl/__init__.py +30 -0
- pyglet/config/gl/egl.py +120 -0
- pyglet/config/gl/macos.py +262 -0
- pyglet/config/gl/windows.py +267 -0
- pyglet/config/gl/x11.py +142 -0
- pyglet/customtypes.py +43 -2
- pyglet/display/__init__.py +8 -6
- pyglet/display/base.py +3 -63
- pyglet/display/cocoa.py +12 -17
- pyglet/display/emscripten.py +39 -0
- pyglet/display/headless.py +23 -30
- pyglet/display/wayland.py +157 -0
- pyglet/display/win32.py +5 -21
- pyglet/display/xlib.py +19 -27
- pyglet/display/xlib_vidmoderestore.py +2 -2
- pyglet/enums.py +183 -0
- pyglet/event.py +0 -1
- pyglet/experimental/geoshader_sprite.py +15 -13
- pyglet/experimental/hidraw.py +6 -15
- pyglet/experimental/multitexture_sprite.py +31 -19
- pyglet/experimental/particles.py +13 -35
- pyglet/font/__init__.py +251 -85
- pyglet/font/base.py +116 -61
- pyglet/font/dwrite/__init__.py +349 -204
- pyglet/font/dwrite/dwrite_lib.py +27 -5
- pyglet/font/fontconfig.py +14 -6
- pyglet/font/freetype.py +138 -87
- pyglet/font/freetype_lib.py +19 -0
- pyglet/font/group.py +179 -0
- pyglet/font/harfbuzz/__init__.py +3 -3
- pyglet/font/pyodide_js.py +310 -0
- pyglet/font/quartz.py +319 -126
- pyglet/font/ttf.py +45 -3
- pyglet/font/user.py +14 -19
- pyglet/font/win32.py +45 -21
- pyglet/graphics/__init__.py +8 -787
- pyglet/graphics/allocation.py +115 -1
- pyglet/graphics/api/__init__.py +77 -0
- pyglet/graphics/api/base.py +299 -0
- pyglet/graphics/api/gl/__init__.py +58 -0
- pyglet/graphics/api/gl/base.py +24 -0
- pyglet/graphics/{vertexbuffer.py → api/gl/buffer.py} +104 -159
- pyglet/graphics/api/gl/cocoa/context.py +76 -0
- pyglet/graphics/api/gl/context.py +391 -0
- pyglet/graphics/api/gl/default_shaders.py +0 -0
- pyglet/graphics/api/gl/draw.py +627 -0
- pyglet/graphics/api/gl/egl/__init__.py +0 -0
- pyglet/graphics/api/gl/egl/context.py +92 -0
- pyglet/graphics/api/gl/enums.py +76 -0
- pyglet/graphics/api/gl/framebuffer.py +315 -0
- pyglet/graphics/api/gl/gl.py +5463 -0
- pyglet/graphics/api/gl/gl_info.py +188 -0
- pyglet/graphics/api/gl/global_opengl.py +226 -0
- pyglet/{gl → graphics/api/gl}/lib.py +34 -18
- pyglet/graphics/api/gl/shader.py +1476 -0
- pyglet/graphics/api/gl/shapes.py +55 -0
- pyglet/graphics/api/gl/sprite.py +102 -0
- pyglet/graphics/api/gl/state.py +219 -0
- pyglet/graphics/api/gl/text.py +190 -0
- pyglet/graphics/api/gl/texture.py +1526 -0
- pyglet/graphics/{vertexarray.py → api/gl/vertexarray.py} +11 -13
- pyglet/graphics/api/gl/vertexdomain.py +751 -0
- pyglet/graphics/api/gl/win32/__init__.py +0 -0
- pyglet/graphics/api/gl/win32/context.py +108 -0
- pyglet/graphics/api/gl/win32/wgl_info.py +24 -0
- pyglet/graphics/api/gl/xlib/__init__.py +0 -0
- pyglet/graphics/api/gl/xlib/context.py +174 -0
- pyglet/{gl → graphics/api/gl/xlib}/glx_info.py +26 -31
- pyglet/graphics/api/gl1/__init__.py +0 -0
- pyglet/{gl → graphics/api/gl1}/gl_compat.py +3 -2
- pyglet/graphics/api/gl2/__init__.py +0 -0
- pyglet/graphics/api/gl2/buffer.py +320 -0
- pyglet/graphics/api/gl2/draw.py +600 -0
- pyglet/graphics/api/gl2/global_opengl.py +122 -0
- pyglet/graphics/api/gl2/shader.py +200 -0
- pyglet/graphics/api/gl2/shapes.py +51 -0
- pyglet/graphics/api/gl2/sprite.py +79 -0
- pyglet/graphics/api/gl2/text.py +175 -0
- pyglet/graphics/api/gl2/vertexdomain.py +364 -0
- pyglet/graphics/api/webgl/__init__.py +233 -0
- pyglet/graphics/api/webgl/buffer.py +302 -0
- pyglet/graphics/api/webgl/context.py +234 -0
- pyglet/graphics/api/webgl/draw.py +590 -0
- pyglet/graphics/api/webgl/enums.py +76 -0
- pyglet/graphics/api/webgl/framebuffer.py +360 -0
- pyglet/graphics/api/webgl/gl.py +1537 -0
- pyglet/graphics/api/webgl/gl_info.py +130 -0
- pyglet/graphics/api/webgl/shader.py +1346 -0
- pyglet/graphics/api/webgl/shapes.py +92 -0
- pyglet/graphics/api/webgl/sprite.py +102 -0
- pyglet/graphics/api/webgl/state.py +227 -0
- pyglet/graphics/api/webgl/text.py +187 -0
- pyglet/graphics/api/webgl/texture.py +1227 -0
- pyglet/graphics/api/webgl/vertexarray.py +54 -0
- pyglet/graphics/api/webgl/vertexdomain.py +616 -0
- pyglet/graphics/api/webgl/webgl_js.pyi +307 -0
- pyglet/{image → graphics}/atlas.py +33 -32
- pyglet/graphics/base.py +10 -0
- pyglet/graphics/buffer.py +245 -0
- pyglet/graphics/draw.py +578 -0
- pyglet/graphics/framebuffer.py +26 -0
- pyglet/graphics/instance.py +178 -69
- pyglet/graphics/shader.py +267 -1553
- pyglet/graphics/state.py +83 -0
- pyglet/graphics/texture.py +703 -0
- pyglet/graphics/vertexdomain.py +695 -538
- pyglet/gui/ninepatch.py +10 -10
- pyglet/gui/widgets.py +120 -10
- pyglet/image/__init__.py +20 -1973
- pyglet/image/animation.py +12 -12
- pyglet/image/base.py +730 -0
- pyglet/image/codecs/__init__.py +9 -0
- pyglet/image/codecs/bmp.py +53 -30
- pyglet/image/codecs/dds.py +53 -31
- pyglet/image/codecs/gdiplus.py +38 -14
- pyglet/image/codecs/gdkpixbuf2.py +0 -2
- pyglet/image/codecs/js_image.py +99 -0
- pyglet/image/codecs/ktx2.py +161 -0
- pyglet/image/codecs/pil.py +1 -1
- pyglet/image/codecs/png.py +1 -1
- pyglet/image/codecs/wic.py +11 -2
- pyglet/info.py +26 -24
- pyglet/input/__init__.py +8 -0
- pyglet/input/base.py +163 -105
- pyglet/input/controller.py +13 -19
- pyglet/input/controller_db.py +39 -24
- pyglet/input/emscripten/__init__.py +18 -0
- pyglet/input/emscripten/gamepad_js.py +397 -0
- pyglet/input/linux/__init__.py +11 -5
- pyglet/input/linux/evdev.py +10 -11
- pyglet/input/linux/x11_xinput.py +2 -2
- pyglet/input/linux/x11_xinput_tablet.py +1 -1
- pyglet/input/macos/__init__.py +7 -2
- pyglet/input/macos/darwin_gc.py +559 -0
- pyglet/input/win32/__init__.py +1 -1
- pyglet/input/win32/directinput.py +34 -29
- pyglet/input/win32/xinput.py +11 -61
- pyglet/lib.py +3 -3
- pyglet/libs/__init__.py +1 -1
- pyglet/{gl → libs/darwin}/agl.py +1 -1
- pyglet/libs/darwin/cocoapy/__init__.py +2 -2
- pyglet/libs/darwin/cocoapy/cocoahelpers.py +181 -0
- pyglet/libs/darwin/cocoapy/cocoalibs.py +31 -0
- pyglet/libs/darwin/cocoapy/cocoatypes.py +27 -0
- pyglet/libs/darwin/cocoapy/runtime.py +81 -45
- pyglet/libs/darwin/coreaudio.py +4 -4
- pyglet/{gl → libs/darwin}/lib_agl.py +9 -8
- pyglet/libs/darwin/quartzkey.py +1 -3
- pyglet/libs/egl/__init__.py +2 -0
- pyglet/libs/egl/egl_lib.py +576 -0
- pyglet/libs/egl/eglext.py +51 -5
- pyglet/libs/linux/__init__.py +0 -0
- pyglet/libs/linux/egl/__init__.py +0 -0
- pyglet/libs/linux/egl/eglext.py +22 -0
- pyglet/libs/linux/glx/__init__.py +0 -0
- pyglet/{gl → libs/linux/glx}/glx.py +13 -14
- pyglet/{gl → libs/linux/glx}/glxext_arb.py +408 -192
- pyglet/{gl → libs/linux/glx}/glxext_mesa.py +1 -1
- pyglet/{gl → libs/linux/glx}/glxext_nv.py +345 -164
- pyglet/{gl → libs/linux/glx}/lib_glx.py +3 -2
- pyglet/libs/linux/wayland/__init__.py +0 -0
- pyglet/libs/linux/wayland/client.py +1068 -0
- pyglet/libs/linux/wayland/lib_wayland.py +207 -0
- pyglet/libs/linux/wayland/wayland_egl.py +38 -0
- pyglet/libs/{wayland → linux/wayland}/xkbcommon.py +26 -0
- pyglet/libs/{x11 → linux/x11}/xf86vmode.py +4 -4
- pyglet/libs/{x11 → linux/x11}/xinerama.py +2 -2
- pyglet/libs/{x11 → linux/x11}/xinput.py +10 -10
- pyglet/libs/linux/x11/xrandr.py +0 -0
- pyglet/libs/{x11 → linux/x11}/xrender.py +1 -1
- pyglet/libs/shared/__init__.py +0 -0
- pyglet/libs/shared/spirv/__init__.py +0 -0
- pyglet/libs/shared/spirv/lib_shaderc.py +85 -0
- pyglet/libs/shared/spirv/lib_spirv_cross.py +126 -0
- pyglet/libs/win32/__init__.py +28 -8
- pyglet/libs/win32/constants.py +59 -48
- pyglet/libs/win32/context_managers.py +20 -3
- pyglet/libs/win32/dinput.py +105 -88
- pyglet/{gl → libs/win32}/lib_wgl.py +52 -26
- pyglet/libs/win32/types.py +58 -23
- pyglet/{gl → libs/win32}/wgl.py +32 -25
- pyglet/{gl → libs/win32}/wglext_arb.py +364 -2
- pyglet/media/__init__.py +9 -10
- pyglet/media/codecs/__init__.py +12 -1
- pyglet/media/codecs/base.py +99 -96
- pyglet/media/codecs/ffmpeg.py +2 -2
- pyglet/media/codecs/ffmpeg_lib/libavformat.py +3 -8
- pyglet/media/codecs/webaudio_pyodide.py +111 -0
- pyglet/media/drivers/__init__.py +9 -4
- pyglet/media/drivers/base.py +4 -4
- pyglet/media/drivers/openal/__init__.py +1 -1
- pyglet/media/drivers/openal/adaptation.py +3 -3
- pyglet/media/drivers/pulse/__init__.py +1 -1
- pyglet/media/drivers/pulse/adaptation.py +3 -3
- pyglet/media/drivers/pyodide_js/__init__.py +8 -0
- pyglet/media/drivers/pyodide_js/adaptation.py +288 -0
- pyglet/media/drivers/xaudio2/adaptation.py +3 -3
- pyglet/media/player.py +276 -193
- pyglet/media/player_worker_thread.py +1 -1
- pyglet/model/__init__.py +39 -29
- pyglet/model/codecs/base.py +4 -4
- pyglet/model/codecs/gltf.py +3 -3
- pyglet/model/codecs/obj.py +71 -43
- pyglet/resource.py +129 -78
- pyglet/shapes.py +154 -194
- pyglet/sprite.py +47 -164
- pyglet/text/__init__.py +44 -54
- pyglet/text/caret.py +12 -7
- pyglet/text/document.py +19 -17
- pyglet/text/formats/html.py +2 -2
- pyglet/text/formats/structured.py +10 -40
- pyglet/text/layout/__init__.py +20 -13
- pyglet/text/layout/base.py +176 -287
- pyglet/text/layout/incremental.py +9 -10
- pyglet/text/layout/scrolling.py +7 -95
- pyglet/window/__init__.py +183 -172
- pyglet/window/cocoa/__init__.py +62 -51
- pyglet/window/cocoa/pyglet_delegate.py +2 -25
- pyglet/window/cocoa/pyglet_view.py +9 -8
- pyglet/window/dialog/__init__.py +184 -0
- pyglet/window/dialog/base.py +99 -0
- pyglet/window/dialog/darwin.py +121 -0
- pyglet/window/dialog/linux.py +72 -0
- pyglet/window/dialog/windows.py +194 -0
- pyglet/window/emscripten/__init__.py +779 -0
- pyglet/window/headless/__init__.py +44 -28
- pyglet/window/key.py +2 -0
- pyglet/window/mouse.py +2 -2
- pyglet/window/wayland/__init__.py +377 -0
- pyglet/window/win32/__init__.py +101 -46
- pyglet/window/xlib/__init__.py +104 -66
- {pyglet-2.1.13.dist-info → pyglet-3.0.dev1.dist-info}/METADATA +2 -3
- pyglet-3.0.dev1.dist-info/RECORD +322 -0
- {pyglet-2.1.13.dist-info → pyglet-3.0.dev1.dist-info}/WHEEL +1 -1
- pyglet/gl/__init__.py +0 -208
- pyglet/gl/base.py +0 -499
- pyglet/gl/cocoa.py +0 -309
- pyglet/gl/gl.py +0 -4625
- pyglet/gl/gl.pyi +0 -2320
- pyglet/gl/gl_compat.pyi +0 -3097
- pyglet/gl/gl_info.py +0 -190
- pyglet/gl/headless.py +0 -166
- pyglet/gl/wgl_info.py +0 -36
- pyglet/gl/wglext_nv.py +0 -1096
- pyglet/gl/win32.py +0 -268
- pyglet/gl/xlib.py +0 -295
- pyglet/image/buffer.py +0 -274
- pyglet/image/codecs/s3tc.py +0 -354
- pyglet/libs/x11/xrandr.py +0 -166
- pyglet-2.1.13.dist-info/RECORD +0 -234
- /pyglet/{libs/wayland → graphics/api/gl/cocoa}/__init__.py +0 -0
- /pyglet/libs/{egl → linux/egl}/egl.py +0 -0
- /pyglet/libs/{egl → linux/egl}/lib.py +0 -0
- /pyglet/libs/{ioctl.py → linux/ioctl.py} +0 -0
- /pyglet/libs/{wayland → linux/wayland}/gbm.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/__init__.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/cursorfont.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/xlib.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/xsync.py +0 -0
- {pyglet-2.1.13.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
|
@@ -0,0 +1,703 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import abstractmethod
|
|
4
|
+
from typing import Iterator, Literal, TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
import pyglet
|
|
7
|
+
from pyglet.enums import AddressMode, ComponentFormat, TextureFilter, TextureType
|
|
8
|
+
from pyglet.image.base import (
|
|
9
|
+
_AbstractImage,
|
|
10
|
+
_AbstractImageSequence,
|
|
11
|
+
ImageData,
|
|
12
|
+
ImageDataRegion,
|
|
13
|
+
ImageException,
|
|
14
|
+
ImageGrid,
|
|
15
|
+
_AbstractGrid,
|
|
16
|
+
CompressionFormat,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from pyglet.graphics.api.base import SurfaceContext
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TextureArraySizeExceeded(ImageException):
|
|
24
|
+
"""Exception occurs ImageData dimensions are larger than the array supports."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class TextureArrayDepthExceeded(ImageException):
|
|
28
|
+
"""Exception occurs when depth has hit the maximum supported of the array."""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class TextureSequence(_AbstractImageSequence):
|
|
32
|
+
"""Interface for a sequence of textures.
|
|
33
|
+
|
|
34
|
+
Typical implementations store multiple :py:class:`~pyglet.graphics.TextureRegion`s
|
|
35
|
+
within one :py:class:`~pyglet.graphics.Texture` to minimise state changes.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __getitem__(self, item) -> TextureBase:
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
|
|
41
|
+
def __setitem__(self, item, texture: type[TextureBase]) -> _AbstractImage:
|
|
42
|
+
raise NotImplementedError
|
|
43
|
+
|
|
44
|
+
def __len__(self) -> int:
|
|
45
|
+
raise NotImplementedError
|
|
46
|
+
|
|
47
|
+
def __iter__(self) -> Iterator[TextureBase]:
|
|
48
|
+
raise NotImplementedError
|
|
49
|
+
|
|
50
|
+
def get_texture_sequence(self) -> TextureSequence:
|
|
51
|
+
return self
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class TextureBase(_AbstractImage):
|
|
55
|
+
"""An image loaded into GPU memory.
|
|
56
|
+
|
|
57
|
+
Typically, you will get an instance of Texture by accessing calling
|
|
58
|
+
the ``get_texture()`` method of any AbstractImage class (such as ImageData).
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
region_class: TextureRegionBase # Set to TextureRegion after it's defined
|
|
62
|
+
"""The class to use when constructing regions of this texture.
|
|
63
|
+
The class should be a subclass of TextureRegion.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
tex_coords = (0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0)
|
|
67
|
+
"""12-tuple of float, named (u1, v1, r1, u2, v2, r2, ...).
|
|
68
|
+
``u, v, r`` give the 3D texture coordinates for vertices 1-4. The vertices
|
|
69
|
+
are specified in the order bottom-left, bottom-right, top-right and top-left.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
tex_coords_order: tuple[int, int, int, int] = (0, 1, 2, 3)
|
|
73
|
+
"""The default vertex winding order for a quad.
|
|
74
|
+
This defaults to counter-clockwise, starting at the bottom-left.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
target: int
|
|
78
|
+
"""The GL texture target (e.g., ``GL_TEXTURE_2D``)."""
|
|
79
|
+
|
|
80
|
+
level: int = 0
|
|
81
|
+
"""The mipmap level of this texture."""
|
|
82
|
+
|
|
83
|
+
images = 1
|
|
84
|
+
|
|
85
|
+
default_filters: TextureFilter | tuple[TextureFilter, TextureFilter] = TextureFilter.LINEAR, TextureFilter.LINEAR
|
|
86
|
+
"""The default minification and magnification filters, as a tuple.
|
|
87
|
+
Both default to LINEAR. If a texture is created without specifying
|
|
88
|
+
a filter, these defaults will be used.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
x: int = 0
|
|
92
|
+
y: int = 0
|
|
93
|
+
z: int = 0
|
|
94
|
+
|
|
95
|
+
def __init__(self, width: int, height: int, tex_id: int,
|
|
96
|
+
tex_type: TextureType = TextureType.TYPE_2D,
|
|
97
|
+
internal_format: ComponentFormat = ComponentFormat.RGBA,
|
|
98
|
+
internal_format_size: int = 8,
|
|
99
|
+
internal_format_type: str = "b",
|
|
100
|
+
filters: TextureFilter | tuple[TextureFilter, TextureFilter] | None = None,
|
|
101
|
+
address_mode: AddressMode = AddressMode.REPEAT,
|
|
102
|
+
anisotropic_level: int = 0,
|
|
103
|
+
) -> None:
|
|
104
|
+
super().__init__(width, height)
|
|
105
|
+
self.id = tex_id
|
|
106
|
+
self.tex_type = tex_type
|
|
107
|
+
|
|
108
|
+
# Use class defaults if None:
|
|
109
|
+
filters = filters or self.default_filters
|
|
110
|
+
|
|
111
|
+
if isinstance(filters, TextureFilter):
|
|
112
|
+
self.min_filter = filters
|
|
113
|
+
self.mag_filter = filters
|
|
114
|
+
else:
|
|
115
|
+
self.min_filter, self.mag_filter = filters
|
|
116
|
+
|
|
117
|
+
self.address_mode = address_mode
|
|
118
|
+
self.internal_format = internal_format
|
|
119
|
+
self.internal_format_size = internal_format_size
|
|
120
|
+
self.internal_format_type = internal_format_type
|
|
121
|
+
self.anisotropic_level = anisotropic_level
|
|
122
|
+
|
|
123
|
+
def delete(self) -> None:
|
|
124
|
+
"""Delete this texture and the memory it occupies.
|
|
125
|
+
|
|
126
|
+
Textures are invalid after deletion, and may no longer be used.
|
|
127
|
+
"""
|
|
128
|
+
self.id = None
|
|
129
|
+
|
|
130
|
+
#def __del__(self):
|
|
131
|
+
# raise NotImplementedError
|
|
132
|
+
|
|
133
|
+
def bind(self, texture_unit: int = 0) -> None:
|
|
134
|
+
"""Bind to a specific Texture Unit by number."""
|
|
135
|
+
raise NotImplementedError
|
|
136
|
+
|
|
137
|
+
# def bind_image_texture(self, unit: int, level: int = 0, layered: bool = False,
|
|
138
|
+
# layer: int = 0, access: int = GL_READ_WRITE, fmt: int = GL_RGBA32F):
|
|
139
|
+
# """Bind as an ImageTexture for use with a :py:class:`~pyglet.shader.ComputeShaderProgram`.
|
|
140
|
+
#
|
|
141
|
+
# .. note:: OpenGL 4.3, or 4.2 with the GL_ARB_compute_shader extention is required.
|
|
142
|
+
# """
|
|
143
|
+
# raise NotImplementedError
|
|
144
|
+
|
|
145
|
+
@classmethod
|
|
146
|
+
def create(cls, width: int, height: int,
|
|
147
|
+
tex_type: TextureType = TextureType.TYPE_2D,
|
|
148
|
+
internal_format: ComponentFormat = ComponentFormat.RGBA,
|
|
149
|
+
data_type: str = "b",
|
|
150
|
+
filters: TextureFilter | tuple[TextureFilter, TextureFilter] | None = None,
|
|
151
|
+
address_mode: AddressMode = AddressMode.REPEAT,
|
|
152
|
+
anisotropic_level: int = 0,
|
|
153
|
+
blank_data: bool = True,
|
|
154
|
+
context: SurfaceContext | None = None) -> TextureBase:
|
|
155
|
+
"""Create a Texture.
|
|
156
|
+
|
|
157
|
+
Create a Texture with the specified dimensions, target and format.
|
|
158
|
+
On return, the texture will be bound.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
width:
|
|
162
|
+
Width of texture in pixels.
|
|
163
|
+
height:
|
|
164
|
+
Height of texture in pixels.
|
|
165
|
+
tex_type:
|
|
166
|
+
The type of texture.
|
|
167
|
+
internal_format:
|
|
168
|
+
The components of the internal format.
|
|
169
|
+
data_type:
|
|
170
|
+
The data type of the internal format, as a struct string value.
|
|
171
|
+
filters:
|
|
172
|
+
The texture filter for the min and mag filters. If a single value is passed, both values will
|
|
173
|
+
be used as the filter.
|
|
174
|
+
address_mode:
|
|
175
|
+
The wrapping address mode of the texture.
|
|
176
|
+
anisotropic_level:
|
|
177
|
+
The anisotropic level of the texture.
|
|
178
|
+
blank_data:
|
|
179
|
+
If True, initialize the texture data with all zeros. If False, do not pass initial data.
|
|
180
|
+
context:
|
|
181
|
+
If multiple contexts are being used, a specified context the texture is tied to.
|
|
182
|
+
"""
|
|
183
|
+
raise NotImplementedError
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def create_from_image(cls, image_data: ImageData | ImageDataRegion,
|
|
187
|
+
tex_type: TextureType = TextureType.TYPE_2D,
|
|
188
|
+
internal_format_size: int = 8,
|
|
189
|
+
filters: TextureFilter | tuple[TextureFilter, TextureFilter] | None = None,
|
|
190
|
+
address_mode: AddressMode = AddressMode.REPEAT,
|
|
191
|
+
anisotropic_level: int = 0,
|
|
192
|
+
context: SurfaceContext | None = None,
|
|
193
|
+
) -> TextureBase:
|
|
194
|
+
"""Create a Texture from image data.
|
|
195
|
+
|
|
196
|
+
On return, the texture will be bound.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
image_data:
|
|
200
|
+
The image instance.
|
|
201
|
+
tex_type:
|
|
202
|
+
The type of texture.
|
|
203
|
+
internal_format_size:
|
|
204
|
+
The bit size of the internal format.
|
|
205
|
+
filters:
|
|
206
|
+
The texture filter for the min and mag filters. If a single value is passed, both values will
|
|
207
|
+
be used as the filter.
|
|
208
|
+
address_mode:
|
|
209
|
+
The wrapping address mode of the texture.
|
|
210
|
+
anisotropic_level:
|
|
211
|
+
The anisotropic level of the texture.
|
|
212
|
+
context:
|
|
213
|
+
If multiple contexts are being used, a specified context the texture will be tied to.
|
|
214
|
+
"""
|
|
215
|
+
|
|
216
|
+
def get_image_data(self, z: int = 0) -> ImageData:
|
|
217
|
+
"""To be removed and replaced with fetch."""
|
|
218
|
+
raise NotImplementedError
|
|
219
|
+
|
|
220
|
+
def get_texture(self) -> TextureBase:
|
|
221
|
+
return self
|
|
222
|
+
|
|
223
|
+
def blit(self, x: int, y: int, z: int = 0, width: int | None = None, height: int | None = None) -> None:
|
|
224
|
+
"""Blit the texture to the screen.
|
|
225
|
+
|
|
226
|
+
Removed as of 3.0. Instead, consider creating a :py:class:`~pyglet.sprite.Sprite` with the Texture,
|
|
227
|
+
and drawing it as part of a larger :py:class:`~pyglet.graphics.Batch`.
|
|
228
|
+
"""
|
|
229
|
+
raise NotImplementedError("This method has been removed. See the 3.0 migration documentation.")
|
|
230
|
+
|
|
231
|
+
def fetch(self, z: int = 0) -> ImageData:
|
|
232
|
+
"""Fetch the image data of this texture by reading pixel data back from the GPU.
|
|
233
|
+
|
|
234
|
+
This can be a somewhat costly operation.
|
|
235
|
+
|
|
236
|
+
Modifying the returned ImageData object has no effect on the
|
|
237
|
+
texture itself. Uploading ImageData back to the GPU/texture
|
|
238
|
+
can be done with the :py:meth:`~Texture.upload` method.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
z:
|
|
242
|
+
For 3D textures, the image slice to retrieve.
|
|
243
|
+
"""
|
|
244
|
+
raise NotImplementedError
|
|
245
|
+
|
|
246
|
+
def get_mipmapped_texture(self) -> TextureBase:
|
|
247
|
+
raise NotImplementedError(f"Not implemented for {self}.")
|
|
248
|
+
|
|
249
|
+
def upload(self, image: ImageData | ImageDataRegion, x: int, y: int, z: int) -> None:
|
|
250
|
+
"""Upload image data into the Texture at specific coordinates.
|
|
251
|
+
|
|
252
|
+
You must have this texture bound before uploading data.
|
|
253
|
+
|
|
254
|
+
The image's anchor point will be aligned to the given ``x`` and ``y``
|
|
255
|
+
coordinates. If this texture is a 3D texture, the ``z``
|
|
256
|
+
parameter gives the image slice to blit into.
|
|
257
|
+
"""
|
|
258
|
+
raise NotImplementedError(f"Not implemented for {self}")
|
|
259
|
+
|
|
260
|
+
def get_region(self, x: int, y: int, width: int, height: int) -> TextureRegionBase:
|
|
261
|
+
return self.region_class(x, y, 0, width, height, self)
|
|
262
|
+
|
|
263
|
+
def get_transform(self, flip_x: bool = False, flip_y: bool = False,
|
|
264
|
+
rotate: Literal[0, 90, 180, 270, 360] = 0) -> TextureRegionBase:
|
|
265
|
+
"""Create a copy of this image applying a simple transformation.
|
|
266
|
+
|
|
267
|
+
The transformation is applied to the texture coordinates only;
|
|
268
|
+
:py:meth:`~pyglet.image.AbstractImage.get_image_data` will return the
|
|
269
|
+
untransformed data. The transformation is applied around the anchor point.
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
flip_x:
|
|
273
|
+
If True, the returned image will be flipped horizontally.
|
|
274
|
+
flip_y:
|
|
275
|
+
If True, the returned image will be flipped vertically.
|
|
276
|
+
rotate:
|
|
277
|
+
Degrees of clockwise rotation of the returned image. Only
|
|
278
|
+
90-degree increments are supported.
|
|
279
|
+
"""
|
|
280
|
+
transform = self.get_region(0, 0, self.width, self.height)
|
|
281
|
+
bl, br, tr, tl = 0, 1, 2, 3
|
|
282
|
+
transform.anchor_x = self.anchor_x
|
|
283
|
+
transform.anchor_y = self.anchor_y
|
|
284
|
+
if flip_x:
|
|
285
|
+
bl, br, tl, tr = br, bl, tr, tl
|
|
286
|
+
transform.anchor_x = self.width - self.anchor_x
|
|
287
|
+
if flip_y:
|
|
288
|
+
bl, br, tl, tr = tl, tr, bl, br
|
|
289
|
+
transform.anchor_y = self.height - self.anchor_y
|
|
290
|
+
rotate %= 360
|
|
291
|
+
if rotate < 0:
|
|
292
|
+
rotate += 360
|
|
293
|
+
if rotate == 0:
|
|
294
|
+
pass
|
|
295
|
+
elif rotate == 90:
|
|
296
|
+
bl, br, tr, tl = br, tr, tl, bl
|
|
297
|
+
transform.anchor_x, transform.anchor_y = transform.anchor_y, transform.width - transform.anchor_x
|
|
298
|
+
elif rotate == 180:
|
|
299
|
+
bl, br, tr, tl = tr, tl, bl, br
|
|
300
|
+
transform.anchor_x = transform.width - transform.anchor_x
|
|
301
|
+
transform.anchor_y = transform.height - transform.anchor_y
|
|
302
|
+
elif rotate == 270:
|
|
303
|
+
bl, br, tr, tl = tl, bl, br, tr
|
|
304
|
+
transform.anchor_x, transform.anchor_y = transform.height - transform.anchor_y, transform.anchor_x
|
|
305
|
+
else:
|
|
306
|
+
raise ImageException("Only 90 degree rotations are supported.")
|
|
307
|
+
if rotate in (90, 270):
|
|
308
|
+
transform.width, transform.height = transform.height, transform.width
|
|
309
|
+
transform._set_tex_coords_order(bl, br, tr, tl)
|
|
310
|
+
return transform
|
|
311
|
+
|
|
312
|
+
def _set_tex_coords_order(self, bl, br, tr, tl):
|
|
313
|
+
tex_coords = (self.tex_coords[:3],
|
|
314
|
+
self.tex_coords[3:6],
|
|
315
|
+
self.tex_coords[6:9],
|
|
316
|
+
self.tex_coords[9:])
|
|
317
|
+
self.tex_coords = tex_coords[bl] + tex_coords[br] + tex_coords[tr] + tex_coords[tl]
|
|
318
|
+
|
|
319
|
+
order = self.tex_coords_order
|
|
320
|
+
self.tex_coords_order = (order[bl], order[br], order[tr], order[tl])
|
|
321
|
+
|
|
322
|
+
@property
|
|
323
|
+
def uv(self) -> tuple[float, float, float, float]:
|
|
324
|
+
"""Tuple containing the left, bottom, right, top 2D texture coordinates."""
|
|
325
|
+
tex_coords = self.tex_coords
|
|
326
|
+
return tex_coords[0], tex_coords[1], tex_coords[3], tex_coords[7]
|
|
327
|
+
|
|
328
|
+
@property
|
|
329
|
+
def filters(self) -> tuple[TextureFilter, TextureFilter]:
|
|
330
|
+
"""The current Texture filters.
|
|
331
|
+
|
|
332
|
+
Providing a single TextureFilter will adjust both minification and magnification filters. Otherwise, a tuple
|
|
333
|
+
can be provided to adjust each individually.
|
|
334
|
+
"""
|
|
335
|
+
return self.min_filter, self.mag_filter
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def __repr__(self) -> str:
|
|
339
|
+
return f"{self.__class__.__name__}(id={self.id}, size={self.width}x{self.height})"
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
class TextureRegionBase(TextureBase):
|
|
343
|
+
"""A rectangular region of a texture, presented as if it were a separate texture."""
|
|
344
|
+
|
|
345
|
+
def __init__(self, x: int, y: int, z: int, width: int, height: int, owner: TextureBase):
|
|
346
|
+
super().__init__(width, height, owner.id, owner.tex_type, owner.internal_format,
|
|
347
|
+
owner.internal_format_size, owner.internal_format_type, owner.filters, owner.address_mode,
|
|
348
|
+
owner.anisotropic_level)
|
|
349
|
+
|
|
350
|
+
self.x = x
|
|
351
|
+
self.y = y
|
|
352
|
+
self.z = z
|
|
353
|
+
self._width = width
|
|
354
|
+
self._height = height
|
|
355
|
+
self.owner = owner
|
|
356
|
+
owner_u1 = owner.tex_coords[0]
|
|
357
|
+
owner_v1 = owner.tex_coords[1]
|
|
358
|
+
owner_u2 = owner.tex_coords[3]
|
|
359
|
+
owner_v2 = owner.tex_coords[7]
|
|
360
|
+
scale_u = owner_u2 - owner_u1
|
|
361
|
+
scale_v = owner_v2 - owner_v1
|
|
362
|
+
u1 = x / owner.width * scale_u + owner_u1
|
|
363
|
+
v1 = y / owner.height * scale_v + owner_v1
|
|
364
|
+
u2 = (x + width) / owner.width * scale_u + owner_u1
|
|
365
|
+
v2 = (y + height) / owner.height * scale_v + owner_v1
|
|
366
|
+
r = z / owner.images + owner.tex_coords[2]
|
|
367
|
+
self.tex_coords = (u1, v1, r, u2, v1, r, u2, v2, r, u1, v2, r)
|
|
368
|
+
raise Exception
|
|
369
|
+
|
|
370
|
+
def fetch(self, _z = 0) -> ImageDataRegion:
|
|
371
|
+
image_data = self.owner.get_image_data(self.z)
|
|
372
|
+
return image_data.get_region(self.x, self.y, self.width, self.height)
|
|
373
|
+
|
|
374
|
+
def get_image_data(self) -> ImageDataRegion:
|
|
375
|
+
return self.fetch()
|
|
376
|
+
|
|
377
|
+
def get_region(self, x: int, y: int, width: int, height: int) -> TextureRegionBase:
|
|
378
|
+
x += self.x
|
|
379
|
+
y += self.y
|
|
380
|
+
region = self.region_class(x, y, self.z, width, height, self.owner)
|
|
381
|
+
region._set_tex_coords_order(*self.tex_coords_order)
|
|
382
|
+
return region
|
|
383
|
+
|
|
384
|
+
def upload(self, source: ImageData, x: int, y: int, z: int) -> None:
|
|
385
|
+
assert source.width <= self._width and source.height <= self._height, f"{source} is larger than {self}"
|
|
386
|
+
self.owner.upload(source, x + self.x, y + self.y, z + self.z)
|
|
387
|
+
|
|
388
|
+
def __repr__(self) -> str:
|
|
389
|
+
return (f"{self.__class__.__name__}(id={self.id},"
|
|
390
|
+
f" size={self.width}x{self.height}, owner={self.owner.width}x{self.owner.height})")
|
|
391
|
+
|
|
392
|
+
def delete(self) -> None:
|
|
393
|
+
"""Deleting a TextureRegion has no effect. Operate on the owning texture instead."""
|
|
394
|
+
|
|
395
|
+
def __del__(self):
|
|
396
|
+
pass
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
class UniformTextureSequence(TextureSequence):
|
|
400
|
+
"""Interface for a sequence of textures, each with the same dimensions."""
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
class TextureArrayRegionBase(TextureRegionBase):
|
|
404
|
+
"""A region of a TextureArray, presented as if it were a separate texture."""
|
|
405
|
+
|
|
406
|
+
def __repr__(self):
|
|
407
|
+
return f"{self.__class__.__name__}(id={self.id}, size={self.width}x{self.height}, layer={self.z})"
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
class TextureArrayBase(TextureBase, UniformTextureSequence):
|
|
411
|
+
def __init__(self, width, height, tex_id, max_depth,
|
|
412
|
+
internal_format: ComponentFormat = ComponentFormat.RGBA,
|
|
413
|
+
internal_format_size: int = 8,
|
|
414
|
+
internal_format_type: str = "b",
|
|
415
|
+
filters: TextureFilter | tuple[TextureFilter, TextureFilter] | None = None,
|
|
416
|
+
address_mode: AddressMode = AddressMode.REPEAT,
|
|
417
|
+
anisotropic_level: int = 0,
|
|
418
|
+
):
|
|
419
|
+
super().__init__(width, height, tex_id, TextureType.TYPE_2D_ARRAY, internal_format, internal_format_size,
|
|
420
|
+
internal_format_type, filters, address_mode, anisotropic_level)
|
|
421
|
+
self.max_depth = max_depth
|
|
422
|
+
self.items = []
|
|
423
|
+
|
|
424
|
+
@classmethod
|
|
425
|
+
def create(cls, width: int, height: int,
|
|
426
|
+
internal_format: ComponentFormat = ComponentFormat.RGBA,
|
|
427
|
+
internal_format_size: int = 8,
|
|
428
|
+
internal_format_type: str = "b",
|
|
429
|
+
filters: TextureFilter | tuple[TextureFilter, TextureFilter] | None = None,
|
|
430
|
+
address_mode: AddressMode = AddressMode.REPEAT,
|
|
431
|
+
anisotropic_level: int = 0,
|
|
432
|
+
max_depth: int = 256) -> TextureArray:
|
|
433
|
+
"""Create an empty TextureArray.
|
|
434
|
+
|
|
435
|
+
You may specify the maximum depth, or layers, the Texture Array should have. This defaults
|
|
436
|
+
to 256, but will be hardware and driver dependent.
|
|
437
|
+
|
|
438
|
+
Args:
|
|
439
|
+
width:
|
|
440
|
+
Width of the texture.
|
|
441
|
+
height:
|
|
442
|
+
Height of the texture.
|
|
443
|
+
descriptor:
|
|
444
|
+
Texture description.
|
|
445
|
+
max_depth:
|
|
446
|
+
The number of layers in the texture array.
|
|
447
|
+
|
|
448
|
+
.. versionadded:: 2.0
|
|
449
|
+
"""
|
|
450
|
+
raise NotImplementedError
|
|
451
|
+
|
|
452
|
+
def _verify_size(self, image: _AbstractImage) -> None:
|
|
453
|
+
if image.width > self.width or image.height > self.height:
|
|
454
|
+
raise TextureArraySizeExceeded(
|
|
455
|
+
f'Image ({image.width}x{image.height}) exceeds the size of the TextureArray ({self.width}x'
|
|
456
|
+
f'{self.height})')
|
|
457
|
+
|
|
458
|
+
def add(self, image: ImageData) -> TextureArrayRegion:
|
|
459
|
+
if len(self.items) >= self.max_depth:
|
|
460
|
+
raise TextureArrayDepthExceeded("TextureArray is full.")
|
|
461
|
+
|
|
462
|
+
self._verify_size(image)
|
|
463
|
+
start_length = len(self.items)
|
|
464
|
+
item = self.region_class(0, 0, start_length, image.width, image.height, self)
|
|
465
|
+
|
|
466
|
+
self.blit_into(image, image.anchor_x, image.anchor_y, start_length)
|
|
467
|
+
self.items.append(item)
|
|
468
|
+
return item
|
|
469
|
+
|
|
470
|
+
def allocate(self, *images: _AbstractImage) -> list[TextureArrayRegion]:
|
|
471
|
+
"""Allocates multiple images at once."""
|
|
472
|
+
raise NotImplementedError
|
|
473
|
+
|
|
474
|
+
@classmethod
|
|
475
|
+
@abstractmethod
|
|
476
|
+
def create_for_image_grid(cls, grid) -> TextureArray:
|
|
477
|
+
...
|
|
478
|
+
|
|
479
|
+
def __len__(self) -> int:
|
|
480
|
+
return len(self.items)
|
|
481
|
+
|
|
482
|
+
def __getitem__(self, index) -> TextureArrayRegion:
|
|
483
|
+
return self.items[index]
|
|
484
|
+
|
|
485
|
+
def __setitem__(self, index, value) -> None:
|
|
486
|
+
raise NotImplementedError
|
|
487
|
+
|
|
488
|
+
def __iter__(self) -> Iterator[TextureRegionBase]:
|
|
489
|
+
return iter(self.items)
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
class Texture3D(TextureBase, UniformTextureSequence):
|
|
493
|
+
"""A texture with more than one image slice.
|
|
494
|
+
|
|
495
|
+
Use the :py:meth:`create_for_images` or :py:meth:`create_for_image_grid`
|
|
496
|
+
classmethod to construct a Texture3D.
|
|
497
|
+
"""
|
|
498
|
+
item_width: int = 0
|
|
499
|
+
item_height: int = 0
|
|
500
|
+
items: tuple
|
|
501
|
+
|
|
502
|
+
@classmethod
|
|
503
|
+
def create_for_images(cls, images,
|
|
504
|
+
internal_format_size: int = 8,
|
|
505
|
+
internal_format_type: str = "b",
|
|
506
|
+
filters: TextureFilter | tuple[TextureFilter, TextureFilter] | None = None,
|
|
507
|
+
address_mode: AddressMode = AddressMode.REPEAT,
|
|
508
|
+
anisotropic_level: int = 0, blank_data=True):
|
|
509
|
+
raise NotImplementedError
|
|
510
|
+
|
|
511
|
+
@classmethod
|
|
512
|
+
def create_for_image_grid(cls, grid,
|
|
513
|
+
internal_format: ComponentFormat = ComponentFormat.RGBA,
|
|
514
|
+
internal_format_size: int = 8,
|
|
515
|
+
internal_format_type: str = "b",
|
|
516
|
+
filters: TextureFilter | tuple[TextureFilter, TextureFilter] | None = None,
|
|
517
|
+
address_mode: AddressMode = AddressMode.REPEAT,
|
|
518
|
+
anisotropic_level: int = 0):
|
|
519
|
+
return cls.create_for_images(grid[:], internal_format, internal_format_size, internal_format_type,
|
|
520
|
+
filters, address_mode, anisotropic_level)
|
|
521
|
+
|
|
522
|
+
def __len__(self):
|
|
523
|
+
return len(self.items)
|
|
524
|
+
|
|
525
|
+
def __getitem__(self, index):
|
|
526
|
+
return self.items[index]
|
|
527
|
+
|
|
528
|
+
def __setitem__(self, index, value):
|
|
529
|
+
raise NotImplementedError
|
|
530
|
+
|
|
531
|
+
def __iter__(self) -> Iterator[TextureRegionBase]:
|
|
532
|
+
return iter(self.items)
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
class TextureGridBase(_AbstractGrid):
|
|
537
|
+
"""A texture containing a regular grid of texture regions.
|
|
538
|
+
|
|
539
|
+
To construct, create an :py:class:`~pyglet.image.ImageGrid` first::
|
|
540
|
+
|
|
541
|
+
image_grid = ImageGrid(...)
|
|
542
|
+
texture_grid = TextureGrid(image_grid)
|
|
543
|
+
|
|
544
|
+
The texture grid can be accessed as a single texture, or as a sequence
|
|
545
|
+
of :py:class:`~pyglet.graphics.TextureRegion`. When accessing as a sequence, you can specify
|
|
546
|
+
integer indexes, in which the images are arranged in rows from the
|
|
547
|
+
bottom-left to the top-right::
|
|
548
|
+
|
|
549
|
+
# assume the texture_grid is 3x3:
|
|
550
|
+
current_texture = texture_grid[3] # get the middle-left image
|
|
551
|
+
|
|
552
|
+
You can also specify tuples in the sequence methods, which are addressed
|
|
553
|
+
as ``row, column``::
|
|
554
|
+
|
|
555
|
+
# equivalent to the previous example:
|
|
556
|
+
current_texture = texture_grid[1, 0]
|
|
557
|
+
|
|
558
|
+
When using tuples in a slice, the returned sequence is over the
|
|
559
|
+
rectangular region defined by the slice::
|
|
560
|
+
|
|
561
|
+
# returns center, center-right, center-top, top-right images in that
|
|
562
|
+
# order:
|
|
563
|
+
images = texture_grid[(1,1):]
|
|
564
|
+
# equivalent to
|
|
565
|
+
images = texture_grid[(1,1):(3,3)]
|
|
566
|
+
|
|
567
|
+
"""
|
|
568
|
+
def __init__(self, texture: Texture | TextureRegion, rows: int, columns: int, item_width: int,
|
|
569
|
+
item_height: int, row_padding: int = 0, column_padding: int = 0) -> None:
|
|
570
|
+
"""Construct a grid for the given image.
|
|
571
|
+
|
|
572
|
+
You can specify parameters for the grid, for example setting
|
|
573
|
+
the padding between cells. Grids are always aligned to the
|
|
574
|
+
bottom-left corner of the image.
|
|
575
|
+
|
|
576
|
+
Args:
|
|
577
|
+
texture:
|
|
578
|
+
A texture or region over which to construct the grid.
|
|
579
|
+
rows:
|
|
580
|
+
Number of rows in the grid.
|
|
581
|
+
columns:
|
|
582
|
+
Number of columns in the grid.
|
|
583
|
+
item_width:
|
|
584
|
+
Width of each column. If unspecified, is calculated such
|
|
585
|
+
that the entire texture width is used.
|
|
586
|
+
item_height:
|
|
587
|
+
Height of each row. If unspecified, is calculated such that
|
|
588
|
+
the entire texture height is used.
|
|
589
|
+
row_padding:
|
|
590
|
+
Pixels separating adjacent rows. The padding is only
|
|
591
|
+
inserted between rows, not at the edges of the grid.
|
|
592
|
+
column_padding:
|
|
593
|
+
Pixels separating adjacent columns. The padding is only
|
|
594
|
+
inserted between columns, not at the edges of the grid.
|
|
595
|
+
"""
|
|
596
|
+
if isinstance(texture, TextureRegion):
|
|
597
|
+
owner = texture.owner
|
|
598
|
+
else:
|
|
599
|
+
owner = texture
|
|
600
|
+
|
|
601
|
+
item_width = item_width or (texture.width - column_padding * (columns - 1)) // columns
|
|
602
|
+
item_height = item_height or (texture.height - row_padding * (rows - 1)) // rows
|
|
603
|
+
self.texture = owner
|
|
604
|
+
super().__init__(rows, columns, item_width, item_height, row_padding, column_padding)
|
|
605
|
+
|
|
606
|
+
@classmethod
|
|
607
|
+
def from_image_grid(cls, image_grid: ImageGrid) -> TextureGridBase:
|
|
608
|
+
texture = image_grid.image.get_texture()
|
|
609
|
+
return cls(
|
|
610
|
+
texture,
|
|
611
|
+
image_grid.rows,
|
|
612
|
+
image_grid.columns,
|
|
613
|
+
image_grid.item_width,
|
|
614
|
+
image_grid.item_height,
|
|
615
|
+
image_grid.row_padding,
|
|
616
|
+
image_grid.column_padding,
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
TextureBase.region_class = TextureRegionBase
|
|
621
|
+
|
|
622
|
+
TextureArrayBase.region_class = TextureArrayRegionBase
|
|
623
|
+
TextureArrayRegionBase.region_class = TextureArrayRegionBase
|
|
624
|
+
|
|
625
|
+
class CompressedTextureBase(_AbstractImage):
|
|
626
|
+
tex_coords = (0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0)
|
|
627
|
+
"""12-tuple of float, named (u1, v1, r1, u2, v2, r2, ...).
|
|
628
|
+
``u, v, r`` give the 3D texture coordinates for vertices 1-4. The vertices
|
|
629
|
+
are specified in the order bottom-left, bottom-right, top-right and top-left.
|
|
630
|
+
"""
|
|
631
|
+
|
|
632
|
+
tex_coords_order: tuple[int, int, int, int] = (0, 1, 2, 3)
|
|
633
|
+
"""The default vertex winding order for a quad.
|
|
634
|
+
This defaults to counter-clockwise, starting at the bottom-left.
|
|
635
|
+
"""
|
|
636
|
+
|
|
637
|
+
target: int
|
|
638
|
+
"""The GL texture target (e.g., ``GL_TEXTURE_2D``)."""
|
|
639
|
+
|
|
640
|
+
level: int = 0
|
|
641
|
+
"""The mipmap level of this texture."""
|
|
642
|
+
|
|
643
|
+
images = 1
|
|
644
|
+
|
|
645
|
+
x: int = 0
|
|
646
|
+
y: int = 0
|
|
647
|
+
z: int = 0
|
|
648
|
+
|
|
649
|
+
def __init__(self, width: int, height: int, tex_id: int,
|
|
650
|
+
compression_format: CompressionFormat,
|
|
651
|
+
tex_type: TextureType = TextureType.TYPE_2D,
|
|
652
|
+
filters: TextureFilter | tuple[TextureFilter, TextureFilter] | None = None,
|
|
653
|
+
address_mode: AddressMode = AddressMode.REPEAT,
|
|
654
|
+
anisotropic_level: int = 0,
|
|
655
|
+
) -> None:
|
|
656
|
+
super().__init__(width, height)
|
|
657
|
+
self.id = tex_id
|
|
658
|
+
self.tex_type = tex_type
|
|
659
|
+
|
|
660
|
+
if isinstance(filters, TextureFilter):
|
|
661
|
+
self.min_filter = filters
|
|
662
|
+
self.mag_filter = filters
|
|
663
|
+
else:
|
|
664
|
+
self.min_filter, self.mag_filter = filters
|
|
665
|
+
|
|
666
|
+
self.address_mode = address_mode
|
|
667
|
+
self.internal_format = compression_format
|
|
668
|
+
self.anisotropic_level = anisotropic_level
|
|
669
|
+
|
|
670
|
+
def get_texture(self) -> CompressedTextureBase:
|
|
671
|
+
return self
|
|
672
|
+
|
|
673
|
+
if pyglet.options.backend in ("opengl", "gles3", "gl2", "gles2"):
|
|
674
|
+
from pyglet.graphics.api.gl.framebuffer import ( # noqa: F401
|
|
675
|
+
Framebuffer,
|
|
676
|
+
Renderbuffer,
|
|
677
|
+
get_max_color_attachments,
|
|
678
|
+
get_screenshot,
|
|
679
|
+
)
|
|
680
|
+
from pyglet.graphics.api.gl.texture import (
|
|
681
|
+
CompressedTexture, # noqa: F401
|
|
682
|
+
Texture,
|
|
683
|
+
TextureRegion,
|
|
684
|
+
Texture3D,
|
|
685
|
+
TextureArray,
|
|
686
|
+
TextureArrayRegion,
|
|
687
|
+
TextureGrid,
|
|
688
|
+
get_max_texture_size,
|
|
689
|
+
get_max_array_texture_layers,
|
|
690
|
+
)
|
|
691
|
+
elif pyglet.options.backend in ("webgl"):
|
|
692
|
+
from pyglet.graphics.api.webgl.texture import (
|
|
693
|
+
Texture,
|
|
694
|
+
TextureRegion,
|
|
695
|
+
Texture3D, # noqa: F401
|
|
696
|
+
TextureArray,
|
|
697
|
+
TextureArrayRegion,
|
|
698
|
+
TextureGrid, # noqa: F401
|
|
699
|
+
get_max_texture_size, # noqa: F401
|
|
700
|
+
get_max_array_texture_layers, # noqa: F401
|
|
701
|
+
)
|
|
702
|
+
elif pyglet.options.backend == "vulkan":
|
|
703
|
+
pass
|