93 lines
2.6 KiB
GDScript3
93 lines
2.6 KiB
GDScript3
|
|
extends Control
|
||
|
|
|
||
|
|
@export var min_zoom: float = 0.3
|
||
|
|
@export var max_zoom: float = 3.0
|
||
|
|
|
||
|
|
@onready var content: Node2D = $MapContent
|
||
|
|
@onready var open_button: IconButton = get_node("../MapButton")
|
||
|
|
@onready var recenter_button: IconButton = $RecenterButton
|
||
|
|
@onready var close_button: IconButton = $CloseButton
|
||
|
|
@onready var fleet: Node2D = get_node("../../Fleet")
|
||
|
|
|
||
|
|
var touches: Dictionary = {}
|
||
|
|
var pinch_active: bool = false
|
||
|
|
var pinch_start_distance: float = 0.0
|
||
|
|
var pinch_start_zoom: float = 1.0
|
||
|
|
|
||
|
|
|
||
|
|
func _ready() -> void:
|
||
|
|
open_button.pressed.connect(open_map)
|
||
|
|
recenter_button.pressed.connect(recenter_view)
|
||
|
|
close_button.pressed.connect(close_map)
|
||
|
|
|
||
|
|
|
||
|
|
func open_map() -> void:
|
||
|
|
visible = true
|
||
|
|
open_button.visible = false
|
||
|
|
recenter_view()
|
||
|
|
|
||
|
|
|
||
|
|
func close_map() -> void:
|
||
|
|
visible = false
|
||
|
|
open_button.visible = true
|
||
|
|
touches.clear()
|
||
|
|
pinch_active = false
|
||
|
|
|
||
|
|
|
||
|
|
func recenter_view() -> void:
|
||
|
|
var fleet_local: Vector2 = fleet.get_centroid() * content.WORLD_TO_LOCAL
|
||
|
|
var viewport_center: Vector2 = get_viewport_rect().size / 2.0
|
||
|
|
content.position = viewport_center - fleet_local * content.scale.x
|
||
|
|
|
||
|
|
|
||
|
|
func _input(event: InputEvent) -> void:
|
||
|
|
if not visible:
|
||
|
|
return
|
||
|
|
|
||
|
|
if event is InputEventScreenTouch:
|
||
|
|
_handle_touch(event)
|
||
|
|
get_viewport().set_input_as_handled()
|
||
|
|
elif event is InputEventScreenDrag:
|
||
|
|
_handle_drag(event)
|
||
|
|
get_viewport().set_input_as_handled()
|
||
|
|
elif event is InputEventMagnifyGesture:
|
||
|
|
_handle_magnify(event)
|
||
|
|
get_viewport().set_input_as_handled()
|
||
|
|
|
||
|
|
|
||
|
|
func _handle_touch(event: InputEventScreenTouch) -> void:
|
||
|
|
if event.pressed:
|
||
|
|
touches[event.index] = event.position
|
||
|
|
if touches.size() == 2:
|
||
|
|
pinch_active = true
|
||
|
|
var positions: Array = touches.values()
|
||
|
|
pinch_start_distance = positions[0].distance_to(positions[1])
|
||
|
|
pinch_start_zoom = content.scale.x
|
||
|
|
else:
|
||
|
|
touches.erase(event.index)
|
||
|
|
if touches.size() < 2:
|
||
|
|
pinch_active = false
|
||
|
|
|
||
|
|
|
||
|
|
func _handle_drag(event: InputEventScreenDrag) -> void:
|
||
|
|
if not touches.has(event.index):
|
||
|
|
return
|
||
|
|
var previous_pos: Vector2 = touches[event.index]
|
||
|
|
touches[event.index] = event.position
|
||
|
|
|
||
|
|
if pinch_active and touches.size() == 2 and pinch_start_distance > 0.0:
|
||
|
|
var positions: Array = touches.values()
|
||
|
|
var current_distance: float = positions[0].distance_to(positions[1])
|
||
|
|
var new_zoom: float = pinch_start_zoom * (current_distance / max(pinch_start_distance, 1.0))
|
||
|
|
_set_zoom(new_zoom)
|
||
|
|
elif touches.size() == 1:
|
||
|
|
content.position += event.position - previous_pos
|
||
|
|
|
||
|
|
|
||
|
|
func _handle_magnify(event: InputEventMagnifyGesture) -> void:
|
||
|
|
_set_zoom(content.scale.x * event.factor)
|
||
|
|
|
||
|
|
|
||
|
|
func _set_zoom(z: float) -> void:
|
||
|
|
var clamped: float = clamp(z, min_zoom, max_zoom)
|
||
|
|
content.scale = Vector2(clamped, clamped)
|