Controller input box is currently in development, but has reached alpha.

This commit is contained in:
Jamie Greunbaum 2024-06-07 02:08:10 -04:00
parent 8432df5456
commit e576dc7907
22 changed files with 1059 additions and 4 deletions

View File

@ -0,0 +1,10 @@
[gd_resource type="Resource" script_class="ControllerInputWheelDataPack" load_steps=4 format=3 uid="uid://clfqsqcsr4hns"]
[ext_resource type="Resource" uid="uid://oiupgjqy1f8s" path="res://addons/Bugbot/UI/ControllerInput/WheelData/qwerty_lowercase_alphanumeric.tres" id="1_04qmu"]
[ext_resource type="Script" path="res://addons/Bugbot/UI/ControllerInput/wheel_data_pack.gd" id="1_ux2y7"]
[ext_resource type="Resource" uid="uid://bi8wyvfejil2l" path="res://addons/Bugbot/UI/ControllerInput/WheelData/qwerty_uppercase_alphanumeric.tres" id="3_80dkp"]
[resource]
script = ExtResource("1_ux2y7")
lowercase = ExtResource("1_04qmu")
uppercase = ExtResource("3_80dkp")

View File

@ -0,0 +1,7 @@
[gd_resource type="Resource" script_class="ControllerInputWheelData" load_steps=2 format=3 uid="uid://oiupgjqy1f8s"]
[ext_resource type="Script" path="res://addons/Bugbot/UI/ControllerInput/wheel_data.gd" id="1_lbkw6"]
[resource]
script = ExtResource("1_lbkw6")
characters = Array[PackedStringArray]([PackedStringArray("6", "7", "u", "y", "t", "5"), PackedStringArray("9", "0", "-", "o", "i", "8"), PackedStringArray("=", "\'", "\\", "]", "[", "p"), PackedStringArray(";", "/", ".", ",", "k", "l"), PackedStringArray("h", "j", "m", "␣", "n", "g"), PackedStringArray("s", "d", "f", "b", "v", "c"), PackedStringArray("`", "w", "q", "a", "x", "z"), PackedStringArray("3", "4", "r", "e", "1", "2")])

View File

@ -0,0 +1,7 @@
[gd_resource type="Resource" script_class="ControllerInputWheelData" load_steps=2 format=3 uid="uid://bi8wyvfejil2l"]
[ext_resource type="Script" path="res://addons/Bugbot/UI/ControllerInput/wheel_data.gd" id="1_px0r8"]
[resource]
script = ExtResource("1_px0r8")
characters = Array[PackedStringArray]([PackedStringArray("^", "&", "U", "Y", "T", "%"), PackedStringArray("(", ")", "_", "O", "I", "*"), PackedStringArray("+", "\"", "|", "}", "{", "P"), PackedStringArray(":", "?", ">", "<", "K", "L"), PackedStringArray("H", "J", "M", "␣", "N", "G"), PackedStringArray("S", "D", "F", "B", "V", "C"), PackedStringArray("~", "W", "Q", "A", "X", "Z"), PackedStringArray("#", "$", "R", "E", "!", "@")])

View File

@ -0,0 +1,7 @@
shader_type canvas_item;
void fragment() {
float dist = 1.0f - (distance(vec2(0.5f, 0.5f), UV.xy) * 2.0);
float value = smoothstep(0.0f, 0.01, dist);
COLOR = vec4(1.0, 1.0, 1.0, value);
}

Binary file not shown.

View File

@ -0,0 +1,11 @@
class_name ControllerInputAction
extends Resource
@export var name : StringName = &""
@export var left : Array[InputEvent]
@export var right : Array[InputEvent]
@export var up : Array[InputEvent]
@export var down : Array[InputEvent]
@export_range(0.0, 1.0, 0.025) var deadzone : float = 0.05

View File

@ -0,0 +1,352 @@
@tool
class_name ControllerInputSelectWheel
extends Control
@export var wheel_data_pack : ControllerInputWheelDataPack : set = __set_wheel_data_pack
@export_range(0.0, 2.0, 0.01) var unselected_radius : float = 1.5 : set = __set_unselected_radius
@export_range(0.0, 2.0, 0.01) var selected_radius : float = 1.5 : set = __set_selected_radius
@export var unselected_scale : Vector2 = Vector2(0.5, 0.5) : set = __set_unselected_scale
@export var selected_scale : Vector2 = Vector2(1.0, 1.0) : set = __set_selected_scale
@export_range(0.0, 1.0, 0.01) var tween_speed : float = 0.15
@export_range(0.0, 1.0, 0.01) var caret_move_delay : float = 0.25
@export_range(0.0, 1.0, 0.01) var caret_move_repeat_delay : float = 0.1
@export_group("Inputs")
@export_subgroup("Joypad", "joypad_")
@export var joypad_wheel_up : InputEventJoypadMotion
@export var joypad_wheel_down : InputEventJoypadMotion
@export var joypad_wheel_left : InputEventJoypadMotion
@export var joypad_wheel_right : InputEventJoypadMotion
@export var joypad_caret_up : InputEventJoypadButton
@export var joypad_caret_down : InputEventJoypadButton
@export var joypad_caret_left : InputEventJoypadButton
@export var joypad_caret_right : InputEventJoypadButton
@export var joypad_shift : InputEventJoypadButton
@export var joypad_backspace : InputEventJoypadButton
@export var joypad_delete : InputEventJoypadButton
@onready var caret_horizontal_move_timer : Timer = $CaretHorizontalMoveTimer
@onready var caret_vertical_move_timer : Timer = $CaretVerticalMoveTimer
@onready var caret_remove_text_timer : Timer = $CaretRemoveTextTimer
signal new_character(char:String)
signal move_caret_up
signal move_caret_down
signal move_caret_left
signal move_caret_right
signal backspace
signal delete
var __wheel_data : ControllerInputWheelData = null
var __wheels : Array = []
var __selected_wheel : int = -1
var __symbol_wheel : PackedScene = preload("res://addons/Bugbot/UI/ControllerInput/controller_input_symbol_wheel.tscn")
func _init() -> void:
resized.connect(__spin_wheels_around_centre)
func _enter_tree() -> void:
__initialise_input()
__regenerate_wheels()
func _exit_tree() -> void:
__uninitialise_input()
func _input(event:InputEvent) -> void:
if event.is_action_pressed(&"select_wheel_shift"):
__wheel_data = wheel_data_pack.uppercase
__regenerate_wheels()
elif event.is_action_released(&"select_wheel_shift"):
__wheel_data = wheel_data_pack.lowercase
__regenerate_wheels()
__move_caret(event)
__backspace_caret(event)
__delete_caret(event)
var wheels_count : int = __wheels.size()
var index : int = -1
var left_stick_vector : Vector2 = Input.get_vector(&"select_wheel_left", &"select_wheel_right", &"select_wheel_up", &"select_wheel_down", 0.95)
if left_stick_vector.length_squared() - 0.01 > 0.0:
var stick_angle : float = ((Vector2.UP).rotated(left_stick_vector.angle() + (TAU / wheels_count / 2.0)).angle() + PI) / TAU
index = int(floor(stick_angle * wheels_count))
if index != __selected_wheel:
var old_selected_wheel : int = __selected_wheel
__selected_wheel = index
if old_selected_wheel >= 0:
__deselect_wheel(old_selected_wheel)
if __selected_wheel >= 0:
__select_wheel(__selected_wheel)
func __select_wheel(selection:int) -> void:
var wheel : ControllerInputSymbolWheel = __wheels[selection]
wheel.z_index = 1
wheel.new_character.connect(__print_character)
var wheel_tween_activate : Tween = get_tree().create_tween()
wheel_tween_activate.bind_node(wheel)
wheel_tween_activate.tween_property(wheel, "scale", __calculate_wheel_scale(selection), tween_speed)
var position : Vector2 = __calculate_wheel_position(wheel, selection, selected_radius)
var wheel_tween_radius : Tween = get_tree().create_tween()
wheel_tween_radius.bind_node(wheel)
wheel_tween_radius.tween_property(wheel, "position", position, tween_speed)
wheel.select()
func __deselect_wheel(deselection:int) -> void:
var wheel : ControllerInputSymbolWheel = __wheels[deselection]
wheel.z_index = 0
wheel.new_character.disconnect(__print_character)
var wheel_tween_deactivate : Tween = get_tree().create_tween()
wheel_tween_deactivate.bind_node(wheel)
wheel_tween_deactivate.tween_property(wheel, "scale", __calculate_wheel_scale(deselection), tween_speed)
var position : Vector2 = __calculate_wheel_position(wheel, deselection, unselected_radius)
var wheel_tween_radius : Tween = get_tree().create_tween()
wheel_tween_radius.bind_node(wheel)
wheel_tween_radius.tween_property(wheel, "position", position, tween_speed)
wheel.deselect()
func __print_character(char:String) -> void:
new_character.emit(char)
func __regenerate_wheels() -> void:
for i:ControllerInputSymbolWheel in __wheels:
i.deselect()
i.queue_free()
__wheels.clear()
if not __wheel_data:
if not wheel_data_pack.lowercase: return
__wheel_data = wheel_data_pack.lowercase
for character_group:PackedStringArray in __wheel_data.characters:
var wheel : ControllerInputSymbolWheel = __symbol_wheel.instantiate()
wheel.wheel_characters = character_group
if __selected_wheel == __wheels.size():
wheel.select()
wheel.new_character.connect(__print_character)
add_child(wheel)
__wheels.append(wheel)
__spin_wheels_around_centre()
func __spin_wheels_around_centre() -> void:
if not is_inside_tree(): return
for i:int in range(__wheels.size()):
var wheel : ControllerInputSymbolWheel = __wheels[i]
var radius : float = selected_radius if __selected_wheel == i else unselected_radius
wheel.scale = __calculate_wheel_scale(i)
wheel.position = __calculate_wheel_position(wheel, i, radius)
func __calculate_wheel_position(wheel:ControllerInputSymbolWheel, wheel_index:int, radius:float) -> Vector2:
var angle_slice : float = PI / float(__wheels.size()) * 2.0
var min_size : int = min(size.x, size.y)
var max_wheel_size : int = max(wheel.size.x, wheel.size.y)
var position : Vector2 = (size / 2.0) - wheel.size / 2.0
position += (Vector2.UP * radius).rotated(angle_slice * wheel_index) * ((min_size - max_wheel_size) / 3.0)
return position
func __calculate_wheel_scale(wheel_index:int) -> Vector2:
return (selected_scale if wheel_index == __selected_wheel else unselected_scale) * __get_proportional_scale()
func __refresh_scales() -> void:
for i:int in range(__wheels.size()):
var wheel : ControllerInputSymbolWheel = __wheels[i]
wheel.scale = __calculate_wheel_scale(i)
func __initialise_input() -> void:
InputMap.add_action(&"select_wheel_up", 0.75)
InputMap.action_add_event(&"select_wheel_up", joypad_wheel_up)
InputMap.add_action(&"select_wheel_down", 0.75)
InputMap.action_add_event(&"select_wheel_down", joypad_wheel_down)
InputMap.add_action(&"select_wheel_left", 0.75)
InputMap.action_add_event(&"select_wheel_left", joypad_wheel_left)
InputMap.add_action(&"select_wheel_right", 0.75)
InputMap.action_add_event(&"select_wheel_right", joypad_wheel_right)
InputMap.add_action(&"select_wheel_caret_up", 0.75)
InputMap.action_add_event(&"select_wheel_caret_up", joypad_caret_up)
InputMap.add_action(&"select_wheel_caret_down", 0.75)
InputMap.action_add_event(&"select_wheel_caret_down", joypad_caret_down)
InputMap.add_action(&"select_wheel_caret_left", 0.75)
InputMap.action_add_event(&"select_wheel_caret_left", joypad_caret_left)
InputMap.add_action(&"select_wheel_caret_right", 0.75)
InputMap.action_add_event(&"select_wheel_caret_right", joypad_caret_right)
InputMap.add_action(&"select_wheel_shift", 0.5)
InputMap.action_add_event(&"select_wheel_shift", joypad_shift)
InputMap.add_action(&"select_wheel_backspace", 0.5)
InputMap.action_add_event(&"select_wheel_backspace", joypad_backspace)
InputMap.add_action(&"select_wheel_delete", 0.5)
InputMap.action_add_event(&"select_wheel_delete", joypad_delete)
func __uninitialise_input() -> void:
InputMap.action_erase_event(&"select_wheel_delete", joypad_delete)
InputMap.erase_action(&"select_wheel_delete")
InputMap.action_erase_event(&"select_wheel_backspace", joypad_backspace)
InputMap.erase_action(&"select_wheel_backspace")
InputMap.action_erase_event(&"select_wheel_shift", joypad_shift)
InputMap.erase_action(&"select_wheel_shift")
InputMap.action_erase_event(&"select_wheel_caret_up", joypad_caret_up)
InputMap.erase_action(&"select_wheel_caret_up")
InputMap.action_erase_event(&"select_wheel_caret_down", joypad_caret_down)
InputMap.erase_action(&"select_wheel_caret_down")
InputMap.action_erase_event(&"select_wheel_caret_left", joypad_caret_left)
InputMap.erase_action(&"select_wheel_caret_left")
InputMap.action_erase_event(&"select_wheel_caret_right", joypad_caret_right)
InputMap.erase_action(&"select_wheel_caret_right")
InputMap.action_erase_event(&"select_wheel_right", joypad_wheel_right)
InputMap.erase_action(&"select_wheel_right")
InputMap.action_erase_event(&"select_wheel_left", joypad_wheel_left)
InputMap.erase_action(&"select_wheel_left")
InputMap.action_erase_event(&"select_wheel_down", joypad_wheel_down)
InputMap.erase_action(&"select_wheel_down")
InputMap.action_erase_event(&"select_wheel_up", joypad_wheel_up)
InputMap.erase_action(&"select_wheel_up")
func __move_caret(event:InputEvent) -> void:
if event.is_action_pressed(&"select_wheel_caret_up"):
__clear_vertical_move_caret_timeouts()
move_caret_up.emit()
caret_vertical_move_timer.timeout.connect(__move_caret_up_timeout)
caret_vertical_move_timer.start(caret_move_delay)
elif event.is_action_released(&"select_wheel_caret_up"):
__clear_vertical_move_caret_timeouts()
if event.is_action_pressed(&"select_wheel_caret_down"):
__clear_vertical_move_caret_timeouts()
move_caret_down.emit()
caret_vertical_move_timer.timeout.connect(__move_caret_down_timeout)
caret_vertical_move_timer.start(caret_move_delay)
elif event.is_action_released(&"select_wheel_caret_down"):
__clear_vertical_move_caret_timeouts()
if event.is_action_pressed(&"select_wheel_caret_left"):
__clear_horizontal_move_caret_timeouts()
move_caret_left.emit()
caret_horizontal_move_timer.timeout.connect(__move_caret_left_timeout)
caret_horizontal_move_timer.start(caret_move_delay)
elif event.is_action_released(&"select_wheel_caret_left"):
__clear_horizontal_move_caret_timeouts()
if event.is_action_pressed(&"select_wheel_caret_right"):
__clear_horizontal_move_caret_timeouts()
move_caret_right.emit()
caret_horizontal_move_timer.timeout.connect(__move_caret_right_timeout)
caret_horizontal_move_timer.start(caret_move_delay)
elif event.is_action_released(&"select_wheel_caret_right"):
__clear_horizontal_move_caret_timeouts()
func __move_caret_up_timeout() -> void:
move_caret_up.emit()
caret_vertical_move_timer.start(caret_move_repeat_delay)
func __move_caret_down_timeout() -> void:
move_caret_down.emit()
caret_vertical_move_timer.start(caret_move_repeat_delay)
func __move_caret_left_timeout() -> void:
move_caret_left.emit()
caret_horizontal_move_timer.start(caret_move_repeat_delay)
func __move_caret_right_timeout() -> void:
move_caret_right.emit()
caret_horizontal_move_timer.start(caret_move_repeat_delay)
func __clear_horizontal_move_caret_timeouts() -> void:
caret_horizontal_move_timer.stop()
var connections : Array = caret_horizontal_move_timer.timeout.get_connections()
for c:Dictionary in connections:
caret_horizontal_move_timer.timeout.disconnect(c["callable"])
func __clear_vertical_move_caret_timeouts() -> void:
caret_vertical_move_timer.stop()
var connections : Array = caret_vertical_move_timer.timeout.get_connections()
for c:Dictionary in connections:
caret_vertical_move_timer.timeout.disconnect(c["callable"])
func __backspace_caret(event:InputEvent) -> void:
if event.is_action_pressed(&"select_wheel_backspace"):
__clear_backspace_caret_timeouts()
backspace.emit()
caret_remove_text_timer.timeout.connect(__backspace_caret_timeout)
caret_remove_text_timer.start(caret_move_delay)
elif event.is_action_released(&"select_wheel_backspace"):
__clear_backspace_caret_timeouts()
func __backspace_caret_timeout() -> void:
backspace.emit()
caret_remove_text_timer.start(caret_move_repeat_delay)
func __clear_backspace_caret_timeouts() -> void:
caret_remove_text_timer.stop()
var connections : Array = caret_remove_text_timer.timeout.get_connections()
for c:Dictionary in connections:
caret_remove_text_timer.timeout.disconnect(c["callable"])
func __delete_caret(event:InputEvent) -> void:
if event.is_action_pressed(&"select_wheel_delete"):
__clear_backspace_caret_timeouts()
delete.emit()
caret_remove_text_timer.timeout.connect(__delete_caret_timeout)
caret_remove_text_timer.start(caret_move_delay)
elif event.is_action_released(&"select_wheel_delete"):
__clear_backspace_caret_timeouts()
func __delete_caret_timeout() -> void:
delete.emit()
caret_remove_text_timer.start(caret_move_repeat_delay)
func __set_wheel_data_pack(data:ControllerInputWheelDataPack) -> void:
wheel_data_pack = data
if __wheel_data == wheel_data_pack.lowercase:
__regenerate_wheels()
func __set_unselected_radius(r:float) -> void:
unselected_radius = r
__spin_wheels_around_centre()
func __set_selected_radius(r:float) -> void:
selected_radius = r
__spin_wheels_around_centre()
func __set_unselected_scale(s:Vector2) -> void:
unselected_scale = s
__refresh_scales()
func __set_selected_scale(s:Vector2) -> void:
selected_scale = s
__refresh_scales()
func __get_proportional_scale() -> float:
var viewport_rect : Vector2 = get_viewport_rect().size
if Engine.is_editor_hint():
viewport_rect.x = ProjectSettings.get_setting("display/window/size/viewport_width")
viewport_rect.y = ProjectSettings.get_setting("display/window/size/viewport_height")
return min(size.x, size.y) / min(viewport_rect.x, viewport_rect.y)

View File

@ -0,0 +1,112 @@
[gd_scene load_steps=16 format=3 uid="uid://b4cfqtvyfb80m"]
[ext_resource type="Script" path="res://addons/Bugbot/UI/ControllerInput/controller_input_select_wheel.gd" id="1_4y52p"]
[ext_resource type="Theme" uid="uid://bc7mjpjex4ovr" path="res://addons/Bugbot/UI/ControllerInput/select_wheel_theme.theme" id="1_5fmnc"]
[ext_resource type="Resource" uid="uid://clfqsqcsr4hns" path="res://addons/Bugbot/UI/ControllerInput/WheelData/qwerty_layout.tres" id="3_fpjxt"]
[ext_resource type="Material" uid="uid://bnh0d5o2riay8" path="res://addons/Bugbot/UI/ControllerInput/circle_backing.material" id="5_bebuy"]
[sub_resource type="InputEventJoypadMotion" id="InputEventJoypadMotion_lmyr0"]
device = -1
axis = 1
axis_value = -1.0
[sub_resource type="InputEventJoypadMotion" id="InputEventJoypadMotion_0dcbb"]
device = -1
axis = 1
axis_value = 1.0
[sub_resource type="InputEventJoypadMotion" id="InputEventJoypadMotion_tfsyf"]
device = -1
axis_value = -1.0
[sub_resource type="InputEventJoypadMotion" id="InputEventJoypadMotion_m64q4"]
device = -1
axis_value = 1.0
[sub_resource type="InputEventJoypadButton" id="InputEventJoypadButton_fdjsj"]
device = -1
button_index = 11
pressed = true
[sub_resource type="InputEventJoypadButton" id="InputEventJoypadButton_v7n5e"]
device = -1
button_index = 12
pressed = true
[sub_resource type="InputEventJoypadButton" id="InputEventJoypadButton_yuo6c"]
device = -1
button_index = 13
pressed = true
[sub_resource type="InputEventJoypadButton" id="InputEventJoypadButton_y13vx"]
device = -1
button_index = 14
pressed = true
[sub_resource type="InputEventJoypadButton" id="InputEventJoypadButton_iuf4w"]
device = -1
button_index = 9
pressed = true
[sub_resource type="InputEventJoypadButton" id="InputEventJoypadButton_8d326"]
device = -1
button_index = 2
pressed = true
[sub_resource type="InputEventJoypadButton" id="InputEventJoypadButton_jo62l"]
device = -1
button_index = 1
pressed = true
[node name="ControllerInputWheel" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
pivot_offset = Vector2(640, 360)
focus_mode = 2
theme = ExtResource("1_5fmnc")
script = ExtResource("1_4y52p")
wheel_data_pack = ExtResource("3_fpjxt")
unselected_radius = 0.9
selected_radius = 1.0
unselected_scale = Vector2(0.65, 0.65)
selected_scale = Vector2(0.75, 0.75)
tween_speed = 0.05
caret_move_delay = 0.15
caret_move_repeat_delay = 0.05
joypad_wheel_up = SubResource("InputEventJoypadMotion_lmyr0")
joypad_wheel_down = SubResource("InputEventJoypadMotion_0dcbb")
joypad_wheel_left = SubResource("InputEventJoypadMotion_tfsyf")
joypad_wheel_right = SubResource("InputEventJoypadMotion_m64q4")
joypad_caret_up = SubResource("InputEventJoypadButton_fdjsj")
joypad_caret_down = SubResource("InputEventJoypadButton_v7n5e")
joypad_caret_left = SubResource("InputEventJoypadButton_yuo6c")
joypad_caret_right = SubResource("InputEventJoypadButton_y13vx")
joypad_shift = SubResource("InputEventJoypadButton_iuf4w")
joypad_backspace = SubResource("InputEventJoypadButton_8d326")
joypad_delete = SubResource("InputEventJoypadButton_jo62l")
[node name="AspectRatioContainer" type="AspectRatioContainer" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_top = 0.25
anchor_right = 1.0
anchor_bottom = 0.75
grow_horizontal = 2
grow_vertical = 2
[node name="ColorRect" type="ColorRect" parent="AspectRatioContainer"]
material = ExtResource("5_bebuy")
layout_mode = 2
[node name="CaretHorizontalMoveTimer" type="Timer" parent="."]
one_shot = true
[node name="CaretVerticalMoveTimer" type="Timer" parent="."]
one_shot = true
[node name="CaretRemoveTextTimer" type="Timer" parent="."]
one_shot = true

View File

@ -0,0 +1,188 @@
@tool
class_name ControllerInputSymbolWheel
extends Control
@export() var wheel_characters : PackedStringArray = [] : set = __set_wheel_characters
@export_range(0.0, 10.0, 0.01) var unselected_radius : float = 1.5 : set = __set_unselected_radius
@export_range(0.0, 10.0, 0.01) var selected_radius : float = 1.5 : set = __set_selected_radius
@export_range(0.0, 1.0, 0.01) var font_scale : float = 0.45 : set = __set_font_scale
@export var unselected_scale : Vector2 = Vector2(0.5, 0.5) : set = __set_unselected_scale
@export var selected_scale : Vector2 = Vector2(1.0, 1.0) : set = __set_selected_scale
@export_range(0.0, 1.0, 0.01) var tween_speed : float = 0.15
@export_group("Inputs")
@export_subgroup("Joypad", "joypad_")
@export var joypad_symbol_up : InputEventJoypadMotion
@export var joypad_symbol_down : InputEventJoypadMotion
@export var joypad_symbol_left : InputEventJoypadMotion
@export var joypad_symbol_right : InputEventJoypadMotion
signal new_character(char:String)
var __symbol_labels : Array = []
var __selected_label : int = -1
var __selected : bool = false
func _init() -> void:
if not resized.is_connected(__spin_labels_around_centre):
resized.connect(__spin_labels_around_centre)
func _enter_tree() -> void:
__regenerate_labels()
func _exit_tree() -> void:
if resized.is_connected(__spin_labels_around_centre):
resized.disconnect(__spin_labels_around_centre)
func _input(event:InputEvent) -> void:
if not __selected: return
var symbols_count : int = __symbol_labels.size()
var index : int = -1
var right_stick_vector : Vector2 = Input.get_vector(&"select_symbol_left", &"select_symbol_right", &"select_symbol_up", &"select_symbol_down", 0.95)
if right_stick_vector.length_squared() - 0.01 > 0.0:
var stick_angle : float = ((Vector2.UP).rotated(right_stick_vector.angle() + (TAU / (symbols_count + symbols_count))).angle() + PI) / TAU
index = clamp(int(floor(stick_angle * symbols_count)), 0, symbols_count - 1)
__new_symbol_selection(index)
func select() -> void:
if __selected: return
__selected = true
__spin_labels_around_centre()
__initialise_input()
func deselect() -> void:
if not __selected: return
__selected = false
if __selected_label >= 0:
__deselect_symbol(__selected_label)
__selected_label = -1
__uninitialise_input()
__spin_labels_around_centre()
func __new_symbol_selection(new_selection:int) -> void:
if __selected_label == new_selection: return
if new_selection < 0:
var send_char : String = wheel_characters[__selected_label]
if not send_char.is_empty():
if send_char == "":
new_character.emit(" ")
else:
new_character.emit(send_char)
if __selected_label >= 0:
__deselect_symbol(__selected_label)
__selected_label = new_selection
if __selected_label >= 0:
__select_symbol(__selected_label)
func __select_symbol(selection:int) -> void:
var label : Label = __symbol_labels[selection]
label.z_index = 1
var label_tween_activate : Tween = get_tree().create_tween()
label_tween_activate.bind_node(label)
label_tween_activate.tween_property(label, "scale", selected_scale, tween_speed)
var position : Vector2 = __calculate_label_position(label, selection, selected_radius)
var label_tween_radius : Tween = get_tree().create_tween()
label_tween_radius.bind_node(label)
label_tween_radius.tween_property(label, "position", position, tween_speed)
func __deselect_symbol(selection:int) -> void:
var label : Label = __symbol_labels[selection]
label.z_index = 0
var label_tween_deactivate : Tween = get_tree().create_tween()
label_tween_deactivate.bind_node(label)
label_tween_deactivate.tween_property(label, "scale", unselected_scale, tween_speed)
var position : Vector2 = __calculate_label_position(label, selection, unselected_radius)
var label_tween_radius : Tween = get_tree().create_tween()
label_tween_radius.bind_node(label)
label_tween_radius.tween_property(label, "position", position, tween_speed)
func __calculate_label_position(label:Label, label_index:int, radius:float) -> Vector2:
var angle_slice : float = PI / float(__symbol_labels.size()) * 2.0
var min_size : int = min(size.x, size.y)
var max_label_size : int = max(label.size.x, label.size.y)
label.pivot_offset = label.size / 2.0
var position : Vector2 = (size / 2.0) - label.size / 2.0
position += (-Vector2.UP * radius).rotated(angle_slice * label_index) * ((min_size - max_label_size) / 3.0)
return position
func __regenerate_labels() -> void:
for i:Label in __symbol_labels:
i.queue_free()
__symbol_labels = []
for char:String in wheel_characters:
var label : Label = Label.new()
add_child(label)
label.text = char
label.horizontal_alignment = HorizontalAlignment.HORIZONTAL_ALIGNMENT_CENTER
label.vertical_alignment = VerticalAlignment.VERTICAL_ALIGNMENT_CENTER
label.size = Vector2(20.0, 20.0)
label.pivot_offset = label.size / 2.0
__symbol_labels.append(label)
__spin_labels_around_centre()
func __spin_labels_around_centre() -> void:
for i:int in range(__symbol_labels.size()):
var label : Label = __symbol_labels[i]
var max_label_size : int = max(label.size.x, label.size.y)
var radius : float = selected_radius if i == __selected_label else unselected_radius
label.scale = selected_scale if i == __selected_label else unselected_scale
label.position = __calculate_label_position(label, i, radius)
func __initialise_input() -> void:
InputMap.add_action(&"select_symbol_up", 0.75)
InputMap.action_add_event(&"select_symbol_up", joypad_symbol_up)
InputMap.add_action(&"select_symbol_down", 0.75)
InputMap.action_add_event(&"select_symbol_down", joypad_symbol_down)
InputMap.add_action(&"select_symbol_left", 0.75)
InputMap.action_add_event(&"select_symbol_left", joypad_symbol_left)
InputMap.add_action(&"select_symbol_right", 0.75)
InputMap.action_add_event(&"select_symbol_right", joypad_symbol_right)
func __uninitialise_input() -> void:
InputMap.action_erase_event(&"select_symbol_right", joypad_symbol_right)
InputMap.erase_action(&"select_symbol_right")
InputMap.action_erase_event(&"select_symbol_left", joypad_symbol_left)
InputMap.erase_action(&"select_symbol_left")
InputMap.action_erase_event(&"select_symbol_down", joypad_symbol_down)
InputMap.erase_action(&"select_symbol_down")
InputMap.action_erase_event(&"select_symbol_up", joypad_symbol_up)
InputMap.erase_action(&"select_symbol_up")
func __set_wheel_characters(characters:PackedStringArray) -> void:
wheel_characters = characters
__regenerate_labels()
func __set_selected_radius(r:float) -> void:
selected_radius = r
func __set_unselected_radius(r:float) -> void:
unselected_radius = r
func __set_font_scale(s:float) -> void:
font_scale = s
func __set_unselected_scale(s:Vector2) -> void:
unselected_scale = s
func __set_selected_scale(s:Vector2) -> void:
selected_scale = s

View File

@ -0,0 +1,54 @@
[gd_scene load_steps=7 format=3 uid="uid://lrexjid1ddug"]
[ext_resource type="Script" path="res://addons/Bugbot/UI/ControllerInput/controller_input_symbol_wheel.gd" id="1_j7n7k"]
[ext_resource type="Material" uid="uid://bnh0d5o2riay8" path="res://addons/Bugbot/UI/ControllerInput/circle_backing.material" id="2_87ps1"]
[sub_resource type="InputEventJoypadMotion" id="InputEventJoypadMotion_q0thm"]
device = -1
axis = 3
axis_value = -1.0
[sub_resource type="InputEventJoypadMotion" id="InputEventJoypadMotion_ktlvj"]
device = -1
axis = 3
axis_value = 1.0
[sub_resource type="InputEventJoypadMotion" id="InputEventJoypadMotion_8y7ye"]
device = -1
axis = 2
axis_value = -1.0
[sub_resource type="InputEventJoypadMotion" id="InputEventJoypadMotion_222jf"]
device = -1
axis = 2
axis_value = 1.0
[node name="ControllerInputSymbolWheel" type="Control"]
layout_mode = 3
anchors_preset = 0
script = ExtResource("1_j7n7k")
wheel_characters = PackedStringArray()
unselected_scale = Vector2(0.6, 0.6)
selected_scale = Vector2(0.75, 0.75)
tween_speed = 0.05
joypad_symbol_up = SubResource("InputEventJoypadMotion_q0thm")
joypad_symbol_down = SubResource("InputEventJoypadMotion_ktlvj")
joypad_symbol_left = SubResource("InputEventJoypadMotion_8y7ye")
joypad_symbol_right = SubResource("InputEventJoypadMotion_222jf")
[node name="ColorRect" type="ColorRect" parent="."]
material = ExtResource("2_87ps1")
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -175.0
offset_top = -175.0
offset_right = 175.0
offset_bottom = 175.0
grow_horizontal = 2
grow_vertical = 2
scale = Vector2(0.85, 0.85)
pivot_offset = Vector2(175, 175)

View File

@ -0,0 +1,55 @@
[gd_scene load_steps=5 format=3 uid="uid://ce8w5d3nv0eli"]
[ext_resource type="PackedScene" uid="uid://b4cfqtvyfb80m" path="res://addons/Bugbot/UI/ControllerInput/controller_input_select_wheel.tscn" id="1_55kuj"]
[ext_resource type="Theme" uid="uid://cw07kl24clcs0" path="res://addons/Bugbot/UI/bug_report_form.theme" id="1_apys2"]
[ext_resource type="Script" path="res://addons/Bugbot/UI/ControllerInput/controller_input_wheel_text_edit.gd" id="2_e8edy"]
[sub_resource type="InputEventJoypadButton" id="InputEventJoypadButton_qubfr"]
device = -1
button_index = 3
pressed = true
[node name="ControllerInputWheelScreen" type="ColorRect"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme = ExtResource("1_apys2")
color = Color(0, 0, 0, 0.25098)
script = ExtResource("2_e8edy")
edit_mode = 1
joypad_exit = SubResource("InputEventJoypadButton_qubfr")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.05
anchor_top = 0.1
anchor_right = 0.95
anchor_bottom = 0.9
grow_horizontal = 2
grow_vertical = 2
[node name="ControllerInputWheel" parent="VBoxContainer" instance=ExtResource("1_55kuj")]
layout_mode = 2
size_flags_vertical = 3
size_flags_stretch_ratio = 2.5
[node name="LineEdit" type="LineEdit" parent="VBoxContainer"]
layout_mode = 2
[node name="TextEdit" type="TextEdit" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
focus_mode = 1
wrap_mode = 1
caret_multiple = false
[connection signal="backspace" from="VBoxContainer/ControllerInputWheel" to="." method="_on_controller_input_wheel_backspace"]
[connection signal="delete" from="VBoxContainer/ControllerInputWheel" to="." method="_on_controller_input_wheel_delete"]
[connection signal="move_caret_down" from="VBoxContainer/ControllerInputWheel" to="." method="_on_controller_input_wheel_move_caret_down"]
[connection signal="move_caret_left" from="VBoxContainer/ControllerInputWheel" to="." method="_on_controller_input_wheel_move_caret_left"]
[connection signal="move_caret_right" from="VBoxContainer/ControllerInputWheel" to="." method="_on_controller_input_wheel_move_caret_right"]
[connection signal="move_caret_up" from="VBoxContainer/ControllerInputWheel" to="." method="_on_controller_input_wheel_move_caret_up"]
[connection signal="new_character" from="VBoxContainer/ControllerInputWheel" to="." method="_on_controller_input_wheel_new_character"]

View File

@ -0,0 +1,148 @@
class_name ControllerInputWheelTextEdit
extends Control
enum EditMode { LINE_EDIT, TEXT_EDIT }
@onready var line_edit : LineEdit = $VBoxContainer/LineEdit
@onready var text_edit : TextEdit = $VBoxContainer/TextEdit
@export_enum("LineEdit", "TextEdit") var edit_mode : int = EditMode.LINE_EDIT : set = __set_mode
@export var text : String : set = __set_text, get = __get_text
@export_group("Inputs")
@export_subgroup("Joypad", "joypad_")
@export var joypad_exit : InputEventJoypadButton
var __stored_ui_actions : Dictionary = {}
func _enter_tree() -> void:
__configure_inputs()
func _ready() -> void:
match edit_mode:
EditMode.LINE_EDIT:
line_edit.visible = true
text_edit.visible = false
line_edit.grab_focus()
EditMode.TEXT_EDIT:
line_edit.visible = false
text_edit.visible = true
text_edit.grab_focus()
func _input(event:InputEvent) -> void:
if event.is_action_pressed(&"ui_exit_text_editor"):
queue_free()
return
match edit_mode:
EditMode.LINE_EDIT: line_edit.grab_focus()
EditMode.TEXT_EDIT: text_edit.grab_focus()
func _exit_tree() -> void:
__deconfigure_inputs()
func _on_controller_input_wheel_new_character(char:String) -> void:
match edit_mode:
EditMode.LINE_EDIT: line_edit.insert_text_at_caret(char)
EditMode.TEXT_EDIT: text_edit.insert_text_at_caret(char)
func _on_controller_input_wheel_backspace() -> void:
match edit_mode:
EditMode.LINE_EDIT:
if line_edit.caret_column > 0:
line_edit.delete_text(line_edit.caret_column - 1, line_edit.caret_column)
EditMode.TEXT_EDIT:
text_edit.backspace()
func _on_controller_input_wheel_delete() -> void:
match edit_mode:
EditMode.LINE_EDIT:
if line_edit.caret_column < line_edit.text.length():
line_edit.delete_text(line_edit.caret_column, line_edit.caret_column + 1)
EditMode.TEXT_EDIT:
text_edit.begin_complex_operation()
text_edit.start_action(TextEdit.EditAction.ACTION_DELETE)
var caret_line : int = text_edit.get_caret_line()
var caret_column : int = text_edit.get_caret_column()
var current_line_length : int = text_edit.get_line(caret_line).length()
var next_line : int = caret_line if caret_column < current_line_length else caret_line + 1;
var next_column : int = (caret_column + 1) if caret_column < current_line_length else 0;
if next_line < text_edit.get_line_count() or next_column > current_line_length:
text_edit.remove_text(caret_line, caret_column, next_line, next_column)
text_edit.end_action()
text_edit.end_complex_operation()
text_edit.set_caret_column(caret_column)
func _on_controller_input_wheel_move_caret_up() -> void:
match edit_mode:
EditMode.TEXT_EDIT: text_edit.set_caret_line(clamp(text_edit.get_caret_line() - 1, 0, text_edit.get_line_count() - 1))
func _on_controller_input_wheel_move_caret_down() -> void:
match edit_mode:
EditMode.TEXT_EDIT: text_edit.set_caret_line(clamp(text_edit.get_caret_line() + 1, 0, text_edit.get_line_count() - 1))
func _on_controller_input_wheel_move_caret_left() -> void:
match edit_mode:
EditMode.LINE_EDIT: line_edit.caret_column = line_edit.caret_column - 1
EditMode.TEXT_EDIT: text_edit.set_caret_column(text_edit.get_caret_column() - 1)
func _on_controller_input_wheel_move_caret_right() -> void:
match edit_mode:
EditMode.LINE_EDIT: line_edit.caret_column = line_edit.caret_column + 1
EditMode.TEXT_EDIT: text_edit.set_caret_column(text_edit.get_caret_column() + 1)
func __configure_inputs() -> void:
__stored_ui_actions[&"ui_up"] = InputMap.action_get_events(&"ui_up")
InputMap.action_erase_events(&"ui_up")
__stored_ui_actions[&"ui_down"] = InputMap.action_get_events(&"ui_down")
InputMap.action_erase_events(&"ui_down")
__stored_ui_actions[&"ui_left"] = InputMap.action_get_events(&"ui_left")
InputMap.action_erase_events(&"ui_left")
__stored_ui_actions[&"ui_right"] = InputMap.action_get_events(&"ui_right")
InputMap.action_erase_events(&"ui_right")
InputMap.add_action(&"ui_exit_text_editor")
InputMap.action_add_event(&"ui_exit_text_editor", joypad_exit)
func __deconfigure_inputs() -> void:
InputMap.action_erase_event(&"ui_exit_text_editor", joypad_exit)
InputMap.erase_action(&"ui_exit_text_editor")
for event:InputEvent in __stored_ui_actions[&"ui_right"]:
InputMap.action_add_event(&"ui_right", event)
for event:InputEvent in __stored_ui_actions[&"ui_left"]:
InputMap.action_add_event(&"ui_left", event)
for event:InputEvent in __stored_ui_actions[&"ui_down"]:
InputMap.action_add_event(&"ui_down", event)
for event:InputEvent in __stored_ui_actions[&"ui_up"]:
InputMap.action_add_event(&"ui_up", event)
func __set_mode(new_mode:int) -> void:
edit_mode = new_mode
match edit_mode:
EditMode.LINE_EDIT:
if line_edit: line_edit.visible = true
if text_edit: text_edit.visible = false
EditMode.TEXT_EDIT:
if line_edit: line_edit.visible = false
if text_edit: text_edit.visible = true
func __set_text(t:String) -> void:
match edit_mode:
EditMode.LINE_EDIT:
line_edit.text = t
line_edit.caret_column = t.length()
EditMode.TEXT_EDIT:
text_edit.text = t
text_edit.set_caret_line(text_edit.get_line_count()-1)
text_edit.set_caret_column(text_edit.get_line(text_edit.get_line_count()-1).length())
func __get_text() -> String:
match edit_mode:
EditMode.LINE_EDIT: return line_edit.text
EditMode.TEXT_EDIT: return text_edit.text
return text

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,6 @@
class_name ControllerInputWheelData
extends Resource
## Each element in this array should be an array of characters to place in the
## character select wheel. Starts at the North position and works clockwise.
@export var characters : Array[PackedStringArray] = []

View File

@ -0,0 +1,5 @@
class_name ControllerInputWheelDataPack
extends Resource
@export var lowercase : ControllerInputWheelData
@export var uppercase : ControllerInputWheelData

BIN
UI/OpenSans-Bold.ttf Normal file

Binary file not shown.

View File

@ -0,0 +1,33 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://cv7v7vevkpyom"
path="res://.godot/imported/OpenSans-Bold.ttf-a68d4d185430d0af4d5b991faccda030.fontdata"
[deps]
source_file="res://addons/Bugbot/UI/OpenSans-Bold.ttf"
dest_files=["res://.godot/imported/OpenSans-Bold.ttf-a68d4d185430d0af4d5b991faccda030.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=true
multichannel_signed_distance_field=true
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=false
force_autohinter=false
hinting=1
subpixel_positioning=1
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}

BIN
UI/OpenSans-ExtraBold.ttf Normal file

Binary file not shown.

View File

@ -0,0 +1,33 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://yuiijm2kdpi5"
path="res://.godot/imported/OpenSans-ExtraBold.ttf-e66c4766fe9bac5ce673f04c4e04f638.fontdata"
[deps]
source_file="res://addons/Bugbot/UI/OpenSans-ExtraBold.ttf"
dest_files=["res://.godot/imported/OpenSans-ExtraBold.ttf-e66c4766fe9bac5ce673f04c4e04f638.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=true
multichannel_signed_distance_field=true
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=false
force_autohinter=false
hinting=1
subpixel_positioning=1
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}

View File

@ -1,9 +1,6 @@
class_name BugReportForm class_name BugReportForm
extends ColorRect extends ColorRect
signal submitted(map_name:String, bug_location:Vector3, bug_rotation:Vector3)
signal cancelled
@onready var __product_name : Label = $VBoxContainer/Form/VBoxContainerLeft/GridContainer/ProductName as Label @onready var __product_name : Label = $VBoxContainer/Form/VBoxContainerLeft/GridContainer/ProductName as Label
@onready var __version_label : Label = $VBoxContainer/Form/VBoxContainerLeft/GridContainer/VersionLabel as Label @onready var __version_label : Label = $VBoxContainer/Form/VBoxContainerLeft/GridContainer/VersionLabel as Label
@onready var __version_button : MenuButton = $VBoxContainer/Form/VBoxContainerLeft/GridContainer/VersionButton as MenuButton @onready var __version_button : MenuButton = $VBoxContainer/Form/VBoxContainerLeft/GridContainer/VersionButton as MenuButton
@ -23,6 +20,9 @@ signal cancelled
@onready var __submit_button : Button = $VBoxContainer/Form/VBoxContainerRight/SubmitButton as Button @onready var __submit_button : Button = $VBoxContainer/Form/VBoxContainerRight/SubmitButton as Button
signal submitted(map_name:String, bug_location:Vector3, bug_rotation:Vector3)
signal cancelled
var map_name : String var map_name : String
var bug_location : Vector3 var bug_location : Vector3
var bug_rotation : Vector3 var bug_rotation : Vector3
@ -31,6 +31,9 @@ var __label_groups : Array
var __stored_mouse_mode : int var __stored_mouse_mode : int
var __server_api : BugbotServerAPI var __server_api : BugbotServerAPI
var __text_input_dialogue_preload : PackedScene = preload("res://addons/Bugbot/UI/ControllerInput/controller_input_wheel_screen.tscn")
var __text_input_dialogue : ControllerInputWheelTextEdit
const __DEFAULT_PRODUCT_NAME : StringName = &"NameOfProductHere" const __DEFAULT_PRODUCT_NAME : StringName = &"NameOfProductHere"
const __BUTTON_DISABLED_MESSAGE : StringName = &"Not available" const __BUTTON_DISABLED_MESSAGE : StringName = &"Not available"
const __ERROR_TEXT_COLOUR : Color = Color(0.75, 0.0, 0.0) const __ERROR_TEXT_COLOUR : Color = Color(0.75, 0.0, 0.0)
@ -65,6 +68,7 @@ func fill_tags(tag_list:Array) -> void:
elif __os_button.visible: __os_button.grab_focus() elif __os_button.visible: __os_button.grab_focus()
elif __component_button.visible: __component_button.grab_focus() elif __component_button.visible: __component_button.grab_focus()
elif __severity_button.visible: __severity_button.grab_focus() elif __severity_button.visible: __severity_button.grab_focus()
else: __submit_button.grab_focus()
func __fill_item_list(menu_button:MenuButton, menu_label:Label, label_group:int) -> void: func __fill_item_list(menu_button:MenuButton, menu_label:Label, label_group:int) -> void:
var menu_options : Array = __label_groups[label_group] var menu_options : Array = __label_groups[label_group]
@ -80,6 +84,28 @@ func __fill_item_list(menu_button:MenuButton, menu_label:Label, label_group:int)
menu.id_pressed.connect(func(id:int): menu_button.text = menu_options[id]["name"]) menu.id_pressed.connect(func(id:int): menu_button.text = menu_options[id]["name"])
func _on_summary_text_gui_input(event:InputEvent) -> void:
if event.is_action_pressed(&"ui_accept") and event is InputEventJoypadButton:
__text_input_dialogue = __text_input_dialogue_preload.instantiate()
add_child(__text_input_dialogue)
__text_input_dialogue.edit_mode = ControllerInputWheelTextEdit.EditMode.LINE_EDIT
__text_input_dialogue.tree_exiting.connect(__retrieve_summary_text)
__text_input_dialogue.text = __summary_text.text
func __retrieve_summary_text():
__summary_text.text = __text_input_dialogue.text
__summary_text.grab_focus()
func _on_description_text_gui_input(event:InputEvent) -> void:
if event.is_action_pressed(&"ui_accept") and event is InputEventJoypadButton:
__text_input_dialogue = __text_input_dialogue_preload.instantiate()
add_child(__text_input_dialogue)
__text_input_dialogue.edit_mode = ControllerInputWheelTextEdit.EditMode.TEXT_EDIT
__text_input_dialogue.tree_exiting.connect(__retrieve_description_text)
__text_input_dialogue.text = __description_text.text
func __retrieve_description_text():
__description_text.text = __text_input_dialogue.text
__description_text.grab_focus()
func _on_submit_button_pressed() -> void: func _on_submit_button_pressed() -> void:
__submit_button.disabled = true __submit_button.disabled = true
@ -152,7 +178,6 @@ func __get_label_ids_for_submission_data(tag:Array, label_group_id:int, label:La
label.remove_theme_color_override("font_color") label.remove_theme_color_override("font_color")
button.remove_theme_color_override("font_color") button.remove_theme_color_override("font_color")
return true return true
func __submission_response(bug:BugbotBugData) -> void: func __submission_response(bug:BugbotBugData) -> void:
submitted.emit(bug) submitted.emit(bug)
queue_free() queue_free()

View File

@ -165,4 +165,6 @@ layout_mode = 2
text = "Submit" text = "Submit"
[connection signal="pressed" from="VBoxContainer/Form/VBoxContainerLeft/CancelButton" to="." method="_on_cancel_button_pressed"] [connection signal="pressed" from="VBoxContainer/Form/VBoxContainerLeft/CancelButton" to="." method="_on_cancel_button_pressed"]
[connection signal="gui_input" from="VBoxContainer/Form/VBoxContainerRight/GridContainer/SummaryText" to="." method="_on_summary_text_gui_input"]
[connection signal="gui_input" from="VBoxContainer/Form/VBoxContainerRight/GridContainer/DescriptionText" to="." method="_on_description_text_gui_input"]
[connection signal="pressed" from="VBoxContainer/Form/VBoxContainerRight/SubmitButton" to="." method="_on_submit_button_pressed"] [connection signal="pressed" from="VBoxContainer/Form/VBoxContainerRight/SubmitButton" to="." method="_on_submit_button_pressed"]