extends Node3D @onready var skeleton_flying = $BallFlyingMesh.get_node("SKL_projectile_flying/Skeleton3D") @onready var skeleton_bouncing = $BallBouncingMesh.get_node("SKL_projectile_bouncing/Skeleton3D") @onready var ball = owner @onready var timer = ball.get_node("TimerCollision") var is_bouncing = false var max_squish_xy = 0.5 # Starts at 0 var max_squish_z = 0.8 # From 0 to 1 # Apply a small offset to the up vector in the look_at function to fix it # not working when the target is perfectly aligned with the up vector const LOOK_AT_OFFSET_FIX = Vector3(0.01, 1, 0.01) func _ready(): ball.ball_collision_started.connect(_on_collision) ball.ball_collision_ended.connect(_after_collision) func _process(delta): _align_mesh_to_direction() _squish_animation() func _align_mesh_to_direction(): # Align the RotationNode to the movement direction $RotationNode.look_at(ball.captured_velocity + ball.global_position, LOOK_AT_OFFSET_FIX) # Convert the rotation euler into a quaternion var euler_rotation = $RotationNode.rotation var quaternion_rotation : Quaternion quaternion_rotation = quaternion_rotation.from_euler(euler_rotation) # Rotate the bone skeleton_flying.set_bone_pose_rotation(1, quaternion_rotation) func _on_collision(): $BallFlyingMesh.visible = false $BallBouncingMesh.visible = true is_bouncing = true # Align the Meshes node to the surface normal so the bouncing mesh is properly aligned look_at(ball.collision_normal + ball.global_position, LOOK_AT_OFFSET_FIX) func _after_collision(): $BallFlyingMesh.visible = true $BallBouncingMesh.visible = false is_bouncing = false # Reset the Meshes node rotation rotation = Vector3.ZERO func _squish_animation(): if is_bouncing: # Remap the time_left value of the timer var time_left_remap = remap(timer.time_left, timer.wait_time, 0, 0, 2) var time_left_pingpong = pingpong(time_left_remap, 1) # Multiply the scaling by the collision angle factor to reduce # the squishing effect at shallow angles var scale_xy_factor = 1.0 + (ball.collision_angle_factor * max_squish_xy) var scale_xy = 1.0 * remap(time_left_pingpong, 0, 1, 1, scale_xy_factor) var scale_z_factor = 1.0 - (ball.collision_angle_factor * max_squish_z) var scale_z = 1.0 * remap(time_left_pingpong, 0, 1, 1, scale_z_factor) # Compose the vector for the bone scaling var scale_squish_vector = Vector3(scale_xy, scale_xy, scale_z) # Scale the bone skeleton_bouncing.set_bone_pose_scale(1, scale_squish_vector)