104 lines
3.1 KiB
GDScript
104 lines
3.1 KiB
GDScript
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 {}
|
|
if _catalog.has(id):
|
|
return _catalog[id]
|
|
if (id.contains("bizon") or id.contains("bison")) and _catalog.has("bison"):
|
|
return _catalog["bison"]
|
|
if (id == "tree_pine" or id.begins_with("tree")) and _catalog.has("tree_pine_01"):
|
|
return _catalog["tree_pine_01"]
|
|
if (id == "lamp_post" or id.begins_with("lamp")) and _catalog.has("lamp_post_01"):
|
|
return _catalog["lamp_post_01"]
|
|
if (id == "chest" or id.begins_with("chest")) and _catalog.has("chest_01"):
|
|
return _catalog["chest_01"]
|
|
if (id == "rock" or id.begins_with("rock")) and _catalog.has("rock_01"):
|
|
return _catalog["rock_01"]
|
|
if (id == "spawn_pad" or id.begins_with("spawn")) and _catalog.has("spawn_point"):
|
|
return _catalog["spawn_point"]
|
|
return {}
|
|
|
|
|
|
func has_object(id: String) -> bool:
|
|
if not _loaded:
|
|
return false
|
|
if _catalog.has(id):
|
|
return true
|
|
if (id.contains("bizon") or id.contains("bison")) and _catalog.has("bison"):
|
|
return true
|
|
return false
|
|
|
|
|
|
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 register_custom_object(id: String, entry: Dictionary) -> bool:
|
|
if not _loaded:
|
|
_catalog = {}
|
|
_loaded = true
|
|
_catalog[id] = entry
|
|
return true
|
|
|
|
|
|
func remove_custom_object(id: String) -> bool:
|
|
if not _loaded:
|
|
return false
|
|
return _catalog.erase(id)
|
|
|
|
|
|
func get_catalog_path() -> String:
|
|
return _catalog_path
|
|
|