diff --git a/UI/ControllerInput/WheelData/qwerty_layout.tres b/UI/ControllerInput/WheelData/qwerty_layout.tres new file mode 100644 index 0000000..44bfece --- /dev/null +++ b/UI/ControllerInput/WheelData/qwerty_layout.tres @@ -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") diff --git a/UI/ControllerInput/WheelData/qwerty_lowercase_alphanumeric.tres b/UI/ControllerInput/WheelData/qwerty_lowercase_alphanumeric.tres new file mode 100644 index 0000000..3c9e437 --- /dev/null +++ b/UI/ControllerInput/WheelData/qwerty_lowercase_alphanumeric.tres @@ -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")]) diff --git a/UI/ControllerInput/WheelData/qwerty_uppercase_alphanumeric.tres b/UI/ControllerInput/WheelData/qwerty_uppercase_alphanumeric.tres new file mode 100644 index 0000000..363e588 --- /dev/null +++ b/UI/ControllerInput/WheelData/qwerty_uppercase_alphanumeric.tres @@ -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", "!", "@")]) diff --git a/UI/ControllerInput/circle_backing.gdshader b/UI/ControllerInput/circle_backing.gdshader new file mode 100644 index 0000000..76372a1 --- /dev/null +++ b/UI/ControllerInput/circle_backing.gdshader @@ -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); +} diff --git a/UI/ControllerInput/circle_backing.material b/UI/ControllerInput/circle_backing.material new file mode 100644 index 0000000..ff59ff1 Binary files /dev/null and b/UI/ControllerInput/circle_backing.material differ diff --git a/UI/ControllerInput/controller_input_action.gd b/UI/ControllerInput/controller_input_action.gd new file mode 100644 index 0000000..d680f5e --- /dev/null +++ b/UI/ControllerInput/controller_input_action.gd @@ -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 diff --git a/UI/ControllerInput/controller_input_select_wheel.gd b/UI/ControllerInput/controller_input_select_wheel.gd new file mode 100644 index 0000000..9e8fbf6 --- /dev/null +++ b/UI/ControllerInput/controller_input_select_wheel.gd @@ -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) diff --git a/UI/ControllerInput/controller_input_select_wheel.tscn b/UI/ControllerInput/controller_input_select_wheel.tscn new file mode 100644 index 0000000..ccaadc9 --- /dev/null +++ b/UI/ControllerInput/controller_input_select_wheel.tscn @@ -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 diff --git a/UI/ControllerInput/controller_input_symbol_wheel.gd b/UI/ControllerInput/controller_input_symbol_wheel.gd new file mode 100644 index 0000000..4848a9f --- /dev/null +++ b/UI/ControllerInput/controller_input_symbol_wheel.gd @@ -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 diff --git a/UI/ControllerInput/controller_input_symbol_wheel.tscn b/UI/ControllerInput/controller_input_symbol_wheel.tscn new file mode 100644 index 0000000..40302fb --- /dev/null +++ b/UI/ControllerInput/controller_input_symbol_wheel.tscn @@ -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) diff --git a/UI/ControllerInput/controller_input_wheel_screen.tscn b/UI/ControllerInput/controller_input_wheel_screen.tscn new file mode 100644 index 0000000..9c9e48c --- /dev/null +++ b/UI/ControllerInput/controller_input_wheel_screen.tscn @@ -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"] diff --git a/UI/ControllerInput/controller_input_wheel_text_edit.gd b/UI/ControllerInput/controller_input_wheel_text_edit.gd new file mode 100644 index 0000000..7b61410 --- /dev/null +++ b/UI/ControllerInput/controller_input_wheel_text_edit.gd @@ -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 diff --git a/UI/ControllerInput/select_wheel_action.res b/UI/ControllerInput/select_wheel_action.res new file mode 100644 index 0000000..6c57191 Binary files /dev/null and b/UI/ControllerInput/select_wheel_action.res differ diff --git a/UI/ControllerInput/select_wheel_theme.theme b/UI/ControllerInput/select_wheel_theme.theme new file mode 100644 index 0000000..5929460 Binary files /dev/null and b/UI/ControllerInput/select_wheel_theme.theme differ diff --git a/UI/ControllerInput/wheel_data.gd b/UI/ControllerInput/wheel_data.gd new file mode 100644 index 0000000..3938247 --- /dev/null +++ b/UI/ControllerInput/wheel_data.gd @@ -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] = [] diff --git a/UI/ControllerInput/wheel_data_pack.gd b/UI/ControllerInput/wheel_data_pack.gd new file mode 100644 index 0000000..ef08b82 --- /dev/null +++ b/UI/ControllerInput/wheel_data_pack.gd @@ -0,0 +1,5 @@ +class_name ControllerInputWheelDataPack +extends Resource + +@export var lowercase : ControllerInputWheelData +@export var uppercase : ControllerInputWheelData diff --git a/UI/OpenSans-Bold.ttf b/UI/OpenSans-Bold.ttf new file mode 100644 index 0000000..b2cdd32 Binary files /dev/null and b/UI/OpenSans-Bold.ttf differ diff --git a/UI/OpenSans-Bold.ttf.import b/UI/OpenSans-Bold.ttf.import new file mode 100644 index 0000000..de3dddb --- /dev/null +++ b/UI/OpenSans-Bold.ttf.import @@ -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={} diff --git a/UI/OpenSans-ExtraBold.ttf b/UI/OpenSans-ExtraBold.ttf new file mode 100644 index 0000000..4eb3393 Binary files /dev/null and b/UI/OpenSans-ExtraBold.ttf differ diff --git a/UI/OpenSans-ExtraBold.ttf.import b/UI/OpenSans-ExtraBold.ttf.import new file mode 100644 index 0000000..c704953 --- /dev/null +++ b/UI/OpenSans-ExtraBold.ttf.import @@ -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={} diff --git a/UI/bug_report_form.gd b/UI/bug_report_form.gd index 2966b85..60550ad 100644 --- a/UI/bug_report_form.gd +++ b/UI/bug_report_form.gd @@ -1,9 +1,6 @@ class_name BugReportForm 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 __version_label : Label = $VBoxContainer/Form/VBoxContainerLeft/GridContainer/VersionLabel as Label @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 +signal submitted(map_name:String, bug_location:Vector3, bug_rotation:Vector3) +signal cancelled + var map_name : String var bug_location : Vector3 var bug_rotation : Vector3 @@ -31,6 +31,9 @@ var __label_groups : Array var __stored_mouse_mode : int 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 __BUTTON_DISABLED_MESSAGE : StringName = &"Not available" 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 __component_button.visible: __component_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: 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"]) +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: __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") button.remove_theme_color_override("font_color") return true - func __submission_response(bug:BugbotBugData) -> void: submitted.emit(bug) queue_free() diff --git a/UI/bug_report_form.tscn b/UI/bug_report_form.tscn index d0c712c..280c574 100644 --- a/UI/bug_report_form.tscn +++ b/UI/bug_report_form.tscn @@ -165,4 +165,6 @@ layout_mode = 2 text = "Submit" [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"]