showbase: make input device binding explicit, not automatic

This commit is contained in:
rdb 2018-09-16 20:22:40 +02:00
parent 8edc019307
commit 76365f3ed1

View File

@ -307,12 +307,7 @@ class ShowBase(DirectObject.DirectObject):
## This is the global input device manager, which keeps track of ## This is the global input device manager, which keeps track of
## connected input devices. ## connected input devices.
self.devices = InputDeviceManager.getGlobalPtr() self.devices = InputDeviceManager.getGlobalPtr()
# add existing devices to the data graph self.__inputDeviceNodes = {}
for device in self.devices.devices:
self.connectDevice(device)
# Checks for device connection and disconnection
self.accept('connect-device', self.connectDevice)
self.accept('disconnect-device', self.disconnectDevice)
self.createStats() self.createStats()
@ -1681,76 +1676,56 @@ class ShowBase(DirectObject.DirectObject):
return self.mouseWatcherNode.getModifierButtons().isDown( return self.mouseWatcherNode.getModifierButtons().isDown(
KeyboardButton.meta()) KeyboardButton.meta())
def connectDevice(self, device): def attachInputDevice(self, device, prefix=None):
""" """
This function will get called each time a new device got This function attaches an input device to the data graph, which will
connected and will add that new device to the data graph. cause the device to be polled and generate events. If a prefix is
given and not None, it is used to prefix events generated by this
device, separated by a hyphen.
Each device class will get a specific prefix for thrown events. Those If you call this, you should consider calling detachInputDevice when
are currently as follow you are done with the device or when it is disconnected.
gamepad
flight_stick
steering_wheel
dance_pad
mouse
keyboard
unclassified_device
In addition, the index of that device will appended to the prefix,
so for example if you hit the A button of the first connected gamepad
you will get an event like "gamepad0-action_a" the second gamepad will
then be catchable via "gamepad1-button_event" and so on.
Note, each device class will have a separate 0 based index, this way
you can have a gamepad0 as well as a steering_wheel0 and flight_stick0.
All newly created button throwers will be stored in
the deviceButtonThrowers lsit
""" """
idn = self.dataRoot.attachNewNode(InputDeviceNode(device, device.getName()))
prefix = "unclassified_device"
if device.getDeviceClass() == InputDevice.DC_gamepad:
prefix = "gamepad"
elif device.getDeviceClass() == InputDevice.DC_flight_stick:
prefix = "flight_stick"
elif device.getDeviceClass() == InputDevice.DC_steering_wheel:
prefix = "steering_wheel"
elif device.getDeviceClass() == InputDevice.DC_dance_pad:
prefix = "dance_pad"
elif device.getDeviceClass() == InputDevice.DC_mouse:
prefix = "mouse"
elif device.getDeviceClass() == InputDevice.DC_keyboard:
prefix = "keyboard"
currentPrefixes = [] # Protect against the same device being attached multiple times.
for np in self.dataRoot.findAllMatches("**/{}".format(prefix)): assert device not in self.__inputDeviceNodes
bt = np.node()
currentPrefixes.append(bt.getPrefix())
id = 0 idn = self.dataRoot.attachNewNode(InputDeviceNode(device, device.name))
# Find the next free ID for the newly connected device
while "{}{}-".format(prefix, id) in currentPrefixes: # Setup the button thrower to generate events for the device.
id+=1 bt = idn.attachNewNode(ButtonThrower(device.name))
# Setup the button thrower for that device and register it's event prefix if prefix is not None:
bt = idn.attachNewNode(ButtonThrower(prefix)) bt.node().setPrefix(prefix + '-')
assert self.notify.debug("Registered event prefix {}{}-".format(prefix, id))
bt.node().setPrefix("{}{}-".format(prefix, id)) assert self.notify.debug("Attached input device {0} with prefix {1}".format(device, prefix))
# append the new button thrower to the list of device button throwers self.__inputDeviceNodes[device] = idn
self.deviceButtonThrowers.append(bt) self.deviceButtonThrowers.append(bt)
def disconnectDevice(self, device): def detachInputDevice(self, device):
""" """
This function will get called each time a new device got This should be called after attaching an input device using
connected. It is then used to clean up the given device from the attachInputDevice and the device is disconnected or you no longer wish
data graph. to keep polling this device for events.
You do not strictly need to call this if you expect the device to be
reconnected (but be careful that you don't reattach it).
""" """
self.notify.debug("Disconnect device {}".format(device.getName()))
idn = self.dataRoot.find("**/{}".format(device.getName())) if device not in self.__inputDeviceNodes:
for bt in list(self.deviceButtonThrowers): assert device in self.__inputDeviceNodes
if bt.getName() == idn.getName(): return
assert self.notify.debug("Detached device {0}".format(device.name))
# Remove the ButtonThrower from the deviceButtonThrowers list.
idn = self.__inputDeviceNodes[device]
for bt in self.deviceButtonThrowers:
if idn.isAncestorOf(bt):
self.deviceButtonThrowers.remove(bt) self.deviceButtonThrowers.remove(bt)
break break
idn.removeNode() idn.removeNode()
del self.__inputDeviceNodes[device]
def addAngularIntegrator(self): def addAngularIntegrator(self):
if not self.physicsMgrAngular: if not self.physicsMgrAngular:
@ -1944,10 +1919,6 @@ class ShowBase(DirectObject.DirectObject):
# Check if there were newly connected devices. # Check if there were newly connected devices.
self.devices.update() self.devices.update()
# Poll all connected devices.
for device in self.devices.devices:
device.poll()
# traverse the data graph. This reads all the control # traverse the data graph. This reads all the control
# inputs (from the mouse and keyboard, for instance) and also # inputs (from the mouse and keyboard, for instance) and also
# directly acts upon them (for instance, to move the avatar). # directly acts upon them (for instance, to move the avatar).
@ -3163,6 +3134,8 @@ class ShowBase(DirectObject.DirectObject):
setup_mouse = setupMouse setup_mouse = setupMouse
setup_mouse_cb = setupMouseCB setup_mouse_cb = setupMouseCB
enable_software_mouse_pointer = enableSoftwareMousePointer enable_software_mouse_pointer = enableSoftwareMousePointer
detach_input_device = detachInputDevice
attach_input_device = attachInputDevice
add_angular_integrator = addAngularIntegrator add_angular_integrator = addAngularIntegrator
enable_particles = enableParticles enable_particles = enableParticles
disable_particles = disableParticles disable_particles = disableParticles