Skip to content

Instantly share code, notes, and snippets.

@Decapitated
Last active April 5, 2025 19:25
Show Gist options
  • Select an option

  • Save Decapitated/826858ae2d1b58afad53143c725fe0e9 to your computer and use it in GitHub Desktop.

Select an option

Save Decapitated/826858ae2d1b58afad53143c725fe0e9 to your computer and use it in GitHub Desktop.
GDScript version of `_draw_rulers`
# Conversion of built-in canvas item editor plugin method: https://github.com/godotengine/godot/blob/d52b84e472408e185b619bbb1cbd680887269f57/editor/plugins/canvas_item_editor_plugin.cpp#L3026
@tool
extends Control
@export var show_grid: bool = false:
set(value):
show_grid = value
queue_redraw()
@export_range(1.0, 10.0, 0.1, "or_greater") var zoom: float = 1.0:
set(value):
zoom = value
queue_redraw()
@export var width: float = 11.0:
set(value):
width = value
queue_redraw()
var font: Font = ThemeDB.fallback_font
var grid_step: Vector2= EditorInterface.get_editor_settings().get_project_metadata("2d_editor", "grid_step", Vector2(8, 8))
var grid_step_multiplier: int = 0
func _draw():
var bg_color := Color.BLACK
var font_color := Color.WHITE
var graduation_color := font_color.lerp(bg_color, 0.5)
font_color.a = 0.8
# The rule transform
var transform := get_global_transform_with_canvas()
var ruler_transform: Transform2D
if show_grid:
ruler_transform = Transform2D().scaled(grid_step * pow(2.0, grid_step_multiplier))
while (transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50:
ruler_transform = ruler_transform.scaled(Vector2(2, 2))
else:
var basic_rule := 100.0
var ri := 0
while basic_rule * (1.0 / zoom) > 100.0:
basic_rule /= 5.0 if ri % 2 else 2.0
ri += 1
ri = 0
while basic_rule * (1.0 / zoom) < 100.0:
basic_rule *= 2.0 if ri % 2 else 5.0
ri += 1
ruler_transform = Transform2D().scaled(Vector2(basic_rule, basic_rule))
# Subdivisions
var major_subdivision := 2
var major_subdivide := Transform2D().scaled(Vector2(1.0 / major_subdivision, 1.0 / major_subdivision))
var minor_subdivision := 5
var minor_subdivide := Transform2D().scaled(Vector2(1.0 / minor_subdivision, 1.0 / minor_subdivision))
# First and last graduations to draw (in the ruler space)
var first := (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().basis_xform(Vector2(width, width))
var last := (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().basis_xform(size)
# Draw top ruler
draw_rect(Rect2(Vector2(width, 0), Vector2(size.x, width)), bg_color)
for i in range(ceili(first.x), last.x):
var tick_position := (transform * ruler_transform * major_subdivide * minor_subdivide).basis_xform(Vector2(i, 0)).round()
if i % (major_subdivision * minor_subdivision) == 0:
draw_line(Vector2(tick_position.x, 0), Vector2(tick_position.x, width), graduation_color, 1.0);
var val := (ruler_transform * major_subdivide * minor_subdivide).basis_xform(Vector2(i, 0)).x;
draw_string(font, Vector2(tick_position.x + 2, font.get_height(int(min(width, 11))) / 2.0 + 2.0), "%.1f" % val, HORIZONTAL_ALIGNMENT_LEFT, -1, int(min(width, 11)), font_color)
else:
if i % minor_subdivision == 0:
draw_line(Vector2(tick_position.x, width * 0.33), Vector2(tick_position.x, width), graduation_color, 1.0)
else:
draw_line(Vector2(tick_position.x, width * 0.75), Vector2(tick_position.x, width), graduation_color, 1.0)
# Draw left ruler
draw_rect(Rect2(Vector2(0, width), Vector2(width, size.y)), bg_color)
for i in range(ceili(first.y), last.y):
var tick_position := (transform * ruler_transform * major_subdivide * minor_subdivide).basis_xform(Vector2(0, i)).round()
if i % (major_subdivision * minor_subdivision) == 0:
draw_line(Vector2(0, tick_position.y), Vector2(width, tick_position.y), graduation_color, 1.0);
var val := (ruler_transform * major_subdivide * minor_subdivide).basis_xform(Vector2(0, i)).y;
var text_transform := Transform2D(-PI / 2.0, Vector2(font.get_height(int(min(width, 11))) / 2.0 + 2.0, tick_position.y - 2))
draw_set_transform_matrix(transform * text_transform)
draw_string(font, Vector2(), "%.1f" % val, HORIZONTAL_ALIGNMENT_LEFT, -1, int(min(width, 11)), font_color)
draw_set_transform_matrix(transform)
else:
if i % minor_subdivision == 0:
draw_line(Vector2(width * 0.33, tick_position.y), Vector2(width, tick_position.y), graduation_color, 1.0)
else:
draw_line(Vector2(width * 0.75, tick_position.y), Vector2(width, tick_position.y), graduation_color, 1.0)
# Draw top left corner
draw_rect(Rect2(Vector2(0, 0), Vector2(width, width)), graduation_color)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment