Bugs are now filed with their position information, and loaded into Godot with their proper positions intact.

This commit is contained in:
Jamie Greunbaum 2024-05-26 02:32:55 -04:00
parent 5b4dc53a62
commit ded09a8fa8
6 changed files with 109 additions and 67 deletions

View File

@ -68,6 +68,7 @@ extends CharacterBody3D
#region Private Properties #region Private Properties
var __bugbot_server : BugbotServerAPI var __bugbot_server : BugbotServerAPI
var __bug_report_form : BugReportForm
var __movement_speed : float = 5.0 var __movement_speed : float = 5.0
@ -239,6 +240,27 @@ func _physics_process(_delta:float) -> void:
static func instantiate(tree:SceneTree) -> void: static func instantiate(tree:SceneTree) -> void:
tree.root.add_child(load("res://addons/Bugbot/Scenes/bugbot_player.tscn").instantiate() as CharacterBody3D) 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: func __calculate_movement_speed() -> void:
if Input.is_action_pressed(&"bugbot_movement_speed_down") or Input.is_action_just_pressed(&"bugbot_movement_speed_down"): 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): func __bug_report_form_data_prepared(tag_lists:Array):
var bug_report_form : Control = preload("res://addons/Bugbot/UI/bug_report_form.tscn").instantiate() __bug_report_form = preload("res://addons/Bugbot/UI/bug_report_form.tscn").instantiate()
add_child(bug_report_form) add_child(__bug_report_form)
bug_report_form.fill_tags(tag_lists) __bug_report_form.map_name = get_tree().current_scene.scene_file_path
bug_report_form.closed.connect(__form_closed) __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(): func __form_closed():
__bug_report_form.queue_free()
process_mode = Node.PROCESS_MODE_ALWAYS process_mode = Node.PROCESS_MODE_ALWAYS

View File

@ -6,7 +6,8 @@ var title : String
var body : String var body : String
var component : StringName var component : StringName
var map_name : StringName var map_name : StringName
var marker_location : StringName var marker_position : Vector3
var marker_normal : Vector3
var platform : StringName var platform : StringName
var operating_system : StringName var operating_system : StringName
var is_open : bool var is_open : bool

View File

@ -11,7 +11,7 @@ func _init():
__bugbot_server_thread = Thread.new() __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.") print("Insert list of ", _current_server_api(), " bugs here.")
return BugbotServerError.OK return BugbotServerError.OK
@ -19,7 +19,7 @@ func _prepare_form(callback:Callable) -> int:
print("Prepare ", _current_server_api(), " form here.") print("Prepare ", _current_server_api(), " form here.")
return BugbotServerError.OK 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.") print("Send ", _current_server_api(), " form data here.")
return BugbotServerError.OK return BugbotServerError.OK
@ -31,11 +31,6 @@ static func _create_new_server_api() -> BugbotServerAPI:
BugReportPlatform.JIRA: return BugbotServerAPI.new() BugReportPlatform.JIRA: return BugbotServerAPI.new()
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: func __connect_to_server(http_client:HTTPClient, default_server:String) -> int:
var full_server : String = ProjectSettings.get_setting("bugbot/reporting/gitea/server", default_server) 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 [] 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 pass

View File

@ -21,17 +21,17 @@ const RESOLVED_TAG : StringName = &"Status/Resolved"
#endregion #endregion
func _return_list_of_bugs(callback:Callable) -> int: func _return_list_of_bugs(map_name:String, callback:Callable) -> int:
return __start_thread_with_callback(__return_list_of_bugs_thread.bind(callback)) return __start_thread_with_callback(__return_list_of_bugs_thread.bind(map_name, callback))
func _prepare_form(callback:Callable) -> int: func _prepare_form(callback:Callable) -> int:
return __start_thread_with_callback(__prepare_form_thread.bind(callback)) return __start_thread_with_callback(__prepare_form_thread.bind(callback))
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:
return __start_thread_with_callback(__send_form_data_thread.bind(data, callback)) 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() var http_client : HTTPClient = HTTPClient.new()
if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED: if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED:
printerr("Could not connect to server.") 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") var show_unresolved : bool = ProjectSettings.get_setting("bugbot/markers/unresolved/show_unresolved_bugs")
for bug_in:Dictionary in response_data: 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() 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 bug_labels : Array = []
var resolved_tag_found : bool = false var resolved_tag_found : bool = false
var in_progress_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(): elif unresolved_tag_found or unresolved_labels.is_empty():
bug.resolution = UNRESOLVED_TAG bug.resolution = UNRESOLVED_TAG
show_marker = show_unresolved show_marker = show_unresolved
if not show_marker: continue if not show_marker:
continue
bug.id = bug_in["id"] bug.id = bug_in["id"]
bug.title = bug_in["title"] 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.severity = "Severity will go here."
bug.status = bug_in["state"] bug.status = bug_in["state"]
bug.duplicate_of = -1 bug.duplicate_of = -1
bug.map_name = "Map name will go here."
bug.marker_location = "Marker location will go here."
bug_array.append(bug) bug_array.append(bug)
@ -169,12 +183,13 @@ func __prepare_form_thread(callback:Callable) -> void:
callback.call_deferred(tag_lists) callback.call_deferred(tag_lists)
__bugbot_server_thread.call_deferred("wait_to_finish") __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() var http_client : HTTPClient = HTTPClient.new()
if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED: if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED:
printerr("Could not connect to server.") printerr("Could not connect to server.")
return return
# Get a list of available labels to apply to the issue
var api_url : String = __build_url_string("labels") var api_url : String = __build_url_string("labels")
var header_data : Array = __create_header_data() var header_data : Array = __create_header_data()
var error : int = http_client.request(HTTPClient.METHOD_GET, api_url, 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: while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
http_client.poll() http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED) 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 : Variant = JSON.parse_string(__get_http_client_chunk_response(http_client))
var response_data := JSON.parse_string(response_string)
if __validate_server_response(response_data) != Error.OK: if __validate_server_response(response_data) != Error.OK:
return return
# Collect the label IDs for each label we want to apply to this issue
var labels : Array var labels : Array
var bug_label : String = ProjectSettings.get_setting("bugbot/reporting/gitea/bug_label", DEFAULT_BUG_LABEL) 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) 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"]) labels.append(label_in["id"])
(data["labels"] as Array).append_array(labels) (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") api_url = __build_url_string("issues")
var post_data_string : String = JSON.stringify(data) var post_data_string : String = JSON.stringify(data)
header_data = __create_header_data(post_data_string.length()) 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: while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
http_client.poll() http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED) 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") __bugbot_server_thread.call_deferred("wait_to_finish")
@ -234,9 +253,9 @@ func __create_header_data(content_length:int = -1) -> Array:
return header return header
func __validate_server_response(_response:Variant) -> int: func __validate_server_response(_response:Variant) -> int:
# If the response is a dictionary and not an array, make the assumption # If the response has a message field, make the assumption that this is
# that this is because the response was an error code. # because the response was an error code.
if _response is Dictionary: if _response.has("message"):
var error_data : BugbotErrorData = BugbotErrorData.new() var error_data : BugbotErrorData = BugbotErrorData.new()
error_data.code = 1 error_data.code = 1
error_data.message = _response["message"] error_data.message = _response["message"]

View File

@ -12,6 +12,12 @@ signal closed
@onready var __summary_text : LineEdit = $Form/VBoxContainerRight/GridContainer/SummaryText @onready var __summary_text : LineEdit = $Form/VBoxContainerRight/GridContainer/SummaryText
@onready var __description_text : TextEdit = $Form/VBoxContainerRight/GridContainer/DescriptionText @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 __label_groups : Array
var __stored_mouse_mode : int var __stored_mouse_mode : int
var __server_api : BugbotServerAPI var __server_api : BugbotServerAPI
@ -52,6 +58,8 @@ func __fill_item_list(menu_button:MenuButton, label_group:int):
func _on_submit_button_pressed() -> void: func _on_submit_button_pressed() -> void:
__submit_button.disabled = true
var error_detected : bool = false var error_detected : bool = false
var summary_text : String = __summary_text.text var summary_text : String = __summary_text.text
@ -83,10 +91,7 @@ func _on_submit_button_pressed() -> void:
"labels": labels_to_be_added, "labels": labels_to_be_added,
} }
__server_api._send_form_data(bug_report_form_data, __form_data_response) __server_api._send_form_data(bug_report_form_data, map_name, bug_location, bug_rotation, __submission_response)
func __form_data_response(response:Variant):
print(response)
func __get_label_ids_for_submission_data(label_array:Array, label_group_id:int): func __get_label_ids_for_submission_data(label_array:Array, label_group_id:int):
for label in __label_groups[label_group_id]: 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"]) label_array.append(label["id"])
break break
func __submission_response(response:Array): func __submission_response(response:Variant):
print(response) print(response)
queue_free() queue_free()
closed.emit() closed.emit()

View File

@ -11,6 +11,8 @@ var __bugbot_marker_containers : Dictionary
var __editor_server_api : BugbotServerAPI var __editor_server_api : BugbotServerAPI
func _enter_tree() -> void: 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() __initialise_project_settings()
__bugbot_menu_button = preload("res://addons/Bugbot/bugbot_menu_button.tscn").instantiate() as BugbotMenuButton __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.add_item("Hide Bug Markers", BugbotMenuItems.HIDE_BUG_MARKERS)
bugbot_menu.id_pressed.connect(__on_bugbot_menu_item_pressed) bugbot_menu.id_pressed.connect(__on_bugbot_menu_item_pressed)
func _exit_tree() -> void: func _exit_tree() -> void:
remove_control_from_container(CustomControlContainer.CONTAINER_SPATIAL_EDITOR_MENU, __bugbot_menu_button) remove_control_from_container(CustomControlContainer.CONTAINER_SPATIAL_EDITOR_MENU, __bugbot_menu_button)
__bugbot_menu_button.queue_free() __bugbot_menu_button.queue_free()
@ -30,7 +31,7 @@ func _exit_tree() -> void:
# This is where we should remove any visible bug markers # This is where we should remove any visible bug markers
func __initialise_project_settings(): func __initialise_project_settings() -> void:
#region Placement #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/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") __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): func __on_bugbot_menu_item_pressed(id:int):
match id: match id:
BugbotMenuItems.SHOW_BUG_MARKERS: BugbotMenuItems.SHOW_BUG_MARKERS:
var scene_root : Node = EditorInterface.get_edited_scene_root() __show_editor_bug_markers()
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)
BugbotMenuItems.HIDE_BUG_MARKERS: BugbotMenuItems.HIDE_BUG_MARKERS:
var scene_root : Node = EditorInterface.get_edited_scene_root() var scene : String = EditorInterface.get_edited_scene_root().scene_file_path
var scene_path : String = scene_root.scene_file_path if __bugbot_marker_containers.has(scene) and __bugbot_marker_containers[scene]:
if __bugbot_marker_containers.has(scene_path): __bugbot_marker_containers[scene].queue_free()
var marker_container : Node3D = __bugbot_marker_containers[scene_path] __bugbot_marker_containers.erase(scene)
BugbotServerAPI._hide_markers(marker_container)
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: func __show_bug_markers_response(bug_list:Array) -> void:
var scene_root : Node = EditorInterface.get_edited_scene_root() var scene_root : Node = EditorInterface.get_edited_scene_root()
var marker_container : Node3D = __bugbot_marker_containers[scene_root.scene_file_path] var marker_container : Node3D = __bugbot_marker_containers[scene_root.scene_file_path]
for bugbot_data:Resource in bug_list: Bugbot.load_bug_markers(marker_container, 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
func __add_project_setting(_setting:String, _type:int, _default_value:Variant, _hint:int = PropertyHint.PROPERTY_HINT_NONE, _hint_string:String = ""): func __add_project_setting(_setting:String, _type:int, _default_value:Variant, _hint:int = PropertyHint.PROPERTY_HINT_NONE, _hint_string:String = ""):