feat(M03): add environment snapshot facade
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
class_name WorldEnvironmentSnapshot
|
||||
extends RefCounted
|
||||
|
||||
## Immutable renderer input describing the authoritative time within one world day.
|
||||
## DBC light, area, fog and skybox selection remain owned by the sky controller.
|
||||
|
||||
const HOURS_PER_DAY := 24.0
|
||||
const SCRIPT_PATH := "res://src/render/environment/world_environment_snapshot.gd"
|
||||
|
||||
var is_valid: bool:
|
||||
get:
|
||||
return _is_valid
|
||||
|
||||
var time_of_day_hours: float:
|
||||
get:
|
||||
return _time_of_day_hours
|
||||
|
||||
var failure_code: StringName:
|
||||
get:
|
||||
return _failure_code
|
||||
|
||||
var _is_valid: bool
|
||||
var _time_of_day_hours: float
|
||||
var _failure_code: StringName
|
||||
|
||||
|
||||
## Creates a snapshot and normalizes finite input into the half-open [0, 24) day.
|
||||
## Non-finite input produces an explicit invalid value instead of renderer state.
|
||||
static func at_time_of_day(time_of_day_hours_value: float) -> RefCounted:
|
||||
return load(SCRIPT_PATH).new(time_of_day_hours_value)
|
||||
|
||||
|
||||
func _init(time_of_day_hours_value: float) -> void:
|
||||
_is_valid = is_finite(time_of_day_hours_value)
|
||||
_time_of_day_hours = (
|
||||
fposmod(time_of_day_hours_value, HOURS_PER_DAY)
|
||||
if _is_valid
|
||||
else 0.0
|
||||
)
|
||||
_failure_code = &"" if _is_valid else &"environment_time_not_finite"
|
||||
@@ -0,0 +1 @@
|
||||
uid://dass4mi3ex2fu
|
||||
@@ -8,17 +8,24 @@ extends Node
|
||||
const GODOT_WORLD_POSITION_SCRIPT := preload("res://src/domain/coordinates/godot_world_position.gd")
|
||||
const STREAMING_FOCUS_SCRIPT := preload("res://src/domain/streaming/streaming_focus.gd")
|
||||
const RENDERED_GROUND_SAMPLE_SCRIPT := preload("res://src/render/terrain/rendered_ground_sample.gd")
|
||||
const WORLD_ENVIRONMENT_SNAPSHOT_SCRIPT := preload("res://src/render/environment/world_environment_snapshot.gd")
|
||||
|
||||
## Internal renderer implementation resolved relative to this node.
|
||||
## The referenced node remains owned by its scene parent.
|
||||
@export var streaming_world_loader_path: NodePath = NodePath("..")
|
||||
|
||||
## Scene-owned outdoor environment implementation resolved relative to this node.
|
||||
## The facade delegates snapshots but owns neither the controller nor Environment.
|
||||
@export var world_environment_controller_path: NodePath = NodePath("../WowSkyController")
|
||||
|
||||
## Optional explicit Node3D source sampled in Godot world coordinates.
|
||||
## Runtime scenes use the player; capture and probe tools replace it with their camera.
|
||||
@export var streaming_focus_source_path: NodePath
|
||||
|
||||
var _streaming_world_loader: Node
|
||||
var _world_environment_controller: Node
|
||||
var _missing_loader_reported := false
|
||||
var _missing_environment_controller_reported := false
|
||||
var _missing_focus_source_reported := false
|
||||
|
||||
|
||||
@@ -94,6 +101,21 @@ func renderer_ground_query_snapshot(godot_world_position: GodotWorldPosition) ->
|
||||
return (snapshot_variant as Dictionary).duplicate(true)
|
||||
|
||||
|
||||
## Applies an immutable environment snapshot through the renderer-owned sky path.
|
||||
## Returns false for an invalid value or unavailable/incompatible controller.
|
||||
func apply_environment_snapshot(world_environment_snapshot: RefCounted) -> bool:
|
||||
if (
|
||||
world_environment_snapshot == null
|
||||
or world_environment_snapshot.get_script() != WORLD_ENVIRONMENT_SNAPSHOT_SCRIPT
|
||||
or not bool(world_environment_snapshot.get("is_valid"))
|
||||
):
|
||||
return false
|
||||
var controller := _resolve_world_environment_controller()
|
||||
if controller == null:
|
||||
return false
|
||||
return bool(controller.call("apply_environment_snapshot", world_environment_snapshot))
|
||||
|
||||
|
||||
func _capture_streaming_focus_from_source() -> void:
|
||||
if streaming_focus_source_path == NodePath():
|
||||
return
|
||||
@@ -138,3 +160,20 @@ func _resolve_streaming_world_loader() -> Node:
|
||||
_streaming_world_loader = candidate
|
||||
_missing_loader_reported = false
|
||||
return _streaming_world_loader
|
||||
|
||||
|
||||
func _resolve_world_environment_controller() -> Node:
|
||||
if is_instance_valid(_world_environment_controller):
|
||||
return _world_environment_controller
|
||||
var candidate := get_node_or_null(world_environment_controller_path)
|
||||
if candidate == null or not candidate.has_method(&"apply_environment_snapshot"):
|
||||
if not _missing_environment_controller_reported:
|
||||
push_error(
|
||||
"WorldRenderFacade cannot resolve a compatible environment controller at %s"
|
||||
% world_environment_controller_path
|
||||
)
|
||||
_missing_environment_controller_reported = true
|
||||
return null
|
||||
_world_environment_controller = candidate
|
||||
_missing_environment_controller_reported = false
|
||||
return _world_environment_controller
|
||||
|
||||
Reference in New Issue
Block a user