From 9c7effdba3d3d4fd46fe9f605daa67e8aa5fdaac Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:05:22 +0300 Subject: [PATCH] Optimize previews of the ellipse selection and the shape tools Before this commit, when these tools were being used on large areas, the software would start being very slow due to the polyline drawing. Now it simply draws an image. TODO: - Optimize the lasso, pixel and polygon select tools - Mirror the previews of ellipse selection and shape tools, for consistency with the lasso, pixel and polygon select tools - Perhaps somehow remove Previews.gd since its work is even more limited now. --- src/Tools/BaseShapeDrawer.gd | 30 ++++++++++------------ src/Tools/DesignTools/CurveTool.gd | 28 ++++++++++---------- src/Tools/DesignTools/LineTool.gd | 31 ++++++++--------------- src/Tools/SelectionTools/EllipseSelect.gd | 30 +++++++++++----------- src/UI/Canvas/Canvas.gd | 1 + src/UI/Canvas/Canvas.tscn | 13 +++++++--- 6 files changed, 64 insertions(+), 69 deletions(-) diff --git a/src/Tools/BaseShapeDrawer.gd b/src/Tools/BaseShapeDrawer.gd index 2b9c77c72..e61f8e79c 100644 --- a/src/Tools/BaseShapeDrawer.gd +++ b/src/Tools/BaseShapeDrawer.gd @@ -153,26 +153,24 @@ func draw_end(pos: Vector2i) -> void: func draw_preview() -> void: + var canvas := Global.canvas.previews_sprite if _drawing: - var canvas: CanvasItem = Global.canvas.previews - var indicator := BitMap.new() var rect := _get_result_rect(_start, _dest) var points := _get_points(rect.size) - var t_offset := _thickness - 1 - var t_offsetv := Vector2i(t_offset, t_offset) - indicator.create(rect.size + t_offsetv) - for point in points: - indicator.set_bitv(point, 1) - - var transform_pos := ( - rect.position - t_offsetv + Vector2i((Vector2(0.5, 0.5) * (t_offset - 1)).ceil()) + var image := Image.create( + Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_LA8 ) - canvas.draw_set_transform(transform_pos, canvas.rotation, canvas.scale) - - for line in _create_polylines(indicator): - canvas.draw_polyline(PackedVector2Array(line), Color.BLACK) - - canvas.draw_set_transform(canvas.position, canvas.rotation, canvas.scale) + var thickness_vector := ( + rect.position - Vector2i((Vector2(0.5, 0.5) * (_thickness - 1)).ceil()) + ) + for point in points: + var draw_pos := point + thickness_vector + if Rect2i(Vector2i.ZERO, image.get_size()).has_point(draw_pos): + image.set_pixelv(draw_pos, Color.WHITE) + var texture := ImageTexture.create_from_image(image) + canvas.texture = texture + else: + canvas.texture = null func _draw_shape(origin: Vector2i, dest: Vector2i) -> void: diff --git a/src/Tools/DesignTools/CurveTool.gd b/src/Tools/DesignTools/CurveTool.gd index ae4a0a9b9..306496bf5 100644 --- a/src/Tools/DesignTools/CurveTool.gd +++ b/src/Tools/DesignTools/CurveTool.gd @@ -121,24 +121,24 @@ func draw_end(pos: Vector2i) -> void: func draw_preview() -> void: + var previews := Global.canvas.previews_sprite if not _drawing: + previews.texture = null return - var canvas: Node2D = Global.canvas.previews - var pos := canvas.position - var canvas_scale := canvas.scale - if Global.mirror_view: # This fixes previewing in mirror mode - pos.x = pos.x + Global.current_project.size.x - canvas_scale.x = -1 - var points := _bezier() - canvas.draw_set_transform(pos, canvas.rotation, canvas_scale) - var indicator := _fill_bitmap_with_points(points, Global.current_project.size) - - for line in _create_polylines(indicator): - canvas.draw_polyline(PackedVector2Array(line), Color.BLACK) - - canvas.draw_set_transform(canvas.position, canvas.rotation, canvas.scale) + var image := Image.create( + Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_LA8 + ) + for point in points: + var draw_point := point + if Global.mirror_view: # This fixes previewing in mirror mode + draw_point.x = image.get_width() - point.x - 1 + if Rect2i(Vector2i.ZERO, image.get_size()).has_point(draw_point): + image.set_pixelv(draw_point, Color.WHITE) + var texture := ImageTexture.create_from_image(image) + previews.texture = texture + var canvas := Global.canvas.previews var circle_radius := Vector2.ONE * (5.0 / Global.camera.zoom.x) if _is_hovering_first_position(_last_mouse_position) and _curve.point_count > 1: var circle_center := _curve.get_point_position(0) diff --git a/src/Tools/DesignTools/LineTool.gd b/src/Tools/DesignTools/LineTool.gd index c48c9235d..7b1d84f00 100644 --- a/src/Tools/DesignTools/LineTool.gd +++ b/src/Tools/DesignTools/LineTool.gd @@ -147,30 +147,19 @@ func draw_end(pos: Vector2i) -> void: func draw_preview() -> void: + var canvas := Global.canvas.previews_sprite if _drawing: - var canvas: CanvasItem = Global.canvas.previews - var indicator := BitMap.new() - var start := _start - if _start.x > _dest.x: - start.x = _dest.x - if _start.y > _dest.y: - start.y = _dest.y - var points := _get_points() - var t_offset := _thickness - 1 - var t_offsetv := Vector2i(t_offset, t_offset) - indicator.create((_dest - _start).abs() + t_offsetv * 2 + Vector2i.ONE) - + var image := Image.create( + Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_LA8 + ) for point in points: - var p := point - start + t_offsetv - indicator.set_bitv(p, 1) - - canvas.draw_set_transform(start - t_offsetv, canvas.rotation, canvas.scale) - - for line in _create_polylines(indicator): - canvas.draw_polyline(PackedVector2Array(line), Color.BLACK) - - canvas.draw_set_transform(canvas.position, canvas.rotation, canvas.scale) + if Rect2i(Vector2i.ZERO, image.get_size()).has_point(point): + image.set_pixelv(point, Color.WHITE) + var texture := ImageTexture.create_from_image(image) + canvas.texture = texture + else: + canvas.texture = null func _draw_shape() -> void: diff --git a/src/Tools/SelectionTools/EllipseSelect.gd b/src/Tools/SelectionTools/EllipseSelect.gd index 1680c30de..692acebea 100644 --- a/src/Tools/SelectionTools/EllipseSelect.gd +++ b/src/Tools/SelectionTools/EllipseSelect.gd @@ -48,24 +48,24 @@ func draw_end(pos: Vector2i) -> void: func draw_preview() -> void: + var canvas := Global.canvas.previews_sprite if !_move && _rect.has_area(): - var canvas: Node2D = Global.canvas.previews - var pos := canvas.position - var canvas_scale := canvas.scale var temp_rect := _rect - if Global.mirror_view: - pos.x = pos.x + Global.current_project.size.x - temp_rect.position.x = Global.current_project.size.x - temp_rect.position.x - canvas_scale.x = -1 - var border := DrawingAlgos.get_ellipse_points_filled(Vector2.ZERO, temp_rect.size) - var indicator := _fill_bitmap_with_points(border, temp_rect.size) - - canvas.draw_set_transform(temp_rect.position, canvas.rotation, canvas_scale) - for line in _create_polylines(indicator): - canvas.draw_polyline(PackedVector2Array(line), Color.BLACK) - - canvas.draw_set_transform(canvas.position, canvas.rotation, canvas.scale) + var points := DrawingAlgos.get_ellipse_points(Vector2.ZERO, temp_rect.size) + var image := Image.create( + Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_LA8 + ) + for point in points: + var draw_point := point + temp_rect.position + if Global.mirror_view: # This fixes previewing in mirror mode + draw_point.x = image.get_width() - draw_point.x - 1 + if Rect2i(Vector2i.ZERO, image.get_size()).has_point(draw_point): + image.set_pixelv(draw_point, Color.WHITE) + var texture := ImageTexture.create_from_image(image) + canvas.texture = texture + else: + canvas.texture = null func apply_selection(_position: Vector2i) -> void: diff --git a/src/UI/Canvas/Canvas.gd b/src/UI/Canvas/Canvas.gd index f908644b0..9b5891ee0 100644 --- a/src/UI/Canvas/Canvas.gd +++ b/src/UI/Canvas/Canvas.gd @@ -23,6 +23,7 @@ var layer_metadata_texture := ImageTexture.new() @onready var crop_rect := $CropRect as CropRect @onready var indicators := $Indicators as Node2D @onready var previews := $Previews as Node2D +@onready var previews_sprite := $PreviewsSprite as Sprite2D @onready var mouse_guide_container := $MouseGuideContainer as Node2D @onready var gizmos_3d := $Gizmos3D as Node2D @onready var measurements := $Measurements as Node2D diff --git a/src/UI/Canvas/Canvas.tscn b/src/UI/Canvas/Canvas.tscn index 48c7441de..4e124c85a 100644 --- a/src/UI/Canvas/Canvas.tscn +++ b/src/UI/Canvas/Canvas.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=22 format=3 uid="uid://ba24iuv55m4l3"] +[gd_scene load_steps=23 format=3 uid="uid://ba24iuv55m4l3"] [ext_resource type="Script" path="res://src/UI/Canvas/Canvas.gd" id="1"] [ext_resource type="Shader" path="res://src/Shaders/BlendLayers.gdshader" id="1_253dh"] @@ -10,12 +10,12 @@ [ext_resource type="Script" path="res://src/UI/Canvas/Previews.gd" id="7"] [ext_resource type="Script" path="res://src/UI/Canvas/Selection.gd" id="8"] [ext_resource type="Shader" path="res://src/Shaders/MarchingAntsOutline.gdshader" id="9"] -[ext_resource type="Shader" path="res://src/Shaders/AutoInvertColors.gdshader" id="10"] [ext_resource type="PackedScene" uid="uid://no3w7e2264u4" path="res://src/UI/Canvas/MouseGuideContainer.tscn" id="11"] [ext_resource type="Script" path="res://src/UI/Canvas/OnionSkinning.gd" id="12"] [ext_resource type="Script" path="res://src/UI/Canvas/CropRect.gd" id="13"] [ext_resource type="Script" path="res://src/UI/Canvas/Gizmos3D.gd" id="14"] [ext_resource type="Script" path="res://src/UI/Canvas/Measurements.gd" id="16_nxilb"] +[ext_resource type="Shader" path="res://src/Shaders/AutoInvertColors.gdshader" id="17_lowhf"] [ext_resource type="Script" path="res://src/UI/Canvas/ReferenceImages.gd" id="17_qfjb4"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_6b0ox"] @@ -36,7 +36,10 @@ shader_parameter/frequency = 200.0 shader_parameter/stripe_direction = 0.5 [sub_resource type="ShaderMaterial" id="3"] -shader = ExtResource("10") +shader = ExtResource("17_lowhf") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_tb70k"] +shader = ExtResource("17_lowhf") [node name="Canvas" type="Node2D"] material = SubResource("ShaderMaterial_6b0ox") @@ -81,6 +84,10 @@ script = ExtResource("3") material = SubResource("3") script = ExtResource("7") +[node name="PreviewsSprite" type="Sprite2D" parent="."] +material = SubResource("ShaderMaterial_tb70k") +centered = false + [node name="OnionPast" type="Node2D" parent="."] script = ExtResource("12")