class_name EditorObjectCatalog extends RefCounted ## Catalog of placeable world objects for the in-game editor's ## `PalettePanel` (docs/architecture/editor.md ยง7.2). ## ## Mirrors the loading convention already used twice in this codebase -- ## `scripts/avatar/avatar_catalog.gd` (AvatarCatalog) and ## `scripts/scripting/spawn_catalog.gd` (SpawnCatalog): a data-driven JSON ## manifest, loaded once, looked up by id. Checked both before adding this: ## `AvatarCatalog` is avatar-attachment-specific (base_body/slot/mount_bone) ## and `SpawnCatalog` is scoped to `ScriptBehavior`'s `spawn_from_catalog` ## verb specifically (its own doc comment says as much) -- neither is a ## general "placeable world object" catalog, so this is a new, small one ## rather than a reuse of either. ## Catalog manifest structure: ## { "objects": { "id": { "type", "asset_id", "display_name", ... } } } var _catalog: Dictionary = {} var _loaded: bool = false var _catalog_path: String = "res://assets/editor/object_catalog.json" func load_catalog(path: String = _catalog_path) -> Error: _catalog_path = path _catalog = {} var file := FileAccess.open(path, FileAccess.READ) if file == null: return FileAccess.get_open_error() var json_text: String = file.get_as_text() file.close() var result: Variant = JSON.parse_string(json_text) if result == null or not (result is Dictionary) or not (result as Dictionary).has("objects"): return ERR_INVALID_DATA _catalog = (result as Dictionary)["objects"] _loaded = true return OK func is_loaded() -> bool: return _loaded ## Resolve a catalog id to its template Dictionary ({} if unknown/unloaded). func resolve(id: String) -> Dictionary: if not _loaded: return {} return _catalog.get(id, {}) func has_object(id: String) -> bool: return _loaded and _catalog.has(id) func get_all_ids() -> Array[String]: if not _loaded: return [] var ids: Array[String] = [] for id in _catalog.keys(): ids.append(id) return ids func get_catalog_path() -> String: return _catalog_path