File size: 4,195 Bytes
d82cf6a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
from typing import Dict, Optional

import pyglet

from pyglet.input import base
from pyglet.input.win32.directinput import DirectInputDevice, _create_controller
from pyglet.input.win32.directinput import _di_manager as _di_device_manager

from pyglet.input.win32.directinput import get_devices as dinput_get_devices
from pyglet.input.win32.directinput import get_controllers as dinput_get_controllers
from pyglet.input.win32.directinput import get_joysticks

try:
    from pyglet.input.win32.wintab import get_tablets
except:
    def get_tablets(display=None):
        import warnings
        warnings.warn("Failed to initialize wintab framework.")
        return []


_xinput_enabled = False
if not pyglet.options["win32_disable_xinput"]:
    try:
        from pyglet.input.win32.xinput import XInputControllerManager, XInputController, XInputDevice
        from pyglet.input.win32.xinput import _device_manager as _xinput_device_manager
        from pyglet.input.win32.xinput import get_devices as xinput_get_devices
        from pyglet.input.win32.xinput import get_controllers as xinput_get_controllers

        _xinput_enabled = True
    except OSError:
        # Fail to import XInput.
        pass


class Win32ControllerManager(base.ControllerManager):
    """This class manages XInput and DirectInput as a combined manager.
       XInput will override any XInput compatible DirectInput devices.
       Any devices not supported by XInput will fall back to DirectInput.
    """

    def __init__(self):
        self._di_controllers: Dict[DirectInputDevice, base.Controller] = {}

        if _xinput_enabled:
            self._xinput_controllers: Dict[XInputDevice, XInputController] = {}

            for xdevice in _xinput_device_manager.all_devices:  # All 4 devices are initialized.
                meta = {'name': xdevice.name, 'guid': "XINPUTCONTROLLER"}
                self._xinput_controllers[xdevice] = XInputController(xdevice, meta)

            @_xinput_device_manager.event
            def on_connect(xdevice):
                self.dispatch_event('on_connect', self._xinput_controllers[xdevice])

            @_xinput_device_manager.event
            def on_disconnect(xdevice):
                self.dispatch_event('on_disconnect', self._xinput_controllers[xdevice])

        self._set_initial_didevices()

        @_di_device_manager.event
        def on_connect(di_device):
            if di_device not in self._di_controllers:
                if self._add_di_controller(di_device):
                    pyglet.app.platform_event_loop.post_event(self, 'on_connect', self._di_controllers[di_device])

        @_di_device_manager.event
        def on_disconnect(di_device):
            if di_device in self._di_controllers:
                _controller = self._di_controllers[di_device]
                del self._di_controllers[di_device]
                pyglet.app.platform_event_loop.post_event(self, 'on_disconnect', _controller)

    def _set_initial_didevices(self):
        if not _di_device_manager.registered:
            _di_device_manager.register_device_events()
            _di_device_manager.set_current_devices()

        for device in _di_device_manager.devices:
            self._add_di_controller(device)

    def _add_di_controller(self, device: DirectInputDevice) -> Optional[base.Controller]:
        controller = _create_controller(device)
        if controller:
            self._di_controllers[device] = controller
            return controller

        return None

    def _get_xinput_controllers(self) -> list:
        if not _xinput_enabled:
            return []
        return [ctlr for ctlr in self._xinput_controllers.values() if ctlr.device.connected]

    def _get_di_controllers(self) -> list:
        return list(self._di_controllers.values())

    def get_controllers(self):
        return self._get_xinput_controllers() + self._get_di_controllers()


def xinput_get_devices():
    return []


def xinput_get_controllers():
    return []


def get_devices(display=None):
    return xinput_get_devices() + dinput_get_devices(display)


def get_controllers(display=None):
    return xinput_get_controllers() + dinput_get_controllers(display)