class_name PlayerInputSource extends RefCounted ## Converts remappable Godot Input Map actions into immutable [MoveIntent] values. ## This adapter owns no movement state and may be replaced independently of the ## local movement controller. ## Samples the current Input singleton state for one physics tick. func sample_move_intent() -> MoveIntent: return compose_move_intent( Input.get_action_strength(PlayerInputActions.MOVE_FORWARD), Input.get_action_strength(PlayerInputActions.MOVE_BACKWARD), Input.get_action_strength(PlayerInputActions.STRAFE_LEFT), Input.get_action_strength(PlayerInputActions.STRAFE_RIGHT), Input.get_action_strength(PlayerInputActions.DEBUG_FLY_UP), Input.get_action_strength(PlayerInputActions.DEBUG_FLY_DOWN), Input.is_action_pressed(PlayerInputActions.DEBUG_SPRINT) ) ## Builds a normalized intent from action strengths for deterministic tests and ## alternative input adapters. Strengths outside `[0, 1]` are clamped. static func compose_move_intent( forward_strength: float, backward_strength: float, strafe_left_strength: float, strafe_right_strength: float, fly_up_strength: float, fly_down_strength: float, sprint_requested: bool ) -> MoveIntent: var planar_axis := Vector2( clampf(strafe_right_strength, 0.0, 1.0) - clampf(strafe_left_strength, 0.0, 1.0), clampf(forward_strength, 0.0, 1.0) - clampf(backward_strength, 0.0, 1.0) ) if planar_axis.length_squared() > 1.0: planar_axis = planar_axis.normalized() var vertical_axis := clampf(fly_up_strength, 0.0, 1.0) - clampf(fly_down_strength, 0.0, 1.0) return MoveIntent.new( planar_axis.y, planar_axis.x, vertical_axis, sprint_requested )