pyglet 2.1.12__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.
Files changed (267) hide show
  1. pyglet/__init__.py +67 -61
  2. pyglet/__init__.pyi +15 -8
  3. pyglet/app/__init__.py +22 -13
  4. pyglet/app/async_app.py +212 -0
  5. pyglet/app/base.py +2 -1
  6. pyglet/app/{xlib.py → linux.py} +3 -3
  7. pyglet/config/__init__.py +101 -0
  8. pyglet/config/gl/__init__.py +30 -0
  9. pyglet/config/gl/egl.py +120 -0
  10. pyglet/config/gl/macos.py +262 -0
  11. pyglet/config/gl/windows.py +267 -0
  12. pyglet/config/gl/x11.py +142 -0
  13. pyglet/customtypes.py +43 -2
  14. pyglet/display/__init__.py +8 -6
  15. pyglet/display/base.py +3 -63
  16. pyglet/display/cocoa.py +12 -17
  17. pyglet/display/emscripten.py +39 -0
  18. pyglet/display/headless.py +23 -30
  19. pyglet/display/wayland.py +157 -0
  20. pyglet/display/win32.py +4 -17
  21. pyglet/display/xlib.py +19 -27
  22. pyglet/display/xlib_vidmoderestore.py +2 -2
  23. pyglet/enums.py +183 -0
  24. pyglet/event.py +0 -1
  25. pyglet/experimental/geoshader_sprite.py +15 -13
  26. pyglet/experimental/hidraw.py +6 -15
  27. pyglet/experimental/multitexture_sprite.py +31 -19
  28. pyglet/experimental/particles.py +13 -35
  29. pyglet/font/__init__.py +251 -85
  30. pyglet/font/base.py +116 -61
  31. pyglet/font/dwrite/__init__.py +349 -204
  32. pyglet/font/dwrite/dwrite_lib.py +27 -5
  33. pyglet/font/fontconfig.py +14 -6
  34. pyglet/font/freetype.py +138 -87
  35. pyglet/font/freetype_lib.py +19 -0
  36. pyglet/font/group.py +179 -0
  37. pyglet/font/harfbuzz/__init__.py +3 -3
  38. pyglet/font/pyodide_js.py +310 -0
  39. pyglet/font/quartz.py +319 -126
  40. pyglet/font/ttf.py +45 -3
  41. pyglet/font/user.py +14 -19
  42. pyglet/font/win32.py +45 -21
  43. pyglet/graphics/__init__.py +8 -787
  44. pyglet/graphics/allocation.py +115 -1
  45. pyglet/graphics/api/__init__.py +77 -0
  46. pyglet/graphics/api/base.py +299 -0
  47. pyglet/graphics/api/gl/__init__.py +58 -0
  48. pyglet/graphics/api/gl/base.py +24 -0
  49. pyglet/graphics/{vertexbuffer.py → api/gl/buffer.py} +104 -159
  50. pyglet/graphics/api/gl/cocoa/context.py +76 -0
  51. pyglet/graphics/api/gl/context.py +391 -0
  52. pyglet/graphics/api/gl/default_shaders.py +0 -0
  53. pyglet/graphics/api/gl/draw.py +627 -0
  54. pyglet/graphics/api/gl/egl/__init__.py +0 -0
  55. pyglet/graphics/api/gl/egl/context.py +92 -0
  56. pyglet/graphics/api/gl/enums.py +76 -0
  57. pyglet/graphics/api/gl/framebuffer.py +315 -0
  58. pyglet/graphics/api/gl/gl.py +5463 -0
  59. pyglet/graphics/api/gl/gl_info.py +188 -0
  60. pyglet/graphics/api/gl/global_opengl.py +226 -0
  61. pyglet/{gl → graphics/api/gl}/lib.py +34 -18
  62. pyglet/graphics/api/gl/shader.py +1476 -0
  63. pyglet/graphics/api/gl/shapes.py +55 -0
  64. pyglet/graphics/api/gl/sprite.py +102 -0
  65. pyglet/graphics/api/gl/state.py +219 -0
  66. pyglet/graphics/api/gl/text.py +190 -0
  67. pyglet/graphics/api/gl/texture.py +1526 -0
  68. pyglet/graphics/{vertexarray.py → api/gl/vertexarray.py} +11 -13
  69. pyglet/graphics/api/gl/vertexdomain.py +751 -0
  70. pyglet/graphics/api/gl/win32/__init__.py +0 -0
  71. pyglet/graphics/api/gl/win32/context.py +108 -0
  72. pyglet/graphics/api/gl/win32/wgl_info.py +24 -0
  73. pyglet/graphics/api/gl/xlib/__init__.py +0 -0
  74. pyglet/graphics/api/gl/xlib/context.py +174 -0
  75. pyglet/{gl → graphics/api/gl/xlib}/glx_info.py +26 -31
  76. pyglet/graphics/api/gl1/__init__.py +0 -0
  77. pyglet/{gl → graphics/api/gl1}/gl_compat.py +3 -2
  78. pyglet/graphics/api/gl2/__init__.py +0 -0
  79. pyglet/graphics/api/gl2/buffer.py +320 -0
  80. pyglet/graphics/api/gl2/draw.py +600 -0
  81. pyglet/graphics/api/gl2/global_opengl.py +122 -0
  82. pyglet/graphics/api/gl2/shader.py +200 -0
  83. pyglet/graphics/api/gl2/shapes.py +51 -0
  84. pyglet/graphics/api/gl2/sprite.py +79 -0
  85. pyglet/graphics/api/gl2/text.py +175 -0
  86. pyglet/graphics/api/gl2/vertexdomain.py +364 -0
  87. pyglet/graphics/api/webgl/__init__.py +233 -0
  88. pyglet/graphics/api/webgl/buffer.py +302 -0
  89. pyglet/graphics/api/webgl/context.py +234 -0
  90. pyglet/graphics/api/webgl/draw.py +590 -0
  91. pyglet/graphics/api/webgl/enums.py +76 -0
  92. pyglet/graphics/api/webgl/framebuffer.py +360 -0
  93. pyglet/graphics/api/webgl/gl.py +1537 -0
  94. pyglet/graphics/api/webgl/gl_info.py +130 -0
  95. pyglet/graphics/api/webgl/shader.py +1346 -0
  96. pyglet/graphics/api/webgl/shapes.py +92 -0
  97. pyglet/graphics/api/webgl/sprite.py +102 -0
  98. pyglet/graphics/api/webgl/state.py +227 -0
  99. pyglet/graphics/api/webgl/text.py +187 -0
  100. pyglet/graphics/api/webgl/texture.py +1227 -0
  101. pyglet/graphics/api/webgl/vertexarray.py +54 -0
  102. pyglet/graphics/api/webgl/vertexdomain.py +616 -0
  103. pyglet/graphics/api/webgl/webgl_js.pyi +307 -0
  104. pyglet/{image → graphics}/atlas.py +33 -32
  105. pyglet/graphics/base.py +10 -0
  106. pyglet/graphics/buffer.py +245 -0
  107. pyglet/graphics/draw.py +578 -0
  108. pyglet/graphics/framebuffer.py +26 -0
  109. pyglet/graphics/instance.py +178 -69
  110. pyglet/graphics/shader.py +267 -1553
  111. pyglet/graphics/state.py +83 -0
  112. pyglet/graphics/texture.py +703 -0
  113. pyglet/graphics/vertexdomain.py +695 -538
  114. pyglet/gui/ninepatch.py +10 -10
  115. pyglet/gui/widgets.py +120 -10
  116. pyglet/image/__init__.py +20 -1973
  117. pyglet/image/animation.py +12 -12
  118. pyglet/image/base.py +730 -0
  119. pyglet/image/codecs/__init__.py +9 -0
  120. pyglet/image/codecs/bmp.py +53 -30
  121. pyglet/image/codecs/dds.py +53 -31
  122. pyglet/image/codecs/gdiplus.py +38 -14
  123. pyglet/image/codecs/gdkpixbuf2.py +0 -2
  124. pyglet/image/codecs/js_image.py +99 -0
  125. pyglet/image/codecs/ktx2.py +161 -0
  126. pyglet/image/codecs/pil.py +1 -1
  127. pyglet/image/codecs/png.py +1 -1
  128. pyglet/image/codecs/wic.py +11 -2
  129. pyglet/info.py +26 -24
  130. pyglet/input/__init__.py +8 -0
  131. pyglet/input/base.py +163 -105
  132. pyglet/input/controller.py +13 -19
  133. pyglet/input/controller_db.py +39 -24
  134. pyglet/input/emscripten/__init__.py +18 -0
  135. pyglet/input/emscripten/gamepad_js.py +397 -0
  136. pyglet/input/linux/__init__.py +11 -5
  137. pyglet/input/linux/evdev.py +10 -11
  138. pyglet/input/linux/x11_xinput.py +2 -2
  139. pyglet/input/linux/x11_xinput_tablet.py +1 -1
  140. pyglet/input/macos/__init__.py +7 -2
  141. pyglet/input/macos/darwin_gc.py +559 -0
  142. pyglet/input/win32/__init__.py +1 -1
  143. pyglet/input/win32/directinput.py +34 -29
  144. pyglet/input/win32/xinput.py +11 -61
  145. pyglet/lib.py +3 -3
  146. pyglet/libs/__init__.py +1 -1
  147. pyglet/{gl → libs/darwin}/agl.py +1 -1
  148. pyglet/libs/darwin/cocoapy/__init__.py +2 -2
  149. pyglet/libs/darwin/cocoapy/cocoahelpers.py +181 -0
  150. pyglet/libs/darwin/cocoapy/cocoalibs.py +31 -0
  151. pyglet/libs/darwin/cocoapy/cocoatypes.py +27 -0
  152. pyglet/libs/darwin/cocoapy/runtime.py +81 -45
  153. pyglet/libs/darwin/coreaudio.py +4 -4
  154. pyglet/{gl → libs/darwin}/lib_agl.py +9 -8
  155. pyglet/libs/darwin/quartzkey.py +1 -3
  156. pyglet/libs/egl/__init__.py +2 -0
  157. pyglet/libs/egl/egl_lib.py +576 -0
  158. pyglet/libs/egl/eglext.py +51 -5
  159. pyglet/libs/linux/__init__.py +0 -0
  160. pyglet/libs/linux/egl/__init__.py +0 -0
  161. pyglet/libs/linux/egl/eglext.py +22 -0
  162. pyglet/libs/linux/glx/__init__.py +0 -0
  163. pyglet/{gl → libs/linux/glx}/glx.py +13 -14
  164. pyglet/{gl → libs/linux/glx}/glxext_arb.py +408 -192
  165. pyglet/{gl → libs/linux/glx}/glxext_mesa.py +1 -1
  166. pyglet/{gl → libs/linux/glx}/glxext_nv.py +345 -164
  167. pyglet/{gl → libs/linux/glx}/lib_glx.py +3 -2
  168. pyglet/libs/linux/wayland/__init__.py +0 -0
  169. pyglet/libs/linux/wayland/client.py +1068 -0
  170. pyglet/libs/linux/wayland/lib_wayland.py +207 -0
  171. pyglet/libs/linux/wayland/wayland_egl.py +38 -0
  172. pyglet/libs/{wayland → linux/wayland}/xkbcommon.py +26 -0
  173. pyglet/libs/{x11 → linux/x11}/xf86vmode.py +4 -4
  174. pyglet/libs/{x11 → linux/x11}/xinerama.py +2 -2
  175. pyglet/libs/{x11 → linux/x11}/xinput.py +10 -10
  176. pyglet/libs/linux/x11/xrandr.py +0 -0
  177. pyglet/libs/{x11 → linux/x11}/xrender.py +1 -1
  178. pyglet/libs/shared/__init__.py +0 -0
  179. pyglet/libs/shared/spirv/__init__.py +0 -0
  180. pyglet/libs/shared/spirv/lib_shaderc.py +85 -0
  181. pyglet/libs/shared/spirv/lib_spirv_cross.py +126 -0
  182. pyglet/libs/win32/__init__.py +27 -5
  183. pyglet/libs/win32/constants.py +59 -48
  184. pyglet/libs/win32/context_managers.py +20 -3
  185. pyglet/libs/win32/dinput.py +105 -88
  186. pyglet/{gl → libs/win32}/lib_wgl.py +52 -26
  187. pyglet/libs/win32/types.py +58 -23
  188. pyglet/{gl → libs/win32}/wgl.py +32 -25
  189. pyglet/{gl → libs/win32}/wglext_arb.py +364 -2
  190. pyglet/media/__init__.py +9 -10
  191. pyglet/media/codecs/__init__.py +12 -1
  192. pyglet/media/codecs/base.py +99 -96
  193. pyglet/media/codecs/ffmpeg.py +2 -2
  194. pyglet/media/codecs/ffmpeg_lib/libavformat.py +3 -8
  195. pyglet/media/codecs/webaudio_pyodide.py +111 -0
  196. pyglet/media/drivers/__init__.py +9 -4
  197. pyglet/media/drivers/base.py +4 -4
  198. pyglet/media/drivers/openal/__init__.py +1 -1
  199. pyglet/media/drivers/openal/adaptation.py +3 -3
  200. pyglet/media/drivers/pulse/__init__.py +1 -1
  201. pyglet/media/drivers/pulse/adaptation.py +3 -3
  202. pyglet/media/drivers/pyodide_js/__init__.py +8 -0
  203. pyglet/media/drivers/pyodide_js/adaptation.py +288 -0
  204. pyglet/media/drivers/xaudio2/adaptation.py +3 -3
  205. pyglet/media/player.py +276 -193
  206. pyglet/media/player_worker_thread.py +1 -1
  207. pyglet/model/__init__.py +39 -29
  208. pyglet/model/codecs/base.py +4 -4
  209. pyglet/model/codecs/gltf.py +3 -3
  210. pyglet/model/codecs/obj.py +71 -43
  211. pyglet/resource.py +129 -78
  212. pyglet/shapes.py +147 -177
  213. pyglet/sprite.py +47 -164
  214. pyglet/text/__init__.py +44 -54
  215. pyglet/text/caret.py +12 -7
  216. pyglet/text/document.py +19 -17
  217. pyglet/text/formats/html.py +2 -2
  218. pyglet/text/formats/structured.py +10 -40
  219. pyglet/text/layout/__init__.py +20 -13
  220. pyglet/text/layout/base.py +176 -287
  221. pyglet/text/layout/incremental.py +9 -10
  222. pyglet/text/layout/scrolling.py +7 -95
  223. pyglet/window/__init__.py +183 -172
  224. pyglet/window/cocoa/__init__.py +62 -51
  225. pyglet/window/cocoa/pyglet_delegate.py +2 -25
  226. pyglet/window/cocoa/pyglet_view.py +9 -8
  227. pyglet/window/dialog/__init__.py +184 -0
  228. pyglet/window/dialog/base.py +99 -0
  229. pyglet/window/dialog/darwin.py +121 -0
  230. pyglet/window/dialog/linux.py +72 -0
  231. pyglet/window/dialog/windows.py +194 -0
  232. pyglet/window/emscripten/__init__.py +779 -0
  233. pyglet/window/headless/__init__.py +44 -28
  234. pyglet/window/key.py +2 -0
  235. pyglet/window/mouse.py +2 -2
  236. pyglet/window/wayland/__init__.py +377 -0
  237. pyglet/window/win32/__init__.py +101 -46
  238. pyglet/window/xlib/__init__.py +104 -66
  239. {pyglet-2.1.12.dist-info → pyglet-3.0.dev1.dist-info}/METADATA +2 -3
  240. pyglet-3.0.dev1.dist-info/RECORD +322 -0
  241. {pyglet-2.1.12.dist-info → pyglet-3.0.dev1.dist-info}/WHEEL +1 -1
  242. pyglet/gl/__init__.py +0 -208
  243. pyglet/gl/base.py +0 -499
  244. pyglet/gl/cocoa.py +0 -309
  245. pyglet/gl/gl.py +0 -4625
  246. pyglet/gl/gl.pyi +0 -2320
  247. pyglet/gl/gl_compat.pyi +0 -3097
  248. pyglet/gl/gl_info.py +0 -190
  249. pyglet/gl/headless.py +0 -166
  250. pyglet/gl/wgl_info.py +0 -36
  251. pyglet/gl/wglext_nv.py +0 -1096
  252. pyglet/gl/win32.py +0 -268
  253. pyglet/gl/xlib.py +0 -295
  254. pyglet/image/buffer.py +0 -274
  255. pyglet/image/codecs/s3tc.py +0 -354
  256. pyglet/libs/x11/xrandr.py +0 -166
  257. pyglet-2.1.12.dist-info/RECORD +0 -234
  258. /pyglet/{libs/wayland → graphics/api/gl/cocoa}/__init__.py +0 -0
  259. /pyglet/libs/{egl → linux/egl}/egl.py +0 -0
  260. /pyglet/libs/{egl → linux/egl}/lib.py +0 -0
  261. /pyglet/libs/{ioctl.py → linux/ioctl.py} +0 -0
  262. /pyglet/libs/{wayland → linux/wayland}/gbm.py +0 -0
  263. /pyglet/libs/{x11 → linux/x11}/__init__.py +0 -0
  264. /pyglet/libs/{x11 → linux/x11}/cursorfont.py +0 -0
  265. /pyglet/libs/{x11 → linux/x11}/xlib.py +0 -0
  266. /pyglet/libs/{x11 → linux/x11}/xsync.py +0 -0
  267. {pyglet-2.1.12.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
@@ -1,7 +1,9 @@
1
+ from __future__ import annotations
2
+
1
3
  import ctypes
2
4
  import warnings
3
5
 
4
- from typing import List, Dict, Optional
6
+ from typing import Optional
5
7
 
6
8
  from pyglet.libs.win32.constants import WM_DEVICECHANGE, DBT_DEVICEARRIVAL, DBT_DEVICEREMOVECOMPLETE, \
7
9
  DBT_DEVTYP_DEVICEINTERFACE, DEVICE_NOTIFY_WINDOW_HANDLE
@@ -55,7 +57,7 @@ def _create_control(object_instance):
55
57
  elif ctrl_type & dinput.DIDFT_POV:
56
58
  control = base.AbsoluteAxis(base.AbsoluteAxis.HAT, 0, 0xffffffff, raw_name)
57
59
  else:
58
- return
60
+ return None
59
61
 
60
62
  control._type = object_instance.dwType
61
63
  return control
@@ -124,17 +126,18 @@ class DirectInputDevice(base.Device):
124
126
  prop.dwData = 64 * ctypes.sizeof(dinput.DIDATAFORMAT)
125
127
  self._device.SetProperty(dinput.DIPROP_BUFFERSIZE, ctypes.byref(prop.diph))
126
128
 
127
- def open(self, window=None, exclusive=False):
129
+ def open(self, window: pyglet.window.Window | None=None, exclusive: bool=False) -> None:
128
130
  if not self.controls:
129
131
  return
130
132
 
131
133
  if window is None:
132
- # Pick any open window, or the shadow window if no windows
133
- # have been created yet.
134
- window = pyglet.gl._shadow_window
134
+ # Pick any open window or the shadow window if no windows are available.
135
135
  for window in pyglet.app.windows:
136
136
  break
137
137
 
138
+ if not window:
139
+ window = pyglet.window._shadow_window # noqa: SLF001
140
+
138
141
  flags = dinput.DISCL_BACKGROUND
139
142
  if exclusive:
140
143
  flags |= dinput.DISCL_EXCLUSIVE
@@ -215,31 +218,34 @@ class DIDeviceManager(EventDispatcher):
215
218
  self.registered = False
216
219
  self.window = None
217
220
  self._devnotify = None
218
- self.devices: List[DirectInputDevice] = []
221
+ self.devices: list[DirectInputDevice] = []
219
222
 
220
223
  if self.register_device_events(skip_warning=True):
221
224
  self.set_current_devices()
222
225
 
223
- def set_current_devices(self):
224
- """Sets all currently discovered devices in the devices list.
225
- Be careful when using this, as this creates new device objects. Should only be called on initialization of
226
- the manager and if for some reason the window connection event isn't registered.
226
+ def set_current_devices(self) -> None:
227
+ """Sets all currently discovered devices in the device list.
228
+
229
+ .. note:: Be careful when using this, as this creates new device objects. Only to be called on the
230
+ initialization of the manager, and if the window connection event isn't already registered.
227
231
  """
228
232
  new_devices, _ = self._get_devices()
229
233
  self.devices = new_devices
230
234
 
231
- def register_device_events(self, skip_warning=False, window=None):
235
+ def register_device_events(self, skip_warning: bool=False, window: pyglet.window.Window | None=None) -> bool:
232
236
  """Register the first OS Window to receive events of disconnect and connection of devices.
233
- Returns True if events were successfully registered.
237
+
238
+ Returns:
239
+ True if events were successfully registered.
234
240
  """
235
241
  if not self.registered:
236
- # If a specific window is not specified, find one.
237
- if not window:
238
- # Pick any open window, or the shadow window if no windows have been created yet.
239
- window = pyglet.gl._shadow_window
242
+ # Pick any open window or the shadow window if no windows are available.
243
+ if window is None:
244
+ for window in pyglet.app.windows:
245
+ break
246
+
240
247
  if not window:
241
- for window in pyglet.app.windows:
242
- break
248
+ window = pyglet.window._shadow_window # noqa: SLF001
243
249
 
244
250
  self.window = window
245
251
  if self.window is not None:
@@ -255,9 +261,8 @@ class DIDeviceManager(EventDispatcher):
255
261
  self.registered = True
256
262
  self.window.push_handlers(self)
257
263
  return True
258
- else:
259
- if not skip_warning:
260
- warnings.warn("DirectInput Device Manager requires a window to receive device connection events.")
264
+ if not skip_warning:
265
+ warnings.warn("DirectInput Device Manager requires a window to receive device connection events.")
261
266
 
262
267
  return False
263
268
 
@@ -288,12 +293,13 @@ class DIDeviceManager(EventDispatcher):
288
293
 
289
294
  def _get_devices(self, display=None):
290
295
  """Enumerate all the devices on the system.
291
- Returns two values: new devices, missing devices"""
296
+ Returns two values: new devices, missing devices
297
+ """
292
298
  _missing_devices = list(self.devices)
293
299
  _new_devices = []
294
300
  _xinput_devices = []
295
301
 
296
- if not pyglet.options["win32_disable_xinput"]:
302
+ if not pyglet.options.win32_disable_xinput:
297
303
  try:
298
304
  from pyglet.input.win32.xinput import get_xinput_guids
299
305
  _xinput_devices = get_xinput_guids()
@@ -359,7 +365,7 @@ class DIControllerManager(ControllerManager):
359
365
 
360
366
  def __init__(self, display=None):
361
367
  self._display = display
362
- self._controllers: Dict[DirectInputDevice, base.Controller] = {}
368
+ self._controllers: dict[DirectInputDevice, base.Controller] = {}
363
369
 
364
370
  for device in _di_manager.devices:
365
371
  self._add_controller(device)
@@ -398,7 +404,7 @@ def get_devices(display=None):
398
404
  _devices = []
399
405
  _xinput_devices = []
400
406
 
401
- if not pyglet.options["win32_disable_xinput"]:
407
+ if not pyglet.options.win32_disable_xinput:
402
408
  try:
403
409
  from pyglet.input.win32.xinput import get_xinput_guids
404
410
  _xinput_devices = get_xinput_guids()
@@ -429,9 +435,8 @@ def _create_controller(device):
429
435
  if device._type in (dinput.DI8DEVTYPE_JOYSTICK, dinput.DI8DEVTYPE_1STPERSON, dinput.DI8DEVTYPE_GAMEPAD):
430
436
  if mapping is not None:
431
437
  return base.Controller(device, mapping)
432
- else:
433
- warnings.warn(f"Warning: {device} (GUID: {device.get_guid()}) "
434
- f"has no controller mappings. Update the mappings in the Controller DB.")
438
+ warnings.warn(f"Warning: {device} (GUID: {device.get_guid()}) "
439
+ f"has no controller mappings. Update the mappings in the Controller DB.")
435
440
 
436
441
 
437
442
  def _create_joystick(device):
@@ -6,13 +6,12 @@ from ctypes.wintypes import DWORD, LONG, LPCWSTR, SHORT, ULONG, WORD
6
6
 
7
7
  import pyglet
8
8
  from pyglet.event import EventDispatcher
9
- from pyglet.input.base import AbsoluteAxis, Button, Controller, ControllerManager, Device
9
+ from pyglet.input.base import AbsoluteAxis, Button, Controller, ControllerManager, Device, Sign
10
10
  from pyglet.libs.win32 import _ole32 as ole32
11
11
  from pyglet.libs.win32 import _oleaut32 as oleaut32
12
12
  from pyglet.libs.win32 import com
13
13
  from pyglet.libs.win32.constants import CLSCTX_INPROC_SERVER
14
14
  from pyglet.libs.win32.types import BYTE, VARIANT
15
- from pyglet.math import Vec2
16
15
 
17
16
  for library_name in ['xinput1_4', 'xinput9_1_0', 'xinput1_3']:
18
17
  try:
@@ -360,8 +359,8 @@ controller_api_to_pyglet = {
360
359
  XINPUT_GAMEPAD_START: "start",
361
360
  XINPUT_GAMEPAD_BACK: "back",
362
361
  XINPUT_GAMEPAD_GUIDE: "guide",
363
- XINPUT_GAMEPAD_LEFT_THUMB: "leftstick",
364
- XINPUT_GAMEPAD_RIGHT_THUMB: "rightstick",
362
+ XINPUT_GAMEPAD_LEFT_THUMB: "leftthumb",
363
+ XINPUT_GAMEPAD_RIGHT_THUMB: "rightthumb",
365
364
  XINPUT_GAMEPAD_LEFT_SHOULDER: "leftshoulder",
366
365
  XINPUT_GAMEPAD_RIGHT_SHOULDER: "rightshoulder",
367
366
  XINPUT_GAMEPAD_A: "a",
@@ -396,17 +395,17 @@ class XInputDevice(Device):
396
395
  'guide': Button('guide'),
397
396
  'leftshoulder': Button('leftshoulder'),
398
397
  'rightshoulder': Button('rightshoulder'),
399
- 'leftstick': Button('leftstick'),
400
- 'rightstick': Button('rightstick'),
398
+ 'leftthumb': Button('leftthumb'),
399
+ 'rightthumb': Button('rightthumb'),
401
400
  'dpup': Button('dpup'),
402
401
  'dpdown': Button('dpdown'),
403
402
  'dpleft': Button('dpleft'),
404
403
  'dpright': Button('dpright'),
405
404
 
406
405
  'leftx': AbsoluteAxis('leftx', -32768, 32768),
407
- 'lefty': AbsoluteAxis('lefty', -32768, 32768),
406
+ 'lefty': AbsoluteAxis('lefty', -32768, 32768, inverted=True),
408
407
  'rightx': AbsoluteAxis('rightx', -32768, 32768),
409
- 'righty': AbsoluteAxis('righty', -32768, 32768),
408
+ 'righty': AbsoluteAxis('righty', -32768, 32768, inverted=True),
410
409
  'lefttrigger': AbsoluteAxis('lefttrigger', 0, 255),
411
410
  'righttrigger': AbsoluteAxis('righttrigger', 0, 255)
412
411
  }
@@ -546,68 +545,19 @@ _device_manager = XInputDeviceManager()
546
545
 
547
546
  class XInputController(Controller):
548
547
 
548
+ device: XInputDevice
549
+
549
550
  def _initialize_controls(self):
550
551
 
551
552
  for button_name in controller_api_to_pyglet.values():
552
553
  control = self.device.controls[button_name]
553
554
  self._button_controls.append(control)
554
- self._add_button(control, button_name)
555
+ self._bind_button_control(control, button_name)
555
556
 
556
557
  for axis_name in "leftx", "lefty", "rightx", "righty", "lefttrigger", "righttrigger":
557
558
  control = self.device.controls[axis_name]
558
559
  self._axis_controls.append(control)
559
- self._add_axis(control, axis_name)
560
-
561
- def _add_axis(self, control, name):
562
- tscale = 1.0 / (control.max - control.min)
563
- scale = 2.0 / (control.max - control.min)
564
- bias = -1.0 - control.min * scale
565
-
566
- if name in ("lefttrigger", "righttrigger"):
567
- @control.event
568
- def on_change(value):
569
- normalized_value = value * tscale
570
- setattr(self, name, normalized_value)
571
- self.dispatch_event('on_trigger_motion', self, name, normalized_value)
572
-
573
- elif name in ("leftx", "lefty"):
574
- @control.event
575
- def on_change(value):
576
- normalized_value = value * scale + bias
577
- setattr(self, name, normalized_value)
578
- self.leftanalog = Vec2(self.leftx, self.lefty)
579
- self.dispatch_event('on_stick_motion', self, "leftstick", self.leftanalog)
580
-
581
- elif name in ("rightx", "righty"):
582
- @control.event
583
- def on_change(value):
584
- normalized_value = value * scale + bias
585
- setattr(self, name, normalized_value)
586
- self.rightanalog = Vec2(self.rightx, self.righty)
587
- self.dispatch_event('on_stick_motion', self, "rightstick", self.rightanalog)
588
-
589
- def _add_button(self, control, name):
590
-
591
- if name in ("dpleft", "dpright", "dpup", "dpdown"):
592
- @control.event
593
- def on_change(value):
594
- target, bias = {'dpleft': ('dpadx', -1.0), 'dpright': ('dpadx', 1.0),
595
- 'dpdown': ('dpady', -1.0), 'dpup': ('dpady', 1.0)}[name]
596
- setattr(self, target, bias * value)
597
- self.dpad = Vec2(self.dpadx, self.dpady)
598
- self.dispatch_event('on_dpad_motion', self, self.dpad)
599
- else:
600
- @control.event
601
- def on_change(value):
602
- setattr(self, name, value)
603
-
604
- @control.event
605
- def on_press():
606
- self.dispatch_event('on_button_press', self, name)
607
-
608
- @control.event
609
- def on_release():
610
- self.dispatch_event('on_button_release', self, name)
560
+ self._bind_axis_control(control, axis_name, Sign.DEFAULT)
611
561
 
612
562
  def rumble_play_weak(self, strength=1.0, duration=0.5):
613
563
  self.device.vibration.wRightMotorSpeed = int(max(min(1.0, strength), 0) * 0xFFFF)
pyglet/lib.py CHANGED
@@ -15,12 +15,12 @@ import ctypes.util
15
15
  import pyglet
16
16
  from typing import NoReturn, Callable, Any
17
17
 
18
- _debug_lib = pyglet.options['debug_lib']
19
- _debug_trace = pyglet.options['debug_trace']
18
+ _debug_lib = pyglet.options.debug_lib
19
+ _debug_trace = pyglet.options.debug_trace
20
20
 
21
21
  _is_pyglet_doc_run = getattr(sys, "is_pyglet_doc_run", False)
22
22
 
23
- if pyglet.options['search_local_libs']:
23
+ if pyglet.options.search_local_libs:
24
24
  script_path = pyglet.resource.get_script_home()
25
25
  cwd = os.getcwd()
26
26
  _local_lib_paths = [script_path, os.path.join(script_path, 'lib'), os.path.join(cwd, 'lib')]
pyglet/libs/__init__.py CHANGED
@@ -13,7 +13,7 @@ When documenting these modules:
13
13
 
14
14
  Simple docstrings with minimal formatting are best because:
15
15
 
16
- 1. No web doc is built for pyglet.lib
16
+ 1. No web doc is built for pyglet.libs
17
17
  2. The docstrings will be used to debug complex platform issues
18
18
  3. IDEs mangle formatting in any hover tooltips while debugging
19
19
  """
@@ -5,7 +5,7 @@ Do not modify this file.
5
5
  """
6
6
 
7
7
  from ctypes import Structure, POINTER, c_int, c_long, c_ubyte, c_ulong
8
- from pyglet.gl.lib import link_AGL as _link_function
8
+ from pyglet.graphics.api.gl.lib import link_AGL as _link_function
9
9
 
10
10
  if not _link_function:
11
11
  raise ImportError('AGL framework is not available.')
@@ -30,10 +30,10 @@
30
30
  # POSSIBILITY OF SUCH DAMAGE.
31
31
  from contextlib import contextmanager
32
32
 
33
- from .runtime import objc, send_message, send_super, AutoReleasePool
33
+ from .runtime import objc, send_message, send_super, AutoReleasePool, ObjCBlock
34
34
  from .runtime import get_selector
35
35
  from .runtime import ObjCClass, ObjCInstance, ObjCSubclass
36
36
 
37
37
  from .cocoatypes import *
38
38
  from .cocoalibs import *
39
-
39
+ from .cocoahelpers import *
@@ -0,0 +1,181 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from pyglet.libs.darwin.cocoapy.runtime import ObjCInstance, ObjCClass
6
+
7
+ NSSet = ObjCClass('NSSet')
8
+ NSNull = ObjCClass('NSNull')
9
+ NSString = ObjCClass("NSString")
10
+ NSData = ObjCClass("NSData")
11
+ NSNumber = ObjCClass("NSNumber")
12
+ NSMutableArray = ObjCClass("NSMutableArray")
13
+ NSArray = ObjCClass("NSArray")
14
+ NSDictionary = ObjCClass("NSDictionary")
15
+ NSMutableDictionary = ObjCClass("NSMutableDictionary")
16
+
17
+ def pystr_to_ns(value: str):
18
+ return NSString.stringWithUTF8String_(value.encode("utf-8"))
19
+
20
+ def pybool_to_ns(value: bool):
21
+ return NSNumber.numberWithBool_(value)
22
+
23
+ def pyint_to_ns(value: int):
24
+ return NSNumber.numberWithInt_(value)
25
+
26
+ def pyfloat_to_ns(value: float):
27
+ return NSNumber.numberWithDouble_(value)
28
+
29
+ def pynone_to_ns(_value):
30
+ return NSNull.null()
31
+
32
+ def _iterable_to_mutable_array(value: list | tuple):
33
+ arr = NSMutableArray.array()
34
+ for item in value:
35
+ arr.addObject_(py_to_ns(item))
36
+ return arr
37
+
38
+ def pylist_to_ns(value: list) -> NSMutableArray:
39
+ """Convert Python list to NSMutableArray."""
40
+ return _iterable_to_mutable_array(value)
41
+
42
+ def pytuple_to_ns(value: tuple) -> NSArray:
43
+ """Convert Python tuple to NSArray (immutable)."""
44
+ mutable = _iterable_to_mutable_array(value)
45
+ return NSArray.arrayWithArray_(mutable)
46
+
47
+ def pydict_to_ns(value: dict, mutable: bool=True) -> NSMutableDictionary | NSDictionary:
48
+ """Convert Python dict to NSMutableDictionary."""
49
+ d = NSMutableDictionary.dictionary()
50
+ for k, v in value.items():
51
+ ns_key = py_to_ns(k)
52
+ ns_val = py_to_ns(v)
53
+ d.setObject_forKey_(ns_val, ns_key)
54
+ if not mutable:
55
+ return NSDictionary.dictionaryWithDictionary_(d)
56
+ return d
57
+
58
+
59
+ _CONVERTERS = {
60
+ str: pystr_to_ns,
61
+ bool: pybool_to_ns,
62
+ int: pyint_to_ns,
63
+ float: pyfloat_to_ns,
64
+ list: pylist_to_ns,
65
+ tuple: pytuple_to_ns,
66
+ dict: pydict_to_ns,
67
+ type(None): pynone_to_ns,
68
+ }
69
+
70
+ def py_to_ns(value: Any) -> ObjCInstance:
71
+ """General Python to NS object converter.
72
+
73
+ Should be used whenever interacting with AppKit, Cocoa, or any other NS-related functions.
74
+ """
75
+ if isinstance(value, ObjCInstance):
76
+ return value
77
+
78
+ t = type(value)
79
+ converter = _CONVERTERS.get(t)
80
+
81
+ if converter:
82
+ return converter(value)
83
+
84
+ raise TypeError(f"Cannot convert Python type {t} to NS object")
85
+
86
+ # ===== Converting from NS to Python
87
+ def nsstr_to_py(nsobj: NSString) -> str:
88
+ return nsobj.UTF8String().decode("utf-8")
89
+
90
+
91
+ def nsnum_to_py(nsobj: NSNumber) -> int | float:
92
+ """Converting from NSNumber
93
+
94
+ NSNumber can represent bool, int, or float internally"""
95
+ t = nsobj.objCType().decode()
96
+
97
+ if t == 'c': # char / BOOL
98
+ return bool(nsobj.boolValue())
99
+ elif t in ('i', 'l', 'q', 's'):
100
+ return int(nsobj.intValue())
101
+ elif t in ('f', 'd'):
102
+ return float(nsobj.doubleValue())
103
+
104
+ return nsobj.doubleValue()
105
+
106
+
107
+ def nsarray_to_py(nsobj: NSArray) -> list:
108
+ py_list = []
109
+ for i in range(nsobj.count()):
110
+ item = nsobj.objectAtIndex_(i)
111
+ py_list.append(ns_to_py(item))
112
+ return py_list
113
+
114
+
115
+ def nsmutarray_to_py(nsobj: NSMutableArray):
116
+ return nsarray_to_py(nsobj)
117
+
118
+
119
+ def nsdict_to_py(nsobj: NSDictionary):
120
+ py_dict = {}
121
+
122
+ # NSDictionary requires enumerating keys
123
+ keys = nsobj.allKeys()
124
+ for i in range(keys.count()):
125
+ key = keys.objectAtIndex_(i)
126
+ val = nsobj.objectForKey_(key)
127
+
128
+ py_key = ns_to_py(key)
129
+ py_val = ns_to_py(val)
130
+
131
+ py_dict[py_key] = py_val
132
+
133
+ return py_dict
134
+
135
+
136
+ # NSMutableDictionary handled the same
137
+ def nsmutdict_to_py(nsobj: NSMutableDictionary):
138
+ return nsdict_to_py(nsobj)
139
+
140
+
141
+ def nsset_to_py(nsset) -> set:
142
+ """Convert NSSet or NSFrozenSet to a Python set."""
143
+ py = set()
144
+ enumerator = nsset.objectEnumerator()
145
+ while True:
146
+ obj = enumerator.nextObject()
147
+ if obj is None:
148
+ break
149
+ py.add(ns_to_py(obj))
150
+ return py
151
+
152
+ def nsnull_to_py(_nsnull):
153
+ return None
154
+
155
+ _NS_TO_PY_CONVERTERS = {
156
+ NSString: nsstr_to_py,
157
+ NSNumber: nsnum_to_py,
158
+ NSArray: nsarray_to_py,
159
+ NSMutableArray: nsmutarray_to_py,
160
+ NSDictionary: nsdict_to_py,
161
+ NSMutableDictionary: nsmutdict_to_py,
162
+ NSNull: nsnull_to_py,
163
+ NSSet: nsset_to_py,
164
+ }
165
+
166
+
167
+ def ns_to_py(nsobj: ObjCInstance):
168
+ """Convert NS object to Python, recursively."""
169
+ if nsobj is None:
170
+ return None
171
+
172
+ if not isinstance(nsobj, ObjCInstance):
173
+ raise Exception(f"{nsobj} Not an ObjCInstance")
174
+
175
+ for cls, converter in _NS_TO_PY_CONVERTERS.items():
176
+ # NS Objects have many different variations of the same type.
177
+ # For example a string can be NSTaggedPointerString, __NSCFString, NSMutableString, NSString, etc..
178
+ if nsobj.isKindOfClass_(cls):
179
+ return converter(nsobj)
180
+
181
+ return nsobj
@@ -24,6 +24,7 @@ CFURLRef = c_void_p
24
24
  CFStringRef = c_void_p
25
25
  CFURLPathStyle = c_int
26
26
  CFDataRef = c_void_p
27
+ CTRunRef = c_void_p
27
28
 
28
29
  cf.CFStringCreateWithCString.restype = c_void_p
29
30
  cf.CFStringCreateWithCString.argtypes = [CFAllocatorRef, c_char_p, CFStringEncoding]
@@ -46,6 +47,9 @@ cf.CFStringGetTypeID.argtypes = []
46
47
  cf.CFAttributedStringCreate.restype = c_void_p
47
48
  cf.CFAttributedStringCreate.argtypes = [CFAllocatorRef, c_void_p, c_void_p]
48
49
 
50
+ cf.CFShow.restype = None
51
+ cf.CFShow.argtypes = [c_void_p]
52
+
49
53
  # Core Foundation type to Python type conversion functions
50
54
 
51
55
  def CFSTR(string: str):
@@ -649,6 +653,18 @@ ct.CTFontCopyFamilyName.argtypes = [c_void_p]
649
653
  ct.CTFontCopyFullName.restype = c_void_p
650
654
  ct.CTFontCopyFullName.argtypes = [c_void_p]
651
655
 
656
+ ct.CTFontCopyPostScriptName.restype = c_void_p
657
+ ct.CTFontCopyPostScriptName.argtypes = [c_void_p]
658
+
659
+ ct.CTFontCreateUIFontForLanguage.restype = c_void_p
660
+ ct.CTFontCreateUIFontForLanguage.argtypes = [c_uint32, c_double, c_void_p]
661
+
662
+ ct.CTFontCreateCopyWithSymbolicTraits.restype = c_void_p
663
+ ct.CTFontCreateCopyWithSymbolicTraits.argtypes = [c_void_p, CGFloat, c_void_p, c_uint32, c_uint32]
664
+
665
+ ct.CTFontCreateCopyWithAttributes.restype = c_void_p
666
+ ct.CTFontCreateCopyWithAttributes.argtypes = [c_void_p, c_double, c_void_p, c_void_p]
667
+
652
668
  ct.CTFontCreateWithFontDescriptor.restype = c_void_p
653
669
  ct.CTFontCreateWithFontDescriptor.argtypes = [c_void_p, CGFloat, c_void_p]
654
670
 
@@ -667,6 +683,21 @@ ct.CTFontDescriptorCreateMatchingFontDescriptor.argtypes = [c_void_p, c_void_p]
667
683
  ct.CTFontCopyTraits.restype = c_void_p
668
684
  ct.CTFontCopyTraits.argtypes = [c_void_p]
669
685
 
686
+ ct.CTLineGetGlyphRuns.restype = c_void_p # CFArrayRef
687
+ ct.CTLineGetGlyphRuns.argtypes = [c_void_p] # CTLineRef
688
+
689
+ ct.CTRunGetGlyphCount.restype = CFIndex
690
+ ct.CTRunGetGlyphCount.argtypes = [CTRunRef]
691
+
692
+ ct.CTRunGetGlyphs.restype = None
693
+ ct.CTRunGetGlyphs.argtypes = [CTRunRef, CFRange, POINTER(CGGlyph)]
694
+
695
+ ct.CTRunGetPositions.restype = None
696
+ ct.CTRunGetPositions.argtypes = [CTRunRef, CFRange, POINTER(CGPoint)]
697
+
698
+ ct.CTRunGetAttributes.restype = c_void_p
699
+ ct.CTRunGetAttributes.argtypes = [CTRunRef]
700
+
670
701
  kCTFontURLAttribute = c_void_p.in_dll(ct, 'kCTFontURLAttribute')
671
702
 
672
703
  ######################################################################
@@ -46,6 +46,10 @@ NSZoneEncoding = b'{_NSZone=}'
46
46
  # from /System/Library/Frameworks/Foundation.framework/Headers/NSGeometry.h
47
47
  class NSPoint(Structure):
48
48
  _fields_ = [ ("x", CGFloat), ("y", CGFloat) ]
49
+
50
+ def __repr__(self):
51
+ return f"{self.__class__.__name__}(x={self.x}, y={self.y})"
52
+
49
53
  CGPoint = NSPoint
50
54
 
51
55
  class NSSize(Structure):
@@ -83,3 +87,26 @@ NSZeroPoint = NSPoint(0,0)
83
87
 
84
88
  CFTypeID = c_ulong
85
89
  CFNumberType = c_uint32
90
+
91
+ _dispose_helper_cb = CFUNCTYPE(c_void_p, c_void_p)
92
+ _copy_helper_cb = CFUNCTYPE(c_void_p, c_void_p, c_void_p)
93
+
94
+ class Block_descriptor_1(Structure):
95
+ _fields_ = [
96
+ ("reserved", c_ulong),
97
+ ("Block_size", c_ulong),
98
+ ("copy_helper", _copy_helper_cb), # Optional
99
+ ("dispose_helper", _dispose_helper_cb), # Optional
100
+ ("signature", c_char_p),
101
+ ]
102
+
103
+
104
+ class Block_literal_1(Structure):
105
+ _fields_ = [
106
+ ("isa", c_void_p), # address to ConcreteStack/ConcreteGlobal
107
+ ("flags", c_int),
108
+ ("reserved", c_int),
109
+ ("invoke", c_void_p), # Invoke function
110
+ ("descriptor", Block_descriptor_1),
111
+ ]
112
+