U-Nachlauf t_efb3d022: assets_panel _library_load_open_states robuster Typ-Check

bool(cfg.get_value()) warf SCRIPT ERROR "Nonexistent bool constructor" bei
Nicht-Bool-Eintraegen in [library] (Array-Eintraege neben zuletzt_benutzt) —
die Klapp-Zustaende luden dann gar nicht (STATES leer).

Fix: nur echte Bool-Werte uebernehmen, String/Int/Array auf Fallback true,
kein Crash mehr.

Beweis-Probe tests/probe_t_efb3d022_repro.gd:
  vorher: 2x SCRIPT ERROR "Invalid call. Nonexistent 'bool' constructor",
          STATES leer
  nachher: 0 Fehler, 3 Zustaende geladen (Array-Eintrag -> Fallback true)

Suite test_assets_panel.gd erweitert um Testgruppe 0
"Klapp-Zustaende aus kaputter cfg" (6 neue Checks, 75 -> 81, ALL OK):
Array/String/Int-Eintraege + save->load-Rundtrip.

test_inspector 47/47, test_gui_smoke 92/92, --import 0 Parse-Errors.
This commit is contained in:
Hermes (scopedvr-dev) 2026-10-20 09:52:03 +00:00
parent 4fb883a44c
commit 7c7dc38566
4 changed files with 75 additions and 1 deletions

View file

@ -328,7 +328,15 @@ func _library_load_open_states() -> Dictionary:
for key in cfg.get_section_keys(LIBRARY_CFG_SECTION): for key in cfg.get_section_keys(LIBRARY_CFG_SECTION):
if str(key) == RECENT_CFG_KEY: if str(key) == RECENT_CFG_KEY:
continue continue
out[str(key)] = bool(cfg.get_value(LIBRARY_CFG_SECTION, str(key), true)) # Robustheit (t_efb3d022): cfg-Einträge dieser Sektion müssen Bool-
# Zustände sein. Ein kaputter Eintrag (String/Array/sonstwas) darf
# KEINEN SCRIPT ERROR werfen (bool(<Array>) ist kein gültiger
# Konstruktor) — sonst brechen die Klapp-Zustände komplett weg.
var val = cfg.get_value(LIBRARY_CFG_SECTION, str(key), true)
if typeof(val) == TYPE_BOOL:
out[str(key)] = val
else:
out[str(key)] = true
return out return out

View file

@ -0,0 +1,36 @@
extends SceneTree
## Beweis-Probe t_efb3d022: `[library]` enthält einen Array-Eintrag.
## Vor dem Fix: SCRIPT ERROR "Invalid call. Nonexistent 'bool' constructor"
## beim Laden der Klapp-Zustände (bool(<Array>) ist kein gültiger Konstruktor).
## Nach dem Fix: sauberes Laden, Zustände kommen zurück, keine Fehler.
##
## godot4 --headless --path . -s res://tests/probe_t_efb3d022_repro.gd
##
## Grep-Muster für den Gegenbeweis: "SCRIPT ERROR" + "Nonexistent 'bool' constructor"
func _initialize() -> void:
_run.call_deferred()
func _run() -> void:
# Kaputte cfg simulieren: Array-Eintrag (Nicht-Bool) neben echtem Bool,
# plus zuletzt_benutzt (U4 schreibt das Array in dieselbe Sektion).
var cfg := ConfigFile.new()
cfg.set_value("library", "zuletzt_benutzt", PackedStringArray(["crate_metal", "crate_wood"]))
cfg.set_value("library", "gruppen_kisten", true)
cfg.set_value("library", "gruppen_bauteile", false)
cfg.set_value("library", "array_gruppe", PackedStringArray(["a", "b"]))
cfg.save("user://scopedvr_editor.cfg")
var scene: PackedScene = load("res://scenes/main.tscn")
var main: Control = scene.instantiate()
root.add_child(main)
await process_frame
await process_frame
var assets = main.assets_mod
var states: Dictionary = assets._library_load_open_states()
print("STATES=", states)
print("PROBE_ENDE states=", states.size(), " kisten=", states.get("gruppen_kisten", "?"),
" bauteile=", states.get("gruppen_bauteile", "?"))
quit(0)

View file

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

View file

@ -51,6 +51,7 @@ func _run_all() -> void:
assets.object_selected.connect(_on_selected) assets.object_selected.connect(_on_selected)
assets.object_activated.connect(_on_activated) assets.object_activated.connect(_on_activated)
_test_klapp_zustaende_cfg_robus()
_test_kategorien() _test_kategorien()
_test_suche_und_zaehler() _test_suche_und_zaehler()
_test_kategorie_filter() _test_kategorie_filter()
@ -98,6 +99,34 @@ func _clear_library_cfg_section() -> void:
cfg.save("user://scopedvr_editor.cfg") cfg.save("user://scopedvr_editor.cfg")
# --------------------------------------- 0 Klapp-Zustände aus kaputter cfg ----
func _test_klapp_zustaende_cfg_robus() -> void:
print("Testgruppe: Klapp-Zustände laden sauber aus kaputter cfg (t_efb3d022)")
# Kaputte cfg: [library] enthält einen Array-Eintrag (zuletzt_benutzt) und
# einen korrupten Eintrag (String statt Bool) neben einem echten Bool.
var cfg := ConfigFile.new()
cfg.set_value("library", "zuletzt_benutzt", PackedStringArray(["crate_metal", "crate_wood"]))
cfg.set_value("library", "gruppen_kisten", true)
cfg.set_value("library", "gruppen_bauteile", "kaputt")
cfg.set_value("library", "gruppen_spawn", 42)
cfg.save("user://scopedvr_editor.cfg")
# Direkt aufrufen: darf KEINEN SCRIPT ERROR werfen (bool(<Array>) war der
# alte Crash) und muss die sauberen Bool-Zustände trotzdem liefern.
var states: Dictionary = assets._library_load_open_states()
_check(states.size() == 3, "3 Zustände geladen, Array-Eintrag übersprungen (ist %d)" % states.size())
_check(states.get("gruppen_kisten") == true, "echter Bool bleibt true")
_check(states.get("gruppen_bauteile") == true, "String-Eintrag auf Fallback true")
_check(states.get("gruppen_spawn") == true, "Int-Eintrag auf Fallback true")
# Und der Persistenz-Weg (save → load) liefert die Zustände unverändert:
assets._library_save_open_state("gruppen_kisten", false)
var states2: Dictionary = assets._library_load_open_states()
_check(states2.get("gruppen_kisten") == false, "save→load Rundtrip: false kommt zurück")
_check(states2.get("gruppen_bauteile") == true, "kaputter Eintrag nach Rundtrip weiter Fallback true")
# Aufräumen: nächste Testgruppen brauchen eine saubere cfg.
_clear_library_cfg_section()
# ------------------------------------------------------------- 1 Kategorien ---- # ------------------------------------------------------------- 1 Kategorien ----
func _test_kategorien() -> void: func _test_kategorien() -> void: