73 lines
2.2 KiB
GDScript
73 lines
2.2 KiB
GDScript
# Copyright © 2023 Kasper Arnklit Frandsen - MIT License
|
|
# See `LICENSE.md` included in the source distribution for details.
|
|
@tool
|
|
extends Node3D
|
|
|
|
const WaterSystem = preload("res://addons/waterways/water_system_manager.gd")
|
|
|
|
|
|
@export var water_system_group_name : String = "waterways_system"
|
|
@export var buoyancy_force := 50.0
|
|
@export var up_correcting_force := 5.0
|
|
@export var flow_force := 50.0
|
|
@export var water_resistance := 5.0
|
|
|
|
var _rb : RigidBody3D
|
|
var _system : WaterSystem
|
|
var _default_linear_damp := -1.0
|
|
var _default_angular_damp := -1.0
|
|
|
|
|
|
func _enter_tree() -> void:
|
|
var parent = get_parent()
|
|
if parent is RigidBody3D:
|
|
_rb = parent as RigidBody3D
|
|
_default_linear_damp = _rb.linear_damp
|
|
_default_angular_damp = _rb.angular_damp
|
|
|
|
|
|
func _exit_tree() -> void:
|
|
_rb = null
|
|
|
|
|
|
func _ready() -> void:
|
|
var systems = get_tree().get_nodes_in_group(water_system_group_name)
|
|
if systems.size() > 0:
|
|
if systems[0] is WaterSystem:
|
|
_system = systems[0] as WaterSystem
|
|
|
|
|
|
func _get_configuration_warning() -> String:
|
|
if _rb == null:
|
|
return "Bouyant node must be a direct child of a RigidDynamicBody3D to function."
|
|
return ""
|
|
|
|
|
|
func _get_rotation_correction() -> Vector3:
|
|
var rotation_transform := Transform3D()
|
|
var up_vector := global_transform.basis.y
|
|
var angle := up_vector.angle_to(Vector3.UP)
|
|
if angle < 0.1:
|
|
# Don't reaturn a rotation as object is almost upright, since the cross
|
|
# product at an angle that small might cause precission errors.
|
|
return Vector3.ZERO
|
|
var cross := up_vector.cross(Vector3.UP).normalized()
|
|
rotation_transform = rotation_transform.rotated(cross, angle)
|
|
return rotation_transform.basis.get_euler()
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
if Engine.is_editor_hint() || _system == null || _rb == null:
|
|
return
|
|
var altitude = _system.get_water_altitude(global_transform.origin)
|
|
if altitude < 0.0:
|
|
var flow = _system.get_water_flow(global_transform.origin)
|
|
_rb.apply_central_force(Vector3.UP * buoyancy_force * -altitude)
|
|
var rot = _get_rotation_correction()
|
|
_rb.apply_torque(rot * up_correcting_force)
|
|
_rb.apply_central_force(flow * flow_force)
|
|
_rb.linear_damp = water_resistance
|
|
_rb.angular_damp = water_resistance
|
|
else:
|
|
_rb.linear_damp = _default_linear_damp
|
|
_rb.angular_damp = _default_angular_damp
|