From 0dc8e69785a383b2268b6a06954c25b7188af7de Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 3 Jun 2025 13:01:27 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/tilemap/tilemap.gd | 104 ++++++++++++++------------------------ 1 file changed, 39 insertions(+), 65 deletions(-) diff --git a/scenes/tilemap/tilemap.gd b/scenes/tilemap/tilemap.gd index 93d5aac4..6c15e782 100644 --- a/scenes/tilemap/tilemap.gd +++ b/scenes/tilemap/tilemap.gd @@ -142,16 +142,12 @@ func _on_resize() -> void: ## Создаёт новую отметку из координат экрана -func add_mark_from_screen_pos(id: int, x: float, y: float, mark: Node) -> bool: +func add_mark_from_screen_pos(id: int, scr_xy: Vector2, mark: Node) -> bool: if _marks.has(id): return false - var wrld_pos = screen_to_world(_xyz, x, y) - var p = world_to_tile(wrld_pos.x, wrld_pos.y, _xyz.z) - var tile_index = xyz_to_idx(p.x, p.y, _xyz.z) - var dot = { 'position': wrld_pos, 'tile_index': tile_index, 'mark': mark } - _marks[id] = dot + var wrld_pos = screen_to_world(_xyz, scr_xy) + _marks[id] = { 'position': wrld_pos, 'mark': mark, 'gap_size': 0.0 } add_child(mark) - fix_mark_position(dot) return true @@ -169,9 +165,7 @@ func add_mark_from_lon_lat(id: int, lon: float, lat: float, mark: Node, gap_size if _marks.has(id): return false var wrld_pos = lonlat_to_world(lon, lat) - var scr_pos = world_to_screen(wrld_pos.x, wrld_pos.y) - mark.set_global_position(scr_pos) - _marks[id] = {'position': wrld_pos, 'mark': mark, 'gap_size': gap_size } + _marks[id] = {'position': wrld_pos, 'mark': mark, 'gap_size': gap_size} add_child(mark) queue_redraw() return true @@ -189,7 +183,7 @@ func fix_mark_position(dot) -> void: func is_mark_visible(dot) -> bool: - var screen_pos = world_to_screen(dot.position.x, dot.position.y) + var screen_pos = world_to_screen(dot.position) return screen_pos.x > 0 and screen_pos.x < $canvas.size.x @@ -208,11 +202,11 @@ func _input(e) -> void: queue_redraw() if e.button_index == MOUSE_BUTTON_LEFT: _dragging = e.pressed - _drag_pos = screen_to_world(_xyz, lmp.x, lmp.y) + _drag_pos = screen_to_world(_xyz, lmp) elif e is InputEventMouseMotion: if _dragging: - var wp = screen_to_world(_xyz, lmp.x, lmp.y) + var wp = screen_to_world(_xyz, lmp) var diff = _drag_pos - wp _xyz.x += diff.x @@ -231,40 +225,34 @@ func _input(e) -> void: signaller.emmit(signaller.map_user_panning) -## Возвращает true, если видна область за краем карты -func is_border_visible(): - var z = min(max_zoom_level, _xyz.z) - return screen_to_tile(0, 0, z).y != 0 - - func multiply_zoom(multiplier: float, pivot: Vector2) -> void: - var p1: = screen_to_world(_xyz, pivot.x, pivot.y) + var p1: = screen_to_world(_xyz, pivot) _xyz.z = clampf(_xyz.z * multiplier, min_zoom_level, max_zoom_level) - var p2: = screen_to_world(_xyz, pivot.x, pivot.y) + var p2: = screen_to_world(_xyz, pivot) _xyz.x -= p2.x - p1.x _xyz.y -= p2.y - p1.y func increment_zoom(increment: float, pivot: Vector2) -> void: - var p1: = screen_to_world(_xyz, pivot.x, pivot.y) + var p1: = screen_to_world(_xyz, pivot) _xyz.z = clampf(_xyz.z + increment, min_zoom_level, max_zoom_level) - var p2: = screen_to_world(_xyz, pivot.x, pivot.y) + var p2: = screen_to_world(_xyz, pivot) _xyz.x -= p2.x - p1.x _xyz.y -= p2.y - p1.y func set_zoom(zoom: float, pivot: Vector2) -> void: - var p1: = screen_to_world(_xyz, pivot.x, pivot.y) + var p1: = screen_to_world(_xyz, pivot) _xyz.z = clampf(zoom, max_zoom_level, min_zoom_level) - var p2: = screen_to_world(_xyz, pivot.x, pivot.y) + var p2: = screen_to_world(_xyz, pivot) _xyz.x -= p2.x - p1.x _xyz.y -= p2.y - p1.y func _draw() -> void: var z = min(max_zoom_level, _xyz.z) - var t1 = screen_to_tile(0, 0, z) - var t2 = screen_to_tile($canvas.size.x, $canvas.size.y, z) + Vector2(1, 1) + var t1 = screen_to_tile(Vector2(0, 0), z) + var t2 = screen_to_tile($canvas.size, z) + Vector2(1, 1) is_out_border1 = true is_out_border2 = true for tx in range(t1.x, t2.x): @@ -272,29 +260,21 @@ func _draw() -> void: _draw_tile(tx, ty, z) var n = pow(2, z) var dx = n * tile_width - var c = $canvas.size / 2.0 - var r = min($canvas.size.x, $canvas.size.y) / 2.0 + var c: Vector2 = $canvas.size / 2.0 + var r = c.length() visible_marks_count = 0 for dot in _marks.values(): - var pos = world_to_screen(dot.position.x, dot.position.y) - if pos.x >= 0: - pos.x = fmod(pos.x, dx) - else: - pos.x = -pos.x - 1 - pos.x = int(dx - 1) - fmod(pos.x, dx) - dot.mark.position = pos - dot.mark.visible = c.distance_to(pos) < (r - dot.gap_size) + var scr_pos = world_to_screen(dot.position) + scr_pos.x = posmod(scr_pos.x, dx) + dot.mark.position = scr_pos + dot.mark.visible = c.distance_to(scr_pos) < (r - dot.gap_size) visible_marks_count += int(dot.mark.visible) func _clean_all() -> void: _queue.clear() _cache.clear() - _marks.clear() _req_count = 0 - for c in get_children().filter(func (item): return not item.is_in_group('gui_items')): - remove_child(c) - c.queue_free() # get the tile from queue with the newest timestamp @@ -449,7 +429,7 @@ func lonlat_to_world(lon: float, lat: float) -> Vector2: ## convert lon/lat to screen coords func lonlat_to_screen(lon: float, lat: float) -> Vector2: var w = lonlat_to_world(lon, lat) - return world_to_screen(w.x, w.y) + return world_to_screen(w) ## convert lon/lat to tile coords @@ -466,8 +446,8 @@ func world_to_lonlat(wx: float, wy: float) -> Vector2: ## convert screen coords to lon/lat -func screen_to_lonlat(sx: float, sy: float) -> Vector2: - var w = screen_to_world(_xyz, sx, sy) +func screen_to_lonlat(scr_xy: Vector2) -> Vector2: + var w = screen_to_world(_xyz, scr_xy) return world_to_lonlat(w.x, w.y) @@ -478,12 +458,12 @@ func tile_to_lonlat(tx: float, ty: float, tz: float) -> Vector2: ## convert screen coords to world coords -func screen_to_world(xyz: Vector3, sx: float, sy: float) -> Vector2: +func screen_to_world(xyz: Vector3, s: Vector2) -> Vector2: var n = pow(2.0, xyz.z) var span_w = n * tile_width var span_h = n * tile_height - var px = sx - $canvas.size.x / 2 + span_w / 2 - var py = sy - $canvas.size.y / 2 + span_h / 2 + var px = s.x - $canvas.size.x / 2 + span_w / 2 + var py = s.y - $canvas.size.y / 2 + span_h / 2 var xr = px / span_w var yr = py / span_h var x = (xr * 2.0 - 1.0) + xyz.x @@ -492,15 +472,15 @@ func screen_to_world(xyz: Vector3, sx: float, sy: float) -> Vector2: ## convert screen coords to tile coords -func screen_to_tile(sx: float, sy: float, z: float) -> Vector2: - var world = screen_to_world(_xyz, sx, sy) +func screen_to_tile(scr_xy: Vector2, z: float) -> Vector2: + var world = screen_to_world(_xyz, scr_xy) return world_to_tile(world.x, world.y, z) ## convert tile coords to screen coords func tile_to_screen(tx: float, ty: float, tz: float) -> Vector2: var w = tile_to_world(tx, ty, tz) - return world_to_screen(w.x, w.y) + return world_to_screen(w) ## convert tile coords to world coords @@ -513,30 +493,24 @@ func tile_to_world(tx: float, ty: float, tz: float) -> Vector2: ## convert world coords to tile coords func world_to_tile(wx: float, wy: float, z: float) -> Vector2: - var n: = pow(2.0, floor(z)) - var tx: = ((wx + 1.0) / 2.0) * n - var ty: = ((-wy + 1.0) / 2.0) * n - tx = floor(tx) - ty = floor(ty) + var n: float = pow(2.0, floor(z)) + var tx: float = floor(((wx + 1.0) / 2.0) * n) + var ty: float = floor(((-wy + 1.0) / 2.0) * n) return Vector2(tx, ty) ## convert world coords to screen coords -func world_to_screen(wx: float, wy: float) -> Vector2: +func world_to_screen(pos: Vector2) -> Vector2: var n: = pow(2.0, _xyz.z) - var w: = n * tile_width - var h: = n * tile_height - var xr: = ((wx - _xyz.x) + 1.0) / 2.0 - var yr: = (-(wy - _xyz.y) + 1.0) / 2.0 - var x = w * xr - w / 2.0 + $canvas.size.x / 2.0 - var y = h * yr - h / 2.0 + $canvas.size.y / 2.0 - return Vector2(x, y) + var wh: = Vector2(n * tile_width, n * tile_height) + var rxy: = Vector2(((pos.x - _xyz.x) + 1.0) / 2.0, (-(pos.y - _xyz.y) + 1.0) / 2.0) + return wh * rxy + ($canvas.size - wh) / 2.0 ## get the tile index from xyz tile coords func xyz_to_idx(x: float, y: float, z: float) -> int: var i: = (pow(4.0, z) - 1.0) / 3.0 - var n: = pow(2.0, z) + var n: = pow(2.0, z) return int(i + (y * n + x)) @@ -655,7 +629,7 @@ func find_at_screen_position(screen_pos: Vector2) -> Node: var closest_dot = null var closest_distance = INF for mark in _marks.values(): - var dot_screen_pos = world_to_screen(mark.position.x, mark.position.y) + var dot_screen_pos = world_to_screen(mark.position) var distance = dot_screen_pos.distance_to(screen_pos) if distance < closest_distance: closest_distance = distance