Common APIs - approxeng.input
- class approxeng.input.Controller(controls, node_mappings=None, dead_zone=None, hot_zone=None, ff_device=None)[source]
Superclass for controller implementations
- Variables:
axes (approxeng.input.Axes) – All analogue axes. You can get the individual axis objects from this, but you shouldn’t ever need to do this, use methods on Controller instead!
buttons (approxeng.input.Buttons) – All buttons are managed by this object. This can be used to access Button objects representing buttons on the controller, but you will almost never need to do this - use the methods on Controller instead!
- __init__(controls, node_mappings=None, dead_zone=None, hot_zone=None, ff_device=None)[source]
Populate the controller name, button set and axis set.
- Parameters:
controls – A list of
Button
,CentredAxis
,TriggerAxis
andBinaryAxis
instancesnode_mappings – A dict from device name to a prefix which will be applied to all events from nodes with a matching name before dispatching the corresponding events. This is used to handle controller types which create multiple nodes in /dev/input by keying on the device names reported to evdev for each node. Nodes are grouped by physical or unique ID first so should, in an ideal world at least, all correspond to the same physical controller. This is necessary to support some controllers on modern kernels, particularly 4.15. If not specified, or none, then no per-node renaming is applied. Device names which do not appear in this map are not assigned a prefix, so it’s legitimate to only assign prefixes for ‘new’ functionality which has magically appeared in a later kernel. Similarly, this is ignored if there is only one device node bound to the controller instance, so the best practice is to leave the older mappings named simply by their code, and only use this to handle secondary device nodes such as motion sensors.
dead_zone – If specified, this is applied to all axes
hot_zone – If specified, this is applied to all axes
ff_device – If specified, this is a force feedback compatible device node, defaults to None
- property battery_level: float | None
Read the battery capacity, if available, as a percentage. If not available, return None
- check_presses() ButtonPresses [source]
Return the set of Buttons which have been pressed since this call was last made, clearing it as we do. This is a shortcut to doing ‘buttons.get_and_clear_button_press_history’
- Returns:
A ButtonPresses instance which contains buttons which were pressed since this call was last made.
- property connected: bool
- Returns:
True if the controller object is associated correctly with a physical device, False otherwise. Use this to detect a loss of controller pairing.
- property controls: dict
- Returns:
A dict containing all the names of controls on this controller, this takes the form of a dict with two keys, axes and buttons, the values for each of which are lists of strings containing the names of each type of control.
- property presses: ButtonPresses
The
ButtonPresses
containing buttons pressed between the two most recent calls tocheck_presses()
- read_led_value(led_name) int | None [source]
Read an existing LED value. This may or may not work depending on the underlying implementation. Requires a bound controller with the specified name present in its LED sys classes. Returns None if this does not apply.
- Parameters:
led_name – Name of LED to query
- Returns:
Integer value of LED, or None if either unbound or no such LED name
- register_button_handler(button_handler, button_sname: str)[source]
Register a handler function which will be called when a button is pressed
- Parameters:
button_handler – A function which will be called when any of the specified buttons are pressed. The function is called with the Button that was pressed as the sole argument.
button_sname – The sname of the button which should trigger the handler function
- Returns:
A no-arg function which can be used to remove this registration
- property releases: ButtonPresses
The
ButtonPresses
containing buttons released between the two most recent calls tocheck_presses()
- rumble(milliseconds=1000)[source]
Trigger a force-feedback effect, compiling and sending to the device if necessary first, otherwise using an existing effect that’s already been compiled.
- Parameters:
milliseconds – milliseconds of rumbling required
- property sys_nodes: dict
Returns a dict of discovered sys nodes representing power and LED status for this controller. If the controller isn’t bound to a physical device, or there aren’t LED or power nodes available this returns an empty dict.
- write_led_value(led_name: str, value: int)[source]
Write a value to a named LED. Does nothing if either we’re not bound to a device, or there’s no such LED name.
- Parameters:
led_name – LED name within this device - use self.sys_nodes[‘leds’] keys to discover LED names.
value – Value to write, should be an integer.
- class approxeng.input.CentredAxis(name, min_raw_value, max_raw_value, axis_event_code, dead_zone=0.0, hot_zone=0.0, sname=None)[source]
A single analogue axis on a controller where the expected output range is -1.0 to 1.0 and the resting position of the control is at 0.0, at least in principle.
- __init__(name, min_raw_value, max_raw_value, axis_event_code, dead_zone=0.0, hot_zone=0.0, sname=None)[source]
Create a new CentredAxis - this will be done internally within the
Controller
sub-class.- Parameters:
name – A friendly name for the axis
min_raw_value – The value read from the event system when the axis is at its minimum value
max_raw_value – The value read from the event system when the axis is at its maximum value
axis_event_code – The evdev code for this axis, used to dispatch events to the axis from the event system
dead_zone – Size of the dead zone in the centre of the axis, within which all values will be mapped to 0.0
hot_zone – Size of the hot zones at the ends of the axis, where values will be mapped to -1.0 or 1.0
sname – The standard name for this axis, if specified
- property raw_value: float
Get an uncorrected value for this axis
- Returns:
a float value, negative to the left or down, and ranging from -1.0 to 1.0
- receive_device_value(raw_value: int)[source]
Set a new value, called from within the joystick implementation class when parsing the event queue.
- Parameters:
raw_value – the raw value from the joystick hardware
- Internal:
- reset()[source]
Reset calibration (max, min and centre values) for this axis specifically. Not generally needed, you can just call the reset method on the SixAxis instance.
- Internal:
- property value: float
Get a centre-compensated, scaled, value for the axis, taking any dead-zone into account. The value will scale from 0.0 at the edge of the dead-zone to 1.0 (positive) or -1.0 (negative) at the extreme position of the controller or the edge of the hot zone, if defined as other than 1.0. The axis will auto-calibrate for maximum value, initially it will behave as if the highest possible value from the hardware is 0.9 in each direction, and will expand this as higher values are observed. This is scaled by this function and should always return 1.0 or -1.0 at the extreme ends of the axis.
- Returns:
a float value, negative to the left or down and ranging from -1.0 to 1.0
- class approxeng.input.TriggerAxis(name: str, min_raw_value: int, max_raw_value: int, axis_event_code: int, dead_zone=0.0, hot_zone=0.0, sname: str | None = None, button_sname: str | None = None, button_trigger_value=0.5)[source]
A single analogue axis where the expected output range is 0.0 to 1.0. Typically this is used for triggers, where the resting position is 0.0 and any interaction causes higher values. Whether a particular controller exposes triggers as axes or as buttons depends on the hardware - the PS3 front triggers appear as buttons, the XBox One triggers as axes.
- __init__(name: str, min_raw_value: int, max_raw_value: int, axis_event_code: int, dead_zone=0.0, hot_zone=0.0, sname: str | None = None, button_sname: str | None = None, button_trigger_value=0.5)[source]
Create a new TriggerAxis - this will be done internally within the
Controller
sub-class.- Parameters:
name – A friendly name for the axis
min_raw_value – The value read from the event system when the trigger is not pressed
max_raw_value – The value read from the event system when the trigger is fully pressed
axis_event_code – The evdev code for this axis, used when dispatching events to it from an Axes object
dead_zone – The proportion of the trigger range which will be treated as equivalent to no press
hot_zone – The proportion of the trigger range which will be treated as equivalent to fully depressing the trigger
sname – The standard name for this trigger, if specified
button_sname – If provided, this creates a new Button internally which will be triggered by changes to the axis value. This is useful for triggers which have axis representations but no corresponding button presses such as the XBox1 controller front triggers. If this is set to None then no button is created
button_trigger_value – Defaulting to 0.5, this value determines the point in the trigger axis’ range at which point the button is regarded as being pressed or released.
- property raw_value: float
Get an uncorrected value for this trigger
- Returns:
a float value, 0.0 when not pressed, to 1.0 when fully pressed
- receive_device_value(raw_value: int)[source]
Set a new value, called from within the joystick implementation class when parsing the event queue.
- Parameters:
raw_value – the raw value from the joystick hardware
- Internal:
- reset()[source]
Reset calibration (max, min and centre values) for this axis specifically.
- Internal:
- property value: float
Get a centre-compensated, scaled, value for the axis, taking any dead-zone into account. The value will scale from 0.0 at the edge of the dead-zone to 1.0 (positive) at the extreme position of the trigger or the edge of the hot zone, if defined as other than 1.0.
- Returns:
a float value, 0.0 when not pressed or within the dead zone, to 1.0 when fully pressed or in the hot zone
- class approxeng.input.BinaryAxis(name, axis_event_code, b1name=None, b2name=None)[source]
A fake ‘analogue’ axis which actually corresponds to a pair of buttons. Once associated with a Buttons instance it routes events through to the Buttons instance to create button presses corresponding to axis movements. This is necessary as some controllers expose buttons, especially D-pad buttons, as a pair of axes rather than four buttons, but we almost certainly want to treat them as buttons the way most controllers do.
- __init__(name, axis_event_code, b1name=None, b2name=None)[source]
Create a new binary axis, used to route axis events through to a pair of buttons, which are created as part of this constructor
- Parameters:
name – Name for the axis, use this to describe the axis, it’s not used for anything else
axis_event_code – The evdev event code for changes to this axis
b1name – The sname of the button corresponding to negative values of the axis.
b2name – The sname of the button corresponding to positive values of the axis
- receive_device_value(raw_value: int)[source]
Receive a value from the underlying operating system code, in our case evdev, and update the internal state of this axis object appropriately.
- Parameters:
value – Integer value received from the evdev event handler.
- property value
You probably don’t want to actually get the value of this axis, use the generated buttons instead.
- Returns int:
The raw value from the evdev events driving this axis.
- class approxeng.input.CircularCentredAxis(x: CentredAxis, y: CentredAxis, dead_zone=0.1, hot_zone=0.1)[source]
An aggregation of a pair of
CentredAxis
instances.When using a pair of centred axes to model a single joystick there are some unexpected and probably undesirable issues with dead zones. As each axis is treated independently, the dead zones are also applied independently - this means that, for example, with the joystick fully pushed forwards you still have the dead zone behaviour between left and right. You may prefer a behaviour where both axes are zero if the stick is within a certain distance of its centre position in any direction. This class provides that, and is created from a pair of centred axes, i.e. ‘lx’ and ‘ly’. The value is returns is a tuple of (x,y) positions. Use of this class will constrain the overall motion of the paired axes into the unit circle - in many controllers this is true because of the physical layout of the controller, but it may not always be in hardware terms.
- __init__(x: CentredAxis, y: CentredAxis, dead_zone=0.1, hot_zone=0.1)[source]
Create a new circular centred axis
- Parameters:
x (CentredAxis) – Axis to use for x value
y (CentredAxis) – Axis to use for y value
dead_zone (float) – Specifies the distance from the centre prior to which both x and y will return 0.0, defaults to 0.1
hot_zone (float) – Specifies the distance from the 1.0 distance beyond which both x and y will return +-1.0, i.e. if the hot zone is set to 0.1 then all positions where the distance is greater than 0.9 will return magnitude 1 total distances. Defaults to 0.1
- class approxeng.input.Axes(axes)[source]
A set of TriggerAxis or CentredAxis instances to which events should be routed based on event code. Contains methods to reset calibration on all axes, or to centre all axes for which this is meaningful.
- __init__(axes)[source]
Create a new Axes instance, this will be done within the controller classes, you never have to explicitly instantiate this yourself.
- Parameters:
axes – a sequence of
approxeng.input.TriggerAxis
orapproxeng.input.CentredAxis
orapproxeng.input.BinaryAxis
containing all the axes the controller supports.
- property active_axes: ['Axis']
Return a sequence of all Axis objects which are not in their resting positions
- axis_updated(event: InputEvent, prefix=None)[source]
Called to process an absolute axis event from evdev, this is called internally by the controller implementations
- Internal:
- Parameters:
event – The evdev event to process
prefix – If present, a named prefix that should be applied to the event code when searching for the axis
- class approxeng.input.Button(name, key_code=None, sname=None)[source]
A single button on a controller
- __init__(name, key_code=None, sname=None)[source]
Create a new Button - this will be done by the controller implementation classes, you shouldn’t create your own unless you’re writing such a class.
- Parameters:
name – A friendly name for the button
key_code – The key code for the button, typically an integer used within the button press and release events. Defaults to None if not used.
sname – The standard name for the button, if available.
- class approxeng.input.Buttons(buttons_and_axes)[source]
A set of buttons on a controller. This class manages event binding and triggering, as well as monitoring button states and tracking whether buttons are held down, and how long if so. Controller implementations instantiate and configure an instance of this class when they want to provide button information, the controller is responsible for translating button events from the underlying operating system frameworks and updating this object appropriately, user code (i.e. your code if you’re reading this) uses the methods on this object to react to button presses.
- class ButtonState(button)[source]
Per-button state, including any handlers registered, whether the button was pressed since the last call to check, whether it is currently pressed, and the timestamp of the last button press. From this we can handle all possible forms of interaction required.
- __init__(buttons_and_axes)[source]
Instantiate a new button manager
- Parameters:
buttons_and_axes – a list of
approxeng.input.Button
instances which will be managed by this class
- button_pressed(key_code, prefix=None)[source]
Called from the controller classes to update the state of this button manager when a button is pressed.
- Internal:
- Parameters:
key_code – The code specified when populating Button instances
prefix – Applied to key code if present
- button_released(key_code, prefix=None)[source]
Called from the controller classes to update the state of this button manager when a button is released.
- Internal:
- Parameters:
key_code – The code specified when populating Button instance
prefix – Applied to key code if present
- check_presses()[source]
Return the set of Buttons which have been pressed since this call was last made, clearing it as we do.
- Returns:
A ButtonPresses instance which contains buttons which were pressed since this call was last made.
- held(sname)[source]
Determines whether a button is currently held, identifying it by standard name
- Parameters:
sname – The standard name of the button
- Returns:
None if the button is not held down, or is not available, otherwise the number of seconds as a floating point value since it was pressed
- property names
The snames of all button objects
- property presses
Get the ButtonPresses containing buttons pressed between the most recent two calls to check_presses. This will call the check_presses method if it has never been called before, and is therefore always safe even if your code has never called the update function. To make this property actually do something useful, however, you do need to call check_presses, preferably once immediately before you then want to handle any button presses that may have happened.
- Returns:
a ButtonPresses object containing information about which buttons were pressed
- register_button_handler(button_handler, buttons)[source]
Register a handler function which will be called when a button is pressed
- Parameters:
button_handler – A function which will be called when any of the specified buttons are pressed. The function is called with the Button that was pressed as the sole argument.
buttons ([Button]) – A list or one or more buttons which should trigger the handler when pressed. Buttons are specified as
approxeng.input.Button
instances, in general controller implementations will expose these as constants such as SixAxis.BUTTON_CIRCLE. A single Button can be specified if only one button binding is required.
- Returns:
A no-arg function which can be used to remove this registration
- property releases
Analogous to presses, but returns the set of buttons which were released
- Returns:
a ButtonPresses object containing information about which buttons were released