Files
VRyHungry1/addons/yaml/examples/example_resource_referencing.gd
2026-07-19 10:47:28 +02:00

175 lines
5.8 KiB
GDScript

extends ExampleBase
# This example requires a local texture reference
# For real use, export a texture in your scene
@export var local_texture: Texture2D
func _init() -> void:
icon = "🔗"
func run_examples() -> void:
run_example("Parsing Resources", parsing_resources)
run_example("Stringifying Resources", stringifying_resources)
run_example("Resource Security", resource_security)
run_example("Resource Path Management", resource_path_management)
func parsing_resources() -> void:
var yaml_text := """
scene: !Resource 'res://addons/yaml/examples/assets/simple_scene.tscn'
texture: !Resource 'res://icon.svg'
yaml: !Resource 'res://addons/yaml/examples/data/simple.yaml'
"""
log_code_block(yaml_text)
log_info("Parsing YAML with resource references...")
var parse_result := YAML.parse(yaml_text)
if parse_result.has_error():
log_error("Parse failed: " + parse_result.get_error())
return
var data: Dictionary = parse_result.get_data()
log_success("YAML with resources parsed successfully")
if data.scene is PackedScene:
log_success("PackedScene loaded successfully")
var scene = data.scene.instantiate()
var screen_width: int = ProjectSettings.get_setting("display/window/size/viewport_width")
var screen_height: int = ProjectSettings.get_setting("display/window/size/viewport_height")
scene.position = Vector2(screen_width / 2, screen_height / 2)
add_child(scene)
else:
log_warning("PackedScene not loaded (might be missing file or security restrictions)")
if data.texture is Texture2D:
log_success("Texture loaded successfully")
else:
log_warning("Texture not loaded (might be missing file or security restrictions)")
if data.yaml is Dictionary:
log_success("Nested YAML loaded successfully")
else:
log_warning("Nested YAML not loaded (might be missing file or security restrictions)")
if LOG_VERBOSE:
log_info("Resource types:")
log_info("• scene type: " + str(typeof(data.scene)))
log_info("• texture type: " + str(typeof(data.texture)))
log_info("YAML resource:")
log_info(str(data.yaml))
func stringifying_resources() -> void:
log_info("Stringifying a resource...")
var resource = load("res://icon.svg") # Project icon should always exist
if !resource:
log_error("Could not load resource")
return
var str_result := YAML.stringify(resource)
if str_result.has_error():
log_error("Stringify failed: " + str_result.get_error())
return
log_success("Resource stringified successfully")
if LOG_VERBOSE:
log_result("Stringified Resource:\n" + str_result.get_data())
# Test stringifying local resource (should fail)
if local_texture:
log_info("Attempting to stringify local (non-file) resource...")
var invalid_result := YAML.stringify(local_texture)
if invalid_result.has_error():
log_success("Correctly failed to serialize local resource")
log_info("Error: " + invalid_result.get_error())
else:
log_error("Incorrectly serialized local resource")
else:
log_warning("No local texture assigned, skipping local resource test")
func resource_security() -> void:
log_info("Testing resource security...")
var yaml_text := """
script: !Resource 'res://addons/yaml/examples/scripts/dangerous_script.gd'
"""
log_code_block(yaml_text)
log_info("Parsing with default security...")
var parse_result := YAML.parse(yaml_text)
if parse_result.has_error():
log_success("Default security correctly blocked script resource")
log_info("Error: " + parse_result.get_error())
else:
log_error("Default security failed to block script resource")
log_info("Creating custom security with explicit type blocks...")
var security := YAML.create_security()
security.block_type("Script")
security.block_type("GDExtension")
security.allow_path("res://**", ["Texture2D", "PackedScene"])
log_info("Same file with custom security...")
parse_result = YAML.parse(yaml_text, security)
if parse_result.has_error():
log_success("Custom security correctly blocked script resource")
log_info("Error: " + parse_result.get_error())
else:
log_error("Custom security failed to block script resource")
func resource_path_management() -> void:
log_subheader("Resource Path Management")
log_info("Using relative paths vs absolute paths:")
var yaml_with_absolute_path := """
texture: !Resource 'res://icon.svg'
"""
log_code_block(yaml_with_absolute_path)
log_info("Absolute paths are fixed to specific locations")
var yaml_with_relative_path := """
# When file is in res://addons/yaml/examples/
texture: !Resource '../../../icon.svg'
"""
log_code_block(yaml_with_relative_path)
log_warning("Note: Godot doesn't natively support relative paths in Resource paths")
log_info("You need to implement custom path resolution for relative paths")
log_info("\nSuggested best practices:")
log_info("1. Use absolute paths (res://, user://) for resources")
log_info("2. Keep resources in a structured directory hierarchy")
log_info("3. Use security settings to limit resource access")
log_info("4. For mod support, create custom path remapping in your game code")
# Example of custom path handling
log_info("\nExample of custom path handling:")
var code := """
# Custom path resolver for mod resources
func resolve_mod_path(path: String, mod_id: String) -> String:
if path.begins_with("mod://"):
# Transform mod:// protocol to user://mods/{mod_id}/
return path.replace("mod://", "user://mods/" + mod_id + "/")
return path
# Example usage with YAML
func load_mod_config(mod_id: String) -> Dictionary:
var yaml_text = FileAccess.open("user://mods/" + mod_id + "/config.yaml", FileAccess.READ).get_as_text()
var data = YAML.parse(yaml_text).get_data()
# Process all resource paths in the data
for key in data:
if data[key] is String and data[key].begins_with("mod://"):
# Resolve the path
data[key] = resolve_mod_path(data[key], mod_id)
return data
"""
log_code_block(code)