100 lines
3.3 KiB
Python
100 lines
3.3 KiB
Python
from engine.gamepad import (
|
|
AXIS_LEFT_TRIGGER,
|
|
AXIS_LEFT_X,
|
|
AXIS_RIGHT_TRIGGER,
|
|
DEFAULT_GAMEPAD_BINDINGS,
|
|
GamepadBindings,
|
|
GamepadState,
|
|
apply_deadzone,
|
|
)
|
|
|
|
|
|
# --- apply_deadzone ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_deadzone_zeroes_small_values():
|
|
assert apply_deadzone(0.05) == 0.0
|
|
assert apply_deadzone(-0.1) == 0.0
|
|
|
|
|
|
def test_deadzone_passes_through_large_values():
|
|
assert apply_deadzone(0.5) == 0.5
|
|
assert apply_deadzone(-0.9) == -0.9
|
|
|
|
|
|
def test_deadzone_respects_custom_threshold():
|
|
assert apply_deadzone(0.3, deadzone=0.5) == 0.0
|
|
assert apply_deadzone(0.6, deadzone=0.5) == 0.6
|
|
|
|
|
|
# --- GamepadState ------------------------------------------------------------------------------
|
|
|
|
|
|
def test_axis_out_of_range_defaults_to_zero():
|
|
state = GamepadState(axes=[0.1, 0.2])
|
|
assert state.axis(AXIS_LEFT_X) == 0.1
|
|
assert state.axis(5) == 0.0
|
|
|
|
|
|
def test_digital_buttons_includes_pressed_real_buttons():
|
|
state = GamepadState(buttons={"gp_a": True, "gp_b": False})
|
|
assert state.digital_buttons() == {"gp_a"}
|
|
|
|
|
|
def test_digital_buttons_thresholds_triggers_into_pseudo_buttons():
|
|
axes = [0.0] * 6
|
|
axes[AXIS_LEFT_TRIGGER] = 0.9
|
|
axes[AXIS_RIGHT_TRIGGER] = 0.1
|
|
state = GamepadState(axes=axes)
|
|
assert state.digital_buttons() == {"gp_left_trigger"}
|
|
|
|
|
|
def test_digital_buttons_combines_real_and_trigger_buttons():
|
|
axes = [0.0] * 6
|
|
axes[AXIS_RIGHT_TRIGGER] = 1.0
|
|
state = GamepadState(buttons={"gp_a": True}, axes=axes)
|
|
assert state.digital_buttons() == {"gp_a", "gp_right_trigger"}
|
|
|
|
|
|
# --- GamepadBindings ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_default_bindings_resolve_expected_actions():
|
|
bindings = GamepadBindings(dict(DEFAULT_GAMEPAD_BINDINGS))
|
|
assert bindings.action_for_button("gp_a") == "leap"
|
|
assert bindings.action_for_button("gp_left_trigger") == "activate_left_hand_2"
|
|
|
|
|
|
def test_unbound_button_resolves_to_none():
|
|
bindings = GamepadBindings({"leap": ["gp_a"]})
|
|
assert bindings.action_for_button("gp_y") is None
|
|
|
|
|
|
def test_buttons_for_action_returns_the_configured_list():
|
|
bindings = GamepadBindings({"leap": ["gp_a", "gp_start"]})
|
|
assert bindings.buttons_for_action("leap") == ["gp_a", "gp_start"]
|
|
|
|
|
|
def test_load_falls_back_to_defaults_when_file_missing(tmp_path):
|
|
bindings = GamepadBindings.load(tmp_path / "does_not_exist.conf")
|
|
assert bindings.action_for_button("gp_a") == "leap"
|
|
|
|
|
|
def test_load_reads_conf_file_and_overrides_defaults(tmp_path):
|
|
conf = tmp_path / "controller_bindings.conf"
|
|
conf.write_text("[actions]\nleap = gp_y\n")
|
|
bindings = GamepadBindings.load(conf)
|
|
assert bindings.action_for_button("gp_y") == "leap"
|
|
assert bindings.action_for_button("gp_a") is None # overridden, not appended
|
|
# untouched actions still fall back to the defaults
|
|
assert bindings.action_for_button("gp_left_bumper") == "block"
|
|
|
|
|
|
def test_load_reads_the_real_shipped_controller_bindings_conf():
|
|
from pathlib import Path
|
|
|
|
path = Path(__file__).resolve().parent.parent / "config" / "controller_bindings.conf"
|
|
bindings = GamepadBindings.load(path)
|
|
assert bindings.action_for_button("gp_a") == "leap"
|
|
assert bindings.action_for_button("gp_dpad_up") == "select_ability_1"
|