2025-10-02 16:42:27 -06:00
|
|
|
class_name GenerationFeature extends Node3D
|
|
|
|
|
## Base class for world features generated during worldgen.
|
|
|
|
|
##
|
|
|
|
|
## Layers contain features. Some features may contain layers.
|
|
|
|
|
|
2025-10-03 17:11:59 -06:00
|
|
|
@export var noise_scale := Vector3.ONE
|
|
|
|
|
@export var noise_offset := Vector3.ZERO
|
|
|
|
|
|
2025-10-03 18:37:25 -06:00
|
|
|
var sub_layers: Array[GenerationLayer]:
|
|
|
|
|
get():
|
|
|
|
|
if not _defined_sub_layers:
|
|
|
|
|
sub_layers = _find_sub_layers(self)
|
|
|
|
|
_defined_sub_layers = true
|
|
|
|
|
return sub_layers
|
|
|
|
|
var _defined_sub_layers := false
|
2025-10-03 17:11:59 -06:00
|
|
|
var _generated := false
|
|
|
|
|
|
2025-10-02 16:42:27 -06:00
|
|
|
|
2025-10-03 18:37:25 -06:00
|
|
|
func _find_sub_layers(node: Node) -> Array[GenerationLayer]:
|
|
|
|
|
var layers: Array[GenerationLayer] = []
|
|
|
|
|
if node is GenerationLayer:
|
|
|
|
|
layers.append(node)
|
|
|
|
|
for c: Node in node.get_children():
|
|
|
|
|
# Do not walk outside of this scene
|
|
|
|
|
if c.owner in [owner, self]:
|
|
|
|
|
layers.append_array(_find_sub_layers(c))
|
|
|
|
|
return layers
|
|
|
|
|
|
|
|
|
|
|
2025-10-02 16:42:27 -06:00
|
|
|
func probe() -> void:
|
|
|
|
|
# TODO may want to make low-detail & high-detail probes distinct
|
2025-10-03 17:11:59 -06:00
|
|
|
if not _generated:
|
|
|
|
|
generate()
|
|
|
|
|
_generated = true
|
|
|
|
|
|
|
|
|
|
for layer in sub_layers:
|
|
|
|
|
layer.probe()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Generate elements of this feature. Called by default on the first call to `probe`
|
|
|
|
|
func generate() -> void:
|
|
|
|
|
pass # Implemented in derived type
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func sample_noise() -> float:
|
|
|
|
|
var sample_point := global_position * noise_scale + noise_offset
|
|
|
|
|
return WorldGenManager.noise.get_noise_3dv(sample_point)
|