Skip to content

Commit cf6ba1f

Browse files
committed
Move viewport camera to the subviewport container
1 parent 521254b commit cf6ba1f

7 files changed

Lines changed: 148 additions & 143 deletions

File tree

src/ui_parts/display.tscn

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
[ext_resource type="PackedScene" uid="uid://oltvrf01xrxl" path="res://src/ui_widgets/zoom_menu.tscn" id="8_xtdmn"]
1010
[ext_resource type="Script" uid="uid://b6pmlbnl76wmm" path="res://src/ui_parts/viewport.gd" id="9_4xrk7"]
1111
[ext_resource type="Script" uid="uid://rqrxhe8wa6fn" path="res://src/ui_parts/tab_bar.gd" id="9_rll1m"]
12+
[ext_resource type="Script" uid="uid://cbajqkgudfvh0" path="res://src/ui_parts/viewport_container.gd" id="9_ryr8t"]
1213
[ext_resource type="Shader" uid="uid://i2y5pyhcgra2" path="res://src/shaders/zoom_shader.gdshader" id="10_x7ybk"]
1314
[ext_resource type="Texture2D" uid="uid://c68og6bsqt0lb" path="res://assets/icons/backgrounds/Checkerboard.svg" id="11_1bm1s"]
1415
[ext_resource type="Script" uid="uid://dtplje5mhdmrj" path="res://src/ui_parts/display_texture.gd" id="12_qi23s"]
1516
[ext_resource type="Script" uid="uid://csqewpxr21ywy" path="res://src/ui_parts/handles_manager.gd" id="13_lwhwy"]
16-
[ext_resource type="Script" uid="uid://cm5033meho5vr" path="res://src/ui_widgets/camera.gd" id="15_hevpa"]
1717

1818
[sub_resource type="ShaderMaterial" id="ShaderMaterial_kqplg"]
1919
shader = ExtResource("10_x7ybk")
@@ -101,10 +101,12 @@ unique_name_in_owner = true
101101
layout_mode = 2
102102

103103
[node name="ViewportContainer" type="SubViewportContainer" parent="ViewportPanel/VBoxContainer"]
104+
clip_contents = true
104105
custom_minimum_size = Vector2(450, 0)
105106
layout_mode = 2
106107
size_flags_vertical = 3
107108
stretch = true
109+
script = ExtResource("9_ryr8t")
108110

109111
[node name="Viewport" type="SubViewport" parent="ViewportPanel/VBoxContainer/ViewportContainer"]
110112
unique_name_in_owner = true
@@ -148,12 +150,6 @@ anchors_preset = 0
148150
mouse_filter = 1
149151
script = ExtResource("13_lwhwy")
150152

151-
[node name="Camera" type="Control" parent="ViewportPanel/VBoxContainer/ViewportContainer/Viewport"]
152-
layout_mode = 3
153-
anchors_preset = 0
154-
mouse_filter = 2
155-
script = ExtResource("15_hevpa")
156-
157153
[node name="DebugMargins" type="MarginContainer" parent="ViewportPanel"]
158154
visible = false
159155
layout_mode = 2

src/ui_parts/handles_manager.gd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ func _unhandled_input(event: InputEvent) -> void:
798798
event.button_mask == 0) or (event is InputEventMouseButton and\
799799
(event.button_index in [MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT]))):
800800
var nearest_handle := find_nearest_handle(event.position / State.zoom +\
801-
get_parent().view.position)
801+
get_parent().get_parent().camera_position)
802802
if is_instance_valid(nearest_handle):
803803
hovered_handle = nearest_handle
804804
if hovered_handle is PathHandle:
@@ -910,7 +910,7 @@ func find_nearest_handle(event_pos: Vector2) -> Handle:
910910

911911
# Two 64-bit coordinates instead of a Vector2.
912912
func get_event_pos(event: InputEvent) -> PackedFloat64Array:
913-
return apply_snap(event.position / State.zoom + get_parent().view.position)
913+
return apply_snap(event.position / State.zoom + get_parent().get_parent().camera_position)
914914

915915
func apply_snap(pos: Vector2) -> PackedFloat64Array:
916916
var precision_snap := 0.1 ** maxi(ceili(-log(1.0 / State.zoom) / log(10)), 0)

src/ui_parts/viewport.gd

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
extends SubViewport
22

33
const ZoomMenu = preload("res://src/ui_widgets/zoom_menu.gd")
4-
const Camera = preload("res://src/ui_widgets/camera.gd")
54
const HandlesManager = preload("res://src/ui_parts/handles_manager.gd")
65
const DisplayTexture = preload("res://src/ui_parts/display_texture.gd")
76

@@ -17,7 +16,7 @@ var limit_top := 0.0
1716
var limit_bottom := 0.0
1817

1918
@onready var display: TextureRect = $Checkerboard
20-
@onready var view: Camera = $Camera
19+
@onready var view: SubViewportContainer = get_parent()
2120
@onready var controls: HandlesManager = $Controls
2221
@onready var display_texture: DisplayTexture = $Checkerboard/DisplayTexture
2322
@onready var reference_texture: TextureRect = $ReferenceTexture
@@ -36,14 +35,14 @@ func _ready() -> void:
3635
# Top left corner.
3736
func set_view(new_position: Vector2) -> void:
3837
var scaled_size := size / State.zoom
39-
view.unsnapped_position = new_position.clamp(Vector2(limit_left, limit_top),
38+
view.camera_unsnapped_position = new_position.clamp(Vector2(limit_left, limit_top),
4039
Vector2(limit_right, limit_bottom) - scaled_size)
4140

42-
var stripped_left := maxf(view.unsnapped_position.x, 0.0)
43-
var stripped_top := maxf(view.unsnapped_position.y, 0.0)
44-
var stripped_right := minf(view.unsnapped_position.x + scaled_size.x,
41+
var stripped_left := maxf(view.camera_unsnapped_position.x, 0.0)
42+
var stripped_top := maxf(view.camera_unsnapped_position.y, 0.0)
43+
var stripped_right := minf(view.camera_unsnapped_position.x + scaled_size.x,
4544
State.root_element.width)
46-
var stripped_bottom := minf(view.unsnapped_position.y + scaled_size.y,
45+
var stripped_bottom := minf(view.camera_unsnapped_position.y + scaled_size.y,
4746
State.root_element.height)
4847
display_texture.view_rect = Rect2(stripped_left, stripped_top,
4948
stripped_right - stripped_left, stripped_bottom - stripped_top)
@@ -87,7 +86,7 @@ func _unhandled_input(event: InputEvent) -> void:
8786
# Panning with LMB or MMB. This gives a reliable way to adjust the view
8887
# without dragging the things on it.
8988
else:
90-
set_view(view.unsnapped_position - (wrap_mouse(event.relative) if\
89+
set_view(view.camera_unsnapped_position - (wrap_mouse(event.relative) if\
9190
Configs.savedata.wraparound_panning else event.relative) / State.zoom)
9291

9392
elif event is InputEventPanGesture and not DisplayServer.get_name() == "Android":
@@ -96,7 +95,7 @@ func _unhandled_input(event: InputEvent) -> void:
9695
zoom_menu.set_zoom(State.zoom * (1 + event.delta.y / 2))
9796
# Panning with touch.
9897
else:
99-
set_view(view.unsnapped_position + event.delta * 32 / State.zoom)
98+
set_view(view.camera_unsnapped_position + event.delta * 32 / State.zoom)
10099
# Zooming with touch.
101100
elif event is InputEventMagnifyGesture:
102101
zoom_menu.set_zoom(State.zoom * event.factor)
@@ -142,7 +141,7 @@ func _unhandled_input(event: InputEvent) -> void:
142141
elif zoom_dir == -1:
143142
zoom_menu.zoom_out(factor, mouse_offset)
144143

145-
set_view(view.unsnapped_position + move_vec * factor / State.zoom * 32)
144+
set_view(view.camera_unsnapped_position + move_vec * factor / State.zoom * 32)
146145

147146
else:
148147
if not event.is_echo():
@@ -174,9 +173,9 @@ func adjust_view(offset := Vector2(0.5, 0.5)) -> void:
174173
limit_top = -zoomed_size.y
175174
limit_bottom = zoomed_size.y + svg_h
176175

177-
set_view(Vector2(lerpf(view.unsnapped_position.x, view.unsnapped_position.x +\
178-
old_size.x - size.x / State.zoom, offset.x), lerpf(view.unsnapped_position.y,
179-
view.unsnapped_position.y + old_size.y - size.y / State.zoom, offset.y)))
176+
set_view(Vector2(lerpf(view.camera_unsnapped_position.x, view.camera_unsnapped_position.x +\
177+
old_size.x - size.x / State.zoom, offset.x), lerpf(view.camera_unsnapped_position.y,
178+
view.camera_unsnapped_position.y + old_size.y - size.y / State.zoom, offset.y)))
180179

181180
func _on_size_changed() -> void:
182181
State.set_viewport_size(size)

src/ui_parts/viewport_container.gd

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
extends SubViewportContainer
2+
3+
const TICKS_INTERVAL = 4
4+
const TICK_DISTANCE = float(TICKS_INTERVAL)
5+
6+
var ci := get_canvas_item()
7+
var grid_ci := RenderingServer.canvas_item_create()
8+
var grid_numbers_ci := RenderingServer.canvas_item_create()
9+
10+
var camera_zoom: float
11+
var camera_position: Vector2
12+
var camera_unsnapped_position: Vector2
13+
14+
15+
func _ready() -> void:
16+
Configs.grid_color_changed.connect(queue_redraw)
17+
State.show_grid_changed.connect(update_show_grid)
18+
update_show_grid()
19+
RenderingServer.canvas_item_set_parent(grid_ci, ci)
20+
RenderingServer.canvas_item_set_parent(grid_numbers_ci, ci)
21+
State.svg_resized.connect(queue_redraw)
22+
State.zoom_changed.connect(change_zoom)
23+
State.zoom_changed.connect(queue_redraw)
24+
25+
func exit_tree() -> void:
26+
RenderingServer.free_rid(grid_numbers_ci)
27+
28+
func change_zoom() -> void:
29+
camera_zoom = State.zoom
30+
31+
func update_show_grid() -> void:
32+
RenderingServer.canvas_item_set_visible(grid_ci, State.show_grid)
33+
RenderingServer.canvas_item_set_visible(grid_numbers_ci, State.show_grid)
34+
35+
36+
func update() -> void:
37+
var new_position := camera_unsnapped_position.snapped(Vector2(1, 1) / camera_zoom)
38+
if camera_position != new_position:
39+
camera_position = new_position
40+
State.view_changed.emit()
41+
42+
get_child(0).canvas_transform = Transform2D(0.0, Vector2(camera_zoom, camera_zoom),
43+
0.0, -camera_position * camera_zoom)
44+
queue_redraw()
45+
46+
47+
# Don't ask me to explain this.
48+
func _draw() -> void:
49+
RenderingServer.canvas_item_clear(grid_ci)
50+
RenderingServer.canvas_item_clear(grid_numbers_ci)
51+
52+
var axis_line_color := Color(Configs.savedata.grid_color, 0.75)
53+
var major_grid_color := Color(Configs.savedata.grid_color, 0.35)
54+
var minor_grid_color := Color(Configs.savedata.grid_color, 0.15)
55+
56+
var grid_size := Vector2(State.viewport_size) / camera_zoom
57+
RenderingServer.canvas_item_add_line(grid_ci, Vector2(-camera_position.x * camera_zoom, 0),
58+
Vector2(-camera_position.x * camera_zoom, grid_size.y * camera_zoom), axis_line_color)
59+
RenderingServer.canvas_item_add_line(grid_ci, Vector2(0, -camera_position.y * camera_zoom),
60+
Vector2(grid_size.x * camera_zoom, -camera_position.y * camera_zoom), axis_line_color)
61+
62+
var major_points := PackedVector2Array()
63+
var minor_points := PackedVector2Array()
64+
var draw_minor_lines := (camera_zoom >= 8.0)
65+
var mark_pixel_lines := (camera_zoom >= 128.0)
66+
@warning_ignore("integer_division")
67+
var rate := nearest_po2(roundi(maxf(128.0 / (TICKS_INTERVAL * camera_zoom), 2.0))) / 2
68+
69+
var i := fmod(-camera_position.x, 1.0)
70+
var major_line_h_offset := fposmod(-camera_position.x, TICK_DISTANCE)
71+
# Horizontal offset.
72+
while i <= grid_size.x:
73+
if major_line_h_offset != fposmod(i, TICK_DISTANCE):
74+
if draw_minor_lines:
75+
minor_points.append(Vector2(i * camera_zoom, 0))
76+
minor_points.append(Vector2(i * camera_zoom, grid_size.y * camera_zoom))
77+
if mark_pixel_lines:
78+
ThemeUtils.regular_font.draw_string(grid_numbers_ci,
79+
Vector2(i * camera_zoom + 4, 14), String.num_int64(floori(i + camera_position.x)),
80+
HORIZONTAL_ALIGNMENT_LEFT, -1, 14, axis_line_color)
81+
else:
82+
var coord := snappedi(i + camera_position.x, TICKS_INTERVAL)
83+
if int(coord / TICK_DISTANCE) % rate == 0:
84+
major_points.append(Vector2(i * camera_zoom, 0))
85+
major_points.append(Vector2(i * camera_zoom, grid_size.y * camera_zoom))
86+
ThemeUtils.regular_font.draw_string(grid_numbers_ci,
87+
Vector2(i * camera_zoom + 4, 14), String.num_int64(coord),
88+
HORIZONTAL_ALIGNMENT_LEFT, -1, 14, axis_line_color)
89+
elif coord % rate == 0:
90+
minor_points.append(Vector2(i * camera_zoom, 0))
91+
minor_points.append(Vector2(i * camera_zoom, grid_size.y * camera_zoom))
92+
i += 1.0
93+
94+
i = fmod(-camera_position.y, 1.0)
95+
var major_line_v_offset := fposmod(-camera_position.y, TICK_DISTANCE)
96+
# Vertical offset.
97+
while i < grid_size.y:
98+
if major_line_v_offset != fposmod(i, TICK_DISTANCE):
99+
if draw_minor_lines:
100+
minor_points.append(Vector2(0, i * camera_zoom))
101+
minor_points.append(Vector2(grid_size.x * camera_zoom, i * camera_zoom))
102+
if mark_pixel_lines:
103+
ThemeUtils.regular_font.draw_string(grid_numbers_ci,
104+
Vector2(4, i * camera_zoom + 14), String.num_int64(floori(i + camera_position.y)),
105+
HORIZONTAL_ALIGNMENT_LEFT, -1, 14, axis_line_color)
106+
else:
107+
var coord := snappedi(i + camera_position.y, TICKS_INTERVAL)
108+
if int(coord / TICK_DISTANCE) % rate == 0:
109+
major_points.append(Vector2(0, i * camera_zoom))
110+
major_points.append(Vector2(grid_size.x * camera_zoom, i * camera_zoom))
111+
ThemeUtils.regular_font.draw_string(grid_numbers_ci,
112+
Vector2(4, i * camera_zoom + 14), String.num_int64(coord),
113+
HORIZONTAL_ALIGNMENT_LEFT, -1, 14, axis_line_color)
114+
elif coord % rate == 0:
115+
minor_points.append(Vector2(0, i * camera_zoom))
116+
minor_points.append(Vector2(grid_size.x * camera_zoom, i * camera_zoom))
117+
i += 1.0
118+
119+
if not major_points.is_empty():
120+
var pca := PackedColorArray()
121+
@warning_ignore("integer_division")
122+
pca.resize(major_points.size() / 2)
123+
pca.fill(major_grid_color)
124+
RenderingServer.canvas_item_add_multiline(grid_ci, major_points, pca)
125+
if not minor_points.is_empty():
126+
var pca := PackedColorArray()
127+
@warning_ignore("integer_division")
128+
pca.resize(minor_points.size() / 2)
129+
pca.fill(minor_grid_color)
130+
RenderingServer.canvas_item_add_multiline(grid_ci, minor_points, pca)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
uid://cbajqkgudfvh0

src/ui_widgets/camera.gd

Lines changed: 0 additions & 120 deletions
This file was deleted.

src/ui_widgets/camera.gd.uid

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)