pyglet 2.1.8__py3-none-any.whl → 2.1.9__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 +1 -1
- pyglet/display/headless.py +11 -0
- pyglet/graphics/shader.py +8 -1
- pyglet/input/base.py +14 -4
- pyglet/input/linux/evdev.py +95 -22
- pyglet/input/linux/evdev_constants.py +2 -1
- pyglet/input/win32/xinput.py +6 -3
- pyglet/libs/ioctl.py +2 -2
- pyglet/math.py +25 -5
- {pyglet-2.1.8.dist-info → pyglet-2.1.9.dist-info}/METADATA +1 -1
- {pyglet-2.1.8.dist-info → pyglet-2.1.9.dist-info}/RECORD +13 -13
- {pyglet-2.1.8.dist-info → pyglet-2.1.9.dist-info}/LICENSE +0 -0
- {pyglet-2.1.8.dist-info → pyglet-2.1.9.dist-info}/WHEEL +0 -0
pyglet/__init__.py
CHANGED
pyglet/display/headless.py
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
1
5
|
import pyglet
|
|
2
6
|
import warnings
|
|
3
7
|
|
|
@@ -69,3 +73,10 @@ class HeadlessScreen(Screen):
|
|
|
69
73
|
|
|
70
74
|
def restore_mode(self):
|
|
71
75
|
pass
|
|
76
|
+
|
|
77
|
+
def get_display_id(self) -> str | int:
|
|
78
|
+
# No real unique ID is available, just hash together the properties.
|
|
79
|
+
return hash((self.x, self.y, self.width, self.height))
|
|
80
|
+
|
|
81
|
+
def get_monitor_name(self) -> str | Literal["Unknown"]:
|
|
82
|
+
return "Headless"
|
pyglet/graphics/shader.py
CHANGED
|
@@ -58,6 +58,7 @@ from pyglet.gl.gl import (
|
|
|
58
58
|
glUnmapBuffer,
|
|
59
59
|
glUseProgram,
|
|
60
60
|
glVertexAttribDivisor,
|
|
61
|
+
glVertexAttribIPointer,
|
|
61
62
|
glVertexAttribPointer,
|
|
62
63
|
)
|
|
63
64
|
from pyglet.graphics.vertexbuffer import AttributeBufferObject, BufferObject
|
|
@@ -257,6 +258,9 @@ class Attribute:
|
|
|
257
258
|
self.element_size = sizeof(self.c_type)
|
|
258
259
|
self.stride = count * self.element_size
|
|
259
260
|
|
|
261
|
+
self._is_int = gl_type in (gl.GL_INT, gl.GL_SHORT, gl.GL_BYTE, gl.GL_UNSIGNED_INT,
|
|
262
|
+
gl.GL_UNSIGNED_SHORT, gl.GL_UNSIGNED_BYTE) and self.normalize is False
|
|
263
|
+
|
|
260
264
|
def enable(self) -> None:
|
|
261
265
|
"""Enable the attribute."""
|
|
262
266
|
glEnableVertexAttribArray(self.location)
|
|
@@ -271,7 +275,10 @@ class Attribute:
|
|
|
271
275
|
Pointer offset to the currently bound buffer for this attribute.
|
|
272
276
|
|
|
273
277
|
"""
|
|
274
|
-
|
|
278
|
+
if self._is_int:
|
|
279
|
+
glVertexAttribIPointer(self.location, self.count, self.gl_type, self.stride, ptr)
|
|
280
|
+
else:
|
|
281
|
+
glVertexAttribPointer(self.location, self.count, self.gl_type, self.normalize, self.stride, ptr)
|
|
275
282
|
|
|
276
283
|
def set_divisor(self) -> None:
|
|
277
284
|
glVertexAttribDivisor(self.location, 1)
|
pyglet/input/base.py
CHANGED
|
@@ -520,6 +520,7 @@ class Controller(EventDispatcher):
|
|
|
520
520
|
#: The unique guid for this Device
|
|
521
521
|
self.guid: str = mapping.get('guid')
|
|
522
522
|
|
|
523
|
+
# Pollable
|
|
523
524
|
self.a: bool = False
|
|
524
525
|
self.b: bool = False
|
|
525
526
|
self.x: bool = False
|
|
@@ -534,6 +535,10 @@ class Controller(EventDispatcher):
|
|
|
534
535
|
|
|
535
536
|
self.lefttrigger: float = 0.0
|
|
536
537
|
self.righttrigger: float = 0.0
|
|
538
|
+
self.dpad: Vec2 = Vec2()
|
|
539
|
+
self.leftanalog: Vec2 = Vec2()
|
|
540
|
+
self.rightanalog: Vec2 = Vec2()
|
|
541
|
+
|
|
537
542
|
self.leftx: float = 0.0
|
|
538
543
|
self.lefty: float = 0.0
|
|
539
544
|
self.rightx: float = 0.0
|
|
@@ -617,12 +622,14 @@ class Controller(EventDispatcher):
|
|
|
617
622
|
@control.event
|
|
618
623
|
def on_change(value):
|
|
619
624
|
self.dpady = round(value * scale + bias) * sign # normalized
|
|
625
|
+
self.dpad = Vec2(self.dpadx, self.dpady)
|
|
620
626
|
self.dispatch_event('on_dpad_motion', self, Vec2(self.dpadx, self.dpady))
|
|
621
627
|
|
|
622
628
|
elif axis_name in ("dpleft", "dpright"):
|
|
623
629
|
@control.event
|
|
624
630
|
def on_change(value):
|
|
625
631
|
self.dpadx = round(value * scale + bias) * sign # normalized
|
|
632
|
+
self.dpad = Vec2(self.dpadx, self.dpady)
|
|
626
633
|
self.dispatch_event('on_dpad_motion', self, Vec2(self.dpadx, self.dpady))
|
|
627
634
|
|
|
628
635
|
elif axis_name in ("lefttrigger", "righttrigger"):
|
|
@@ -637,14 +644,16 @@ class Controller(EventDispatcher):
|
|
|
637
644
|
def on_change(value):
|
|
638
645
|
normalized_value = value * scale + bias
|
|
639
646
|
setattr(self, axis_name, normalized_value)
|
|
640
|
-
self.
|
|
647
|
+
self.left_analog = Vec2(self.leftx, -self.lefty)
|
|
648
|
+
self.dispatch_event('on_stick_motion', self, "leftstick", self.left_analog)
|
|
641
649
|
|
|
642
650
|
elif axis_name in ("rightx", "righty"):
|
|
643
651
|
@control.event
|
|
644
652
|
def on_change(value):
|
|
645
653
|
normalized_value = value * scale + bias
|
|
646
654
|
setattr(self, axis_name, normalized_value)
|
|
647
|
-
self.
|
|
655
|
+
self.right_analog = Vec2(self.rightx, -self.righty)
|
|
656
|
+
self.dispatch_event('on_stick_motion', self, "rightstick", self.right_analog)
|
|
648
657
|
|
|
649
658
|
def _bind_button_control(self, relation: Relation, control: Button, button_name: str) -> None:
|
|
650
659
|
if button_name in ("dpleft", "dpright", "dpup", "dpdown"):
|
|
@@ -655,7 +664,8 @@ class Controller(EventDispatcher):
|
|
|
655
664
|
def on_change(value):
|
|
656
665
|
target, bias = defaults[button_name]
|
|
657
666
|
setattr(self, target, bias * value)
|
|
658
|
-
self.
|
|
667
|
+
self.dpad = Vec2(self.dpadx, self.dpady)
|
|
668
|
+
self.dispatch_event('on_dpad_motion', self, self.dpad)
|
|
659
669
|
else:
|
|
660
670
|
@control.event
|
|
661
671
|
def on_change(value):
|
|
@@ -681,7 +691,7 @@ class Controller(EventDispatcher):
|
|
|
681
691
|
@control.event
|
|
682
692
|
def on_change(value):
|
|
683
693
|
vector = _input_map.get(value // _scale, Vec2(0.0, 0.0))
|
|
684
|
-
self.
|
|
694
|
+
self.dpad = vector
|
|
685
695
|
self.dispatch_event('on_dpad_motion', self, vector)
|
|
686
696
|
|
|
687
697
|
def _initialize_controls(self) -> None:
|
pyglet/input/linux/evdev.py
CHANGED
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import os
|
|
4
4
|
import time
|
|
5
5
|
import ctypes
|
|
6
|
+
import select
|
|
6
7
|
import warnings
|
|
7
8
|
import threading
|
|
8
9
|
|
|
@@ -11,6 +12,7 @@ from ctypes import c_int16 as _s16
|
|
|
11
12
|
from ctypes import c_uint32 as _u32
|
|
12
13
|
from ctypes import c_int32 as _s32
|
|
13
14
|
from ctypes import c_int64 as _s64
|
|
15
|
+
from ctypes import c_byte as _c_byte
|
|
14
16
|
|
|
15
17
|
import pyglet
|
|
16
18
|
|
|
@@ -31,6 +33,24 @@ except ImportError:
|
|
|
31
33
|
return c.read(fd, buffers, 3072)
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
KeyMaxArray = _c_byte * ((KEY_MAX // 8) + 1)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class EvdevButton(Button):
|
|
40
|
+
event_type: int
|
|
41
|
+
event_code: int
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class EvdevAbsoluteAxis(AbsoluteAxis):
|
|
45
|
+
event_type: int
|
|
46
|
+
event_code: int
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class EvdevRelativeAxis(RelativeAxis):
|
|
50
|
+
event_type: int
|
|
51
|
+
event_code: int
|
|
52
|
+
|
|
53
|
+
|
|
34
54
|
# Structures from /linux/blob/master/include/uapi/linux/input.h
|
|
35
55
|
|
|
36
56
|
class Timeval(ctypes.Structure):
|
|
@@ -158,11 +178,13 @@ class FFEvent(ctypes.Structure):
|
|
|
158
178
|
)
|
|
159
179
|
|
|
160
180
|
|
|
181
|
+
# Helper "macros" for file io:
|
|
161
182
|
EVIOCGVERSION = _IOR('E', 0x01, ctypes.c_int)
|
|
162
183
|
EVIOCGID = _IOR('E', 0x02, InputID)
|
|
163
184
|
EVIOCGNAME = _IOR_str('E', 0x06)
|
|
164
185
|
EVIOCGPHYS = _IOR_str('E', 0x07)
|
|
165
186
|
EVIOCGUNIQ = _IOR_str('E', 0x08)
|
|
187
|
+
EVIOCGKEY = _IOR_len('E', 0x18)
|
|
166
188
|
EVIOCSFF = _IOW('E', 0x80, FFEvent)
|
|
167
189
|
|
|
168
190
|
|
|
@@ -170,9 +192,14 @@ def EVIOCGBIT(fileno, ev, buffer):
|
|
|
170
192
|
return _IOR_len('E', 0x20 + ev)(fileno, buffer)
|
|
171
193
|
|
|
172
194
|
|
|
173
|
-
def EVIOCGABS(fileno,
|
|
174
|
-
|
|
175
|
-
return _IOR_len('E', 0x40 +
|
|
195
|
+
def EVIOCGABS(fileno, ev, buffer=InputABSInfo()):
|
|
196
|
+
print("absbuffer instance:", buffer)
|
|
197
|
+
return _IOR_len('E', 0x40 + ev)(fileno, buffer)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def get_key_state(fileno, event_code, buffer=KeyMaxArray()):
|
|
201
|
+
buffer = EVIOCGKEY(fileno, buffer)
|
|
202
|
+
return bool(buffer[event_code // 8] & (1 << (event_code % 8)))
|
|
176
203
|
|
|
177
204
|
|
|
178
205
|
def get_set_bits(bytestring):
|
|
@@ -217,18 +244,16 @@ def _create_control(fileno, event_type, event_code):
|
|
|
217
244
|
value = absinfo.value
|
|
218
245
|
minimum = absinfo.minimum
|
|
219
246
|
maximum = absinfo.maximum
|
|
220
|
-
control =
|
|
247
|
+
control = EvdevAbsoluteAxis(name, minimum, maximum, raw_name, inverted=name == 'hat_y')
|
|
221
248
|
control.value = value
|
|
222
|
-
if name == 'hat_y':
|
|
223
|
-
control.inverted = True
|
|
224
249
|
elif event_type == EV_REL:
|
|
225
250
|
raw_name = rel_raw_names.get(event_code, f'EV_REL({event_code:x})')
|
|
226
251
|
name = _rel_names.get(event_code)
|
|
227
|
-
control =
|
|
252
|
+
control = EvdevRelativeAxis(name, raw_name)
|
|
228
253
|
elif event_type == EV_KEY:
|
|
229
254
|
raw_name = key_raw_names.get(event_code, f'EV_KEY({event_code:x})')
|
|
230
255
|
name = None
|
|
231
|
-
control =
|
|
256
|
+
control = EvdevButton(name, raw_name)
|
|
232
257
|
else:
|
|
233
258
|
return None
|
|
234
259
|
control.event_type = event_type
|
|
@@ -248,7 +273,8 @@ event_types = {
|
|
|
248
273
|
|
|
249
274
|
|
|
250
275
|
class EvdevDevice(XlibSelectDevice, Device):
|
|
251
|
-
_fileno
|
|
276
|
+
_fileno: int | None
|
|
277
|
+
_poll: "select.poll | None"
|
|
252
278
|
|
|
253
279
|
def __init__(self, display, filename):
|
|
254
280
|
self._filename = filename
|
|
@@ -301,11 +327,14 @@ class EvdevDevice(XlibSelectDevice, Device):
|
|
|
301
327
|
self.control_map[(event_type, event_code)] = control
|
|
302
328
|
self.controls.append(control)
|
|
303
329
|
|
|
304
|
-
self.controls.sort(key=lambda
|
|
330
|
+
self.controls.sort(key=lambda ctrl: ctrl.event_code)
|
|
305
331
|
os.close(fileno)
|
|
306
332
|
|
|
333
|
+
self._poll = select.poll()
|
|
307
334
|
self._event_size = ctypes.sizeof(InputEvent)
|
|
308
335
|
self._event_buffer = (InputEvent * 64)()
|
|
336
|
+
self._syn_dropped = False
|
|
337
|
+
self._event_queue = []
|
|
309
338
|
|
|
310
339
|
super().__init__(display, name)
|
|
311
340
|
|
|
@@ -321,6 +350,7 @@ class EvdevDevice(XlibSelectDevice, Device):
|
|
|
321
350
|
def open(self, window=None, exclusive=False):
|
|
322
351
|
try:
|
|
323
352
|
self._fileno = os.open(self._filename, os.O_RDWR | os.O_NONBLOCK)
|
|
353
|
+
self._poll.register(self._fileno, select.POLLIN | select.POLLPRI)
|
|
324
354
|
except OSError as e:
|
|
325
355
|
raise DeviceOpenException(e)
|
|
326
356
|
|
|
@@ -333,6 +363,9 @@ class EvdevDevice(XlibSelectDevice, Device):
|
|
|
333
363
|
if not self._fileno:
|
|
334
364
|
return
|
|
335
365
|
|
|
366
|
+
if self._poll:
|
|
367
|
+
self._poll.unregister(self._fileno)
|
|
368
|
+
|
|
336
369
|
pyglet.app.platform_event_loop.select_devices.remove(self)
|
|
337
370
|
os.close(self._fileno)
|
|
338
371
|
self._fileno = None
|
|
@@ -340,6 +373,20 @@ class EvdevDevice(XlibSelectDevice, Device):
|
|
|
340
373
|
def get_controls(self):
|
|
341
374
|
return self.controls
|
|
342
375
|
|
|
376
|
+
def _resync_control_state(self):
|
|
377
|
+
"""Manually resync all Control state.
|
|
378
|
+
|
|
379
|
+
This method queries and resets the state of each Control using the appropriate
|
|
380
|
+
ioctl calls. If this causes the Control value to change, the associated events
|
|
381
|
+
will be dispatched. This is a somewhat expensive operation, but it is necessary
|
|
382
|
+
to perform in some cases (such as when a SYN_DROPPED event is received).
|
|
383
|
+
"""
|
|
384
|
+
for control in self.control_map.values():
|
|
385
|
+
if isinstance(control, EvdevButton):
|
|
386
|
+
control.value = get_key_state(self._fileno, control.event_code)
|
|
387
|
+
if isinstance(control, EvdevAbsoluteAxis):
|
|
388
|
+
control.value = EVIOCGABS(self._fileno, control.event_code).value
|
|
389
|
+
|
|
343
390
|
# Force Feedback methods
|
|
344
391
|
|
|
345
392
|
def ff_upload_effect(self, structure):
|
|
@@ -351,25 +398,51 @@ class EvdevDevice(XlibSelectDevice, Device):
|
|
|
351
398
|
return self._fileno
|
|
352
399
|
|
|
353
400
|
def poll(self):
|
|
354
|
-
return False
|
|
401
|
+
return True if self._poll.poll(0) else False
|
|
355
402
|
|
|
356
403
|
def select(self):
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
404
|
+
"""When the file descriptor is ready, read and process InputEvents.
|
|
405
|
+
|
|
406
|
+
This method has the following behavior:
|
|
407
|
+
- Read and queue all incoming input events.
|
|
408
|
+
- When a SYN_REPORT event is received, dispatch all queued events.
|
|
409
|
+
- If a SYN_DROPPED event is received, set a flag. When the next
|
|
410
|
+
SYN_REPORT event appears, drop all queued events & manually resync
|
|
411
|
+
all Control state.
|
|
412
|
+
"""
|
|
360
413
|
try:
|
|
361
414
|
bytes_read = _readv(self._fileno, self._event_buffer)
|
|
415
|
+
n_events = bytes_read // self._event_size
|
|
362
416
|
except OSError:
|
|
363
417
|
self.close()
|
|
364
418
|
return
|
|
365
419
|
|
|
366
|
-
n_events = bytes_read // self._event_size
|
|
367
|
-
|
|
368
420
|
for event in self._event_buffer[:n_events]:
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
421
|
+
|
|
422
|
+
# Mark the current chain of events as invalid and continue:
|
|
423
|
+
if (event.type, event.code) == (EV_SYN, SYN_DROPPED):
|
|
424
|
+
self._syn_dropped = True
|
|
425
|
+
continue
|
|
426
|
+
|
|
427
|
+
# Dispatch queued events when SYN_REPORT comes in:
|
|
428
|
+
if (event.type, event.code) == (EV_SYN, SYN_REPORT):
|
|
429
|
+
|
|
430
|
+
# Unless a SYN_DROPPED event has been received,
|
|
431
|
+
# in which case discard all queued events and resync:
|
|
432
|
+
if self._syn_dropped:
|
|
433
|
+
self._event_queue.clear()
|
|
434
|
+
self._syn_dropped = False
|
|
435
|
+
self._resync_control_state()
|
|
436
|
+
|
|
437
|
+
# Dispatch all queued events, then clear the queue:
|
|
438
|
+
for queued_event in self._event_queue:
|
|
439
|
+
if control := self.control_map.get((queued_event.type, queued_event.code)):
|
|
440
|
+
control.value = queued_event.value
|
|
441
|
+
self._event_queue.clear()
|
|
442
|
+
|
|
443
|
+
# This is not a SYN_REPORT or SYN_DROPPED event, so it is probably
|
|
444
|
+
# an input event. Queue it until the next SYN_REPORT event comes in:
|
|
445
|
+
self._event_queue.append(event)
|
|
373
446
|
|
|
374
447
|
|
|
375
448
|
class FFController(Controller):
|
|
@@ -551,8 +624,8 @@ def _detect_controller_mapping(device):
|
|
|
551
624
|
ABS_Z: 'lefttrigger', ABS_RZ: 'righttrigger',
|
|
552
625
|
ABS_X: 'leftx', ABS_Y: 'lefty', ABS_RX: 'rightx', ABS_RY: 'righty'}
|
|
553
626
|
|
|
554
|
-
button_controls = [control for control in device.controls if isinstance(control,
|
|
555
|
-
axis_controls = [control for control in device.controls if isinstance(control,
|
|
627
|
+
button_controls = [control for control in device.controls if isinstance(control, EvdevButton)]
|
|
628
|
+
axis_controls = [control for control in device.controls if isinstance(control, EvdevAbsoluteAxis)]
|
|
556
629
|
hat_controls = [control for control in device.controls if control.name in ('hat_x', 'hat_y')]
|
|
557
630
|
|
|
558
631
|
for i, control in enumerate(button_controls):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Event constants from /usr/include/linux/input.h
|
|
1
|
+
"""Event constants from /usr/include/linux/input-event-codes.h"""
|
|
2
2
|
|
|
3
3
|
EV_SYN = 0x00
|
|
4
4
|
EV_KEY = 0x01
|
|
@@ -17,6 +17,7 @@ EV_MAX = 0x1f
|
|
|
17
17
|
|
|
18
18
|
SYN_REPORT = 0
|
|
19
19
|
SYN_CONFIG = 1
|
|
20
|
+
SYN_DROPPED = 3
|
|
20
21
|
|
|
21
22
|
# Keys and buttons
|
|
22
23
|
|
pyglet/input/win32/xinput.py
CHANGED
|
@@ -575,14 +575,16 @@ class XInputController(Controller):
|
|
|
575
575
|
def on_change(value):
|
|
576
576
|
normalized_value = value * scale + bias
|
|
577
577
|
setattr(self, name, normalized_value)
|
|
578
|
-
self.
|
|
578
|
+
self.leftanalog = Vec2(self.leftx, self.lefty)
|
|
579
|
+
self.dispatch_event('on_stick_motion', self, "leftstick", self.leftanalog)
|
|
579
580
|
|
|
580
581
|
elif name in ("rightx", "righty"):
|
|
581
582
|
@control.event
|
|
582
583
|
def on_change(value):
|
|
583
584
|
normalized_value = value * scale + bias
|
|
584
585
|
setattr(self, name, normalized_value)
|
|
585
|
-
self.
|
|
586
|
+
self.rightanalog = Vec2(self.rightx, self.righty)
|
|
587
|
+
self.dispatch_event('on_stick_motion', self, "rightstick", self.rightanalog)
|
|
586
588
|
|
|
587
589
|
def _add_button(self, control, name):
|
|
588
590
|
|
|
@@ -592,7 +594,8 @@ class XInputController(Controller):
|
|
|
592
594
|
target, bias = {'dpleft': ('dpadx', -1.0), 'dpright': ('dpadx', 1.0),
|
|
593
595
|
'dpdown': ('dpady', -1.0), 'dpup': ('dpady', 1.0)}[name]
|
|
594
596
|
setattr(self, target, bias * value)
|
|
595
|
-
self.
|
|
597
|
+
self.dpad = Vec2(self.dpadx, self.dpady)
|
|
598
|
+
self.dispatch_event('on_dpad_motion', self, self.dpad)
|
|
596
599
|
else:
|
|
597
600
|
@control.event
|
|
598
601
|
def on_change(value):
|
pyglet/libs/ioctl.py
CHANGED
|
@@ -41,7 +41,7 @@ from typing import TYPE_CHECKING
|
|
|
41
41
|
if TYPE_CHECKING:
|
|
42
42
|
from ctypes import Structure, c_int, c_uint
|
|
43
43
|
from typing import Callable, Union
|
|
44
|
-
c_data =
|
|
44
|
+
c_data = type[Structure] | type[c_int] | type[c_uint]
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
_IOC_NRBITS = 8
|
|
@@ -64,7 +64,7 @@ _IOC_READ = 2
|
|
|
64
64
|
# 'code' instead of 'type' to indicate the ioctl "magic number" ('H', 'E', etc.).
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
def _IOC(io_dir: _IOC_NONE
|
|
67
|
+
def _IOC(io_dir: Union[_IOC_NONE, _IOC_READ, _IOC_WRITE], code: int, nr: int, size: int) -> int:
|
|
68
68
|
return (io_dir << _IOC_DIRSHIFT) | (code << _IOC_TYPESHIFT) | (nr << _IOC_NRSHIFT) | (size << _IOC_SIZESHIFT)
|
|
69
69
|
|
|
70
70
|
|
pyglet/math.py
CHANGED
|
@@ -1387,7 +1387,10 @@ class Mat4(_typing.NamedTuple):
|
|
|
1387
1387
|
|
|
1388
1388
|
|
|
1389
1389
|
class Quaternion(_typing.NamedTuple):
|
|
1390
|
-
"""Quaternion.
|
|
1390
|
+
"""Quaternion.
|
|
1391
|
+
|
|
1392
|
+
Quaternions are 4-dimensional complex numbers, useful for describing 3D rotations.
|
|
1393
|
+
"""
|
|
1391
1394
|
|
|
1392
1395
|
w: float = 1.0
|
|
1393
1396
|
x: float = 0.0
|
|
@@ -1403,6 +1406,8 @@ class Quaternion(_typing.NamedTuple):
|
|
|
1403
1406
|
raise NotImplementedError
|
|
1404
1407
|
|
|
1405
1408
|
def to_mat4(self) -> Mat4:
|
|
1409
|
+
"""Calculate a 4x4 transform matrix which applies a rotation."""
|
|
1410
|
+
|
|
1406
1411
|
w = self.w
|
|
1407
1412
|
x = self.x
|
|
1408
1413
|
y = self.y
|
|
@@ -1428,6 +1433,8 @@ class Quaternion(_typing.NamedTuple):
|
|
|
1428
1433
|
return Mat4(a, b, c, 0.0, e, f, g, 0.0, i, j, k, 0.0, 0.0, 0.0, 0.0, 1.0)
|
|
1429
1434
|
|
|
1430
1435
|
def to_mat3(self) -> Mat3:
|
|
1436
|
+
"""Create a 3x3 rotation matrix."""
|
|
1437
|
+
|
|
1431
1438
|
w = self.w
|
|
1432
1439
|
x = self.x
|
|
1433
1440
|
y = self.y
|
|
@@ -1453,21 +1460,34 @@ class Quaternion(_typing.NamedTuple):
|
|
|
1453
1460
|
return Mat3(*(a, b, c, e, f, g, i, j, k))
|
|
1454
1461
|
|
|
1455
1462
|
def length(self) -> float:
|
|
1456
|
-
"""Calculate the length of the
|
|
1457
|
-
|
|
1458
|
-
The distance between the coordinates and the origin.
|
|
1459
|
-
"""
|
|
1463
|
+
"""Calculate the length of the quaternion from the origin."""
|
|
1460
1464
|
return _math.sqrt(self.w**2 + self.x**2 + self.y**2 + self.z**2)
|
|
1461
1465
|
|
|
1462
1466
|
def conjugate(self) -> Quaternion:
|
|
1467
|
+
"""Calculate the conjugate of this quaternion.
|
|
1468
|
+
|
|
1469
|
+
This operation:
|
|
1470
|
+
#. leaves the :py:attr:`.w` component alone
|
|
1471
|
+
#. inverts the sign of the :py:attr:`.x`, :py:attr:`.y`, and :py:attr:`.z` components
|
|
1472
|
+
|
|
1473
|
+
"""
|
|
1463
1474
|
return Quaternion(self.w, -self.x, -self.y, -self.z)
|
|
1464
1475
|
|
|
1465
1476
|
def dot(self, other: Quaternion) -> float:
|
|
1477
|
+
"""Calculate the dot product with another quaternion."""
|
|
1466
1478
|
a, b, c, d = self
|
|
1467
1479
|
e, f, g, h = other
|
|
1468
1480
|
return a * e + b * f + c * g + d * h
|
|
1469
1481
|
|
|
1470
1482
|
def normalize(self) -> Quaternion:
|
|
1483
|
+
"""Calculate a unit quaternion from the instance.
|
|
1484
|
+
|
|
1485
|
+
The returned quaternion will be a scaled-down version
|
|
1486
|
+
of the instance which has:
|
|
1487
|
+
|
|
1488
|
+
* a length of ``1``
|
|
1489
|
+
* the same relative of its components
|
|
1490
|
+
"""
|
|
1471
1491
|
m = self.length()
|
|
1472
1492
|
if m == 0:
|
|
1473
1493
|
return self
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
pyglet/__init__.py,sha256=
|
|
1
|
+
pyglet/__init__.py,sha256=8hn6a9j2PHmj1dJjM3pmdw8gCqudjYKiICfMazwc9HQ,21146
|
|
2
2
|
pyglet/__init__.pyi,sha256=g-eSsTUa4WDTqTULiN7cRqagvW58NGCPLj9sabXRFjo,2005
|
|
3
3
|
pyglet/clock.py,sha256=ZiYHckYRIUKuN1XmywQc3Dastd7O40Lw2XeMjC3iMtk,21892
|
|
4
4
|
pyglet/customtypes.py,sha256=e9AB-8WPPhhZXqfDEf4r2Lv0vAQUBjwig5EBejBDz0k,608
|
|
5
5
|
pyglet/event.py,sha256=XF3NPI7ilwUgK72Zxe7TBOAWqEG1sEqbQAJ7uKn_v7Y,19209
|
|
6
6
|
pyglet/info.py,sha256=pDfF59S5uuo_QouRG3I-0j5WVrwxpVYH8EzH2a0qx_8,5835
|
|
7
7
|
pyglet/lib.py,sha256=Mj1W_KDmUQXMg1iPLrM0pIIHDyWPO38J6qvoU_hXKjc,12013
|
|
8
|
-
pyglet/math.py,sha256=
|
|
8
|
+
pyglet/math.py,sha256=lMCspxzd_pOeLQev5HAA92v8nYFPfGjfK-mbO6iHK3E,56117
|
|
9
9
|
pyglet/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
pyglet/resource.py,sha256=EknGIAxDuc8prrGd5faOM4MNPT2q6NN4r3KQlrRg2dM,29374
|
|
11
11
|
pyglet/shapes.py,sha256=KRJz1lLN_jJXBYuW3AWVazbAILvHkJpVnxuo0Dmq_Jc,97445
|
|
@@ -20,7 +20,7 @@ pyglet/display/__init__.py,sha256=qz5Zy1S8XfapRys08uapOZK4N8Iian68yPCla505dcg,33
|
|
|
20
20
|
pyglet/display/__init__.pyi,sha256=JRd3vFMahd1YC3r-uPgr99V9yAmiut1QZXKMFmstg5o,65
|
|
21
21
|
pyglet/display/base.py,sha256=o8TYTl1J4zdy4pRJy9HEz4sOLqmdVMhNRFcrTJKP4U8,10142
|
|
22
22
|
pyglet/display/cocoa.py,sha256=mW3Npw4PjeH29xnAuww6pRToO3Zh4v_xWTEVKubqIAA,6391
|
|
23
|
-
pyglet/display/headless.py,sha256=
|
|
23
|
+
pyglet/display/headless.py,sha256=LwS0dHee0Y6oxPHidMvDVhIFqCDoBwNI0eQdXQgvtpE,2491
|
|
24
24
|
pyglet/display/win32.py,sha256=BqlRbIcDrgavU7pKTCn2bAn3U5sHU0mUpoiCjxPLyBw,9449
|
|
25
25
|
pyglet/display/xlib.py,sha256=6_SjJuqgDesW_jqwrQj7fjX3Csm8bVItnfBUxXds6BY,17264
|
|
26
26
|
pyglet/display/xlib_vidmoderestore.py,sha256=fkcVbCvwQ65UDvAxaIZb3JV_bAWONVgw7l-6UJhEXTs,5663
|
|
@@ -77,7 +77,7 @@ pyglet/gl/xlib.py,sha256=q6BNLJ9lujt3P-0xh3CAvJHCFERAuLSUnXOgeS4jZhY,11357
|
|
|
77
77
|
pyglet/graphics/__init__.py,sha256=O4O7fCQBI7qPReI8tUwLwArJHTWcoE1c_SotlHyUb2A,27940
|
|
78
78
|
pyglet/graphics/allocation.py,sha256=0MTwkK7-00UDs2xl6Te7cf0ljC2mmsOQMbx0zKZCJOU,12430
|
|
79
79
|
pyglet/graphics/instance.py,sha256=pzIaxO0EZCeoQDMR-qzjo4ahwfcbt3dDZm9UinYpZo0,2202
|
|
80
|
-
pyglet/graphics/shader.py,sha256=
|
|
80
|
+
pyglet/graphics/shader.py,sha256=VypoIX5bmP_R2ae_6_23cD06dpyCJTj_slQloQGYxTA,64263
|
|
81
81
|
pyglet/graphics/vertexarray.py,sha256=BWJFvP79JHpKwY91mrkjjhlbK3g87nIpMbCsc4FCcEg,1371
|
|
82
82
|
pyglet/graphics/vertexbuffer.py,sha256=SbtT2cNSXwPMlQRGf2DxTxZCEyj0AjEEDLLdho-ojG8,15284
|
|
83
83
|
pyglet/graphics/vertexdomain.py,sha256=Y4tAi26ABf5kLBGJ0QDvTVeWEL2vSN4HuIeS5svZjsg,32764
|
|
@@ -102,12 +102,12 @@ pyglet/image/codecs/s3tc.py,sha256=XsBcl8tOli61BVEoukb-9Ydw5aPSyydlJXWDC__W84Y,1
|
|
|
102
102
|
pyglet/image/codecs/wic.py,sha256=tPZssIDdkoiJedvM99nHB0ON1KH_n2JF5Vx7pfRbEjs,11156
|
|
103
103
|
pyglet/image/codecs/wincodec_lib.py,sha256=G2FSx9j9gMXpFOGUMt0a06C_DBv4LEaoAg103PW2Vx8,14602
|
|
104
104
|
pyglet/input/__init__.py,sha256=AGo55xX3yMr8TmeNXNFFwAY7WXrsA1rV6GgDRV-0faU,6417
|
|
105
|
-
pyglet/input/base.py,sha256=
|
|
105
|
+
pyglet/input/base.py,sha256=QO9c_cMo-qPT5fTcxR4GGTxHbwx_nX8_7rSDDJ62YLs,39326
|
|
106
106
|
pyglet/input/controller.py,sha256=kkLXJHyVePSlwagV9D7MN2QPjX9qjSk_avPI6G5Zud0,5548
|
|
107
107
|
pyglet/input/controller_db.py,sha256=KFgHVcwDKO6nC6qw_JDT-fE7BsgsYh76aKupc6fOKJY,196312
|
|
108
108
|
pyglet/input/linux/__init__.py,sha256=fd8rAts7soFEND4l5rUtLmEwK4rRpfFZ7Ibj9EOcrrA,391
|
|
109
|
-
pyglet/input/linux/evdev.py,sha256=
|
|
110
|
-
pyglet/input/linux/evdev_constants.py,sha256=
|
|
109
|
+
pyglet/input/linux/evdev.py,sha256=79c5k4CkEO3isv07bQ6y9QhxKmOCWgRgkkicCUpOo_Q,21255
|
|
110
|
+
pyglet/input/linux/evdev_constants.py,sha256=647CtG6a8782mmfdr20yzwC4JeuW702emszR_WSuj44,9816
|
|
111
111
|
pyglet/input/linux/x11_xinput.py,sha256=eezRkEM_Xl8MJcvHpGXUjliz4E-DBVEUNNooWr-LT_k,10939
|
|
112
112
|
pyglet/input/linux/x11_xinput_tablet.py,sha256=wnLrTQLwtAOrOPac3BJPXqBP_nygwRJtnHmdzJoCFjE,2959
|
|
113
113
|
pyglet/input/macos/__init__.py,sha256=5VQqkzxDR6gZfF21vxEG-GKts-BRRpETxJaK7OYiBoo,348
|
|
@@ -115,9 +115,9 @@ pyglet/input/macos/darwin_hid.py,sha256=VnoqvL26tZtU329yegtHUCnEM2zqmPbA2UKaOaSD
|
|
|
115
115
|
pyglet/input/win32/__init__.py,sha256=xYVWmf1_510qFJyPDXIhp6xnULP_B4qpLbFGSQrjX3g,4220
|
|
116
116
|
pyglet/input/win32/directinput.py,sha256=lU70it9a0xqLwEh21Dll0u6mnFmf-2MuEUIV87y8eMA,16974
|
|
117
117
|
pyglet/input/win32/wintab.py,sha256=ST0pYMMTJ0feQHPQqmgkjMjhS1AaTLbiBA2KK4FmXJ8,14430
|
|
118
|
-
pyglet/input/win32/xinput.py,sha256=
|
|
118
|
+
pyglet/input/win32/xinput.py,sha256=BRhGjo2l4fhJTQr_dMu1uD246sQD8gGjlwK1Q_Jc5hk,21701
|
|
119
119
|
pyglet/libs/__init__.py,sha256=GQaW5m1MjFBnoUBcfY1AfHY1C1MiXpbagsS8FVUT7Ck,584
|
|
120
|
-
pyglet/libs/ioctl.py,sha256=
|
|
120
|
+
pyglet/libs/ioctl.py,sha256=bQu9hpqYKMr0m0lXajlmSPGf4w72dGz1YLDOrq2uUz8,3700
|
|
121
121
|
pyglet/libs/darwin/__init__.py,sha256=Kx8qOx_xjgLZj9pf9qDj9-tZiWbzKfSmnmIeMaAiVnU,23
|
|
122
122
|
pyglet/libs/darwin/coreaudio.py,sha256=H0kpmJXPxSUHST56yxucV4iPhYd5SXduJjQ5dRQsNX0,8991
|
|
123
123
|
pyglet/libs/darwin/quartzkey.py,sha256=FhwLyotAdlhJIvmGX1JNPkB0kxPhedRb-9NeRh_HTwg,6051
|
|
@@ -228,7 +228,7 @@ pyglet/window/cocoa/systemcursor.py,sha256=-rMhvPH3DWl4gsSTCUbkn-yUnbyKM7JdQLfb5
|
|
|
228
228
|
pyglet/window/headless/__init__.py,sha256=BLmawFLSJqV_ZjwePGT8DxFSc2ZWuVMDbxATvu1qFX4,3251
|
|
229
229
|
pyglet/window/win32/__init__.py,sha256=2Kl5IM4e4nfZOTfSGTwjq9MVFBus0rFeLAKWeRR2W9Q,55563
|
|
230
230
|
pyglet/window/xlib/__init__.py,sha256=BsxLzjoWof46BLve8LfhAKZD6eYa1-z3vApXcqHeb_M,70722
|
|
231
|
-
pyglet-2.1.
|
|
232
|
-
pyglet-2.1.
|
|
233
|
-
pyglet-2.1.
|
|
234
|
-
pyglet-2.1.
|
|
231
|
+
pyglet-2.1.9.dist-info/LICENSE,sha256=V-fuy2c8jUDPMZJjPEgH-6jIFoUymjfht2PhVW1d7TQ,1546
|
|
232
|
+
pyglet-2.1.9.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
|
|
233
|
+
pyglet-2.1.9.dist-info/METADATA,sha256=SJWYnw8zzpA-hj45FMCDoBRNE-fRNDWSOczO7LbP5VU,7650
|
|
234
|
+
pyglet-2.1.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|