A new version because it was not fully working yet, this one is stable:
@tool
extends Path3D
@export var fence_scene1 = preload("res://fence.tscn")
@export var fence_scene2 = preload("res://fence2.tscn")
@export var terrain: Node3D
@export var spacing = 0.3:
set(value):
spacing = value
if Engine.is_editor_hint() and is_inside_tree():
spawn_fences() # 🔁 Herbouw hekjes bij wijziging in editor
@export var height_offset = 0.0: # Zet standaard hoogte offset op 0 (geen zweven)
set(value):
height_offset = value
if Engine.is_editor_hint() and is_inside_tree():
spawn_fences() # 🔁 Herbouw hekjes bij wijziging in editor
@export var enable_random_rotation := true:
set(value):
enable_random_rotation = value
if Engine.is_editor_hint() and is_inside_tree():
spawn_fences() # 🔁 Herbouw hekjes bij wijziging in editor
var is_updating = false
func _ready():
if !$VisibleItems3:
var visible_items = Node3D.new()
visible_items.name = "VisibleItems3"
add_child(visible_items)
curve.connect("changed", Callable(self, "_on_curve_changed"))
adjust_curve_with_terrain_data()
spawn_fences()
func _on_curve_changed():
if is_updating:
return
is_updating = true
adjust_curve_with_terrain_data()
spawn_fences()
is_updating = false
func adjust_curve_with_terrain_data():
if terrain == null or terrain.data == null:
push_error("❌ Geen geldig Terrain3D gekoppeld!")
return
if curve.point_count == 0:
push_error("❌ Path3D heeft geen punten! Voeg punten toe.")
return
print("🔎 Path3D heeft", curve.point_count, "punten. Start hoogte-aanpassing...")
for i in range(curve.point_count):
var point = curve.get_point_position(i)
var terrain_height = get_terrain_height(point)
if !is_nan(terrain_height) and !is_inf(terrain_height):
var new_point = Vector3(point.x, terrain_height + height_offset, point.z)
curve.set_point_position(i, new_point)
print("✅ Punt aangepast:", new_point)
else:
push_error("⚠️ Ongeldige hoogte voor punt " + str(point) + ", behoud originele hoogte.")
func get_terrain_height(global_position: Vector3) -> float:
print("🌍 Controleren Terrain3DRegion voor positie:", global_position)
if terrain == null or terrain.data == null:
push_error("❌ Geen geldig Terrain3D gekoppeld!")
return global_position.y # Als er geen terrein is, behoud de oorspronkelijke hoogte
global_position = to_global(global_position)
print("🔎 Global position na conversie:", global_position)
var height: float = terrain.data.get_height(global_position) * terrain.scale.y
print("✅ Ontvangen hoogte:", height)
if is_nan(height) or is_inf(height):
push_error("⚠️ Ongeldige hoogte ontvangen voor " + str(global_position) + ", val terug op 0.")
return 0.0
return height
func spawn_fences():
if terrain == null:
push_error("❌ Geen geldig Terrain3D gekoppeld!")
return
for child in $VisibleItems3.get_children():
child.queue_free()
var current_distance = 0.0
while current_distance < curve.get_baked_length():
var pos = curve.sample_baked(current_distance)
var next_pos = curve.sample_baked(current_distance + 0.1)
pos = to_global(pos)
next_pos = to_global(next_pos)
var terrain_height = get_terrain_height(pos)
if !is_nan(terrain_height) and !is_inf(terrain_height):
pos.y = terrain_height + height_offset # Pas de hoogte van het hek aan op de terrain hoogte
var direction = (next_pos - pos).normalized()
direction.y = 0
var fence_instance = (fence_scene1 if randf() < 0.5 else fence_scene2).instantiate()
if direction.length() > 0:
var basis = Basis().looking_at(direction, Vector3.UP)
var transform = Transform3D(basis, pos)
fence_instance.transform = transform
else:
fence_instance.position = pos
$VisibleItems3.add_child(fence_instance)
if enable_random_rotation:
fence_instance.rotate_y(randf_range(0.0, 2.0 * PI))
current_distance += spacing
func randf_range(min_val: float, max_val: float) -> float:
return min_val + (max_val - min_val) * randf()