# From khairul169: https://github.com/khairul169/3rdperson-godot/blob/master/assets/scripts/tpscam.gd extends Spatial var cam_pitch = 0.0; var cam_yaw = 0.0; var cam_cpitch = 0.0; var cam_cyaw = 0.0; var cam_currentradius = 2.0; var cam_radius = 2.0; var cam_pos = Vector3(); var cam_ray_result = {}; var cam_smooth_movement = true; var cam_fov = 60.0; var cam_view_sensitivity = 0.3; var cam_smooth_lerp = 10; var cam_pitch_minmax = Vector2(89, -89); var is_enabled = false; var collision_exception = []; export(NodePath) var cam; export(NodePath) var pivot; func _ready(): cam = get_node(cam); pivot = get_node(pivot); cam_fov = cam.get_fov(); func set_enabled(enabled): if enabled: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED); cam.make_current() else: Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE); set_process(enabled); is_enabled = enabled; func clear_exception(): collision_exception.clear(); func add_collision_exception(node): collision_exception.push_back(node); func _input(ie): if !is_enabled: return; if ie is InputEventMouseMotion: cam_pitch = max(min(cam_pitch+(ie.relative.y*cam_view_sensitivity),cam_pitch_minmax.x),cam_pitch_minmax.y); if cam_smooth_movement: cam_yaw = cam_yaw-(ie.relative.x*cam_view_sensitivity); else: cam_yaw = fmod(cam_yaw-(ie.relative.x*cam_view_sensitivity),360); cam_currentradius = cam_radius; cam_update(); if ie is InputEventMouseButton: if ie.pressed: if ie.button_index == BUTTON_WHEEL_UP: cam_radius = max(min(cam_radius-0.2,4.0),1.0); elif ie.button_index == BUTTON_WHEEL_DOWN: cam_radius = max(min(cam_radius+0.2,4.0),1.0); # Toggle mouse capture: if Input.is_action_just_pressed("toggle_mouse_capture"): set_enabled(!is_enabled) func _process(delta): if !is_enabled: return; if !cam.is_current(): cam.make_current(); if cam.get_projection() == Camera.PROJECTION_PERSPECTIVE: cam.set_perspective(lerp(cam.get_fov(), cam_fov, cam_smooth_lerp*delta), cam.get_znear(), cam.get_zfar()); if cam_smooth_movement: cam_cpitch = lerp(cam_cpitch, cam_pitch, 10*delta); cam_cyaw = lerp(cam_cyaw, cam_yaw, 10*delta); cam_currentradius = lerp(cam_currentradius, cam_radius, 5*delta); cam_update(); func cam_update(): cam_pos = pivot.get_global_transform().origin; if cam_smooth_movement: cam_pos.x += cam_currentradius * sin(deg2rad(cam_cyaw)) * cos(deg2rad(cam_cpitch)); cam_pos.y += cam_currentradius * sin(deg2rad(cam_cpitch)); cam_pos.z += cam_currentradius * cos(deg2rad(cam_cyaw)) * cos(deg2rad(cam_cpitch)); else: cam_pos.x += cam_currentradius * sin(deg2rad(cam_yaw)) * cos(deg2rad(cam_pitch)); cam_pos.y += cam_currentradius * sin(deg2rad(cam_pitch)); cam_pos.z += cam_currentradius * cos(deg2rad(cam_yaw)) * cos(deg2rad(cam_pitch)); var pos = Vector3(); if cam_ray_result.size() != 0: var a = (cam_ray_result.position-pivot.get_global_transform().origin).normalized(); var b = pivot.get_global_transform().origin.distance_to(cam_ray_result.position); pos = pivot.get_global_transform().origin+a*max(b-0.1, 0); else: pos = cam_pos; cam.look_at_from_position(pos, pivot.get_global_transform().origin, Vector3(0,1,0)); func _physics_process(delta): if !is_enabled: return; var ds = get_world().get_direct_space_state(); if ds != null: cam_ray_result = ds.intersect_ray(pivot.get_global_transform().origin, cam_pos, collision_exception);