ile-de-test/addons/waterways/waterfall_manager.gd
2024-01-26 21:00:32 +01:00

141 lines
4.5 KiB
GDScript

@tool
extends Node3D
const WaterfallConfiguration = preload("./waterfall_configuration.gd")
const WaterHelperMethods = preload("./water_helper_methods.gd")
const line_sample_resolution := 100
@export var configuration: WaterfallConfiguration:
set(value):
configuration = value
configuration.changed.connect(_configuration_changed)
print("configuration set function is called")
#@export var width := 3.0:
# set(value):
# width = value
# _generate_waterfall()
#@export var step_length_divs := 1:
# set(value):
# step_length_divs = value
# _generate_waterfall()
#@export var step_width_divs := 1:
# set(value):
# step_width_divs = value
# _generate_waterfall()
var points := PackedVector3Array([Vector3(0.0, 4.0, 0.0), Vector3(0.0, 0.0, 1.0)]):
set(value):
points = value
_generate_waterfall()
emit_signal("waterfall_changed")
var mesh_instance : MeshInstance3D
var _st : SurfaceTool
var _mdt : MeshDataTool
var _steps := 2
var _first_enter_tree = true
# TODO - connect this
signal waterfall_changed
func get_points() -> PackedVector3Array:
return points
func set_point(id: int, position: Vector3) -> void:
points[id] = position
_generate_waterfall()
emit_signal("waterfall_changed")
func _configuration_changed() -> void:
print("_configuration changed")
# TODO - I assume we can pass a parameter about whether a re-gen is needed
_generate_waterfall()
emit_signal("waterfall_changed")
func _enter_tree() -> void:
if Engine.is_editor_hint() and _first_enter_tree:
_first_enter_tree = false
if get_child_count() <= 0:
var new_mesh_instance := MeshInstance3D.new()
new_mesh_instance.name = "WaterfallMeshInstance"
add_child(new_mesh_instance)
mesh_instance = get_child(0) as MeshInstance3D
_generate_waterfall()
else:
mesh_instance = get_child(0) as MeshInstance3D
# TODO set material?
func _generate_waterfall() -> void:
# TODO - This spams "the target vector can't be zero", not sure which part, maybe cross product
var to_from: Vector3 = points[1] - points[0]
var to_from_2d = Vector3(to_from.x, 0.0, to_from.z)
var dist = to_from_2d.length()
var line_points := PackedVector3Array()
var curve := Curve3D.new()
for i in line_sample_resolution + 1:
var val = float(i) / float(line_sample_resolution)
var position = points[0] + to_from_2d * val + Vector3(0.0, ease_back_in(val) * to_from.y, 0.0)
curve.add_point(position)
line_points.append(position)
var curve_length := curve.get_baked_length()
_steps = int( max(1.0, round(curve_length / configuration.width)))
_st = SurfaceTool.new()
_st.begin(Mesh.PRIMITIVE_TRIANGLES)
_st.set_smooth_group(0)
# Generating the verts
for step in _steps * configuration.step_length_divs + 1:
var position := curve.sample_baked(float(step) / float(_steps * configuration.step_length_divs) * curve_length, false)
var backward_pos := curve.sample_baked((float(step) - 0.05) / float(_steps * configuration.step_length_divs) * curve_length, false)
var forward_pos := curve.sample_baked((float(step) + 0.05) / float(_steps *configuration. step_length_divs) * curve_length, false)
var forward_vector := forward_pos - backward_pos
var right_vector := forward_vector.cross(Vector3.UP).normalized()
for w_sub in configuration.step_width_divs + 1:
_st.set_uv(Vector2(float(w_sub) / (float(configuration.step_width_divs)), float(step) / float(configuration.step_length_divs) ))
_st.add_vertex(position + right_vector * configuration.width - 2.0 * right_vector * configuration.width * float(w_sub) / (float(configuration.step_width_divs)))
# Defining the tris
for step in _steps * configuration.step_length_divs:
for w_sub in configuration.step_width_divs:
_st.add_index( (step * (configuration.step_width_divs + 1)) + w_sub)
_st.add_index( (step * (configuration.step_width_divs + 1)) + w_sub + 1)
_st.add_index( (step * (configuration.step_width_divs + 1)) + w_sub + 2 + configuration.step_width_divs - 1)
_st.add_index( (step * (configuration.step_width_divs + 1)) + w_sub + 1)
_st.add_index( (step * (configuration.step_width_divs + 1)) + w_sub + 3 + configuration.step_width_divs - 1)
_st.add_index( (step * (configuration.step_width_divs + 1)) + w_sub + 2 + configuration.step_width_divs - 1)
_st.generate_normals()
_st.generate_tangents()
_st.deindex()
var mesh := ArrayMesh.new()
mesh = _st.commit()
mesh_instance.mesh = mesh
func ease_back_in(x: float) -> float:
var c1 = 1.70158
var c3 = c1 + 1
return c3 * x * x * x - c1 * x * x
# Signal Methods
func properties_changed() -> void:
emit_signal("waterfall_changed")