extends SceneTree ## Editor-Test (headless): UI-Aufräumen 25.10. — eigene Tabs Terrain/Malen/Bauen, ## Viewport-Werkzeugleiste, Dreh-/Kipp-Gizmo (alle Achsen, Undo), Kontrast. ## Ausführen: godot --headless --path . --script res://tests/test_ui_aufraeumen.gd var failures := 0 var checks := 0 var main: Control func _initialize() -> void: _run.call_deferred() func _run() -> void: main = (load("res://scenes/main.tscn") as PackedScene).instantiate() root.add_child(main) await process_frame await process_frame (main.doc["objects"] as Array).append({ "id": "crate_wood", "pos": [4.0, 0.0, 4.0], "scale": 1.0, "rot_y_deg": 0.0}) main.call("_after_structure_change") main.history.clear() await process_frame print("== Tabs ==") var tabs: TabContainer = main.ui_right_panel var titel: Array = [] for i in tabs.get_tab_count(): titel.append(tabs.get_tab_title(i)) _check(titel.has("Terrain") and titel.has("Malen") and titel.has("Bauen"), "Tabs Terrain, Malen, Bauen vorhanden") _check(main.malen_mod != null and main.bauen_mod != null, "Module malen/bauen gebaut") _check(main.terrain_mod.terrain_mode_paint.get_parent() == main.terrain_mod.terrain_panel and not main.terrain_mod.terrain_mode_paint.visible, "Mal-Modus nicht mehr als Knopf im Terrain-Tab") _check(main.build_edit_btn.get_parent() == main.bauen_mod, "Bauen-Knopf wohnt im Bauen-Tab") _check(main.malen_mod.mat_buttons.size() == SvmapIO.MATERIAL_IDS.size(), "Malen: eine Kachel je Material") print("== Malen-Tab ==") main.call("_set_tool_mode", "terrain") _check(main.terrain_mod.terrain_panel.visible and not main.malen_mod.malen_panel.visible, "Terrain aktiv: nur Terrain-Panel") main.terrain_mod.terrain_mode_paint.button_pressed = true _check(main.malen_mod.malen_panel.visible and main.malen_mod.palette.visible and not main.terrain_mod.terrain_panel.visible, "Malen aktiv: Malen-Panel statt Terrain-Panel") _check(tabs.current_tab == main.malen_mod.get_index(), "Tab springt auf Malen") main.malen_mod.radius_slider.value = 20.0 _check(int(main.terrain_mod.terrain_radius_slider.value) == 20, "Malen-Radius steuert den Pinsel") main.call("_set_tool_mode", "objects") print("== Lesbarkeit ==") var muted: Color = main.malen_mod.theme_color("muted") _check(muted.a > 0.7 and muted.r > 0.9, "muted-Farbe ist hell (nicht Schwarz)") _check(main.status_mod.stats_objects.get_theme_color("font_color").a > 0.0, "Statuszeile lesbar") print("== Werkzeugleiste + Dreh-Gizmo ==") _check(not main.viewport_toolbar.visible, "ohne Auswahl keine Werkzeugleiste") main.interaction.call("select_object", 0) await process_frame await process_frame _check(main.viewport_toolbar.visible, "mit Auswahl erscheint die Werkzeugleiste") _check(main.gizmo.mode == "move", "Standard: Verschieben") main.viewport_toolbar.rotate_btn.pressed.emit() _check(main.gizmo.mode == "rotate", "Knopf Drehen schaltet den Gizmo um") var obj: Dictionary = main.doc["objects"][0] var n0: int = main.history.entries.size() _check(main.gizmo.demo_rotate_axis("x", 30.0), "Kippen um X") _check(main.gizmo.demo_rotate_axis("z", -15.0), "Kippen um Z") _check(main.gizmo.demo_rotate_axis("y", 45.0), "Drehen um Y") var rot := SvmapIO.objekt_rotation(obj) _check(is_equal_approx(rot.x, 30.0) and is_equal_approx(fposmod(rot.z, 360.0), 345.0) and is_equal_approx(rot.y, 45.0), "Euler (%s) = (30, 45, 345)" % str(rot)) _check(main.history.entries.size() == n0 + 3, "jeder Zug = ein Undo-Schritt (%d neu)" % (main.history.entries.size() - n0)) main.call("_do_undo") obj = main.doc["objects"][0] _check(is_equal_approx(SvmapIO.objekt_rotation(obj).y, 0.0), "Undo nimmt den Y-Zug zurück") main.call("_do_undo") main.call("_do_undo") obj = main.doc["objects"][0] _check(SvmapIO.objekt_rotation(obj).is_equal_approx(Vector3.ZERO), "dreimal Undo = Ausgangslage") main.viewport_toolbar.move_btn.pressed.emit() _check(main.gizmo.mode == "move", "Verschieben schaltet zurück") var scale_btns := 0 for c in main.viewport_toolbar.find_children("*", "Button", true, false): if str((c as Button).text).to_lower().contains("skal"): scale_btns += 1 _check(scale_btns == 0, "kein Skalieren-Werkzeug (Objekte behalten ihre Größe)") if failures == 0: print("ALL OK: %d checks" % checks) quit(0) else: print("FAILED: %d/%d checks" % [failures, checks]) quit(1) func _check(cond: bool, label: String) -> void: checks += 1 if cond: print(" ok: ", label) else: failures += 1 print(" FAIL: ", label)