joypads.gd 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. extends Control
  2. # Joypads demo, written by Dana Olson <dana@shineuponthee.com>
  3. #
  4. # This is a demo of joypad support, and doubles as a testing application
  5. # inspired by and similar to jstest-gtk.
  6. #
  7. # Licensed under the MIT license
  8. const DEADZONE = 0.2
  9. const FONT_COLOR_DEFAULT = Color(1.0, 1.0, 1.0, 0.5)
  10. const FONT_COLOR_ACTIVE = Color(0.2, 1.0, 0.2, 1.0)
  11. var joy_num
  12. var cur_joy = -1
  13. var axis_value
  14. @onready var axes = $Axes
  15. @onready var button_grid = $Buttons/ButtonGrid
  16. @onready var joypad_axes = $JoypadDiagram/Axes
  17. @onready var joypad_buttons = $JoypadDiagram/Buttons
  18. @onready var joypad_name = $DeviceInfo/JoyName
  19. @onready var joypad_number = $DeviceInfo/JoyNumber
  20. func _ready():
  21. Input.joy_connection_changed.connect(self._on_joy_connection_changed)
  22. for joypad in Input.get_connected_joypads():
  23. print_rich("Found joypad #%d: [b]%s[/b] - %s" % [joypad, Input.get_joy_name(joypad), Input.get_joy_guid(joypad)])
  24. func _process(_delta):
  25. # Get the joypad device number from the spinbox.
  26. joy_num = joypad_number.value
  27. # Display the name of the joypad if we haven't already.
  28. if joy_num != cur_joy:
  29. cur_joy = joy_num
  30. if Input.get_joy_name(joy_num) != "":
  31. set_joypad_name(Input.get_joy_name(joy_num), Input.get_joy_guid(joy_num))
  32. else:
  33. clear_joypad_name()
  34. # Loop through the axes and show their current values.
  35. for axis in range(int(min(JOY_AXIS_MAX, 10))):
  36. axis_value = Input.get_joy_axis(joy_num, axis)
  37. axes.get_node("Axis" + str(axis) + "/ProgressBar").set_value(100 * axis_value)
  38. axes.get_node("Axis" + str(axis) + "/ProgressBar/Value").set_text("[center][fade start=2 length=16]%s[/fade][/center]" % axis_value)
  39. # Scaled value used for alpha channel using valid range rather than including unusable deadzone values.
  40. var scaled_alpha_value = (abs(axis_value) - DEADZONE) / (1.0 - DEADZONE)
  41. # Show joypad direction indicators
  42. if axis <= JOY_AXIS_RIGHT_Y:
  43. if abs(axis_value) < DEADZONE:
  44. joypad_axes.get_node(str(axis) + "+").hide()
  45. joypad_axes.get_node(str(axis) + "-").hide()
  46. elif axis_value > 0:
  47. joypad_axes.get_node(str(axis) + "+").show()
  48. joypad_axes.get_node(str(axis) + "-").hide()
  49. # Transparent white modulate, non-alpha color channels are not changed here.
  50. joypad_axes.get_node(str(axis) + "+").self_modulate.a = scaled_alpha_value
  51. else:
  52. joypad_axes.get_node(str(axis) + "+").hide()
  53. joypad_axes.get_node(str(axis) + "-").show()
  54. # Transparent white modulate, non-alpha color channels are not changed here.
  55. joypad_axes.get_node(str(axis) + "-").self_modulate.a = scaled_alpha_value
  56. elif axis == JOY_AXIS_TRIGGER_LEFT || axis == JOY_AXIS_TRIGGER_RIGHT:
  57. if axis_value <= DEADZONE:
  58. joypad_axes.get_node(str(axis)).hide()
  59. else:
  60. joypad_axes.get_node(str(axis)).show()
  61. # Transparent white modulate, non-alpha color channels are not changed here.
  62. joypad_axes.get_node(str(axis)).self_modulate.a = scaled_alpha_value
  63. # Highlight axis labels that are within the "active" value range. Simular to the button highlighting for loop below.
  64. axes.get_node("Axis" + str(axis) + "/Label").add_theme_color_override("font_color", FONT_COLOR_DEFAULT)
  65. if abs(axis_value) >= DEADZONE:
  66. axes.get_node("Axis" + str(axis) + "/Label").add_theme_color_override("font_color", FONT_COLOR_ACTIVE)
  67. # Loop through the buttons and highlight the ones that are pressed.
  68. for button in range(int(min(JOY_BUTTON_SDL_MAX, 21))):
  69. if Input.is_joy_button_pressed(joy_num, button):
  70. button_grid.get_child(button).add_theme_color_override("font_color", FONT_COLOR_ACTIVE)
  71. if button <= JOY_BUTTON_MISC1:
  72. joypad_buttons.get_child(button).show()
  73. else:
  74. button_grid.get_child(button).add_theme_color_override("font_color", FONT_COLOR_DEFAULT)
  75. if button <= JOY_BUTTON_MISC1:
  76. joypad_buttons.get_child(button).hide()
  77. # Called whenever a joypad has been connected or disconnected.
  78. func _on_joy_connection_changed(device_id, connected):
  79. if connected:
  80. print_rich("[color=green]Found newly connected joypad #%d: [b]%s[/b] - %s[/color]" % [device_id, Input.get_joy_name(device_id), Input.get_joy_guid(device_id)])
  81. else:
  82. print_rich("[color=red]Disconnected joypad #%d.[/color]" % device_id)
  83. if device_id == cur_joy:
  84. # Update current joypad label.
  85. if connected:
  86. set_joypad_name(Input.get_joy_name(device_id), Input.get_joy_guid(device_id))
  87. else:
  88. clear_joypad_name()
  89. func _on_start_vibration_pressed():
  90. var weak = $Vibration/Weak/Value.get_value()
  91. var strong = $Vibration/Strong/Value.get_value()
  92. var duration = $Vibration/Duration/Value.get_value()
  93. Input.start_joy_vibration(cur_joy, weak, strong, duration)
  94. func _on_stop_vibration_pressed():
  95. Input.stop_joy_vibration(cur_joy)
  96. func _on_Remap_pressed():
  97. $RemapWizard.start(cur_joy)
  98. func _on_Clear_pressed():
  99. var guid = Input.get_joy_guid(cur_joy)
  100. if guid.is_empty():
  101. push_error("No gamepad selected.")
  102. return
  103. Input.remove_joy_mapping(guid)
  104. func _on_Show_pressed():
  105. $RemapWizard.show_map()
  106. func _on_joy_name_meta_clicked(meta):
  107. OS.shell_open(meta)
  108. func set_joypad_name(joy_name, joy_guid):
  109. # Make the GUID clickable (and point to Godot's game controller database for easier lookup).
  110. joypad_name.set_text("%s\n[color=#fff9][url=https://github.com/godotengine/godot/blob/master/core/input/gamecontrollerdb.txt]%s[/url][/color]" % [joy_name, joy_guid])
  111. # Make the rest of the UI appear as enabled.
  112. for node in [$JoypadDiagram, $Axes, $Buttons, $Vibration, $VBoxContainer]:
  113. node.modulate.a = 1.0
  114. func clear_joypad_name():
  115. joypad_name.set_text("[i]No controller detected at ID %d.[/i]" % joypad_number.value)
  116. # Make the rest of the UI appear as disabled.
  117. for node in [$JoypadDiagram, $Axes, $Buttons, $Vibration, $VBoxContainer]:
  118. node.modulate.a = 0.5