@tool extends Node2D @export var grid_size: float = 50.0 func _ready(): set_process(true) func _process(delta): queue_redraw() func _draw(): var camera_transform = get_viewport().get_canvas_transform() var camera_scale = camera_transform.get_scale().x var line_width = 1.0 / camera_scale # Get the visible rectangle in world coordinates. var viewport_rect_in_world = camera_transform.affine_inverse() * get_viewport().get_visible_rect() var visible_rect_min = viewport_rect_in_world.position var visible_rect_max = viewport_rect_in_world.end # --- Draw the Axes (always 2px thick in screen space) --- draw_line(Vector2(visible_rect_min.x, 0), Vector2(visible_rect_max.x, 0), Color.RED, 2 / camera_scale) draw_line(Vector2(0, visible_rect_min.y), Vector2(0, visible_rect_max.y), Color.GREEN, 2 / camera_scale) # --- Draw the Major Grid Lines with Culling --- var major_step = grid_size const MIN_SCREEN_SPACING = 30.0 # Minimum pixel spacing between grid lines. # Skip lines if they would be too close on screen. while major_step * camera_scale < MIN_SCREEN_SPACING: major_step *= 2 var first_x_major = floor(visible_rect_min.x / major_step) * major_step var last_x_major = ceil(visible_rect_max.x / major_step) * major_step var first_y_major = floor(visible_rect_min.y / major_step) * major_step var last_y_major = ceil(visible_rect_max.y / major_step) * major_step # Draw major vertical lines for x in range(int(first_x_major / major_step), int(last_x_major / major_step) + 1): var draw_x = x * major_step draw_line(Vector2(draw_x, visible_rect_min.y), Vector2(draw_x, visible_rect_max.y), Color(Color.GRAY, 0.5), line_width) # Draw major horizontal lines for y in range(int(first_y_major / major_step), int(last_y_major / major_step) + 1): var draw_y = y * major_step draw_line(Vector2(visible_rect_min.x, draw_y), Vector2(visible_rect_max.x, draw_y), Color(Color.GRAY, 0.5), line_width) # --- Draw Minor Grid Lines (only when zoomed in) --- if major_step == grid_size: var minor_step = grid_size / 5.0 var first_x_minor = floor(visible_rect_min.x / minor_step) * minor_step var last_x_minor = ceil(visible_rect_max.x / minor_step) * minor_step var first_y_minor = floor(visible_rect_min.y / minor_step) * minor_step var last_y_minor = ceil(visible_rect_max.y / minor_step) * minor_step # Draw minor vertical lines for x in range(int(first_x_minor / minor_step), int(last_x_minor / minor_step) + 1): var draw_x = x * minor_step # Skip major lines to avoid drawing over them. if fmod(draw_x, major_step) != 0: draw_line(Vector2(draw_x, visible_rect_min.y), Vector2(draw_x, visible_rect_max.y), Color(Color.GRAY, 0.2), line_width) # Draw minor horizontal lines for y in range(int(first_y_minor / minor_step), int(last_y_minor / minor_step) + 1): var draw_y = y * minor_step # Skip major lines to avoid drawing over them. if fmod(draw_y, major_step) != 0: draw_line(Vector2(visible_rect_min.x, draw_y), Vector2(visible_rect_max.x, draw_y), Color(Color.GRAY, 0.2), line_width)