Skip to content

Conversation

@AlealarcViva
Copy link
Contributor

This PR introduces a new system for displaying right-stick aiming hints across multiple input devices. It adds the RightStickHint and RightStickHintManager scripts, along with their supporting resources and textures for keyboard, Xbox, PlayStation, Switch, and Steam Deck.

Overview of Changes
Added RightStickHint and RightStickHintManager scripts to manage device-specific right-stick aim prompts.
Added new texture assets and resources for all supported device families.
Implemented unified logic to select the correct prompt based on the active input device.
Updated grappling_hook_start.tscn to use the new aim hint system.
Integrated device-specific input prompt assets to replace hard-coded placeholders.

resolves #1373

Introduces RightStickHint and RightStickHintManager scripts, resources, and textures for displaying right stick aim prompts across keyboard, Xbox, PlayStation, Switch, and Steam Deck. Updates grappling_hook_start.tscn to use the new movement aim hints and integrates device-specific input prompt assets.
@AlealarcViva AlealarcViva requested review from a team as code owners November 25, 2025 23:42
@github-actions
Copy link

Play this branch at https://play.threadbare.game/branches/endlessm/relevantinput.

(This launches the game from the start, not directly at the change(s) in this pull request.)

Improved code structure and readability in input hint scripts.

Reordered declarations in RightStickHintManager.gd to comply with gdlint rules.

Standardized constant formatting and simplified variable declarations for better consistency.

Applied minor formatting improvements to JoypadButtonTexturesAIM.gd to align with project style guidelines.

No functional changes; this PR only includes formatting and code-quality improvements.
Copy link
Collaborator

@manuq manuq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlealarcViva thanks for working on this!

I just played it with my xbox-like joypad and see the following errors in the output:

Image

The texture is also not displayed, obviously because of the errors above:

recording.webm

AlealarcViva and others added 2 commits November 27, 2025 16:31
Corrected the .tres paths to use the 'Aim_'-prefixed assets for all device types,
ensuring consistency across hint visuals. The previous paths were incorrect, and
this update aligns all resources with the intended directory structure.
Copy link
Member

@wjt wjt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is essentially a copy of movement_input_hints.tscn and all its supporting machinery - I would have expected it to be another scene that reuses the same scripts, just with a different set of resources applied to it.

I have some specific suggestions below but I would like to try implementing a different approach next week myself – I think that would be the clearest way to describe what I mean!

Comment on lines +12 to +16
if Engine.has_singleton("InputHelper"):
InputHelper.device_changed.connect(_on_input_device_changed)
_on_input_device_changed(InputHelper.device, InputHelper.device_index)
else:
_on_input_device_changed("keyboard", -1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can assume that the InputHelper singleton is present: we depend on this addon. Is there a particular need to have these checks that I've missed?

Suggested change
if Engine.has_singleton("InputHelper"):
InputHelper.device_changed.connect(_on_input_device_changed)
_on_input_device_changed(InputHelper.device, InputHelper.device_index)
else:
_on_input_device_changed("keyboard", -1)
InputHelper.device_changed.connect(_on_input_device_changed)
_on_input_device_changed(InputHelper.device, InputHelper.device_index)

Comment on lines +22 to +25
if Engine.has_singleton("InputHelper"):
is_keyboard_mode = (device == InputHelper.DEVICE_KEYBOARD)
else:
is_keyboard_mode = device.to_lower() == "keyboard"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if Engine.has_singleton("InputHelper"):
is_keyboard_mode = (device == InputHelper.DEVICE_KEYBOARD)
else:
is_keyboard_mode = device.to_lower() == "keyboard"
is_keyboard_mode = (device == InputHelper.DEVICE_KEYBOARD)

InputHelper="*res://addons/input_helper/input_helper.gd"
AspectRatioDebugger="*res://scenes/globals/aspect_ratio_debugger/aspect_ratio_debugger.tscn"
InputGlobal="*res://scenes/game_elements/props/hint/input_key/InputHintManager.gd"
RightStickHintManager="*res://scenes/game_elements/props/hint/input_key/RightStickHintManager.gd"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand why we need a global for this - can't it live in RightStickHint.gd?

Comment on lines +27 to +36
func _resource_for_device(device: String) -> JoypadButtonTexturesAim:
if device == null or device.is_empty():
return ResourceLoader.load(GENERIC_RESOURCE) as JoypadButtonTexturesAim

var d := device.to_lower()
for key: String in DEVICE_MAP.keys():
if key in d:
return ResourceLoader.load(DEVICE_MAP[key]) as JoypadButtonTexturesAim

return ResourceLoader.load(GENERIC_RESOURCE) as JoypadButtonTexturesAim
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the need to do these string comparisons. The Input Helper addon defines a small set of device types:

const DEVICE_KEYBOARD = "keyboard"
const DEVICE_XBOX_CONTROLLER = "xbox"
const DEVICE_SWITCH_CONTROLLER = "switch"
const DEVICE_PLAYSTATION_CONTROLLER = "playstation"
const DEVICE_STEAMDECK_CONTROLLER = "steamdeck"
const DEVICE_GENERIC = "generic"

These are the possible values for the first parameter of the InputManager.device_changed signal, which is where the device parameter here comes from. So DEVICE_MAP only needs to have these keys (no need for "playstation", "ps" and "play"), and this can be reduced to:

Suggested change
func _resource_for_device(device: String) -> JoypadButtonTexturesAim:
if device == null or device.is_empty():
return ResourceLoader.load(GENERIC_RESOURCE) as JoypadButtonTexturesAim
var d := device.to_lower()
for key: String in DEVICE_MAP.keys():
if key in d:
return ResourceLoader.load(DEVICE_MAP[key]) as JoypadButtonTexturesAim
return ResourceLoader.load(GENERIC_RESOURCE) as JoypadButtonTexturesAim
func _resource_for_device(device: String) -> JoypadButtonTexturesAim:
if device == null or device.is_empty():
return ResourceLoader.load(DEVICE_MAP.get(device, DEVICE_MAP["generic"])) as JoypadButtonTexturesAim

In fact the values could be preload()s of the resource files and then we don't need the load() call either.

Comment on lines +15 to +29
func get_texture_for_action(action_name: String) -> Texture2D:
# Match the action name and return the associated exported texture.
match action_name:
"aim_unpressed":
return aim_unpressed
"aim_up":
return aim_up
"aim_down":
return aim_down
"aim_left":
return aim_left
"aim_right":
return aim_right
_:
return aim_unpressed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func get_texture_for_action(action_name: String) -> Texture2D:
# Match the action name and return the associated exported texture.
match action_name:
"aim_unpressed":
return aim_unpressed
"aim_up":
return aim_up
"aim_down":
return aim_down
"aim_left":
return aim_left
"aim_right":
return aim_right
_:
return aim_unpressed
func get_texture_for_action(action_name: String) -> Texture2D:
var texture := (get(action_name) as Texture2D)
if not texture:
texture = aim_unpressed
return texture

https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-method-get

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Input hints for aiming grappling thread with joypad are misleading

4 participants