89 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			GDScript
		
	
	
	
	
	
			
		
		
	
	
			89 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			GDScript
		
	
	
	
	
	
| extends CanvasLayer
 | |
| 
 | |
| @export var side_change_speed: float = 15
 | |
| @export var screen_inset: float = 100
 | |
| 
 | |
| var _cursor_scene := preload("res://scenes/ui/cursor_base.tscn")
 | |
| 
 | |
| var _cursors: Dictionary
 | |
| 
 | |
| @onready var _single_cursor: Control = $CursorBase
 | |
| 
 | |
| 
 | |
| func _ready() -> void:
 | |
| 	Input.mouse_mode = Input.MOUSE_MODE_HIDDEN
 | |
| 
 | |
| 
 | |
| func _process(delta: float) -> void:
 | |
| 	if not Referencer.players or not Referencer.main_camera:
 | |
| 		var mouse_pos := get_viewport().get_mouse_position()
 | |
| 		_single_cursor.position = mouse_pos - _single_cursor.size / 2
 | |
| 		_single_cursor.visible = true
 | |
| 		return
 | |
| 	_single_cursor.visible = false
 | |
| 
 | |
| 	call_deferred("_handle_cursors", delta)
 | |
| 
 | |
| 
 | |
| func _handle_cursors(delta: float) -> void:
 | |
| 	for player_index in range(Referencer.players_count):
 | |
| 		_handle_cursor(player_index, delta)
 | |
| 
 | |
| 
 | |
| func _init_player_cursor(id: int) -> void:
 | |
| 	var cursor_node: Control = _cursor_scene.instantiate() as Control
 | |
| 	add_child(cursor_node)
 | |
| 	_cursors[id] = {
 | |
| 		"base": cursor_node,
 | |
| 		"bat": cursor_node.get_node("CursorBat"),
 | |
| 		"arrow": cursor_node.get_node("CursorArrow"),
 | |
| 		"side": 0
 | |
| 	}
 | |
| 
 | |
| 
 | |
| func _handle_cursor(player_index: int, delta: float) -> void:
 | |
| 	var player := Referencer.players[player_index]
 | |
| 	var id := player.get_instance_id()
 | |
| 
 | |
| 	if not _cursors.has(id):
 | |
| 		_init_player_cursor(id)
 | |
| 		return
 | |
| 
 | |
| 	var cursor_pos_world := player.attack.global_position + player.aiming.aim_offset
 | |
| 	var cursor_pos_screen := Referencer.main_camera.unproject_position(cursor_pos_world)
 | |
| 
 | |
| 	var clamp_corner_min := Vector2.ZERO
 | |
| 	var clamp_corner_max := get_viewport().get_visible_rect().size
 | |
| 	if player.input_mode_is(Inputer.Mode.CONTROLLER):
 | |
| 		clamp_corner_min += Vector2(screen_inset, screen_inset)
 | |
| 		clamp_corner_max -= Vector2(screen_inset, screen_inset)
 | |
| 
 | |
| 	var cursor: Dictionary = _cursors[id]
 | |
| 
 | |
| 	cursor["base"].position = (
 | |
| 		cursor_pos_screen.clamp(clamp_corner_min, clamp_corner_max)
 | |
| 		- cursor["base"].size / 2
 | |
| 	)
 | |
| 
 | |
| 	cursor["side"] = lerpf(
 | |
| 		cursor["side"] as float,
 | |
| 		(PI / 2.0) * (1.0 if player.attack.side == PlayerAttack.Side.LEFT else -1.0),
 | |
| 		side_change_speed * delta
 | |
| 	)
 | |
| 
 | |
| 	var aim_offset_normalized := player.aiming.aim_offset.normalized()
 | |
| 	var bat_rotation_point_screen := Referencer.main_camera.unproject_position(
 | |
| 		(
 | |
| 			cursor_pos_world
 | |
| 			+ aim_offset_normalized.rotated(Vector3.UP, cursor["side"] as float)
 | |
| 		)
 | |
| 	)
 | |
| 	var arrow_rotation_point_screen := Referencer.main_camera.unproject_position(
 | |
| 		cursor_pos_world + aim_offset_normalized
 | |
| 	)
 | |
| 
 | |
| 	cursor["bat"].rotation = cursor_pos_screen.angle_to_point(bat_rotation_point_screen)
 | |
| 	cursor["arrow"].rotation = cursor_pos_screen.angle_to_point(
 | |
| 		arrow_rotation_point_screen
 | |
| 	)
 |