OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / test_sky3d_sunshine.gd

109 lines · gd ref:
extends Node3D

## Test scene: Sky3DExtended atmosphere + SunshineClouds2 volumetric clouds.
## Sky3D Extended provides atmosphere/sun/moon/stars/cirrus.
## SunshineClouds2 provides volumetric cloud rendering via CompositorEffect.
##
## Controls:
##   T / Shift+T  — advance / rewind time by 1 hour
##   F            — fast forward (1min cycle)
##   G            — normal speed (15min cycle)
##   P            — pause / resume time
##   F12          — screenshot

var _sky3d: Sky3DExtended
var _driver: SunshineCloudsDriverGD

func _ready() -> void:
	_sky3d = $Sky3DExtended as Sky3DExtended
	if not _sky3d:
		push_error("[Sky3D+Sunshine] Sky3DExtended not found")
		return

	# Create SunshineClouds2 driver — it auto-creates the CompositorEffect
	_driver = SunshineCloudsDriverGD.new()
	_driver.name = "SunshineCloudsDriver"
	add_child(_driver)

	# Wait one frame for Sky3D to finish initialization (creates SunLight/MoonLight)
	call_deferred("_setup_sunshine")

	print("[Sky3D+Sunshine] T/Shift+T: ±1hr, F: fast, G: slow, P: pause, F12: screenshot")


func _setup_sunshine() -> void:
	var sun_light := _sky3d.sun
	var moon_light := _sky3d.moon
	if not sun_light:
		push_warning("[Sky3D+Sunshine] No SunLight found in Sky3DExtended")
		return

	# Create the cloud CompositorEffect and attach to Sky3D's WorldEnvironment
	var cloud_res := SunshineCloudsGD.new()
	cloud_res.clouds_coverage = 0.874
	cloud_res.clouds_density = 0.14
	cloud_res.atmospheric_density = 0.503
	cloud_res.lighting_density = 0.982
	cloud_res.clouds_anisotropy = 0.16
	cloud_res.clouds_sharpness = 0.746
	cloud_res.cloud_floor = 1500.0
	cloud_res.cloud_ceiling = 25000.0
	cloud_res.max_step_count = 300.0
	cloud_res.max_lighting_steps = 32.0
	cloud_res.curl_noise_strength = 4500.0
	_driver.clouds_resource = cloud_res

	# Add to Sky3D's compositor
	var we := _sky3d as WorldEnvironment
	if not we.compositor:
		we.compositor = Compositor.new()
	var effects := we.compositor.compositor_effects.duplicate()
	effects.append(cloud_res)
	we.compositor.compositor_effects = effects

	# Track lights
	var lights: Array[DirectionalLight3D] = []
	lights.append(sun_light)
	if moon_light:
		lights.append(moon_light)
	_driver.tracked_directional_lights = lights
	_driver.tracked_directional_light_shadow_steps = [32, 12]

	# Wind
	_driver.wind_direction = Vector3(2, 0, 2)
	_driver.update_continuously = true

	print("[Sky3D+Sunshine] SunshineClouds2 active, tracking %d lights, coverage=%.2f" % [lights.size(), cloud_res.clouds_coverage])


func _unhandled_input(event: InputEvent) -> void:
	if not event is InputEventKey or not event.pressed or not _sky3d:
		return
	match event.keycode:
		KEY_T:
			var delta := -1.0 if event.shift_pressed else 1.0
			_sky3d.current_time = fmod(_sky3d.current_time + delta + 24.0, 24.0)
			print("[Sky3D+Sunshine] Time: %.1f (%s)" % [
				_sky3d.current_time, "day" if _sky3d.is_day() else "night"])
		KEY_F:
			_sky3d.minutes_per_day = 1.0
			print("[Sky3D+Sunshine] Fast forward (1min cycle)")
		KEY_G:
			_sky3d.minutes_per_day = 15.0
			print("[Sky3D+Sunshine] Normal speed (15min cycle)")
		KEY_P:
			if _sky3d.game_time_enabled:
				_sky3d.pause()
				print("[Sky3D+Sunshine] Paused at %.1f" % _sky3d.current_time)
			else:
				_sky3d.resume()
				print("[Sky3D+Sunshine] Resumed")
		KEY_F12:
			var img := get_viewport().get_texture().get_image()
			var ts := Time.get_datetime_string_from_system().replace(":", "-")
			var dir := "/home/fleeky/Desktop/hyper-tps"
			DirAccess.make_dir_recursive_absolute(dir)
			var path := "%s/sky3d_sunshine_%s.png" % [dir, ts]
			img.save_png(path)
			print("[Sky3D+Sunshine] Screenshot: %s" % path)