1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
class_name Camera
extends Camera2D
signal zoomed(zoom: Vector2)
var is_in_drag_mode := false
var drag_anchor := Vector2.ZERO
var is_in_edge_mode := false
var edge := Vector2.ZERO
@export var edge_scroll_margin := 4.0
@export var speed := 25
@export_group("Zoom", "zoom")
@export var zoom_min: float = 0.5
@export var zoom_max: float = 3
@export var zoom_step: float = 0.01
func _ready():
get_viewport().size_changed.connect(func():
set_new_position(global_position)
var new_zoom = Vector2(
(limit_right - limit_left) / get_viewport_rect().size.x,
(limit_bottom - limit_top) / get_viewport_rect().size.y
)
zoom = Vector2(
new_zoom[new_zoom.max_axis_index()],
new_zoom[new_zoom.max_axis_index()]
)
zoomed.emit(zoom)
)
Input.mouse_mode = Input.MOUSE_MODE_CONFINED
func _input(event):
if event.is_action("camera_zoom_out"):
var can_zoom_out = (
(limit_right - limit_left) / get_rect().size.x > 1.0 and
(limit_bottom - limit_top) / get_rect().size.y > 1.0
)
if can_zoom_out:
var new_zoom = max(zoom.x - zoom_step, zoom_min)
zoom = Vector2(new_zoom, new_zoom)
zoomed.emit(zoom)
if event.is_action("camera_zoom_in"):
var new_zoom = min(zoom.x + zoom_step, zoom_max)
zoom = Vector2(new_zoom, new_zoom)
zoomed.emit(zoom)
if event.is_action_pressed("camera_drag"):
is_in_drag_mode = true
drag_anchor = get_global_mouse_position()
Input.set_default_cursor_shape(Input.CURSOR_MOVE)
elif event.is_action_released("camera_drag"):
is_in_drag_mode = false
Input.set_default_cursor_shape(Input.CURSOR_ARROW)
if event is InputEventMouseMotion:
is_in_edge_mode = false
edge = Vector2.ZERO
if get_global_mouse_position().x - edge_scroll_margin <= get_rect().position.x:
is_in_edge_mode = true
edge += Vector2.LEFT
if get_global_mouse_position().y - edge_scroll_margin <= get_rect().position.y:
is_in_edge_mode = true
edge += Vector2.UP
if get_global_mouse_position().x + edge_scroll_margin >= get_rect().end.x:
is_in_edge_mode = true
edge += Vector2.RIGHT
if get_global_mouse_position().y + edge_scroll_margin >= get_rect().end.y:
is_in_edge_mode = true
edge += Vector2.DOWN
edge = edge.normalized()
if event is InputEventMouseButton and event.is_pressed():
Input.mouse_mode = Input.MOUSE_MODE_CONFINED
elif event.is_action_pressed("mouse_escape"):
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
func _process(delta):
if is_in_drag_mode:
set_new_position(global_position + drag_anchor - get_global_mouse_position())
if is_in_edge_mode:
set_new_position(
lerp(
global_position,
global_position + (edge * speed),
speed * delta
)
)
var direction_h = Input.get_axis("ui_left", "ui_right")
var direction_v = Input.get_axis("ui_up", "ui_down")
if direction_h != 0 or direction_v != 0:
set_new_position(
lerp(
global_position,
global_position + Vector2(direction_h * speed, direction_v * speed),
speed * delta
)
)
func set_new_position(new_position: Vector2):
new_position.x = clamp(
new_position.x,
limit_left,
limit_right - get_rect().size.x
)
new_position.y = clamp(
new_position.y,
limit_top,
limit_bottom - get_rect().size.y
)
global_position = new_position
func set_center(center_position: Vector2):
set_new_position(
center_position - (get_rect().size / 2)
)
func get_rect():
var viewport = get_viewport_rect()
return Rect2(
global_position,
viewport.size * Vector2(1 / zoom.x, 1 / zoom.y)
)
|