Source code for simvx.core.input.map

"""InputMap — singleton registry of action -> bindings."""

from __future__ import annotations

import logging
from typing import ClassVar

from .enums import JoyButton, Key, MouseButton
from .events import InputBinding

log = logging.getLogger(__name__)


[docs] class InputMap: """Maps action names to physical inputs. Class-level singleton.""" _actions: ClassVar[dict[str, list[InputBinding]]] = {}
[docs] @classmethod def add_action(cls, name: str, bindings: list[InputBinding | Key | MouseButton | JoyButton] | None = None): """Register a named action with optional initial bindings. Convenience: passing bare Key/MouseButton/JoyButton values auto-wraps them. """ if name in cls._actions: log.warning("Input action %r overwritten (had %s bindings)", name, len(cls._actions[name])) else: cls._actions[name] = [] log.debug("InputMap.add_action(%r, %s)", name, bindings) if bindings: cls._actions[name].extend(cls._to_binding(b) for b in bindings)
[docs] @classmethod def remove_action(cls, name: str): """Remove a named action and all its bindings.""" cls._actions.pop(name, None)
[docs] @classmethod def add_binding(cls, name: str, binding: InputBinding | Key | MouseButton | JoyButton): """Add a binding to an existing action. Creates the action if it does not exist.""" if name not in cls._actions: cls._actions[name] = [] cls._actions[name].append(cls._to_binding(binding))
[docs] @classmethod def remove_binding(cls, name: str, binding: InputBinding): """Remove a specific binding from an action.""" if name in cls._actions: try: cls._actions[name].remove(binding) except ValueError: pass
[docs] @classmethod def get_bindings(cls, name: str) -> list[InputBinding]: """Return bindings for an action (empty list if unknown).""" return cls._actions.get(name, [])
[docs] @classmethod def has_action(cls, name: str) -> bool: """Check if an action is registered.""" return name in cls._actions
[docs] @classmethod def get_actions(cls) -> list[str]: """Return all registered action names.""" return list(cls._actions)
[docs] @classmethod def clear(cls): """Remove all actions and bindings.""" cls._actions.clear()
@classmethod def _to_binding(cls, b: InputBinding | Key | MouseButton | JoyButton) -> InputBinding: if isinstance(b, InputBinding): return b if isinstance(b, Key): return InputBinding(key=b) if isinstance(b, MouseButton): return InputBinding(mouse_button=b) if isinstance(b, JoyButton): return InputBinding(joy_button=b) raise TypeError(f"Cannot create InputBinding from {type(b).__name__}")