godot 4.3 

made this c#


extends Camera3D

@export var pan_speed: float = 20.0
@export var rotation_speed: float = 1.0
@export var zoom_speed: float = 50.0
@export var min_zoom: float = 10.0
@export var max_zoom: float = 100.0
@export var edge_margin: float = 20.0
@export var interpolation_speed: float = 25.0
@export var initial_zoom: float = 10.0  # Initial zoom level

@export var initial_position_offset: Vector3 = Vector3(0, 20, -20)
@export var initial_rotation_degrees: Vector3 = Vector3(-45, 0, 0)  # Initial rotation in degrees

var target_position: Vector3
var target_zoom: float
var current_zoom: float
var start_position: Vector3

@onready var viewport_size: Vector2 = Vector2.ZERO
@onready var player: Node3D = null

func _ready():
	viewport_size = get_viewport().get_visible_rect().size
	
	# Find the player node in the main scene
	player = get_node("/root/Prototype/RTSPlayer")
	
	# Calculate initial position based on player's position
	if player:
		start_position = player.global_transform.origin + initial_position_offset
	else:
		start_position = initial_position_offset  # Default if player not found

	global_transform.origin = start_position
	global_transform.basis = Basis(Vector3(1, 0, 0), deg_to_rad(initial_rotation_degrees.x)) * Basis(Vector3(0, 1, 0), deg_to_rad(initial_rotation_degrees.y)) * Basis(Vector3(0, 0, 1), deg_to_rad(initial_rotation_degrees.z))
	target_position = start_position
	current_zoom = initial_zoom
	target_zoom = initial_zoom

	# Ensure the mouse cursor is visible
	Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)

func _input(event: InputEvent):
	if event is InputEventKey and event.pressed and event.keycode == KEY_R:
		reset_camera()

func _process(delta: float):
	handle_panning(delta)
	handle_edge_panning(delta)
	handle_rotation(delta)
	handle_zoom()
	current_zoom = lerp(current_zoom, target_zoom, interpolation_speed * delta)
	global_transform.origin = global_transform.origin.lerp(target_position, interpolation_speed * delta)
	update_camera_zoom()

func handle_panning(delta: float):
	var adjusted_pan_speed = pan_speed * (current_zoom / max_zoom)  # Adjust pan speed based on current zoom level
	var move_dir = Vector3.ZERO

	if Input.is_action_pressed("pan_left"):
		move_dir.x -= 1
	if Input.is_action_pressed("pan_right"):
		move_dir.x += 1
	if Input.is_action_pressed("pan_up"):
		move_dir.z -= 1  # Pan down
	if Input.is_action_pressed("pan_down"):
		move_dir.z += 1  # Pan up

	move_dir = move_dir.normalized() * adjusted_pan_speed * delta
	var right = global_transform.basis.x
	var forward = global_transform.basis.z  # Forward direction
	target_position += right * move_dir.x
	target_position += forward * move_dir.z

func handle_edge_panning(delta: float):
	var adjusted_pan_speed = pan_speed * (current_zoom / max_zoom)  # Adjust pan speed based on current zoom level
	var mouse_pos = get_viewport().get_mouse_position()
	var move_dir = Vector3.ZERO

	if mouse_pos.x <= edge_margin:
		move_dir.x -= 1
	if mouse_pos.x >= viewport_size.x - edge_margin:
		move_dir.x += 1
	if mouse_pos.y <= edge_margin:
		move_dir.z -= 1  # Pan down
	if mouse_pos.y >= viewport_size.y - edge_margin:
		move_dir.z += 1  # Pan up

	move_dir = move_dir.normalized() * adjusted_pan_speed * delta
	var right = global_transform.basis.x
	var forward = global_transform.basis.z  # Forward direction
	target_position += right * move_dir.x
	target_position += forward * move_dir.z

func handle_rotation(delta: float):
	if Input.is_action_pressed("rotate_camera_left"):
		rotate_y(rotation_speed * delta)
	if Input.is_action_pressed("rotate_camera_right"):
		rotate_y(-rotation_speed * delta)

func handle_zoom():
	if Input.is_action_just_pressed("rts_camera_zoom_in"):
		target_zoom = clamp(target_zoom - zoom_speed * 0.01, min_zoom, max_zoom)
	if Input.is_action_just_pressed("rts_camera_zoom_out"):
		target_zoom = clamp(target_zoom + zoom_speed * 0.01, min_zoom, max_zoom)

func update_camera_zoom():
	global_transform.origin.y = current_zoom

func reset_camera():
	target_position = start_position
	target_zoom = initial_zoom

func move_camera(direction: Vector3):
	target_position += direction

# Add the custom method for ray intersection with a plane
func get_ray_intersection_with_plane(mouse_pos: Vector2, plane: Plane) -> Vector3:
	var ray_origin = project_ray_origin(mouse_pos)
	var ray_normal = project_ray_normal(mouse_pos)
	return plane.intersects_ray(ray_origin, ray_normal)