OverviewFilesCommitsIssuesDocsReleasesPeers

godot-witchy_world_demo / addons / waterways / buoyant_manager.gd

74 lines · gd ref:
# Copyright © 2021 Kasper Arnklit Frandsen - MIT License
# See `LICENSE.md` included in the source distribution for details.
tool
extends Spatial

const WaterSystem = preload("res://addons/waterways/water_system_manager.gd")


export var water_system_group_name : String = "waterways_system"
export(float, 0.0, 200.0) var buoyancy_force := 50.0
export(float, 0.0, 20.0) var up_correcting_force := 5.0
export(float, 0.0, 200.0) var flow_force := 50.0
export(float, 0.0, 30.0) var water_resistance := 5.0

var _rb : RigidBody
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 RigidBody:
		_rb = parent as RigidBody
		_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 RigidBody to function."
	return ""


func _get_rotation_correction() -> Vector3:
	var rotation_transform := Transform()
	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.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.add_central_force(Vector3.UP * buoyancy_force * -altitude)
		var rot = _get_rotation_correction()
		_rb.add_torque(rot * up_correcting_force)
		_rb.add_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