From 35b2c201aed0c9429807736c480b5e48b6cfe5e9 Mon Sep 17 00:00:00 2001 From: OverloadedOrama Date: Mon, 17 Aug 2020 22:54:33 +0300 Subject: [PATCH] Changed how isometric grid is drawn Instead of drawing individual lines, execute draw_isometric_tile() multiple times. What this method does is basically draws a single isometric tile, which then gets repeated for the entire canvas size. Also moved all the grid logic to a new script, which gets updated less often that Canvas.gd, for optimization purposes. Works better than the previous method, although it might be a bit slower, and currently does not work well if the canvas size is not divisible by the grid size. For now, it only gets affected by the grid width. Changing grid height has no effect. --- src/Autoload/Global.gd | 4 ++ src/Canvas.gd | 68 +--------------------------- src/Canvas.tscn | 6 ++- src/Classes/Project.gd | 2 + src/Preferences/PreferencesDialog.gd | 3 +- src/UI/Grid.gd | 53 ++++++++++++++++++++++ src/UI/TopMenuContainer.gd | 1 + 7 files changed, 69 insertions(+), 68 deletions(-) create mode 100644 src/UI/Grid.gd diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 1d84105..89a6c01 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -310,6 +310,8 @@ func undo(_frame_index := -1, _layer_index := -1, project : Project = current_pr if action_name == "Scale": canvas.camera_zoom() + Global.canvas.grid.isometric_polylines.clear() + Global.canvas.grid.update() elif "Frame" in action_name: # This actually means that frames.size is one, but it hasn't been updated yet @@ -338,6 +340,8 @@ func redo(_frame_index := -1, _layer_index := -1, project : Project = current_pr if action_name == "Scale": canvas.camera_zoom() + Global.canvas.grid.isometric_polylines.clear() + Global.canvas.grid.update() elif "Frame" in action_name: if project.frames.size() == 1: # Stop animating diff --git a/src/Canvas.gd b/src/Canvas.gd index 8903aa6..7f5a4b7 100644 --- a/src/Canvas.gd +++ b/src/Canvas.gd @@ -9,6 +9,8 @@ var can_undo := true var cursor_image_has_changed := false var sprite_changed_this_frame := false # for optimization purposes +onready var grid = $Grid + # Called when the node enters the scene tree for the first time. func _ready() -> void: @@ -42,9 +44,6 @@ func _draw() -> void: draw_texture(current_cels[i].image_texture, Vector2(location.x + size.x, location.y), modulate_color) # Right draw_texture(current_cels[i].image_texture, location + size, modulate_color) # Down right - if Global.draw_grid: - draw_grid(Global.grid_type) - # Draw rectangle to indicate the pixel currently being hovered on if Global.has_focus and Global.can_draw: Tools.draw_indicator() @@ -251,66 +250,3 @@ func onion_skinning() -> void: color.a = 0.6 / i draw_texture(layer.image_texture, location, color) layer_i += 1 - - -func draw_grid(grid_type : int) -> void: - var size : Vector2 = Global.current_project.size - if grid_type == Global.Grid_Types.CARTESIAN || grid_type == Global.Grid_Types.ALL: - for x in range(Global.grid_width, size.x, Global.grid_width): - draw_line(Vector2(x, location.y), Vector2(x, size.y), Global.grid_color, true) - - for y in range(Global.grid_height, size.y, Global.grid_height): - draw_line(Vector2(location.x, y), Vector2(size.x, y), Global.grid_color, true) - - # Doesn't work properly yet - if grid_type == Global.Grid_Types.ISOMETRIC || grid_type == Global.Grid_Types.ALL: - var approx_30_degrees = 26.565 - var approx_60_degrees = 90 - 26.565 - var prev_x := 0 - var prev_y := 0 - - # Draw lines starting from the left side, facing down to the right - for y in range(0, size.y + 1, Global.grid_width): - var yy1 = y + size.y * tan(deg2rad(approx_30_degrees)) - # End points touch the right side of the canvas, but not the entire of it - if yy1 <= (size.y + 0.01): - draw_line(Vector2(location.x, y), Vector2(size.x, yy1),Global.grid_color) - # End points touch the bottom side of the canvas - else: - var xx1 = (size.x - y) * tan(deg2rad(approx_60_degrees)) - draw_line(Vector2(location.x, y), Vector2(xx1, size.y), Global.grid_color) - - # Draw lines starting from the left side, facing up to the right - for y in range(0, size.y + 1, Global.grid_height): - var xx2 = y * tan(deg2rad(approx_60_degrees)) - - # End points touch the upper side of the canvas - if xx2 <= (size.x + 0.01): - draw_line(Vector2(location.x, y), Vector2(xx2, location.y), Global.grid_color) - prev_y = location.y - - # End points touch the right side of the canvas, but not the entire of it - else: - var distance = (xx2 - prev_x) / 2 - #var yy2 = (size.y - y) * tan(deg2rad(approx_30_degrees)) - var yy2 = prev_y + distance - draw_line(Vector2(location.x, y), Vector2(size.x, yy2), Global.grid_color) - prev_y = yy2 - - prev_x = xx2 - - # Draw lines from the top side, facing down to the right - # End points touch the right side of the canvas, but not the entire of it - # Problematic when size.y < size.x / 2 - for x in range(0, size.x, Global.grid_width * 2): - if x == 0: - continue - var yy1 = (size.x - x) * tan(deg2rad(approx_30_degrees)) - draw_line(Vector2(x, location.y), Vector2(size.x, yy1), Global.grid_color) - - # Draw lines from the bottom side, facing up to the right. - # End points touch the right side of the canvas, but not the entire of it - # Problematic when size.y < size.x / 2 - for x in range(0, size.x, Global.grid_height * 2): - var yy2 = (size.x - x) * tan(deg2rad(approx_30_degrees)) - draw_line(Vector2(x, size.y), Vector2(size.x, size.y - yy2), Global.grid_color) diff --git a/src/Canvas.tscn b/src/Canvas.tscn index 4ccfc33..fb31f3a 100644 --- a/src/Canvas.tscn +++ b/src/Canvas.tscn @@ -1,6 +1,10 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=3 format=2] [ext_resource path="res://src/Canvas.gd" type="Script" id=1] +[ext_resource path="res://src/UI/Grid.gd" type="Script" id=2] [node name="Canvas" type="Node2D"] script = ExtResource( 1 ) + +[node name="Grid" type="Node2D" parent="."] +script = ExtResource( 2 ) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 4c1254f..5066a17 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -160,6 +160,8 @@ func change_project() -> void: i += 1 Global.zoom_level_label.text = str(round(100 / Global.camera.zoom.x)) + " %" Global.canvas.update() + Global.canvas.grid.isometric_polylines.clear() + Global.canvas.grid.update() Global.transparent_checker._ready() Global.horizontal_ruler.update() Global.vertical_ruler.update() diff --git a/src/Preferences/PreferencesDialog.gd b/src/Preferences/PreferencesDialog.gd index 003e6a8..1203d07 100644 --- a/src/Preferences/PreferencesDialog.gd +++ b/src/Preferences/PreferencesDialog.gd @@ -116,7 +116,8 @@ func preference_update(prop : String) -> void: autosave_interval.mouse_default_cursor_shape = Control.CURSOR_FORBIDDEN if prop in ["grid_width", "grid_height", "grid_color"]: - Global.canvas.update() + Global.canvas.grid.isometric_polylines.clear() + Global.canvas.grid.update() if prop in ["checker_size", "checker_color_1", "checker_color_2", "checker_follow_movement", "checker_follow_scale"]: Global.transparent_checker._ready() diff --git a/src/UI/Grid.gd b/src/UI/Grid.gd new file mode 100644 index 0000000..a4873e2 --- /dev/null +++ b/src/UI/Grid.gd @@ -0,0 +1,53 @@ +extends Node2D + + +var location := Vector2.ZERO +var isometric_polylines := [] # An array of PoolVector2Arrays + + +func _draw() -> void: + if Global.draw_grid: + draw_grid(Global.grid_type) + + +func draw_grid(grid_type : int) -> void: + var size : Vector2 = Global.current_project.size + if grid_type == Global.Grid_Types.CARTESIAN || grid_type == Global.Grid_Types.ALL: + for x in range(Global.grid_width, size.x, Global.grid_width): + draw_line(Vector2(x, location.y), Vector2(x, size.y), Global.grid_color, true) + + for y in range(Global.grid_height, size.y, Global.grid_height): + draw_line(Vector2(location.x, y), Vector2(size.x, y), Global.grid_color, true) + + # Doesn't work properly yet + # Has problems when the canvas isn't a square, and with some grid sizes + if grid_type == Global.Grid_Types.ISOMETRIC || grid_type == Global.Grid_Types.ALL: + var i := 0 + for x in range(Global.grid_width, size.x, Global.grid_width * 2): + for y in range(0, size.y, Global.grid_width): + draw_isometric_tile(i, Vector2(x, y)) + i += 1 + + +func draw_isometric_tile(i : int, origin := Vector2.RIGHT) -> void: + # A random value I found by trial and error, I have no idea why it "works" + var diff = 1.11754 + var approx_30_degrees = deg2rad(26.565) + + var pool := PoolVector2Array() + if i < isometric_polylines.size(): + pool = isometric_polylines[i] + else: + var a = origin + var b = a + Vector2(cos(approx_30_degrees), sin(approx_30_degrees)) * Global.grid_width * diff + var c = a + Vector2.DOWN * Global.grid_width + var d = c - Vector2(cos(approx_30_degrees), sin(approx_30_degrees)) * Global.grid_width * diff + pool.append(a) + pool.append(b) + pool.append(c) + pool.append(d) + pool.append(a) + isometric_polylines.append(pool) + + if pool.size() > 2: + draw_polyline(pool, Global.grid_color) diff --git a/src/UI/TopMenuContainer.gd b/src/UI/TopMenuContainer.gd index 62c0f34..0e9a8db 100644 --- a/src/UI/TopMenuContainer.gd +++ b/src/UI/TopMenuContainer.gd @@ -251,6 +251,7 @@ func toggle_tile_mode() -> void: func toggle_show_grid() -> void: Global.draw_grid = !Global.draw_grid view_menu.set_item_checked(1, Global.draw_grid) + Global.canvas.grid.update() func toggle_show_rulers() -> void: