fixed camera and sword animation issue and upgraded to Godot 4.6
Some checks failed
Create tag and build when new code gets to main / BumpTag (push) Successful in 22s
Create tag and build when new code gets to main / Test (push) Failing after 2m10s
Create tag and build when new code gets to main / Export (push) Has been skipped

This commit is contained in:
2026-01-27 17:47:19 +01:00
parent 056a68b0ad
commit caeae26a09
335 changed files with 3035 additions and 2221 deletions

View File

@@ -1,79 +0,0 @@
@tool
extends Control
var _context_menus := Dictionary()
var _command_handler := GdUnitCommandHandler.instance()
func _init() -> void:
set_name("EditorFileSystemContextMenuHandler")
var is_test_suite := func is_visible(script: Script, is_ts: bool) -> bool:
if script == null:
return false
return GdUnitTestSuiteScanner.is_test_suite(script) == is_ts
var context_menus :Array[GdUnitContextMenuItem] = [
GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_RUN, "Run Testsuites", "Play", is_test_suite.bind(true), _command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTSUITE)),
GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_DEBUG, "Debug Testsuites", "PlayStart", is_test_suite.bind(true), _command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTSUITE_DEBUG)),
]
for menu in context_menus:
_context_menus[menu.id] = menu
var popup := _menu_popup()
var file_tree := _file_tree()
@warning_ignore("return_value_discarded")
popup.about_to_popup.connect(on_context_menu_show.bind(popup, file_tree))
@warning_ignore("return_value_discarded")
popup.id_pressed.connect(on_context_menu_pressed.bind(file_tree))
func on_context_menu_show(context_menu: PopupMenu, file_tree: Tree) -> void:
context_menu.add_separator()
var current_index := context_menu.get_item_count()
for menu_id: int in _context_menus.keys():
var menu_item: GdUnitContextMenuItem = _context_menus[menu_id]
context_menu.add_item(menu_item.name, menu_id)
#context_menu.set_item_icon_modulate(current_index, Color.MEDIUM_PURPLE)
context_menu.set_item_disabled(current_index, !menu_item.is_enabled(null))
context_menu.set_item_icon(current_index, GdUnitUiTools.get_icon(menu_item.icon))
current_index += 1
func on_context_menu_pressed(id: int, file_tree: Tree) -> void:
if !_context_menus.has(id):
return
var menu_item: GdUnitContextMenuItem = _context_menus[id]
var test_suites := collect_testsuites(menu_item, file_tree)
menu_item.execute([test_suites])
func collect_testsuites(_menu_item: GdUnitContextMenuItem, file_tree: Tree) -> Array[Script]:
var file_system := EditorInterface.get_resource_filesystem()
var selected_item := file_tree.get_selected()
var selected_test_suites: Array[Script] = []
var suite_scaner := GdUnitTestSuiteScanner.new()
while selected_item:
var resource_path: String = selected_item.get_metadata(0)
var file_type := file_system.get_file_type(resource_path)
var is_dir := DirAccess.dir_exists_absolute(resource_path)
if is_dir:
selected_test_suites.append_array(suite_scaner.scan_directory(resource_path))
elif is_dir or file_type == "GDScript" or file_type == "CSharpScript":
# find a performant way to check if the selected item a testsuite
var resource: Script = ResourceLoader.load(resource_path, "Script", ResourceLoader.CACHE_MODE_REUSE)
if _menu_item.is_visible(resource):
@warning_ignore("return_value_discarded")
selected_test_suites.append(resource)
selected_item = file_tree.get_next_selected(selected_item)
return selected_test_suites
func _file_tree() -> Tree:
return GdObjects.find_nodes_by_class(EditorInterface.get_file_system_dock(), "Tree", true)[-1]
func _menu_popup() -> PopupMenu:
return GdObjects.find_nodes_by_class(EditorInterface.get_file_system_dock(), "PopupMenu")[-1]

View File

@@ -1 +0,0 @@
uid://njdp45y5pnap

View File

@@ -1,47 +0,0 @@
@tool
extends EditorContextMenuPlugin
var _context_menus := Dictionary()
var _command_handler := GdUnitCommandHandler.instance()
func _init() -> void:
var is_test_suite := func is_visible(script: Script, is_ts: bool) -> bool:
if script == null:
return false
return GdUnitTestSuiteScanner.is_test_suite(script) == is_ts
_context_menus[GdUnitContextMenuItem.MENU_ID.TEST_RUN] = GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_RUN, "Run Testsuites", "Play", is_test_suite.bind(true), _command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTSUITE))
_context_menus[GdUnitContextMenuItem.MENU_ID.TEST_DEBUG] = GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_DEBUG, "Debug Testsuites", "PlayStart", is_test_suite.bind(true), _command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTSUITE_DEBUG))
# setup shortcuts
for menu_item: GdUnitContextMenuItem in _context_menus.values():
var cb := func call(files: Array) -> void:
menu_item.execute([files])
add_menu_shortcut(menu_item.shortcut(), cb)
func _popup_menu(paths: PackedStringArray) -> void:
var test_suites: Array[Script] = []
var suite_scaner := GdUnitTestSuiteScanner.new()
for resource_path in paths:
# directories and test-suites are valid to enable the menu
if DirAccess.dir_exists_absolute(resource_path):
test_suites.append_array(suite_scaner.scan_directory(resource_path))
continue
var file_type := resource_path.get_extension()
if file_type == "gd" or file_type == "cs":
var script: Script = ResourceLoader.load(resource_path, "Script", ResourceLoader.CACHE_MODE_REUSE)
if GdUnitTestSuiteScanner.is_test_suite(script):
test_suites.append(script)
# no direcory or test-suites selected?
if test_suites.is_empty():
return
for menu_item: GdUnitContextMenuItem in _context_menus.values():
@warning_ignore("unused_parameter")
var cb := func call(files: Array) -> void:
menu_item.execute([test_suites])
add_context_menu_item(menu_item.name, cb, GdUnitUiTools.get_icon(menu_item.icon))

View File

@@ -1,18 +1,11 @@
class_name GdUnitContextMenuItem
enum MENU_ID {
UNDEFINED = 0,
TEST_RUN = 1000,
TEST_DEBUG = 1001,
TEST_RERUN = 1002,
CREATE_TEST = 1010,
}
var id: MENU_ID = MENU_ID.UNDEFINED:
var command_id: String:
set(value):
id = value
command_id = value
get:
return id
return command_id
var name: StringName:
set(value):
@@ -20,50 +13,33 @@ var name: StringName:
get:
return name
var command: GdUnitCommand:
set(value):
command = value
get:
return command
var visible: Callable:
set(value):
visible = value
get:
return visible
var icon: String:
set(value):
icon = value
var icon: Texture2D:
get:
return icon
return GdUnitCommandHandler.instance().command_icon(command_id)
func _init(p_id: MENU_ID, p_name: StringName, p_icon :String, p_is_visible: Callable, p_command: GdUnitCommand) -> void:
assert(p_id != null, "(%s) missing parameter 'MENU_ID'" % p_name)
func _init(p_command_id: String, p_name: StringName, p_is_visible: Callable) -> void:
assert(p_command_id != null and not p_command_id.is_empty(), "(%s) missing command id " % p_command_id)
assert(p_is_visible != null, "(%s) missing parameter 'GdUnitCommand'" % p_name)
assert(p_command != null, "(%s) missing parameter 'GdUnitCommand'" % p_name)
self.id = p_id
self.command_id = p_command_id
self.name = p_name
self.icon = p_icon
self.command = p_command
self.visible = p_is_visible
func shortcut() -> Shortcut:
return GdUnitCommandHandler.instance().get_shortcut(command.shortcut)
return GdUnitCommandHandler.instance().command_shortcut(command_id)
func is_enabled(script: Script) -> bool:
return command.is_enabled.call(script)
func is_visible(...args: Array) -> bool:
return visible.callv(args)
func is_visible(script: Script) -> bool:
return visible.call(script)
func execute(arguments:=[]) -> void:
if arguments.is_empty():
command.runnable.call()
else:
command.runnable.callv(arguments)
func execute(...args: Array) -> void:
GdUnitCommandHandler.instance().command_execute(command_id, args)

View File

@@ -1 +1 @@
uid://bla1g2ce6t53i
uid://0cxvd5nclyb0

View File

@@ -0,0 +1,37 @@
@tool
extends EditorContextMenuPlugin
var _context_menus: Array[GdUnitContextMenuItem] = []
func _init() -> void:
var is_test_suite := func is_visible(script: Script, is_ts: bool) -> bool:
if script == null:
return false
return GdUnitTestSuiteScanner.is_test_suite(script) == is_ts
_context_menus.append(GdUnitContextMenuItem.new(
GdUnitCommandFileSystemRunTests.ID,
"Run Testsuites",
is_test_suite.bind(true)
))
_context_menus.append(GdUnitContextMenuItem.new(
GdUnitCommandFileSystemDebugTests.ID,
"Debug Testsuites",
is_test_suite.bind(true)
))
# setup shortcuts
for menu_item in _context_menus:
if menu_item.shortcut():
var cb := func call(...files: Array) -> void:
var paths: Array = files[0]
menu_item.execute.callv(paths)
add_menu_shortcut(menu_item.shortcut(), cb)
func _popup_menu(paths: PackedStringArray) -> void:
for menu_item in _context_menus:
if menu_item.shortcut():
add_context_menu_item_from_shortcut(menu_item.name, menu_item.shortcut(), menu_item.icon)
else:
add_context_menu_item(menu_item.name, menu_item.execute.bindv(paths).unbind(1), menu_item.icon)

View File

@@ -0,0 +1 @@
uid://bygty0ifds7gl

View File

@@ -0,0 +1,63 @@
@tool
class_name GdUnitInspectorContextMenu
extends PopupMenu
const CONTEXT_MENU_RUN_ID = 0
const CONTEXT_MENU_DEBUG_ID = 1
const CONTEXT_MENU_RERUN_UNTIL_ID = 2
# id 3 is the seperator
const CONTEXT_MENU_COLLAPSE_ALL = 4
const CONTEXT_MENU_EXPAND_ALL = 5
var command_handler: GdUnitCommandHandler
func _ready() -> void:
if not Engine.is_editor_hint():
return
command_handler = GdUnitCommandHandler.instance()
_setup_item(CONTEXT_MENU_RUN_ID, "Run Tests", GdUnitCommandInspectorRunTests.ID)
_setup_item(CONTEXT_MENU_DEBUG_ID, "Debug Tests", GdUnitCommandInspectorDebugTests.ID)
_setup_item(CONTEXT_MENU_RERUN_UNTIL_ID, "Run Tests Until Fail", GdUnitCommandInspectorRerunTestsUntilFailure.ID)
_setup_item(CONTEXT_MENU_EXPAND_ALL, "Expand All", GdUnitCommandInspectorTreeExpand.ID)
_setup_item(CONTEXT_MENU_COLLAPSE_ALL, "Collapse All", GdUnitCommandInspectorTreeCollapse.ID)
func _setup_item(item_id: int, item_name: String, command_id: String) -> void:
set_item_text(item_id, item_name)
set_item_icon(item_id, command_handler.command_icon(command_id))
set_item_shortcut(item_id, command_handler.command_shortcut(command_id))
func disable_items() -> void:
set_item_disabled(CONTEXT_MENU_RUN_ID, true)
set_item_disabled(CONTEXT_MENU_DEBUG_ID, true)
set_item_disabled(CONTEXT_MENU_RERUN_UNTIL_ID, true)
func enable_items() -> void:
set_item_disabled(CONTEXT_MENU_RUN_ID, false)
set_item_disabled(CONTEXT_MENU_DEBUG_ID, false)
set_item_disabled(CONTEXT_MENU_RERUN_UNTIL_ID, false)
func _on_tree_item_mouse_selected(mouse_position: Vector2, mouse_button_index: int, source: Tree) -> void:
if mouse_button_index == MOUSE_BUTTON_RIGHT:
position = source.get_screen_position() + mouse_position
popup()
func _on_index_pressed(index: int) -> void:
match index:
CONTEXT_MENU_RUN_ID:
command_handler.command_execute(GdUnitCommandInspectorRunTests.ID)
CONTEXT_MENU_DEBUG_ID:
command_handler.command_execute(GdUnitCommandInspectorDebugTests.ID)
CONTEXT_MENU_RERUN_UNTIL_ID:
command_handler.command_execute(GdUnitCommandInspectorRerunTestsUntilFailure.ID)
CONTEXT_MENU_EXPAND_ALL:
command_handler.command_execute(GdUnitCommandInspectorTreeExpand.ID)
CONTEXT_MENU_COLLAPSE_ALL:
command_handler.command_execute(GdUnitCommandInspectorTreeCollapse.ID)

View File

@@ -0,0 +1 @@
uid://xhy87fbc5yl

View File

@@ -0,0 +1,70 @@
[gd_scene format=3 uid="uid://bjcc71p2h1trr"]
[ext_resource type="Script" path="res://addons/gdUnit4/src/ui/menu/GdUnitInspectorContextMenu.gd" id="1_0x0vc"]
[sub_resource type="DPITexture" id="DPITexture_miuuy"]
_source = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\"><path fill=\"#e0e0e0\" d=\"M4 12a1 1 0 0 0 1.555.832l6-4a1 1 0 0 0 0-1.664l-6-4A1 1 0 0 0 4 4z\"/></svg>
"
saturation = 2.0
color_map = {
Color(1, 0.37254903, 0.37254903, 1): Color(1, 0.47, 0.42, 1),
Color(0.37254903, 1, 0.5921569, 1): Color(0.45, 0.95, 0.5, 1),
Color(1, 0.8666667, 0.39607844, 1): Color(0.83, 0.78, 0.62, 1)
}
[sub_resource type="DPITexture" id="DPITexture_ern2r"]
_source = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\"><path fill=\"#e0e0e0\" d=\"M3 3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zm4.975 0A1 1 0 0 0 7 3.998v8a1 1 0 0 0 1.625.781l5-4a1 1 0 0 0 0-1.56l-5-4A1 1 0 0 0 7.975 3z\"/></svg>
"
saturation = 2.0
color_map = {
Color(1, 0.37254903, 0.37254903, 1): Color(1, 0.47, 0.42, 1),
Color(0.37254903, 1, 0.5921569, 1): Color(0.45, 0.95, 0.5, 1),
Color(1, 0.8666667, 0.39607844, 1): Color(0.83, 0.78, 0.62, 1)
}
[sub_resource type="DPITexture" id="DPITexture_qdci2"]
_source = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\"><path fill=\"#e0e0e0\" d=\"m8 9.669-3.536 2.583H7v2.537h2v-2.537h2.536zm0-3.314L4.464 3.772H7V1.235h2v2.537h2.536zm-7.296.73h14.591v1.831H.704z\"/></svg>
"
saturation = 2.0
color_map = {
Color(1, 0.37254903, 0.37254903, 1): Color(1, 0.47, 0.42, 1),
Color(0.37254903, 1, 0.5921569, 1): Color(0.45, 0.95, 0.5, 1),
Color(1, 0.8666667, 0.39607844, 1): Color(0.83, 0.78, 0.62, 1)
}
[sub_resource type="DPITexture" id="DPITexture_hed0i"]
_source = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\"><path fill=\"#e0e0e0\" d=\"m8 16-3.5-2.5H7V11h2v2.5h2.5zM8 0 4.5 2.5H7V5h2V2.5h2.5zM1 7h14v2H1z\"/></svg>
"
saturation = 2.0
color_map = {
Color(1, 0.37254903, 0.37254903, 1): Color(1, 0.47, 0.42, 1),
Color(0.37254903, 1, 0.5921569, 1): Color(0.45, 0.95, 0.5, 1),
Color(1, 0.8666667, 0.39607844, 1): Color(0.83, 0.78, 0.62, 1)
}
[node name="contextMenu" type="PopupMenu" unique_id=1824556050]
auto_translate_mode = 2
oversampling_override = 1.0
size = Vector2i(241, 170)
visible = true
item_count = 6
item_0/text = "Run Tests"
item_0/icon = SubResource("DPITexture_miuuy")
item_0/id = 0
item_1/text = "Debug Tests"
item_1/icon = SubResource("DPITexture_ern2r")
item_1/id = 1
item_2/text = "Run Tests Until Fail"
item_2/icon = SubResource("DPITexture_miuuy")
item_2/id = 2
item_3/id = 3
item_3/separator = true
item_4/text = "Collapse All"
item_4/icon = SubResource("DPITexture_qdci2")
item_4/id = 4
item_5/text = "Expand All"
item_5/icon = SubResource("DPITexture_hed0i")
item_5/id = 5
script = ExtResource("1_0x0vc")
[connection signal="index_pressed" from="." to="." method="_on_index_pressed"]

View File

@@ -0,0 +1,41 @@
@tool
extends EditorContextMenuPlugin
var _context_menus: Array[GdUnitContextMenuItem] = []
func _init() -> void:
var is_test_suite := func is_visible(script: Script, is_ts: bool) -> bool:
return GdUnitTestSuiteScanner.is_test_suite(script) == is_ts
_context_menus.append(GdUnitContextMenuItem.new(
GdUnitCommandScriptEditorRunTests.ID,
"Run Tests",
is_test_suite.bind(true)
))
_context_menus.append(GdUnitContextMenuItem.new(
GdUnitCommandScriptEditorDebugTests.ID,
"Debug Tests",
is_test_suite.bind(true)
))
_context_menus.append(GdUnitContextMenuItem.new(
GdUnitCommandScriptEditorCreateTest.ID,
"Create Test",
is_test_suite.bind(false)
))
# setup shortcuts
for menu_item in _context_menus:
if menu_item.shortcut():
add_menu_shortcut(menu_item.shortcut(), menu_item.execute.unbind(1))
func _popup_menu(_paths: PackedStringArray) -> void:
var current_script := EditorInterface.get_script_editor().get_current_script()
for menu_item in _context_menus:
if menu_item.is_visible(current_script):
if menu_item.shortcut():
add_context_menu_item_from_shortcut(menu_item.name, menu_item.shortcut())
else:
add_context_menu_item(menu_item.name, menu_item.execute.unbind(1))

View File

@@ -0,0 +1 @@
uid://0osxbi6yvarl

View File

@@ -1,81 +0,0 @@
@tool
extends Control
var _context_menus := Dictionary()
var _editor: ScriptEditor
var _command_handler := GdUnitCommandHandler.instance()
func _init() -> void:
set_name("ScriptEditorContextMenuHandler")
var is_test_suite := func is_visible(script: Script, is_ts: bool) -> bool:
return GdUnitTestSuiteScanner.is_test_suite(script) == is_ts
var context_menus :Array[GdUnitContextMenuItem] = [
GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_RUN, "Run Tests", "Play", is_test_suite.bind(true), _command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTCASE)),
GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_DEBUG, "Debug Tests", "PlayStart", is_test_suite.bind(true), _command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTCASE_DEBUG)),
GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.CREATE_TEST, "Create Test", "New", is_test_suite.bind(false), _command_handler.command(GdUnitCommandHandler.CMD_CREATE_TESTCASE))
]
for menu in context_menus:
_context_menus[menu.id] = menu
_editor = EditorInterface.get_script_editor()
@warning_ignore("return_value_discarded")
_editor.editor_script_changed.connect(on_script_changed)
on_script_changed(active_script())
func _input(event: InputEvent) -> void:
if event is InputEventKey and event.is_pressed():
for action: GdUnitContextMenuItem in _context_menus.values():
if action.shortcut().matches_event(event) and action.is_visible(active_script()):
#if not has_editor_focus():
# return
action.execute()
accept_event()
return
func has_editor_focus() -> bool:
return (Engine.get_main_loop() as SceneTree).root.gui_get_focus_owner() == active_base_editor()
func on_script_changed(script: Script) -> void:
if script is Script:
var popups: Array[Node] = GdObjects.find_nodes_by_class(active_editor(), "PopupMenu", true)
for popup: PopupMenu in popups:
if not popup.about_to_popup.is_connected(on_context_menu_show):
popup.about_to_popup.connect(on_context_menu_show.bind(script, popup))
if not popup.id_pressed.is_connected(on_context_menu_pressed):
popup.id_pressed.connect(on_context_menu_pressed)
func on_context_menu_show(script: Script, context_menu: PopupMenu) -> void:
#prints("on_context_menu_show", _context_menus.keys(), context_menu, self)
context_menu.add_separator()
var current_index := context_menu.get_item_count()
for menu_id: int in _context_menus.keys():
var menu_item: GdUnitContextMenuItem = _context_menus[menu_id]
if menu_item.is_visible(script):
context_menu.add_item(menu_item.name, menu_id)
context_menu.set_item_disabled(current_index, !menu_item.is_enabled(script))
context_menu.set_item_shortcut(current_index, menu_item.shortcut(), true)
current_index += 1
func on_context_menu_pressed(id: int) -> void:
if !_context_menus.has(id):
return
var menu_item: GdUnitContextMenuItem = _context_menus[id]
menu_item.execute()
func active_editor() -> ScriptEditorBase:
return _editor.get_current_editor()
func active_base_editor() -> TextEdit:
return active_editor().get_base_editor()
func active_script() -> Script:
return _editor.get_current_script()

View File

@@ -1 +0,0 @@
uid://cy5cblh8psm0a

View File

@@ -1,33 +0,0 @@
@tool
extends EditorContextMenuPlugin
var _context_menus := Dictionary()
var _editor: ScriptEditor
var _command_handler := GdUnitCommandHandler.instance()
func _init() -> void:
var is_test_suite := func is_visible(script: Script, is_ts: bool) -> bool:
return GdUnitTestSuiteScanner.is_test_suite(script) == is_ts
var context_menus :Array[GdUnitContextMenuItem] = [
GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_RUN, "Run Tests", "Play", is_test_suite.bind(true), _command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTCASE)),
GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.TEST_DEBUG, "Debug Tests", "PlayStart", is_test_suite.bind(true), _command_handler.command(GdUnitCommandHandler.CMD_RUN_TESTCASE_DEBUG)),
GdUnitContextMenuItem.new(GdUnitContextMenuItem.MENU_ID.CREATE_TEST, "Create Test", "New", is_test_suite.bind(false), _command_handler.command(GdUnitCommandHandler.CMD_CREATE_TESTCASE))
]
for menu in context_menus:
_context_menus[menu.id] = menu
_editor = EditorInterface.get_script_editor()
@warning_ignore("return_value_discarded")
func _popup_menu(paths: PackedStringArray) -> void:
var script_path := paths[0]
var script: Script = ResourceLoader.load(script_path, "Script", ResourceLoader.CACHE_MODE_REUSE)
for menu_id: int in _context_menus.keys():
var menu_item: GdUnitContextMenuItem = _context_menus[menu_id]
if menu_item.is_visible(script):
add_context_menu_item(menu_item.name,
func call(files: Array) -> void:
menu_item.execute([script_path]),
GdUnitUiTools.get_icon(menu_item.icon))