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.
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 +5 -21
  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 +28 -8
  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 +154 -194
  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.13.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.13.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.13.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.13.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
@@ -1,77 +1,186 @@
1
- """Concept for higher level instance generation and organization."""
2
1
  from __future__ import annotations
3
2
 
4
- from typing import TYPE_CHECKING, Any, Protocol, Sequence
3
+ import weakref
4
+ from abc import ABC, abstractmethod
5
+ from typing import TYPE_CHECKING, Any
5
6
 
6
7
  if TYPE_CHECKING:
7
- from pyglet.graphics import Batch
8
- from pyglet.graphics.vertexdomain import VertexInstance, VertexList
9
-
10
-
11
- class VertexListObject(Protocol):
12
- batch: Batch
13
- _vertex_list: VertexList
14
-
15
-
16
- class InstanceSourceMixin:
17
- _vertex_list: VertexList
18
-
19
- def __init__(self, attributes: Sequence[str]) -> None:
20
- self._attributes = tuple(attributes)
21
- self._instances = []
8
+ from pyglet.graphics.vertexdomain import InstanceStream, VertexArrayBinding
9
+ from pyglet.graphics.api.gl.vertexdomain import InstanceVertexList, InstanceIndexedVertexList
10
+ from _weakref import ReferenceType
11
+ from pyglet.customtypes import DataTypes
12
+
13
+
14
+ class InstanceAllocator:
15
+ """Allocator for instances within a bucket."""
16
+ count: int
17
+ slot_to_handle: dict[int, VertexInstanceBase]
18
+ handle_to_slot: dict[VertexInstanceBase, int]
19
+
20
+ def __init__(self) -> None: # noqa: D107
21
+ self.count = 0
22
+ self.inst_to_slot = {}
23
+ self.slot_to_inst = {}
24
+
25
+ def clear(self) -> None:
26
+ self.inst_to_slot.clear()
27
+ self.slot_to_inst.clear()
28
+ self.count = 0
29
+
30
+ def add(self, inst) -> int:
31
+ slot = self.count
32
+ self.count += 1
33
+ self.inst_to_slot[inst] = slot
34
+ self.slot_to_inst[slot] = inst
35
+ return slot
36
+
37
+ def remove(self, inst: VertexInstanceBase) -> tuple[int, int, int] | None:
38
+ slot = self.inst_to_slot.pop(inst)
39
+ last = self.count - 1
40
+ if slot != last:
41
+ moved = self.slot_to_inst[last]
42
+ self.slot_to_inst[slot] = moved
43
+ self.inst_to_slot[moved] = slot
44
+ self.slot_to_inst.pop(last, None)
45
+ self.count -= 1
46
+ return slot, last, moved
47
+
48
+ self.slot_to_inst.pop(last, None)
49
+ self.count -= 1
50
+ return None
51
+
52
+ class VertexInstanceBase:
53
+ """Base class for VertexInstance instances."""
54
+ _bucket_ref: ReferenceType[InstanceBucket]
55
+ slot: int
56
+
57
+ __slots__ = ("_bucket_ref", "slot")
58
+
59
+ def __init__(self, bucket_ref: ReferenceType[InstanceBucket], slot: int = -1) -> None: # noqa: D107
60
+ self._bucket_ref = bucket_ref
61
+ self.slot = slot
22
62
 
23
63
  @property
24
- def instances(self) -> list[VertexInstance]:
25
- return self._instances
26
-
27
- def create_instance(self, **kwargs: Any) -> VertexInstance:
28
- instance = self._vertex_list.add_instance(**kwargs)
29
- self._instances.append(instance)
30
- return instance
31
-
32
- def pop(self) -> VertexInstance:
33
- instance = self._instances.pop()
34
- instance.delete()
35
- return instance
36
-
37
-
38
- class InstanceGenerator:
39
- _attributes: tuple[str, ...]
40
-
41
- def __init__(self, source: VertexListObject, attributes: Sequence[str]) -> None:
42
- self.source = source
43
- self._attributes = tuple(attributes)
44
- self._instances = []
45
-
46
- if self.source._vertex_list is None:
47
- raise Exception("No vertex list")
48
-
49
- if self.source.batch is None:
50
- raise Exception("No batch")
51
-
52
- self.migrate()
53
-
54
- @property
55
- def instance_attributes(self) -> tuple[str, ...]:
56
- return self._attributes
57
-
58
- def migrate(self) -> None:
59
- vlist = self.source._vertex_list
60
- batch = self.source.batch
61
-
62
- instanced_domain = batch._convert_to_instanced(vlist.domain, self._attributes)
63
- vlist.set_instance_source(instanced_domain, self._attributes)
64
+ def bucket(self) -> InstanceBucket:
65
+ b = self._bucket_ref()
66
+ if b is None:
67
+ raise RuntimeError("Bucket no longer exists")
68
+ return b
69
+
70
+ def set(self, **attrs: Any) -> None:
71
+ """Partial row update (by attribute name)."""
72
+ self.bucket.stream.set_region(self.slot, 1, attrs)
73
+
74
+ def get(self, name: str) -> list[int]:
75
+ return self.bucket.stream.attrib_name_buffers[name].get_region(self.slot, 1)
76
+
77
+ def delete(self) -> None:
78
+ self.bucket.delete_instance(self)
79
+ self.slot = -1
80
+
81
+ def _make_inst_attr_prop(attr_name: str):
82
+ def _get(self):
83
+ buf = self.bucket.stream.attrib_name_buffers[attr_name]
84
+ return buf.get_region(self.slot, 1)
85
+
86
+ def _set(self, data):
87
+ buf = self.bucket.stream.attrib_name_buffers[attr_name]
88
+ buf.set_region(self.slot, 1, data)
89
+
90
+ return property(_get, _set)
91
+
92
+ class InstanceBucket:
93
+ """Manages the relationship between the instance buffer data and the instance objects."""
94
+ def __init__(self, instance_stream: InstanceStream, vao: VertexArrayBinding) -> None:
95
+ self.stream = instance_stream
96
+ self.vao = vao
97
+ self.allocator = InstanceAllocator()
98
+
99
+ # Build a VertexInstance class with properties for each instanced attribute:
100
+ props = {name: _make_inst_attr_prop(name) for name in self.stream.attrib_name_buffers.keys()}
101
+ props["__slots__"] = ("_bucket_ref", "slot")
102
+ self._InstanceCls = type("VertexInstance", (VertexInstanceBase,), props)
103
+
104
+ def create_instance(self, **attributes: Any) -> VertexInstanceBase:
105
+ v_instance = self._InstanceCls(weakref.ref(self), slot=-1)
106
+ slot = self.allocator.add(v_instance)
107
+ v_instance.slot = slot
108
+
109
+ # Still need to allocate the stream to allow expanding buffers.
110
+ self.stream.alloc(1)
111
+ if attributes:
112
+ self.stream.set_region(slot, 1, attributes)
113
+ return v_instance
114
+
115
+ def delete_instance(self, vi: VertexInstanceBase) -> None:
116
+ # When removing an instance, take the last slot and move to the removed slot to maintain contiguous allocation.
117
+ swap = self.allocator.remove(vi)
118
+ if swap:
119
+ dst, src, moved = swap
120
+ self.stream.copy_data(dst, self.stream, src, count=1)
121
+ moved.slot = dst
64
122
 
65
123
  @property
66
- def instances(self) -> list[VertexInstance]:
67
- return self._instances
68
-
69
- def create(self, **kwargs: Any) -> VertexInstance:
70
- instance = self.source._vertex_list.add_instance(**kwargs)
71
- self._instances.append(instance)
72
- return instance
73
-
74
- def pop(self) -> VertexInstance:
75
- instance = self._instances.pop()
76
- instance.delete()
77
- return instance
124
+ def instance_count(self) -> int:
125
+ return self.allocator.count
126
+
127
+ class BaseInstanceDomain(ABC):
128
+ """Base class for managing instance domains and the buckets associated with each."""
129
+ _geom: dict[InstanceBucket, tuple[Any, ...]]
130
+ _buckets: dict[tuple, InstanceBucket]
131
+
132
+ def __init__(self, domain: Any, initial_instances: int) -> None:
133
+ self._domain = weakref.proxy(domain)
134
+ self._initial = initial_instances
135
+ self._buckets = {}
136
+ self._geom = {}
137
+
138
+ def move_all(self, src_bucket: InstanceBucket, dst_bucket: InstanceBucket) -> None:
139
+ assert src_bucket in self._buckets.values(), "Bucket does not belong to this instance domain."
140
+ if dst_bucket is src_bucket:
141
+ return
142
+ n = src_bucket.allocator.count
143
+ if n == 0:
144
+ # Nothing to move.
145
+ return
146
+
147
+ handles = [src_bucket.allocator.slot_to_inst[i] for i in range(n)]
148
+ start_dst = dst_bucket.allocator.count
149
+ for i, h in enumerate(handles):
150
+ dst_bucket.allocator.add(h)
151
+ h._bucket_ref = weakref.ref(dst_bucket)
152
+ h.slot = start_dst + i
153
+
154
+ dst_bucket.stream.alloc(n)
155
+ src_bucket.stream.copy_data(dst_slot=start_dst, dst_stream=dst_bucket.stream, src_slot=0, count=n)
156
+
157
+ src_bucket.allocator.clear()
158
+
159
+ def get_arrays_bucket(self, *, mode: int, first_vertex: int, vertex_count: int) -> InstanceBucket:
160
+ key = ("arrays", mode, first_vertex, vertex_count)
161
+ bucket = self._buckets.get(key)
162
+ if bucket is None:
163
+ bucket = self._create_bucket_arrays()
164
+ self._buckets[key] = bucket
165
+ self._geom[bucket] = (first_vertex, vertex_count)
166
+ return bucket
167
+
168
+ def get_elements_bucket(self, *, mode: int,
169
+ first_index: int, index_count: int,
170
+ index_type: DataTypes, base_vertex: int = 0) -> InstanceBucket:
171
+ key = ("elements", mode, first_index, index_count, index_type, base_vertex)
172
+ bucket = self._buckets.get(key)
173
+ if bucket is None:
174
+ bucket = self._create_bucket_elements()
175
+ self._buckets[key] = bucket
176
+ self._geom[bucket] = (first_index, index_count, index_type, base_vertex)
177
+ return bucket
178
+
179
+ @abstractmethod
180
+ def _create_bucket_arrays(self) -> InstanceBucket: ...
181
+ @abstractmethod
182
+ def _create_bucket_elements(self) -> InstanceBucket: ...
183
+ @abstractmethod
184
+ def draw(self, mode: Any) -> None: ...
185
+ @abstractmethod
186
+ def draw_subset(self, mode: Any, vertex_list: InstanceVertexList | InstanceIndexedVertexList) -> None: ...