diff --git a/source/match/IsometricCamera3D.gd b/source/match/IsometricCamera3D.gd index c6d40dcd..f616b457 100644 --- a/source/match/IsometricCamera3D.gd +++ b/source/match/IsometricCamera3D.gd @@ -13,7 +13,7 @@ const EXPECTED_PROJECTION = PROJECTION_ORTHOGONAL @export var movement_speed = 1.1 @export var bounding_planes: Array[Plane] = [] @export_group("Rotation") -@export var mouse_rotation_speed = 0.005 +@export var mouse_rotation_speed = 0.005 # [rad/px] @export var arrowkey_rotation_speed = 2 # [rad/s] @export var default_y_rotation_degrees = 0.0 @export var reference_plane_for_rotation = Plane(Vector3.UP, 0.0) @@ -21,9 +21,8 @@ const EXPECTED_PROJECTION = PROJECTION_ORTHOGONAL @export var visible_height_min = -10 @export var visible_height_max = 10 -var _pivot_point_2d = null -var _pivot_point_3d = null -var _camera_point_3d = null +var _mouse_pos_when_rotation_started = null +var _camera_global_pos_when_rotation_started = null func _ready(): @@ -79,8 +78,10 @@ func _try_handling_movement(delta: float) -> bool: * Vector2(movement_speed, movement_speed * 2.0) * size ) - var camera_move_vector = Vector3(scaled_screen_move_vector.x, 0, scaled_screen_move_vector.y) - camera_move_vector = camera_move_vector.rotated(Vector3(0, 1, 0), rotation.y) + var camera_move_vector = ( + Vector3(scaled_screen_move_vector.x, 0, scaled_screen_move_vector.y) + . rotated(Vector3(0, 1, 0), rotation.y) + ) global_translate(camera_move_vector) _align_position_to_bounding_planes() return true @@ -135,7 +136,7 @@ func _try_handling_arrowkey_rotation(delta: float): * arrowkey_rotation_speed ) if not is_zero_approx(angle_radians): - _rotate_by(angle_radians) + _rotate_from_reference_position_by(global_position, angle_radians) func _try_handling_mouse_rotation(event: InputEvent): @@ -146,19 +147,21 @@ func _try_handling_mouse_rotation(event: InputEvent): _start_rotation(event) elif not event.is_pressed() and event.button_index == MOUSE_BUTTON_MIDDLE: _stop_rotation() - elif event is InputEventMouseMotion: + elif event is InputEventMouseMotion and _is_rotating(): var mouse_pos = event.position - if _is_rotating(): - _rotate(mouse_pos) + var angle_radians = ( + (mouse_pos.x - _mouse_pos_when_rotation_started.x) * mouse_rotation_speed + ) + _rotate_from_reference_position_by(_camera_global_pos_when_rotation_started, angle_radians) func _reset_rotation(): - var pivot_point_3d = _calculate_pivot_point_3d() - if pivot_point_3d == null: + var pivot_point = _calculate_pivot_point() + if pivot_point == null: return var camera_point_3d = global_transform.origin var camera_point_2d = Vector2(camera_point_3d.x, camera_point_3d.z) - var pivot_point_2d = Vector2(pivot_point_3d.x, pivot_point_3d.z) + var pivot_point_2d = Vector2(pivot_point.x, pivot_point.z) var pivot_to_camera_distance_2d = camera_point_2d.distance_to(pivot_point_2d) var new_camera_point_2d = ( pivot_point_2d @@ -170,54 +173,38 @@ func _reset_rotation(): global_transform.origin = Vector3( new_camera_point_2d.x, camera_point_3d.y, new_camera_point_2d.y ) - global_transform = global_transform.looking_at(pivot_point_3d, Vector3(0, 1, 0)) + global_transform = global_transform.looking_at(pivot_point, Vector3(0, 1, 0)) func _start_rotation(event: InputEvent): - _pivot_point_3d = _calculate_pivot_point_3d() - if _pivot_point_3d != null: - _pivot_point_2d = event.position - _camera_point_3d = global_transform.origin + _mouse_pos_when_rotation_started = event.position + _camera_global_pos_when_rotation_started = global_transform.origin func _stop_rotation(): - _pivot_point_2d = null - - -func _rotate(mouse_pos: Vector2): - var strength = mouse_pos.x - _pivot_point_2d.x - var camera_point_2d = Vector2(_camera_point_3d.x, _camera_point_3d.z) - var pivot_point_2d = Vector2(_pivot_point_3d.x, _pivot_point_3d.z) - var diff_vec = camera_point_2d - pivot_point_2d - var rotated_diff_vec = diff_vec.rotated(strength * mouse_rotation_speed) - var new_camera_point_2d = pivot_point_2d + rotated_diff_vec - global_transform.origin = Vector3( - new_camera_point_2d.x, _camera_point_3d.y, new_camera_point_2d.y - ) - global_transform = global_transform.looking_at(_pivot_point_3d, Vector3(0, 1, 0)) + _mouse_pos_when_rotation_started = null -func _rotate_by(angle_radians: float): - var pivot_point_3d = _calculate_pivot_point_3d() - if pivot_point_3d == null: +func _rotate_from_reference_position_by(reference_position: Vector3, angle_radians: float): + var pivot_point = _calculate_pivot_point() + if pivot_point == null: return - var camera_point_3d = global_transform.origin - var camera_point_2d = Vector2(camera_point_3d.x, camera_point_3d.z) - var pivot_point_2d = Vector2(pivot_point_3d.x, pivot_point_3d.z) - var diff_vec = camera_point_2d - pivot_point_2d - var rotated_diff_vec = diff_vec.rotated(angle_radians) - var new_camera_point_2d = pivot_point_2d + rotated_diff_vec - global_transform.origin = Vector3( - new_camera_point_2d.x, camera_point_3d.y, new_camera_point_2d.y + + var diff_vec_yless = reference_position * Vector3(1, 0, 1) - pivot_point * Vector3(1, 0, 1) + var rotated_diff_vec_yless = diff_vec_yless.rotated(-Vector3.UP, angle_radians) + var rotated_reference_position = ( + pivot_point + + Vector3(rotated_diff_vec_yless.x, reference_position.y, rotated_diff_vec_yless.z) ) - global_transform = global_transform.looking_at(pivot_point_3d, Vector3(0, 1, 0)) + global_position = rotated_reference_position + global_transform = global_transform.looking_at(pivot_point, Vector3.UP) func _is_rotating() -> bool: - return _pivot_point_2d != null + return _mouse_pos_when_rotation_started != null -func _calculate_pivot_point_3d() -> Vector3: +func _calculate_pivot_point() -> Vector3: var screen_center_pos_2d = get_viewport().size / 2.0 return get_ray_intersection_with_plane(screen_center_pos_2d, reference_plane_for_rotation) @@ -261,7 +248,7 @@ func _align_camera_far_to_size(a_size: float): func _align_position_to_bounding_planes(): - var pivot_point = _calculate_pivot_point_3d() + var pivot_point = _calculate_pivot_point() var aligned_pivot_point = _clamp_position_to_bounding_planes(pivot_point) var diff = aligned_pivot_point - pivot_point global_transform.origin += diff