Camera.gd 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. # Licensed under the MIT License.
  2. # Copyright (c) 2018-2020 Jaccomo Lorenz (Maujoe)
  3. # base on https://github.com/Maujoe/godot-camera-control
  4. extends Spatial
  5. # User settings:
  6. # General settings
  7. export var enabled = true setget set_enabled
  8. # See https://docs.godotengine.org/en/latest/classes/class_input.html?highlight=Input#enumerations
  9. export(int, "Visible", "Hidden", "Captured, Confined") var mouse_mode = Input.MOUSE_MODE_VISIBLE
  10. enum Freelook_Modes {MOUSE, INPUT_ACTION, MOUSE_AND_INPUT_ACTION}
  11. # Freelook settings
  12. export var freelook = true
  13. export (Freelook_Modes) var freelook_mode = 2
  14. export (float, 0.0, 1.0) var sensitivity = 0.5
  15. export (float, 0.0, 0.999, 0.001) var smoothness = 0.5 setget set_smoothness
  16. export (int, 0, 360) var yaw_limit = 360
  17. export (int, 0, 360) var pitch_limit = 360
  18. # Pivot Settings
  19. export(NodePath) var privot setget set_privot
  20. export var distance = 5.0 setget set_distance
  21. export var rotate_privot = false
  22. export var collisions = true setget set_collisions
  23. # Movement settings
  24. export var movement = true
  25. export (float, 0.0, 1.0) var acceleration = 1.0
  26. export (float, 0.0, 0.0, 1.0) var deceleration = 0.1
  27. export var max_speed = Vector3(1.0, 1.0, 1.0)
  28. export var local = true
  29. # Input Actions
  30. export var rotate_left_action = ""
  31. export var rotate_right_action = ""
  32. export var rotate_up_action = ""
  33. export var rotate_down_action = ""
  34. export var forward_action = "ui_up"
  35. export var backward_action = "ui_down"
  36. export var left_action = "ui_left"
  37. export var right_action = "ui_right"
  38. export var up_action = "ui_page_up"
  39. export var down_action = "ui_page_down"
  40. export var trigger_action = ""
  41. # Intern variables.
  42. var _mouse_offset = Vector2()
  43. var _rotation_offset = Vector2()
  44. var _yaw = 0.0
  45. var _pitch = 0.0
  46. var _total_yaw = 0.0
  47. var _total_pitch = 0.0
  48. var _direction = Vector3(0.0, 0.0, 0.0)
  49. var _speed = Vector3(0.0, 0.0, 0.0)
  50. var _triggered=false
  51. const ROTATION_MULTIPLIER = 500
  52. var mouse_c=false
  53. var is_ui=false
  54. var loaded=true
  55. func _ready():
  56. _check_actions([
  57. forward_action,
  58. backward_action,
  59. left_action,
  60. right_action,
  61. up_action,
  62. down_action,
  63. rotate_left_action,
  64. rotate_right_action,
  65. rotate_up_action,
  66. rotate_down_action
  67. ])
  68. if privot:
  69. privot = get_node(privot)
  70. else:
  71. privot = null
  72. set_enabled(enabled)
  73. func _input(event):
  74. if(!loaded):
  75. return
  76. if event is InputEventMouseButton:
  77. if(event.button_index==1):
  78. mouse_c=event.pressed
  79. else:
  80. mouse_c=false
  81. if len(trigger_action)!=0:
  82. if event.is_action_pressed(trigger_action):
  83. _triggered=true
  84. elif event.is_action_released(trigger_action):
  85. _triggered=false
  86. else:
  87. _triggered=true
  88. if freelook and _triggered and mouse_c and !is_ui:
  89. if event is InputEventMouseMotion:
  90. _mouse_offset = event.relative
  91. _rotation_offset.x = Input.get_action_strength(rotate_right_action) - Input.get_action_strength(rotate_left_action)
  92. _rotation_offset.y = Input.get_action_strength(rotate_down_action) - Input.get_action_strength(rotate_up_action)
  93. if movement and _triggered and !is_ui:
  94. _direction.x = Input.get_action_strength(right_action) - Input.get_action_strength(left_action)
  95. _direction.y = Input.get_action_strength(up_action) - Input.get_action_strength(down_action)
  96. _direction.z = Input.get_action_strength(backward_action) - Input.get_action_strength(forward_action)
  97. func _process(delta):
  98. if(!loaded):
  99. return
  100. if _triggered:
  101. if privot:
  102. _update_distance()
  103. if freelook:
  104. _update_rotation(delta)
  105. if movement:
  106. _update_movement(delta)
  107. func _physics_process(delta):
  108. if _triggered:
  109. _update_views_physics(delta)
  110. func _update_views_physics(delta):
  111. # Called when collision are enabled
  112. _update_distance()
  113. if freelook:
  114. _update_rotation(delta)
  115. var space_state = get_world().get_direct_space_state()
  116. var obstacle = space_state.intersect_ray(privot.get_translation(), get_translation())
  117. if not obstacle.empty():
  118. set_translation(obstacle.position)
  119. func _update_movement(delta):
  120. var offset = max_speed * acceleration * _direction
  121. _speed.x = clamp(_speed.x + offset.x, -max_speed.x, max_speed.x)
  122. _speed.y = clamp(_speed.y + offset.y, -max_speed.y, max_speed.y)
  123. _speed.z = clamp(_speed.z + offset.z, -max_speed.z, max_speed.z)
  124. # Apply deceleration if no input
  125. if _direction.x == 0:
  126. _speed.x *= (1.0 - deceleration)
  127. if _direction.y == 0:
  128. _speed.y *= (1.0 - deceleration)
  129. if _direction.z == 0:
  130. _speed.z *= (1.0 - deceleration)
  131. if local:
  132. translate(_speed * delta)
  133. else:
  134. global_translate(_speed * delta)
  135. func _update_rotation(delta):
  136. var offset = Vector2();
  137. if not freelook_mode == Freelook_Modes.INPUT_ACTION:
  138. offset += _mouse_offset * sensitivity
  139. if not freelook_mode == Freelook_Modes.MOUSE:
  140. offset += _rotation_offset * sensitivity * ROTATION_MULTIPLIER * delta
  141. _mouse_offset = Vector2()
  142. _yaw = _yaw * smoothness + offset.x * (1.0 - smoothness)
  143. _pitch = _pitch * smoothness + offset.y * (1.0 - smoothness)
  144. if yaw_limit < 360:
  145. _yaw = clamp(_yaw, -yaw_limit - _total_yaw, yaw_limit - _total_yaw)
  146. if pitch_limit < 360:
  147. _pitch = clamp(_pitch, -pitch_limit - _total_pitch, pitch_limit - _total_pitch)
  148. _total_yaw += _yaw
  149. _total_pitch += _pitch
  150. if privot:
  151. var target = privot.get_translation()
  152. var dist = get_translation().distance_to(target)
  153. set_translation(target)
  154. rotate_y(deg2rad(-_yaw))
  155. rotate_object_local(Vector3(1,0,0), deg2rad(-_pitch))
  156. translate(Vector3(0.0, 0.0, dist))
  157. if rotate_privot:
  158. privot.rotate_y(deg2rad(-_yaw))
  159. else:
  160. rotate_y(deg2rad(-_yaw))
  161. rotate_object_local(Vector3(1,0,0), deg2rad(-_pitch))
  162. func _update_distance():
  163. var t = privot.get_translation()
  164. t.z -= distance
  165. set_translation(t)
  166. func _update_process_func():
  167. # Use physics process if collision are enabled
  168. if collisions and privot:
  169. set_physics_process(true)
  170. set_process(false)
  171. else:
  172. set_physics_process(false)
  173. set_process(true)
  174. func _check_actions(actions=[]):
  175. if OS.is_debug_build():
  176. for action in actions:
  177. if not InputMap.has_action(action):
  178. print('WARNING: No action "' + action + '"')
  179. func set_privot(value):
  180. privot = value
  181. _update_process_func()
  182. if len(trigger_action)!=0:
  183. if privot:
  184. _update_distance()
  185. if freelook:
  186. _update_rotation(0)
  187. if movement:
  188. _update_movement(0)
  189. func set_collisions(value):
  190. collisions = value
  191. _update_process_func()
  192. func set_enabled(value):
  193. enabled = value
  194. if enabled:
  195. Input.set_mouse_mode(mouse_mode)
  196. set_process_input(true)
  197. _update_process_func()
  198. else:
  199. set_process(false)
  200. set_process_input(false)
  201. set_physics_process(false)
  202. func set_smoothness(value):
  203. smoothness = clamp(value, 0.001, 0.999)
  204. func set_distance(value):
  205. distance = max(0, value)