Files
gamedev-the-steward/world/presentation/PresentationCueDefinition.gd
T
2026-08-12 21:41:33 +02:00

90 lines
2.9 KiB
GDScript

class_name PresentationCueDefinition
extends Resource
const ALLOWED_PARAMETER_KEYS := {
"visual_scale": true,
"body_scale": true,
"fluff_scale": true,
"show_horns": true,
"show_beard": true,
}
@export var cue_id: StringName
@export_file("*.tscn") var scene_path: String
@export_file var icon_path: String
@export_file var material_path: String
@export var animation_hook_id: StringName
@export var parameters: Dictionary = {}
func validate_metadata() -> Array[String]:
var errors: Array[String] = []
if not AnimalDefinition.is_valid_stable_id(cue_id):
errors.append("cue_id is invalid")
_validate_optional_path(scene_path, "scene_path", ["tscn", "scn"], errors)
_validate_optional_path(icon_path, "icon_path", ["png", "svg", "webp"], errors)
_validate_optional_path(material_path, "material_path", ["tres", "res", "material"], errors)
if (
not animation_hook_id.is_empty()
and not AnimalDefinition.is_valid_stable_id(animation_hook_id)
):
errors.append("animation_hook_id is invalid for '%s'" % cue_id)
_validate_parameters(errors)
return errors
func validate_assets() -> Array[String]:
var errors := validate_metadata()
if not errors.is_empty():
return errors
for path_field in [
["scene_path", scene_path, "PackedScene"],
["icon_path", icon_path, "Texture2D"],
["material_path", material_path, "Material"],
]:
var path: String = path_field[1]
if not path.is_empty() and not ResourceLoader.exists(path, path_field[2]):
errors.append("%s does not resolve for '%s'" % [path_field[0], cue_id])
return errors
func get_parameters() -> Dictionary:
return parameters.duplicate(true)
func instantiate_scene() -> Node:
if scene_path.is_empty():
return null
var scene := load(scene_path) as PackedScene
return scene.instantiate() if scene != null else null
func _validate_parameters(errors: Array[String]) -> void:
for raw_key in parameters:
if raw_key is not String and raw_key is not StringName:
errors.append("parameter key must be a string for '%s'" % cue_id)
continue
var key := String(raw_key)
if not ALLOWED_PARAMETER_KEYS.has(key):
errors.append("unsupported parameter '%s' for '%s'" % [key, cue_id])
continue
var value: Variant = parameters[raw_key]
if key.ends_with("_scale"):
if value is not Vector3 or not _is_positive_vector(value):
errors.append("parameter '%s' must be a positive Vector3 for '%s'" % [key, cue_id])
elif value is not bool:
errors.append("parameter '%s' must be bool for '%s'" % [key, cue_id])
func _validate_optional_path(
path: String, field: String, extensions: Array[String], errors: Array[String]
) -> void:
if path.is_empty():
return
if not path.begins_with("res://") or path.get_extension().to_lower() not in extensions:
errors.append("%s is invalid for '%s'" % [field, cue_id])
func _is_positive_vector(value: Vector3) -> bool:
return value.is_finite() and value.x > 0.0 and value.y > 0.0 and value.z > 0.0