## Custom Stylebox to draw grid. ## A grid will always start and get reference from (0, 0) class_name StyleBoxGrid extends StyleBox ## Colors @export_subgroup("Colors", "color_") ## Main background color @export var color_background : Color ## Grids color @export var color_grids : Array[Color] ## Text @export_subgroup("Text", "text_") ## Disable text @export var text_disabled : bool ## Grid level to display text @export var text_level : int ## Font @export_subgroup("Fonts", "font_") ## Main font @export var font_main : Font ## Font size @export var font_size : int ## Font color @export var font_color : Color ## Constants @export_subgroup("Constants", "constant_") ## Grid Thickness @export var constant_thickness : Array[float] ## Values @export_subgroup("Values", "value_") ## Grids value steps (on both axises) @export var value_steps : Array[Vector2] ## Ranges @export_subgroup("Ranges", "range_") ## Min value (on Y-Axis) @export var range_min_y : float ## Max value (on Y-Axis) @export var range_max_y : float ## Min domain (on X-Axis) @export var range_min_x: float ## Max domain (on X-Axis) @export var range_max_x : float func _draw(rid: RID, rect: Rect2) -> void: RenderingServer.canvas_item_set_clip(rid, true) var font : Font = font_main if font_main else ThemeDB.fallback_font var ft_sz : int = font_size if font_size != 0 else ThemeDB.fallback_font_size RenderingServer.canvas_item_add_rect(rid, rect, color_background) var valid_grid_num : int = min( color_grids.size(), value_steps.size(), constant_thickness.size()) var max_thickness : float = 0 for i : int in range(valid_grid_num): max_thickness = max(max_thickness, constant_thickness[i]) var rate : Vector2 = rect.size / Vector2(range_max_x - range_min_x, range_max_y - range_min_y) var tx_flags : int = TextServer.BREAK_MANDATORY + TextServer.BREAK_WORD_BOUND + TextServer.BREAK_TRIM_EDGE_SPACES var grid_start : Vector2 = Vector2(range_min_x, range_min_y) for i : int in range(valid_grid_num): # Compute starting offset var cnt : Vector2 = grid_start / value_steps[i] var start : Vector2 = Vector2(int(cnt.x), int(cnt.y)) * value_steps[i] var x_st : float = start.x var x_pos : float = ((x_st - range_min_x) * rate.x) + max_thickness var skip : bool = true while start.x <= range_max_x: var logical : float = start.x - range_min_x var start_line : Vector2 = Vector2(logical, 0) * rate var end_line : Vector2 = Vector2(logical, range_max_y - range_min_y) * rate if i == text_level and not text_disabled: var txt : String = "x:%.02f\ny:%.02f" % [start.x, start.y] if skip else "%.02f" % (start.x) var tx_sz : Vector2 = font.get_multiline_string_size(txt, HORIZONTAL_ALIGNMENT_LEFT, -1, ft_sz, 2, tx_flags) var ft_dsc : float = tx_sz.y - font.get_ascent(ft_sz) var pos : float = max_thickness if end_line.x + max_thickness + tx_sz.x < rect.size.x else -(max_thickness + tx_sz.x) font.draw_multiline_string(rid, end_line + Vector2(pos, - ft_dsc - max_thickness), txt, HORIZONTAL_ALIGNMENT_LEFT, -1, ft_sz, 2, font_color, tx_flags) skip = false RenderingServer.canvas_item_add_line(rid, start_line, end_line, color_grids[i], constant_thickness[i], false) start.x += value_steps[i].x skip = true while start.y <= range_max_y: var r_y : float = range_max_y - range_min_y - start.y var start_line : Vector2 = Vector2(0, r_y + range_min_y) * rate var end_line : Vector2 = Vector2(range_max_x - range_min_x, r_y + range_min_y) * rate if i == text_level and not text_disabled: if not skip: var txt : String = "%.02f" % (start.y) var tx_sz : Vector2 = font.get_string_size(txt, HORIZONTAL_ALIGNMENT_LEFT, -1, ft_sz) var ft_dsc : float = font.get_descent(ft_sz) var y_pos : float = -max_thickness if start_line.y - max_thickness - tx_sz.y > 0 else (max_thickness + tx_sz.y - ft_dsc) font.draw_string(rid, start_line + Vector2(x_pos, y_pos), txt, HORIZONTAL_ALIGNMENT_LEFT, -1, ft_sz, font_color) skip = false RenderingServer.canvas_item_add_line(rid, start_line, end_line, color_grids[i], constant_thickness[i], false) start.y += value_steps[i].y
or share this direct link: