From ded09a8fa8bf7eb79ad595e883596dd28ce8c7d9 Mon Sep 17 00:00:00 2001 From: Jamie Greunbaum Date: Sun, 26 May 2024 02:32:55 -0400 Subject: [PATCH] Bugs are now filed with their position information, and loaded into Godot with their proper positions intact. --- Scenes/bugbot_player.gd | 34 ++++++++++++++++--- Scripts/BugDataStructs/bug_data.gd | 3 +- Scripts/server_api.gd | 17 +++++----- Scripts/server_gitea_api.gd | 53 +++++++++++++++++++---------- UI/bug_report_form.gd | 15 ++++++--- bugbot.gd | 54 ++++++++++++------------------ 6 files changed, 109 insertions(+), 67 deletions(-) diff --git a/Scenes/bugbot_player.gd b/Scenes/bugbot_player.gd index 16917ee..039c498 100644 --- a/Scenes/bugbot_player.gd +++ b/Scenes/bugbot_player.gd @@ -68,6 +68,7 @@ extends CharacterBody3D #region Private Properties var __bugbot_server : BugbotServerAPI +var __bug_report_form : BugReportForm var __movement_speed : float = 5.0 @@ -239,6 +240,27 @@ func _physics_process(_delta:float) -> void: static func instantiate(tree:SceneTree) -> void: tree.root.add_child(load("res://addons/Bugbot/Scenes/bugbot_player.tscn").instantiate() as CharacterBody3D) +static func load_bug_markers(marker_root:Node3D, bug_list:Array): + var bug_marker_preload : PackedScene = preload("res://addons/Bugbot/Scenes/bug_marker.tscn") + for bugbot_data:Resource in bug_list: + if bugbot_data is BugbotBugData: + var bug_status : BugMarker.BugStatus = BugMarker.BugStatus.NEUTRAL + var bug_data : BugbotBugData = bugbot_data as BugbotBugData + + if bug_data.resolution == BugbotServerGiteaAPI.RESOLVED_TAG: + bug_status = BugMarker.BugStatus.RESOLVED + elif bug_data.resolution == BugbotServerGiteaAPI.IN_PROGRESS_TAG: + bug_status = BugMarker.BugStatus.IN_PROGRESS + elif bug_data.resolution == BugbotServerGiteaAPI.UNRESOLVED_TAG: + bug_status = BugMarker.BugStatus.UNRESOLVED + + var bug_marker : BugMarker = bug_marker_preload.instantiate() as BugMarker + marker_root.add_child(bug_marker) + bug_marker.marker_status = bug_status + bug_marker.bug_data = bugbot_data + bug_marker.global_position = bugbot_data.marker_position + bug_marker.set_rotation_to_normal(bugbot_data.marker_normal) + func __calculate_movement_speed() -> void: if Input.is_action_pressed(&"bugbot_movement_speed_down") or Input.is_action_just_pressed(&"bugbot_movement_speed_down"): @@ -317,11 +339,15 @@ func __pop_up_marker_info(_position:Vector3, _normal:Vector3): func __bug_report_form_data_prepared(tag_lists:Array): - var bug_report_form : Control = preload("res://addons/Bugbot/UI/bug_report_form.tscn").instantiate() - add_child(bug_report_form) - bug_report_form.fill_tags(tag_lists) - bug_report_form.closed.connect(__form_closed) + __bug_report_form = preload("res://addons/Bugbot/UI/bug_report_form.tscn").instantiate() + add_child(__bug_report_form) + __bug_report_form.map_name = get_tree().current_scene.scene_file_path + __bug_report_form.bug_location = __raycast_collision["position"] + __bug_report_form.bug_rotation = __raycast_collision["normal"] + __bug_report_form.fill_tags(tag_lists) + __bug_report_form.closed.connect(__form_closed) func __form_closed(): + __bug_report_form.queue_free() process_mode = Node.PROCESS_MODE_ALWAYS diff --git a/Scripts/BugDataStructs/bug_data.gd b/Scripts/BugDataStructs/bug_data.gd index 0d02432..7241a10 100644 --- a/Scripts/BugDataStructs/bug_data.gd +++ b/Scripts/BugDataStructs/bug_data.gd @@ -6,7 +6,8 @@ var title : String var body : String var component : StringName var map_name : StringName -var marker_location : StringName +var marker_position : Vector3 +var marker_normal : Vector3 var platform : StringName var operating_system : StringName var is_open : bool diff --git a/Scripts/server_api.gd b/Scripts/server_api.gd index a0140a4..02338aa 100644 --- a/Scripts/server_api.gd +++ b/Scripts/server_api.gd @@ -11,7 +11,7 @@ func _init(): __bugbot_server_thread = Thread.new() -func _return_list_of_bugs(callback:Callable) -> int: +func _return_list_of_bugs(map_name:String, callback:Callable) -> int: print("Insert list of ", _current_server_api(), " bugs here.") return BugbotServerError.OK @@ -19,7 +19,7 @@ func _prepare_form(callback:Callable) -> int: print("Prepare ", _current_server_api(), " form here.") return BugbotServerError.OK -func _send_form_data(data:Dictionary, callback:Callable) -> int: +func _send_form_data(data:Dictionary, map_name:String, bug_position:Vector3, bug_normal:Vector3, callback:Callable) -> int: print("Send ", _current_server_api(), " form data here.") return BugbotServerError.OK @@ -31,11 +31,6 @@ static func _create_new_server_api() -> BugbotServerAPI: BugReportPlatform.JIRA: return BugbotServerAPI.new() return BugbotServerAPI.new() -static func _hide_markers(marker_root:Node): - var markers : Array = marker_root.get_children() - for marker:Node3D in markers: - marker.queue_free() - func __connect_to_server(http_client:HTTPClient, default_server:String) -> int: var full_server : String = ProjectSettings.get_setting("bugbot/reporting/gitea/server", default_server) @@ -84,5 +79,11 @@ func __create_header_data(content_length:int = -1) -> Array: return [] -func __return_list_of_bugs_thread(callback:Callable) -> void: +func __return_list_of_bugs_thread(map_name:String, callback:Callable) -> void: + pass + +func __prepare_form_thread(callback:Callable) -> void: + pass + +func __send_form_data_thread(data:Dictionary, map_name:String, bug_position:Vector3, bug_normal:Vector3, callback:Callable) -> void: pass diff --git a/Scripts/server_gitea_api.gd b/Scripts/server_gitea_api.gd index f0e8fe9..32c3b5d 100644 --- a/Scripts/server_gitea_api.gd +++ b/Scripts/server_gitea_api.gd @@ -21,17 +21,17 @@ const RESOLVED_TAG : StringName = &"Status/Resolved" #endregion -func _return_list_of_bugs(callback:Callable) -> int: - return __start_thread_with_callback(__return_list_of_bugs_thread.bind(callback)) +func _return_list_of_bugs(map_name:String, callback:Callable) -> int: + return __start_thread_with_callback(__return_list_of_bugs_thread.bind(map_name, callback)) func _prepare_form(callback:Callable) -> int: return __start_thread_with_callback(__prepare_form_thread.bind(callback)) -func _send_form_data(data:Dictionary, callback:Callable) -> int: - return __start_thread_with_callback(__send_form_data_thread.bind(data, callback)) +func _send_form_data(data:Dictionary, map_name:String, bug_position:Vector3, bug_normal:Vector3, callback:Callable) -> int: + return __start_thread_with_callback(__send_form_data_thread.bind(data, map_name, bug_position, bug_normal, callback)) -func __return_list_of_bugs_thread(callback:Callable) -> void: +func __return_list_of_bugs_thread(map_name:String, callback:Callable) -> void: var http_client : HTTPClient = HTTPClient.new() if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED: printerr("Could not connect to server.") @@ -61,8 +61,23 @@ func __return_list_of_bugs_thread(callback:Callable) -> void: var show_unresolved : bool = ProjectSettings.get_setting("bugbot/markers/unresolved/show_unresolved_bugs") for bug_in:Dictionary in response_data: + var bugbot_marker_string : String = bug_in["body"].split("\n")[-1] + if not bugbot_marker_string.begins_with("{") and not bugbot_marker_string.ends_with("}"): + continue + var bug : BugbotBugData = BugbotBugData.new() + # Check if the map name is valid for the scene we're in. + var bugbot_marker_data : Dictionary = JSON.parse_string(bugbot_marker_string) + bug.map_name = bugbot_marker_data["map_name"] + if bug.map_name != map_name: + continue + + var marker_location : Array = bugbot_marker_data["bug_location"] + var marker_normal : Array = bugbot_marker_data["bug_normal"] + bug.marker_position = Vector3(marker_location[0], marker_location[1], marker_location[2]) + bug.marker_normal = Vector3(marker_normal[0], marker_normal[1], marker_normal[2]) + var bug_labels : Array = [] var resolved_tag_found : bool = false var in_progress_tag_found : bool = false @@ -93,7 +108,8 @@ func __return_list_of_bugs_thread(callback:Callable) -> void: elif unresolved_tag_found or unresolved_labels.is_empty(): bug.resolution = UNRESOLVED_TAG show_marker = show_unresolved - if not show_marker: continue + if not show_marker: + continue bug.id = bug_in["id"] bug.title = bug_in["title"] @@ -104,8 +120,6 @@ func __return_list_of_bugs_thread(callback:Callable) -> void: bug.severity = "Severity will go here." bug.status = bug_in["state"] bug.duplicate_of = -1 - bug.map_name = "Map name will go here." - bug.marker_location = "Marker location will go here." bug_array.append(bug) @@ -169,12 +183,13 @@ func __prepare_form_thread(callback:Callable) -> void: callback.call_deferred(tag_lists) __bugbot_server_thread.call_deferred("wait_to_finish") -func __send_form_data_thread(data:Dictionary, callback:Callable) -> void: +func __send_form_data_thread(data:Dictionary, map_name:String, bug_position:Vector3, bug_normal:Vector3, callback:Callable) -> void: var http_client : HTTPClient = HTTPClient.new() if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED: printerr("Could not connect to server.") return + # Get a list of available labels to apply to the issue var api_url : String = __build_url_string("labels") var header_data : Array = __create_header_data() var error : int = http_client.request(HTTPClient.METHOD_GET, api_url, header_data) @@ -182,12 +197,11 @@ func __send_form_data_thread(data:Dictionary, callback:Callable) -> void: while http_client.get_status() == HTTPClient.STATUS_REQUESTING: http_client.poll() assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED) - var response_string : String = __get_http_client_chunk_response(http_client) - - var response_data := JSON.parse_string(response_string) + var response_data : Variant = JSON.parse_string(__get_http_client_chunk_response(http_client)) if __validate_server_response(response_data) != Error.OK: return + # Collect the label IDs for each label we want to apply to this issue var labels : Array var bug_label : String = ProjectSettings.get_setting("bugbot/reporting/gitea/bug_label", DEFAULT_BUG_LABEL) var status_label : String = ProjectSettings.get_setting("bugbot/reporting/gitea/default_status_label", DEFAULT_STATUS_LABEL) @@ -196,6 +210,9 @@ func __send_form_data_thread(data:Dictionary, callback:Callable) -> void: labels.append(label_in["id"]) (data["labels"] as Array).append_array(labels) + data["body"] += "\n\n" + """{ "map_name": "%s", "bug_position": [%.4f, %.4f, %.4f], "bug_normal": [%.4f, %.4f, %.4f] }""" % [map_name, bug_position.x, bug_position.y, bug_position.z, bug_normal.x, bug_normal.y, bug_normal.z] + + # Post issue to Gitea api_url = __build_url_string("issues") var post_data_string : String = JSON.stringify(data) header_data = __create_header_data(post_data_string.length()) @@ -204,9 +221,11 @@ func __send_form_data_thread(data:Dictionary, callback:Callable) -> void: while http_client.get_status() == HTTPClient.STATUS_REQUESTING: http_client.poll() assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED) - response_string = __get_http_client_chunk_response(http_client) + var post_response_data : Variant = JSON.parse_string(__get_http_client_chunk_response(http_client)) + if __validate_server_response(post_response_data) != Error.OK: + return - callback.call_deferred(JSON.parse_string(response_string)) + callback.call_deferred(post_response_data) __bugbot_server_thread.call_deferred("wait_to_finish") @@ -234,9 +253,9 @@ func __create_header_data(content_length:int = -1) -> Array: return header func __validate_server_response(_response:Variant) -> int: - # If the response is a dictionary and not an array, make the assumption - # that this is because the response was an error code. - if _response is Dictionary: + # If the response has a message field, make the assumption that this is + # because the response was an error code. + if _response.has("message"): var error_data : BugbotErrorData = BugbotErrorData.new() error_data.code = 1 error_data.message = _response["message"] diff --git a/UI/bug_report_form.gd b/UI/bug_report_form.gd index 6879b52..e04dba3 100644 --- a/UI/bug_report_form.gd +++ b/UI/bug_report_form.gd @@ -12,6 +12,12 @@ signal closed @onready var __summary_text : LineEdit = $Form/VBoxContainerRight/GridContainer/SummaryText @onready var __description_text : TextEdit = $Form/VBoxContainerRight/GridContainer/DescriptionText +@onready var __submit_button : Button = $Form/VBoxContainerRight/SubmitButton + +var map_name : String +var bug_location : Vector3 +var bug_rotation : Vector3 + var __label_groups : Array var __stored_mouse_mode : int var __server_api : BugbotServerAPI @@ -52,6 +58,8 @@ func __fill_item_list(menu_button:MenuButton, label_group:int): func _on_submit_button_pressed() -> void: + __submit_button.disabled = true + var error_detected : bool = false var summary_text : String = __summary_text.text @@ -83,10 +91,7 @@ func _on_submit_button_pressed() -> void: "labels": labels_to_be_added, } - __server_api._send_form_data(bug_report_form_data, __form_data_response) - -func __form_data_response(response:Variant): - print(response) + __server_api._send_form_data(bug_report_form_data, map_name, bug_location, bug_rotation, __submission_response) func __get_label_ids_for_submission_data(label_array:Array, label_group_id:int): for label in __label_groups[label_group_id]: @@ -94,7 +99,7 @@ func __get_label_ids_for_submission_data(label_array:Array, label_group_id:int): label_array.append(label["id"]) break -func __submission_response(response:Array): +func __submission_response(response:Variant): print(response) queue_free() closed.emit() diff --git a/bugbot.gd b/bugbot.gd index 74647d5..659740b 100644 --- a/bugbot.gd +++ b/bugbot.gd @@ -11,6 +11,8 @@ var __bugbot_marker_containers : Dictionary var __editor_server_api : BugbotServerAPI func _enter_tree() -> void: + scene_changed.connect(func(scene:Node):print("Scene has changed from " + scene.scene_file_path + " to ", EditorInterface.get_edited_scene_root().scene_file_path)) + __initialise_project_settings() __bugbot_menu_button = preload("res://addons/Bugbot/bugbot_menu_button.tscn").instantiate() as BugbotMenuButton @@ -22,7 +24,6 @@ func _enter_tree() -> void: bugbot_menu.add_item("Hide Bug Markers", BugbotMenuItems.HIDE_BUG_MARKERS) bugbot_menu.id_pressed.connect(__on_bugbot_menu_item_pressed) - func _exit_tree() -> void: remove_control_from_container(CustomControlContainer.CONTAINER_SPATIAL_EDITOR_MENU, __bugbot_menu_button) __bugbot_menu_button.queue_free() @@ -30,7 +31,7 @@ func _exit_tree() -> void: # This is where we should remove any visible bug markers -func __initialise_project_settings(): +func __initialise_project_settings() -> void: #region Placement __add_project_setting("bugbot/bug_placement/precise_placement_distance", TYPE_FLOAT, 15.0, PROPERTY_HINT_RANGE, "0.0,100.0,0.1,or_greater") __add_project_setting("bugbot/bug_placement/arbitrary_placement_distance", TYPE_FLOAT, 2.5, PROPERTY_HINT_RANGE, "0.0,100.0,0.1,or_greater") @@ -99,40 +100,29 @@ func __initialise_project_settings(): func __on_bugbot_menu_item_pressed(id:int): match id: BugbotMenuItems.SHOW_BUG_MARKERS: - var scene_root : Node = EditorInterface.get_edited_scene_root() - var scene : String = scene_root.scene_file_path - if not __bugbot_marker_containers.has(scene): - var marker_container : Node3D = Node3D.new() - marker_container.name = "BugMarkerContainer" - __bugbot_marker_containers[scene] = marker_container - scene_root.add_child(marker_container) - __editor_server_api = BugbotServerAPI._create_new_server_api() - __editor_server_api._return_list_of_bugs(__show_bug_markers_response) + __show_editor_bug_markers() BugbotMenuItems.HIDE_BUG_MARKERS: - var scene_root : Node = EditorInterface.get_edited_scene_root() - var scene_path : String = scene_root.scene_file_path - if __bugbot_marker_containers.has(scene_path): - var marker_container : Node3D = __bugbot_marker_containers[scene_path] - BugbotServerAPI._hide_markers(marker_container) + var scene : String = EditorInterface.get_edited_scene_root().scene_file_path + if __bugbot_marker_containers.has(scene) and __bugbot_marker_containers[scene]: + __bugbot_marker_containers[scene].queue_free() + __bugbot_marker_containers.erase(scene) + +func __show_editor_bug_markers(): + var scene_root : Node = EditorInterface.get_edited_scene_root() + var scene : String = scene_root.scene_file_path + var tree_root : Node = scene_root.get_tree().get_root() + if __bugbot_marker_containers.has(scene) and __bugbot_marker_containers[scene]: + __bugbot_marker_containers[scene].queue_free() + var marker_container : Node3D = Node3D.new() + marker_container.name = "BugMarkerContainer" + __bugbot_marker_containers[scene] = marker_container + tree_root.add_child(marker_container) + __editor_server_api = BugbotServerAPI._create_new_server_api() + __editor_server_api._return_list_of_bugs(scene, __show_bug_markers_response) func __show_bug_markers_response(bug_list:Array) -> void: var scene_root : Node = EditorInterface.get_edited_scene_root() var marker_container : Node3D = __bugbot_marker_containers[scene_root.scene_file_path] - for bugbot_data:Resource in bug_list: - if bugbot_data is BugbotBugData: - var bug_status : BugMarker.BugStatus = BugMarker.BugStatus.NEUTRAL - var bug_data : BugbotBugData = bugbot_data as BugbotBugData - - if bug_data.resolution == BugbotServerGiteaAPI.RESOLVED_TAG: - bug_status = BugMarker.BugStatus.RESOLVED - elif bug_data.resolution == BugbotServerGiteaAPI.IN_PROGRESS_TAG: - bug_status = BugMarker.BugStatus.IN_PROGRESS - elif bug_data.resolution == BugbotServerGiteaAPI.UNRESOLVED_TAG: - bug_status = BugMarker.BugStatus.UNRESOLVED - - var bug_marker : BugMarker = load("res://addons/Bugbot/Scenes/bug_marker.tscn").instantiate() - marker_container.add_child(bug_marker) - bug_marker.marker_status = bug_status - bug_marker.bug_data = bugbot_data + Bugbot.load_bug_markers(marker_container, bug_list) func __add_project_setting(_setting:String, _type:int, _default_value:Variant, _hint:int = PropertyHint.PROPERTY_HINT_NONE, _hint_string:String = ""):