Files
2026-06-17 15:28:56 -07:00

79 lines
2.4 KiB
GDScript

class_name Tile
extends Node3D
@export var display_texture: Texture2D
@export var inward_face_flip := true
@export var continuous_billboard := true
@export_range(0.0, 1.0, 0.01) var pulse_strength := 0.08
@export_range(0.05, 4.0, 0.05) var pulse_frequency_hz := 0.45
var tile_material: StandardMaterial3D
var base_scale := Vector3.ONE
var base_emission_energy := 1.0
var scale_multiplier := 1.0
var phase_offset := 0.0
var viewer_camera: Node3D
@onready var mesh_instance := $MeshInstance3D as MeshInstance3D
@onready var animation_player := $AnimationPlayer2 as AnimationPlayer
func _ready() -> void:
var source_material := ((mesh_instance.mesh as PlaneMesh).material as StandardMaterial3D)
if source_material != null:
tile_material = source_material.duplicate() as StandardMaterial3D
mesh_instance.material_override = tile_material
if tile_material != null and display_texture != null:
tile_material.albedo_texture = display_texture
tile_material.emission_texture = display_texture
base_emission_energy = tile_material.emission_energy_multiplier
base_scale = mesh_instance.scale
visible = true
if animation_player != null:
animation_player.play("flying")
func _process(_delta: float) -> void:
if viewer_camera != null and continuous_billboard:
look_at(viewer_camera.global_position, Vector3.UP)
if inward_face_flip:
rotate_object_local(Vector3.UP, PI)
var osc := Time.get_ticks_msec() * 0.001
var pulse := 1.0 + sin((osc * TAU * pulse_frequency_hz) + phase_offset) * pulse_strength
mesh_instance.scale = base_scale * scale_multiplier * pulse
if tile_material != null:
tile_material.emission_energy_multiplier = base_emission_energy * (0.9 + pulse_strength)
func place_on_shell(
center: Vector3,
direction: Vector3,
radius: float,
camera: Node3D
) -> void:
viewer_camera = camera
global_position = center + (direction.normalized() * radius)
if viewer_camera != null:
look_at(viewer_camera.global_position, Vector3.UP)
if inward_face_flip:
rotate_object_local(Vector3.UP, PI)
func set_scale_multiplier(multiplier: float) -> void:
scale_multiplier = max(multiplier, 0.05)
func set_phase_offset(phase: float) -> void:
phase_offset = phase
func set_display_texture(texture: Texture2D) -> void:
if texture == null:
return
display_texture = texture
if tile_material != null:
tile_material.albedo_texture = texture
tile_material.emission_texture = texture
func set_global_position_unclamped(pos: Vector3) -> void:
global_position = pos