Tales-of-PKMN/utils/WaterMaker3D/WaterMaker3D.gd
2026-10-22 16:53:03 +02:00

55 lines
2.3 KiB
GDScript

@tool
extends CSGBox3D
@export var water_texture_move_speed := Vector3(0.0025, 0.0025, 0.0025)
@export var water_texture_uv_scale := 0.04
@export var water_color := Color(0.3098039329052, 0.54117649793625, 0.86666667461395, 0.38823530077934)
@export var fog_color := Color(0, 0.04313725605607, 0.15686275064945)
@export_range(0.0, 250.0) var fog_fade_dist := 5.0
static var last_frame_drew_underwater_effect : int = -999
func _ready():
self.process_priority = 999 # Call _process last to update move after any camera movement
# Track the current camera with an area so we can check if it is inside the water
func should_draw_camera_underwater_effect():
var camera := get_viewport().get_camera_3d() if get_viewport() else null
if not camera: return false
var aabb = self.global_transform * self.get_aabb().grow(0.025)
if not aabb.has_point(camera.global_position): return false
# Don't draw multiple overlays at once, incase 2 water bodies overlap
if last_frame_drew_underwater_effect == Engine.get_process_frames(): return false
%CameraPosShapeCast3D.global_position = camera.global_position
%CameraPosShapeCast3D.force_shapecast_update()
var camera_is_in_water_area3d := false
for i in %CameraPosShapeCast3D.get_collision_count():
if %CameraPosShapeCast3D.get_collider(i) == %SwimmableArea3D:
return true
return false
func _update_mesh():
if get_node_or_null("%CollisionShape3D"):
%CollisionShape3D.shape.size = self.size
func _process(delta):
_update_mesh()
if self.material is StandardMaterial3D:
if not Engine.is_editor_hint():
self.material.uv1_offset += water_texture_move_speed * delta
self.material.uv1_scale = Vector3(water_texture_uv_scale,water_texture_uv_scale,water_texture_uv_scale)
self.material.albedo_color = water_color
%FogVolume.material.set_shader_parameter("albedo", fog_color)
%FogVolume.material.set_shader_parameter("emission", fog_color)
%FogVolume.size = self.size
%FogVolume.fade_distance = self.fog_fade_dist
if not Engine.is_editor_hint():
if should_draw_camera_underwater_effect():
%WaterRippleOverlay.visible = true
%FogVolume.material.set_shader_parameter("edge_fade", 0.1)
last_frame_drew_underwater_effect = Engine.get_process_frames()
else:
%WaterRippleOverlay.visible = false
%FogVolume.material.set_shader_parameter("edge_fade", 1.1)