A6 (t_c5a27ca7): Editor loest Kategorie-GLBs aus der Registry auf (GlbMeshStore + gen_thumbs), Thumbs fuer Beispiel-Objekte

This commit is contained in:
Hermes (scopedvr-dev) 2026-10-19 18:02:12 +00:00
parent 76f8143540
commit 310aa695e6
5 changed files with 74 additions and 9 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B

View file

@ -24,6 +24,10 @@ class_name GlbMeshStore
const QUELLEN_SETTING := "scopedvr/editor/glb_quellen"
## Voreinstellung = dieselben Quellen wie tools/gen_thumbs.gd (Sibling-Repos).
const DEFAULT_QUELLEN := ["../scopedvr-match-server/assets/objekte", "../scopedvr-client/assets/objekte"]
## Registry (A6): liefert das Feld "glb" für die Kategorie-verschachtelte Ablage.
const MANIFEST_PATH := "res://library/objects.json"
static var _manifest: Dictionary = {}
static var _manifest_geladen := false
# Cache pro OID: Mesh (normalisiert) oder `false` = GLB gefunden, aber nicht
# ladbar (Parse-Fehler — kein endloser Retry pro Rebuild). Fehlende Datei
@ -44,6 +48,36 @@ static func quellen() -> Array:
return out if not out.is_empty() else DEFAULT_QUELLEN.duplicate()
## Kandidaten-Pfade (absolut) in Ladereihenfolge: Registry-`glb` (A6, Kategorie-
## Ablage assets/objekte/military_desert/<kategorie>/<oid>.glb) VOR der flachen
## Alt-Ablage <quelle>/<oid>.glb. Die Quelle ist ein Mesh-Lager (<repo>/assets/
## objekte) — für den verschachtelten Pfad wird sie auf die Repo-Wurzel gekürzt.
static func _kandidaten(oid: String) -> Array:
var basis := ProjectSettings.globalize_path("res://")
var out: Array = []
var rel := str(_eintrag(oid).get("glb", ""))
if rel.begins_with("res://"):
var sub := rel.substr(6)
for quelle in quellen():
var q := str(quelle)
var marke := "/assets/objekte"
var wurzel := q.substr(0, q.length() - marke.length()) if q.ends_with(marke) else q
out.append(basis.path_join(wurzel).path_join(sub))
for quelle in quellen():
out.append(basis.path_join(str(quelle)).path_join(oid + ".glb"))
return out
## Registry-Eintrag der OID (einmal gelesen, dann gecacht).
static func _eintrag(oid: String) -> Dictionary:
if not _manifest_geladen:
_manifest_geladen = true
var parsed: Variant = JSON.parse_string(FileAccess.get_file_as_string(MANIFEST_PATH))
if parsed is Dictionary:
_manifest = (parsed as Dictionary).get("objects", {})
return _manifest.get(oid, {})
## Echtes Mesh für eine Objekt-ID (normalisiert, Fußpunkt-Koordinaten) oder
## null = keine brauchbare GLB → Aufrufer zeigt den Platzhalter.
static func mesh_fuer(oid: String) -> Mesh:
@ -51,9 +85,7 @@ static func mesh_fuer(oid: String) -> Mesh:
return null
if _cache.has(oid):
return _cache[oid] if _cache[oid] is Mesh else null
for quelle in quellen():
var basis := ProjectSettings.globalize_path("res://")
var pfad := basis.path_join(quelle).path_join(oid + ".glb")
for pfad in _kandidaten(oid):
if FileAccess.file_exists(pfad):
var m := _glb_mesh(pfad)
if m != null:
@ -73,9 +105,8 @@ static func fehlt(oid: String) -> bool:
return true
if _cache.has(oid):
return not (_cache[oid] is Mesh)
var basis := ProjectSettings.globalize_path("res://")
for quelle in quellen():
if FileAccess.file_exists(basis.path_join(quelle).path_join(oid + ".glb")):
for pfad in _kandidaten(oid):
if FileAccess.file_exists(pfad):
return false
return true
@ -83,6 +114,8 @@ static func fehlt(oid: String) -> bool:
## Cache leeren (Tests / nach manuellem Eingriff ins Mesh-Lager).
static func cache_leeren() -> void:
_cache.clear()
_manifest.clear()
_manifest_geladen = false
# ------------------------------------------------------------ Laden --------

9
tests/probe_store_a6.gd Normal file
View file

@ -0,0 +1,9 @@
extends SceneTree
func _initialize() -> void:
var m := GlbMeshStore.mesh_fuer("beispiel_fass_01")
var m2 := GlbMeshStore.mesh_fuer("crate_wood")
print("GlbMeshStore beispiel_fass_01: ", "MESH " + str((m as Mesh).get_surface_count()) + " Flaechen, AABB " + str((m as Mesh).get_aabb().size) if m != null else "null")
print("GlbMeshStore crate_wood: ", "MESH" if m2 != null else "null (erwartet: kein GLB im Lager)")
print("GlbMeshStore.fehlt(fass)=", GlbMeshStore.fehlt("beispiel_fass_01"), " fehlt(crate_wood)=", GlbMeshStore.fehlt("crate_wood"))
print("STORE_PROBE_OK")
quit(0)

View file

@ -119,10 +119,15 @@ func _process(_delta: float) -> bool:
## Mesh für ein Thumbnail: echtes GLB aus dem Mesh-Lager (Sibling-Repos),
## sonst Kollisions-Platzhalter (alte Fallback-Regel).
##
## A6-Fundament (19.10.): Military-Objekte liegen KATEGORIE-verschachtelt
## (assets/objekte/military_desert/<kategorie>/<oid>.glb, Pfad im Registry-Feld
## "glb"). Deshalb stehen die Kandidaten jetzt in dieser Reihenfolge:
## 1. Registry-`glb` gegen jede QUELLEN-WURZEL (deren "/assets/objekte"-Suffix
## entfernt, damit derselbe relative Pfad aufgeht),
## 2. flache Alt-Ablage <quelle>/<oid>.glb.
func _mesh_fuer(oid: String, col: Dictionary) -> Mesh:
var basis := ProjectSettings.globalize_path("res://")
for quelle in GLB_QUELLEN:
var pfad := basis.path_join(str(quelle)).path_join(oid + ".glb")
for pfad in _kandidaten(oid):
if FileAccess.file_exists(pfad):
var m := _glb_mesh(pfad)
if m != null:
@ -130,6 +135,24 @@ func _mesh_fuer(oid: String, col: Dictionary) -> Mesh:
return MeshShapes.make_placeholder(str(col.get("shape", "box")), col, 1.0)
## Kandidaten-Pfade (absolut) für eine OID — Registry-Pfad vor flacher Alt-Ablage.
func _kandidaten(oid: String) -> Array:
var basis := ProjectSettings.globalize_path("res://")
var out: Array = []
var eintrag: Dictionary = (manifest.get("objects", {}) as Dictionary).get(oid, {})
var rel := str(eintrag.get("glb", ""))
if rel.begins_with("res://"):
var sub := rel.substr(6)
for quelle in GLB_QUELLEN:
var q := str(quelle)
var marke := "/assets/objekte"
var wurzel := q.substr(0, q.length() - marke.length()) if q.ends_with(marke) else q
out.append(basis.path_join(wurzel).path_join(sub))
for quelle in GLB_QUELLEN:
out.append(basis.path_join(str(quelle)).path_join(oid + ".glb"))
return out
## GLB OHNE Import-System laden (GLTFDocument) und das erste Mesh liefern.
## null = Load-Fehlschlag → Aufrufer fällt auf den Platzhalter zurück.
func _glb_mesh(pfad: String) -> Mesh: