Now About Social Code
summaryrefslogtreecommitdiff
path: root/addons/third-person-camera/third_person_camera/ThirdPersonCamera.gd
blob: 7eab1e2e757b048981e48ae50cd6f2e23a9d9ed3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
@icon("./ThirdPersonCameraIcon.svg")
@tool
class_name ThirdPersonCamera extends Node3D


@onready var _camera := $Camera
@onready var _camera_rotation_pivot = $RotationPivot
@onready var _camera_offset_pivot = $RotationPivot/OffsetPivot
@onready var _camera_spring_arm := $RotationPivot/OffsetPivot/CameraSpringArm
@onready var _camera_marker := $RotationPivot/OffsetPivot/CameraSpringArm/CameraMarker



## 
@export var distance_from_pivot := 10.0 :
	set(value) :
		distance_from_pivot = value
		$RotationPivot/OffsetPivot/CameraSpringArm.spring_length = distance_from_pivot

## 
@export var pivot_offset := Vector2.ZERO 

##  
@export_range(-90.0, 90.0) var initial_dive_angle_deg := -20.0 :
	set(value) :
		initial_dive_angle_deg = clampf(value, tilt_lower_limit_deg, tilt_upper_limit_deg)

## 
@export_range(-90.0, 90.0) var tilt_upper_limit_deg := 60.0

##
@export_range(-90.0, 90.0) var tilt_lower_limit_deg := -60.0

##
@export_range(1.0, 1000.0) var tilt_sensitiveness := 10.0

## 
@export_range(1.0, 1000.0) var horizontal_rotation_sensitiveness := 10.0

## 
@export var current : bool = false :
	set(value) :
		$Camera.current = value
		current = value


## 
@export_group("mouse")
## 
@export var mouse_follow : bool = false

##
@export_range(0., 100.) var mouse_x_sensitiveness : float = 1

## 
@export_range(0., 100.) var mouse_y_sensitiveness : float = 1


# Camera3D properies replication
@export_category("Camera3D")
@export var keep_aspect : Camera3D.KeepAspect = Camera3D.KEEP_HEIGHT
@export_flags_3d_render var cull_mask : int = 1048575
@export var environment : Environment 
@export var attributes : CameraAttributes
@export var doppler_tracking : Camera3D.DopplerTracking = Camera3D.DOPPLER_TRACKING_DISABLED
@export var projection : Camera3D.ProjectionType = Camera3D.PROJECTION_PERSPECTIVE
@export_range(1.0, 179.0, 0.1, "suffix:°") var FOV = 75.0 
@export var near := 0.05 
@export var far := 4000.0



var camera_tilt_deg := 0.
var camera_horizontal_rotation_deg := 0.


func _ready():
	_camera.top_level = true


func _physics_process(_delta):
	_update_camera_properties()
	if Engine.is_editor_hint() :
		_camera_marker.global_position = Vector3(0., 0., 1.).rotated(Vector3(1., 0., 0.), deg_to_rad(initial_dive_angle_deg)).rotated(Vector3(0., 1., 0.), deg_to_rad(-camera_horizontal_rotation_deg)) * _camera_spring_arm.spring_length + _camera_spring_arm.global_position
		pass
	#_camera.global_position = _camera_marker.global_position
	tweenCameraToMarker()
	_camera_offset_pivot.global_position = _camera_offset_pivot.get_parent().to_global(Vector3(pivot_offset.x, pivot_offset.y, 0.0)) 
	_camera_rotation_pivot.global_rotation_degrees.x = initial_dive_angle_deg
	_camera_rotation_pivot.global_position = global_position
	_process_tilt_input()
	_process_horizontal_rotation_input()
	_update_camera_tilt()
	_update_camera_horizontal_rotation()

func tweenCameraToMarker() :
	var tween = create_tween()
	tween.tween_property(_camera, "global_position", _camera_marker.global_position, 0.1)

func _process_horizontal_rotation_input() :
	if InputMap.has_action("tp_camera_right") and InputMap.has_action("tp_camera_left") :
		var camera_horizontal_rotation_variation = Input.get_action_strength("tp_camera_right") -  Input.get_action_strength("tp_camera_left")
		camera_horizontal_rotation_variation = camera_horizontal_rotation_variation * get_process_delta_time() * 30 * horizontal_rotation_sensitiveness
		camera_horizontal_rotation_deg += camera_horizontal_rotation_variation
		
func focus_camera(local_pos: Vector3, target_pos: Vector3):
	var local_2d = Vector2(local_pos.x, local_pos.z)
	var target_2d = Vector2(target_pos.x, target_pos.z)
	# This is the amount to tween the camera position
	var target_rotation = target_2d.angle_to_point(local_2d) + PI/2.0
	camera_horizontal_rotation_deg = rad_to_deg(_camera.global_rotation.y - target_rotation)

func _process_tilt_input() :
	if InputMap.has_action("tp_camera_up") and InputMap.has_action("tp_camera_down") :
		var tilt_variation = Input.get_action_strength("tp_camera_up") -  Input.get_action_strength("tp_camera_down")
		tilt_variation = tilt_variation * get_process_delta_time() * 5 * tilt_sensitiveness
		camera_tilt_deg = clamp(camera_tilt_deg + tilt_variation, tilt_lower_limit_deg - initial_dive_angle_deg, tilt_upper_limit_deg - initial_dive_angle_deg)
	


func _update_camera_tilt() :
	var tilt_final_val = clampf(initial_dive_angle_deg + camera_tilt_deg, tilt_lower_limit_deg, tilt_upper_limit_deg)
	var tween = create_tween()
	tween.tween_property(_camera, "global_rotation_degrees:x", tilt_final_val, 0.1)


func _update_camera_horizontal_rotation() :
	# TODO : inverse
	var tween = create_tween()
	tween.tween_property(_camera_rotation_pivot, "global_rotation_degrees:y", camera_horizontal_rotation_deg * -1, 0.1).as_relative()
	camera_horizontal_rotation_deg = 0.0 # reset the value
	var vect_to_offset_pivot : Vector2 = (
		Vector2(_camera_offset_pivot.global_position.x, _camera_offset_pivot.global_position.z) 
		-
		Vector2(_camera.global_position.x, _camera.global_position.z)
		).normalized()
	_camera.global_rotation.y = -Vector2(0., -1.).angle_to(vect_to_offset_pivot.normalized())
	



func _unhandled_input(event):
	if mouse_follow and event is InputEventMouseMotion:
		camera_horizontal_rotation_deg += event.relative.x * 0.1 * mouse_x_sensitiveness
		camera_tilt_deg -= event.relative.y * 0.07 * mouse_y_sensitiveness
		return
	
	pass


func _update_camera_properties() :
	_camera.keep_aspect = keep_aspect
	_camera.cull_mask = cull_mask
	_camera.doppler_tracking = doppler_tracking
	_camera.projection = projection
	_camera.fov = FOV
	_camera.near = near
	_camera.far = far
	if _camera.environment != environment :
		_camera.environment = environment
	if _camera.attributes != attributes :
		_camera.attributes = attributes


func get_camera() :
	return $Camera


func get_front_direction() :
	var dir : Vector3 = _camera_offset_pivot.global_position - _camera.global_position
	dir.y = 0.
	dir = dir.normalized()
	return dir

func get_back_direction() :
	return -get_front_direction()

func get_left_direction() :
	return get_front_direction().rotated(Vector3.UP, PI/2)

func get_right_direction() :
	return get_front_direction().rotated(Vector3.UP, -PI/2)