From 41ccc704c24a9360e6bd7ec228be781996629570 Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com> Date: Mon, 8 Aug 2022 03:03:17 +0300 Subject: [PATCH] Refactor the selection system to use an Image instead of a BitMap (#710) * Use Image instead of BitMap for selection Not complete and Pixelorama is currently broken * Add a SelectionMap class * Make the changes in Selection.gd * Remove selection_bitmap * Replace duplicate() with copy_from() * Fix selection Intersection and transforming are not working * Fix wrong pixel color values * Fix selection transforming * Call selection_bitmap_changed() on scale * Fix clipboard * Remove bitmap_to_image() * Rename selection_image to selection_map * No errors in Magic Wand * Rename selection_bitmap_changed() to selection_map_changed() * Format * Fix selection resizing * Remove a line from image effects * Fast selection inverting using shader * Update SelectionMap.gd * Format * Convert SelectionMap back to LA8 after inverting * Minor refactor in RectSelect.gd * Fix intersections * Use shader for ColorSelect and add color similarity option * Update RotateImage.gd --- project.godot | 6 + src/Autoload/DrawingAlgos.gd | 9 +- src/Autoload/Global.gd | 1 + src/Autoload/Palettes.gd | 2 +- src/Classes/Project.gd | 168 +---------------- src/Classes/SelectionMap.gd | 105 +++++++++++ src/Shaders/ColorSelect.gdshader | 29 +++ src/Tools/BaseTool.gd | 2 +- src/Tools/Bucket.gd | 2 +- src/Tools/Draw.gd | 2 +- src/Tools/SelectionTools/ColorSelect.gd | 62 ++++--- src/Tools/SelectionTools/ColorSelect.tscn | 47 +++++ src/Tools/SelectionTools/EllipseSelect.gd | 29 ++- src/Tools/SelectionTools/Lasso.gd | 36 ++-- src/Tools/SelectionTools/MagicWand.gd | 37 ++-- src/Tools/SelectionTools/PolygonSelect.gd | 36 ++-- src/Tools/SelectionTools/RectSelect.gd | 64 +++---- src/Tools/SelectionTools/SelectionTool.gd | 46 ++--- src/UI/Canvas/Selection.gd | 171 +++++++++--------- .../Dialogs/ImageEffects/DesaturateDialog.gd | 3 +- .../Dialogs/ImageEffects/DropShadowDialog.gd | 3 +- .../Dialogs/ImageEffects/FlipImageDialog.gd | 21 ++- src/UI/Dialogs/ImageEffects/GradientDialog.gd | 2 +- .../Dialogs/ImageEffects/GradientMapDialog.gd | 3 +- src/UI/Dialogs/ImageEffects/HSVDialog.gd | 3 +- .../ImageEffects/InvertColorsDialog.gd | 3 +- src/UI/Dialogs/ImageEffects/OutlineDialog.gd | 3 +- src/UI/Dialogs/ImageEffects/RotateImage.gd | 6 +- 28 files changed, 478 insertions(+), 423 deletions(-) create mode 100644 src/Classes/SelectionMap.gd create mode 100644 src/Shaders/ColorSelect.gdshader diff --git a/project.godot b/project.godot index bbcd7640d..4698f8c86 100644 --- a/project.godot +++ b/project.godot @@ -104,6 +104,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://src/Classes/Project.gd" }, { +"base": "Image", +"class": "SelectionMap", +"language": "GDScript", +"path": "res://src/Classes/SelectionMap.gd" +}, { "base": "BaseTool", "class": "SelectionTool", "language": "GDScript", @@ -149,6 +154,7 @@ _global_script_class_icons={ "PaletteSwatch": "", "Patterns": "", "Project": "", +"SelectionMap": "", "SelectionTool": "", "ShaderImageEffect": "", "ShortcutProfile": "", diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index bcd41ede4..69ffbe607 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -426,8 +426,9 @@ func general_do_scale(width: int, height: int) -> void: var x_ratio = project.size.x / width var y_ratio = project.size.y / height - var bitmap: BitMap - bitmap = project.resize_bitmap(project.selection_bitmap, size) + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) + selection_map_copy.crop(size.x, size.y) var new_x_symmetry_point = project.x_symmetry_point / x_ratio var new_y_symmetry_point = project.y_symmetry_point / y_ratio @@ -441,7 +442,7 @@ func general_do_scale(width: int, height: int) -> void: project.undos += 1 project.undo_redo.create_action("Scale") project.undo_redo.add_do_property(project, "size", size) - project.undo_redo.add_do_property(project, "selection_bitmap", bitmap) + project.undo_redo.add_do_property(project, "selection_map", selection_map_copy) project.undo_redo.add_do_property(project, "x_symmetry_point", new_x_symmetry_point) project.undo_redo.add_do_property(project, "y_symmetry_point", new_y_symmetry_point) project.undo_redo.add_do_property(project.x_symmetry_axis, "points", new_x_symmetry_axis_points) @@ -451,7 +452,7 @@ func general_do_scale(width: int, height: int) -> void: func general_undo_scale() -> void: var project: Project = Global.current_project project.undo_redo.add_undo_property(project, "size", project.size) - project.undo_redo.add_undo_property(project, "selection_bitmap", project.selection_bitmap) + project.undo_redo.add_undo_property(project, "selection_map", project.selection_map) project.undo_redo.add_undo_property(project, "x_symmetry_point", project.x_symmetry_point) project.undo_redo.add_undo_property(project, "y_symmetry_point", project.y_symmetry_point) project.undo_redo.add_undo_property( diff --git a/src/Autoload/Global.gd b/src/Autoload/Global.gd index 0f13ffee7..f9486e658 100644 --- a/src/Autoload/Global.gd +++ b/src/Autoload/Global.gd @@ -452,6 +452,7 @@ func undo_or_redo( canvas.camera_zoom() canvas.grid.update() canvas.pixel_grid.update() + project.selection_map_changed() cursor_position_label.text = "[%s×%s]" % [project.size.x, project.size.y] elif "Frame" in action_name: diff --git a/src/Autoload/Palettes.gd b/src/Autoload/Palettes.gd index d11755274..6d5c97c06 100644 --- a/src/Autoload/Palettes.gd +++ b/src/Autoload/Palettes.gd @@ -144,7 +144,7 @@ func _create_new_palette_from_current_selection( for x in current_project.size.x: for y in current_project.size.y: var pos := Vector2(x, y) - if current_project.selection_bitmap.get_bit(pos): + if current_project.selection_map.is_pixel_selected(pos): pixels.append(pos) _fill_new_palette_with_colors(pixels, new_palette, add_alpha_colors, get_colors_from) diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 8bfb2c800..fe3cba35f 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -25,7 +25,7 @@ var y_symmetry_point var x_symmetry_axis := SymmetryGuide.new() var y_symmetry_axis := SymmetryGuide.new() -var selection_bitmap := BitMap.new() +var selection_map := SelectionMap.new() # This is useful for when the selection is outside of the canvas boundaries, # on the left and/or above (negative coords) var selection_offset := Vector2.ZERO setget _selection_offset_changed @@ -55,7 +55,7 @@ func _init(_frames := [], _name := tr("untitled"), _size := Vector2(64, 64)) -> name = _name size = _size tiles = Tiles.new(size) - selection_bitmap.create(size) + selection_map.create(size.x, size.y, false, Image.FORMAT_LA8) Global.tabs.add_tab(name) OpenSave.current_save_paths.append("") @@ -118,13 +118,11 @@ func new_empty_frame() -> Frame: return frame -func selection_bitmap_changed() -> void: - var image := Image.new() +func selection_map_changed() -> void: var image_texture := ImageTexture.new() - has_selection = selection_bitmap.get_true_bit_count() > 0 + has_selection = !selection_map.is_invisible() if has_selection: - image = bitmap_to_image(selection_bitmap) - image_texture.create_from_image(image, 0) + image_texture.create_from_image(selection_map, 0) Global.canvas.selection.marching_ants_outline.texture = image_texture Global.top_menu_container.edit_menu_button.get_popup().set_item_disabled(6, !has_selection) @@ -261,8 +259,8 @@ func change_project() -> void: # Change selection effect & bounding rectangle Global.canvas.selection.marching_ants_outline.offset = selection_offset - selection_bitmap_changed() - Global.canvas.selection.big_bounding_rectangle = get_selection_rectangle() + selection_map_changed() + Global.canvas.selection.big_bounding_rectangle = selection_map.get_used_rect() Global.canvas.selection.big_bounding_rectangle.position += selection_offset Global.canvas.selection.update() Global.top_menu_container.edit_menu_button.get_popup().set_item_disabled(6, !has_selection) @@ -388,7 +386,7 @@ func deserialize(dict: Dictionary) -> void: size.x = dict.size_x size.y = dict.size_y tiles.tile_size = size - selection_bitmap = resize_bitmap(selection_bitmap, size) + selection_map.crop(size.x, size.y) if dict.has("has_mask"): tiles.has_mask = dict.has_mask if dict.has("tile_mode_x_basis_x") and dict.has("tile_mode_x_basis_y"): @@ -763,7 +761,7 @@ func duplicate_layers() -> Array: func can_pixel_get_drawn( pixel: Vector2, - bitmap: BitMap = selection_bitmap, + image: SelectionMap = selection_map, selection_position: Vector2 = Global.canvas.selection.big_bounding_rectangle.position ) -> bool: if pixel.x < 0 or pixel.y < 0 or pixel.x >= size.x or pixel.y >= size.y: @@ -777,152 +775,6 @@ func can_pixel_get_drawn( pixel.x -= selection_position.x if selection_position.y < 0: pixel.y -= selection_position.y - return bitmap.get_bit(pixel) + return image.is_pixel_selected(pixel) else: return true - - -func invert_bitmap(bitmap: BitMap) -> void: - for x in bitmap.get_size().x: - for y in bitmap.get_size().y: - var pos := Vector2(x, y) - bitmap.set_bit(pos, !bitmap.get_bit(pos)) - - -# Unexposed BitMap class function -# https://github.com/godotengine/godot/blob/master/scene/resources/bit_map.cpp#L605 -func resize_bitmap(bitmap: BitMap, new_size: Vector2) -> BitMap: - if new_size == bitmap.get_size(): - return bitmap - var new_bitmap := BitMap.new() - new_bitmap.create(new_size) - var lw = min(bitmap.get_size().x, new_size.x) - var lh = min(bitmap.get_size().y, new_size.y) - for x in lw: - for y in lh: - new_bitmap.set_bit(Vector2(x, y), bitmap.get_bit(Vector2(x, y))) - - return new_bitmap - - -# Unexposed BitMap class function -# https://github.com/godotengine/godot/blob/master/scene/resources/bit_map.cpp#L622 -func bitmap_to_image(bitmap: BitMap) -> Image: - var image := Image.new() - var width := bitmap.get_size().x - var height := bitmap.get_size().y - image.create(width, height, false, Image.FORMAT_LA8) - image.lock() - for x in width: - for y in height: - var pos := Vector2(x, y) - var color = Color(1, 1, 1, 1) if bitmap.get_bit(pos) else Color(0, 0, 0, 0) - image.set_pixelv(pos, color) - image.unlock() - return image - - -# Algorithm taken from Image.get_used_rect() -# https://github.com/godotengine/godot/blob/master/core/io/image.cpp -func get_selection_rectangle(bitmap: BitMap = selection_bitmap) -> Rect2: - if bitmap.get_true_bit_count() == 0: - return Rect2() - - var minx := 0xFFFFFF - var miny := 0xFFFFFF - var maxx := -1 - var maxy := -1 - for j in bitmap.get_size().y: - for i in bitmap.get_size().x: - if !bitmap.get_bit(Vector2(i, j)): - continue - if i > maxx: - maxx = i - if j > maxy: - maxy = j - if i < minx: - minx = i - if j < miny: - miny = j - - if maxx == -1: - return Rect2() - else: - return Rect2(minx, miny, maxx - minx + 1, maxy - miny + 1) - - -func move_bitmap_values(bitmap: BitMap, move_offset := true) -> void: - var selection_node = Global.canvas.selection - var selection_position: Vector2 = selection_node.big_bounding_rectangle.position - var selection_end: Vector2 = selection_node.big_bounding_rectangle.end - - var image: Image = bitmap_to_image(bitmap) - var selection_rect := image.get_used_rect() - var smaller_image := image.get_rect(selection_rect) - image.fill(Color(0)) - var dst := selection_position - var x_diff = selection_end.x - size.x - var y_diff = selection_end.y - size.y - var nw = max(size.x, size.x + x_diff) - var nh = max(size.y, size.y + y_diff) - - if selection_position.x < 0: - nw -= selection_position.x - if move_offset: - self.selection_offset.x = selection_position.x - dst.x = 0 - else: - if move_offset: - self.selection_offset.x = 0 - if selection_position.y < 0: - nh -= selection_position.y - if move_offset: - self.selection_offset.y = selection_position.y - dst.y = 0 - else: - if move_offset: - self.selection_offset.y = 0 - - if nw <= image.get_size().x: - nw = image.get_size().x - if nh <= image.get_size().y: - nh = image.get_size().y - - image.crop(nw, nh) - image.blit_rect(smaller_image, Rect2(Vector2.ZERO, Vector2(nw, nh)), dst) - bitmap.create_from_image_alpha(image) - - -func resize_bitmap_values(bitmap: BitMap, new_size: Vector2, flip_x: bool, flip_y: bool) -> BitMap: - var selection_node = Global.canvas.selection - var selection_position: Vector2 = selection_node.big_bounding_rectangle.position - var dst := selection_position - var new_bitmap_size := size - new_bitmap_size.x = max(size.x, abs(selection_position.x) + new_size.x) - new_bitmap_size.y = max(size.y, abs(selection_position.y) + new_size.y) - var new_bitmap := BitMap.new() - var image: Image = bitmap_to_image(bitmap) - var selection_rect := image.get_used_rect() - var smaller_image := image.get_rect(selection_rect) - if selection_position.x <= 0: - self.selection_offset.x = selection_position.x - dst.x = 0 - else: - self.selection_offset.x = 0 - if selection_position.y <= 0: - self.selection_offset.y = selection_position.y - dst.y = 0 - else: - self.selection_offset.y = 0 - image.fill(Color(0)) - smaller_image.resize(new_size.x, new_size.y, Image.INTERPOLATE_NEAREST) - if flip_x: - smaller_image.flip_x() - if flip_y: - smaller_image.flip_y() - if new_bitmap_size != size: - image.crop(new_bitmap_size.x, new_bitmap_size.y) - image.blit_rect(smaller_image, Rect2(Vector2.ZERO, new_bitmap_size), dst) - new_bitmap.create_from_image_alpha(image) - - return new_bitmap diff --git a/src/Classes/SelectionMap.gd b/src/Classes/SelectionMap.gd new file mode 100644 index 000000000..ef4598bce --- /dev/null +++ b/src/Classes/SelectionMap.gd @@ -0,0 +1,105 @@ +class_name SelectionMap +extends Image + +var invert_shader: Shader = preload("res://src/Shaders/Invert.shader") + + +func is_pixel_selected(pixel: Vector2) -> bool: + if pixel.x < 0 or pixel.y < 0 or pixel.x >= get_width() or pixel.y >= get_height(): + return false + lock() + var selected: bool = get_pixelv(pixel).a > 0 + unlock() + return selected + + +func select_pixel(pixel: Vector2, select := true) -> void: + lock() + if select: + set_pixelv(pixel, Color(1, 1, 1, 1)) + else: + set_pixelv(pixel, Color(0)) + unlock() + + +func clear() -> void: + fill(Color(0)) + + +func invert() -> void: + var params := {"red": true, "green": true, "blue": true, "alpha": true} + var gen := ShaderImageEffect.new() + gen.generate_image(self, invert_shader, params, get_size()) + self.convert(Image.FORMAT_LA8) + + +func move_bitmap_values(project, move_offset := true) -> void: + var size: Vector2 = project.size + var selection_node = Global.canvas.selection + var selection_position: Vector2 = selection_node.big_bounding_rectangle.position + var selection_end: Vector2 = selection_node.big_bounding_rectangle.end + + var selection_rect := get_used_rect() + var smaller_image := get_rect(selection_rect) + clear() + var dst := selection_position + var x_diff = selection_end.x - size.x + var y_diff = selection_end.y - size.y + var nw = max(size.x, size.x + x_diff) + var nh = max(size.y, size.y + y_diff) + + if selection_position.x < 0: + nw -= selection_position.x + if move_offset: + project.selection_offset.x = selection_position.x + dst.x = 0 + else: + if move_offset: + project.selection_offset.x = 0 + if selection_position.y < 0: + nh -= selection_position.y + if move_offset: + project.selection_offset.y = selection_position.y + dst.y = 0 + else: + if move_offset: + project.selection_offset.y = 0 + + if nw <= size.x: + nw = size.x + if nh <= size.y: + nh = size.y + + crop(nw, nh) + blit_rect(smaller_image, Rect2(Vector2.ZERO, Vector2(nw, nh)), dst) + + +func resize_bitmap_values(project, new_size: Vector2, flip_x: bool, flip_y: bool) -> void: + var size: Vector2 = project.size + var selection_node: Node2D = Global.canvas.selection + var selection_position: Vector2 = selection_node.big_bounding_rectangle.position + var dst := selection_position + var new_bitmap_size := size + new_bitmap_size.x = max(size.x, abs(selection_position.x) + new_size.x) + new_bitmap_size.y = max(size.y, abs(selection_position.y) + new_size.y) + var selection_rect := get_used_rect() + var smaller_image := get_rect(selection_rect) + if selection_position.x <= 0: + project.selection_offset.x = selection_position.x + dst.x = 0 + else: + project.selection_offset.x = 0 + if selection_position.y <= 0: + project.selection_offset.y = selection_position.y + dst.y = 0 + else: + project.selection_offset.y = 0 + clear() + smaller_image.resize(new_size.x, new_size.y, Image.INTERPOLATE_NEAREST) + if flip_x: + smaller_image.flip_x() + if flip_y: + smaller_image.flip_y() + if new_bitmap_size != size: + crop(new_bitmap_size.x, new_bitmap_size.y) + blit_rect(smaller_image, Rect2(Vector2.ZERO, new_bitmap_size), dst) diff --git a/src/Shaders/ColorSelect.gdshader b/src/Shaders/ColorSelect.gdshader new file mode 100644 index 000000000..52b777df4 --- /dev/null +++ b/src/Shaders/ColorSelect.gdshader @@ -0,0 +1,29 @@ +shader_type canvas_item; +render_mode unshaded; + +uniform sampler2D selection : hint_black; +uniform vec4 color; +uniform float similarity_percent : hint_range(0.0, 100.0); +uniform int operation = 0; // 0 = add, 1 = subtract, 2 = intersect + +void fragment() { + vec4 original_color = texture(TEXTURE, UV); + float diff = distance(original_color, color); + float similarity = abs(2.0 - ((similarity_percent/100.0) * 2.0)); + vec4 col = texture(selection, UV); + if (col.rgb == vec3(0.0)) + col.a = 0.0; + + if (diff <= similarity) + { + if (operation == 0) + col = vec4(1.0); + else if (operation == 1) + col = vec4(0.0); + } + else + if (operation == 2) + col = vec4(0.0); + + COLOR = col; +} diff --git a/src/Tools/BaseTool.gd b/src/Tools/BaseTool.gd index f834d4b80..234dae526 100644 --- a/src/Tools/BaseTool.gd +++ b/src/Tools/BaseTool.gd @@ -75,7 +75,7 @@ func draw_preview() -> void: func _get_draw_rect() -> Rect2: if Global.current_project.has_selection: - return Global.current_project.get_selection_rectangle() + return Global.current_project.selection_map.get_used_rect() else: return Rect2(Vector2.ZERO, Global.current_project.size) diff --git a/src/Tools/Bucket.gd b/src/Tools/Bucket.gd index 4f799fc0e..f0011842e 100644 --- a/src/Tools/Bucket.gd +++ b/src/Tools/Bucket.gd @@ -181,7 +181,7 @@ func fill_in_color(position: Vector2) -> void: var selection: Image var selection_tex := ImageTexture.new() if project.has_selection: - selection = project.bitmap_to_image(project.selection_bitmap) + selection = project.selection_map else: selection = Image.new() selection.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8) diff --git a/src/Tools/Draw.gd b/src/Tools/Draw.gd index 452ed0340..7b9236972 100644 --- a/src/Tools/Draw.gd +++ b/src/Tools/Draw.gd @@ -397,7 +397,7 @@ func remove_unselected_parts_of_brush(brush: Image, dst: Vector2) -> Image: for x in size.x: for y in size.y: var pos := Vector2(x, y) + dst - if !project.selection_bitmap.get_bit(pos): + if !project.selection_map.is_pixel_selected(pos): new_brush.set_pixel(x, y, Color(0)) new_brush.unlock() return new_brush diff --git a/src/Tools/SelectionTools/ColorSelect.gd b/src/Tools/SelectionTools/ColorSelect.gd index 7135babb6..dfbe00b4e 100644 --- a/src/Tools/SelectionTools/ColorSelect.gd +++ b/src/Tools/SelectionTools/ColorSelect.gd @@ -1,5 +1,27 @@ extends SelectionTool +var shader: Shader = preload("res://src/Shaders/ColorSelect.gdshader") +var _similarity := 100 + + +func get_config() -> Dictionary: + return {"similarity": _similarity} + + +func set_config(config: Dictionary) -> void: + _similarity = config.get("similarity", _similarity) + + +func update_config() -> void: + $Similarity/SimilaritySpinBox.value = _similarity + $Similarity/SimilaritySlider.value = _similarity + + +func _on_Similarity_value_changed(value: float) -> void: + _similarity = value + update_config() + save_config() + func apply_selection(position: Vector2) -> void: var project: Project = Global.current_project @@ -8,30 +30,28 @@ func apply_selection(position: Vector2) -> void: if position.x > project.size.x - 1 or position.y > project.size.y - 1: return - if !_add and !_subtract and !_intersect: - Global.canvas.selection.clear_selection() - - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() - if _intersect: - var full_rect = Rect2(Vector2.ZERO, selection_bitmap_copy.get_size()) - selection_bitmap_copy.set_bit_rect(full_rect, false) - var cel_image := Image.new() cel_image.copy_from(_get_draw_image()) cel_image.lock() var color := cel_image.get_pixelv(position) - for x in cel_image.get_width(): - for y in cel_image.get_height(): - var pos := Vector2(x, y) - if color.is_equal_approx(cel_image.get_pixelv(pos)): - if _intersect: - selection_bitmap_copy.set_bit(pos, project.selection_bitmap.get_bit(pos)) - else: - selection_bitmap_copy.set_bit(pos, !_subtract) - cel_image.unlock() - project.selection_bitmap = selection_bitmap_copy - Global.canvas.selection.big_bounding_rectangle = project.get_selection_rectangle( - project.selection_bitmap - ) + var operation := 0 + if _subtract: + operation = 1 + elif _intersect: + operation = 2 + + var params := {"color": color, "similarity_percent": _similarity, "operation": operation} + if _add or _subtract or _intersect: + var selection_tex := ImageTexture.new() + selection_tex.create_from_image(project.selection_map, 0) + params["selection"] = selection_tex + var gen := ShaderImageEffect.new() + gen.generate_image(cel_image, shader, params, project.size) + cel_image.convert(Image.FORMAT_LA8) + + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(cel_image) + project.selection_map = selection_map_copy + Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect() Global.canvas.selection.commit_undo("Select", undo_data) diff --git a/src/Tools/SelectionTools/ColorSelect.tscn b/src/Tools/SelectionTools/ColorSelect.tscn index e5c7a5953..96d9660f9 100644 --- a/src/Tools/SelectionTools/ColorSelect.tscn +++ b/src/Tools/SelectionTools/ColorSelect.tscn @@ -5,3 +5,50 @@ [node name="ToolOptions" instance=ExtResource( 1 )] script = ExtResource( 2 ) + +[node name="Similarity" type="VBoxContainer" parent="." index="8"] +margin_top = 166.0 +margin_right = 116.0 +margin_bottom = 228.0 +alignment = 1 + +[node name="Label" type="Label" parent="Similarity" index="0"] +margin_left = 26.0 +margin_right = 90.0 +margin_bottom = 14.0 +size_flags_horizontal = 4 +text = "Similarity:" + +[node name="SimilaritySpinBox" type="SpinBox" parent="Similarity" index="1"] +margin_left = 21.0 +margin_top = 18.0 +margin_right = 95.0 +margin_bottom = 42.0 +hint_tooltip = "How much two colors are Similar/Close together" +mouse_default_cursor_shape = 2 +size_flags_horizontal = 4 +value = 100.0 +align = 1 +suffix = "%" +__meta__ = { +"_editor_description_": "" +} + +[node name="SimilaritySlider" type="HSlider" parent="Similarity" index="2"] +margin_left = 12.0 +margin_top = 46.0 +margin_right = 104.0 +margin_bottom = 62.0 +rect_min_size = Vector2( 92, 0 ) +hint_tooltip = "How much two colors are Similar/Close together" +focus_mode = 0 +mouse_default_cursor_shape = 2 +size_flags_horizontal = 4 +size_flags_vertical = 1 +value = 100.0 +__meta__ = { +"_editor_description_": "" +} + +[connection signal="value_changed" from="Similarity/SimilaritySpinBox" to="." method="_on_Similarity_value_changed"] +[connection signal="value_changed" from="Similarity/SimilaritySlider" to="." method="_on_Similarity_value_changed"] diff --git a/src/Tools/SelectionTools/EllipseSelect.gd b/src/Tools/SelectionTools/EllipseSelect.gd index 440e959ca..7917000ee 100644 --- a/src/Tools/SelectionTools/EllipseSelect.gd +++ b/src/Tools/SelectionTools/EllipseSelect.gd @@ -72,8 +72,9 @@ func apply_selection(_position: Vector2) -> void: Global.canvas.selection.commit_undo("Select", undo_data) if _rect.size != Vector2.ZERO: - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() - set_ellipse(selection_bitmap_copy, _rect.position) + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) + set_ellipse(selection_map_copy, _rect.position) # Handle mirroring if Tools.horizontal_mirror: @@ -84,7 +85,7 @@ func apply_selection(_position: Vector2) -> void: + 1 ) mirror_x_rect.end.x = Global.current_project.x_symmetry_point - _rect.end.x + 1 - set_ellipse(selection_bitmap_copy, mirror_x_rect.abs().position) + set_ellipse(selection_map_copy, mirror_x_rect.abs().position) if Tools.vertical_mirror: var mirror_xy_rect := mirror_x_rect mirror_xy_rect.position.y = ( @@ -93,7 +94,7 @@ func apply_selection(_position: Vector2) -> void: + 1 ) mirror_xy_rect.end.y = Global.current_project.y_symmetry_point - _rect.end.y + 1 - set_ellipse(selection_bitmap_copy, mirror_xy_rect.abs().position) + set_ellipse(selection_map_copy, mirror_xy_rect.abs().position) if Tools.vertical_mirror: var mirror_y_rect := _rect mirror_y_rect.position.y = ( @@ -102,30 +103,28 @@ func apply_selection(_position: Vector2) -> void: + 1 ) mirror_y_rect.end.y = Global.current_project.y_symmetry_point - _rect.end.y + 1 - set_ellipse(selection_bitmap_copy, mirror_y_rect.abs().position) + set_ellipse(selection_map_copy, mirror_y_rect.abs().position) - project.selection_bitmap = selection_bitmap_copy - Global.canvas.selection.big_bounding_rectangle = project.get_selection_rectangle( - project.selection_bitmap - ) + project.selection_map = selection_map_copy + Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect() Global.canvas.selection.commit_undo("Select", undo_data) -func set_ellipse(bitmap: BitMap, position: Vector2) -> void: +func set_ellipse(selection_map: SelectionMap, position: Vector2) -> void: var project: Project = Global.current_project - var bitmap_size: Vector2 = bitmap.get_size() + var bitmap_size: Vector2 = selection_map.get_size() if _intersect: - bitmap.set_bit_rect(Rect2(Vector2.ZERO, bitmap_size), false) + selection_map.clear() var points := _get_shape_points_filled(_rect.size) for p in points: var pos: Vector2 = position + p if pos.x < 0 or pos.y < 0 or pos.x >= bitmap_size.x or pos.y >= bitmap_size.y: continue if _intersect: - if project.selection_bitmap.get_bit(pos): - bitmap.set_bit(pos, true) + if project.selection_map.is_pixel_selected(pos): + selection_map.select_pixel(pos, true) else: - bitmap.set_bit(pos, !_subtract) + selection_map.select_pixel(pos, !_subtract) # Given an origin point and destination point, returns a rect representing diff --git a/src/Tools/SelectionTools/Lasso.gd b/src/Tools/SelectionTools/Lasso.gd index 650a6ba23..15b040e06 100644 --- a/src/Tools/SelectionTools/Lasso.gd +++ b/src/Tools/SelectionTools/Lasso.gd @@ -77,24 +77,22 @@ func apply_selection(_position) -> void: cleared = true Global.canvas.selection.clear_selection() if _draw_points.size() > 3: - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() - var bitmap_size: Vector2 = selection_bitmap_copy.get_size() + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) if _intersect: - selection_bitmap_copy.set_bit_rect(Rect2(Vector2.ZERO, bitmap_size), false) - lasso_selection(selection_bitmap_copy, _draw_points) + selection_map_copy.clear() + lasso_selection(selection_map_copy, _draw_points) # Handle mirroring if Tools.horizontal_mirror: - lasso_selection(selection_bitmap_copy, mirror_array(_draw_points, true, false)) + lasso_selection(selection_map_copy, mirror_array(_draw_points, true, false)) if Tools.vertical_mirror: - lasso_selection(selection_bitmap_copy, mirror_array(_draw_points, true, true)) + lasso_selection(selection_map_copy, mirror_array(_draw_points, true, true)) if Tools.vertical_mirror: - lasso_selection(selection_bitmap_copy, mirror_array(_draw_points, false, true)) + lasso_selection(selection_map_copy, mirror_array(_draw_points, false, true)) - project.selection_bitmap = selection_bitmap_copy - Global.canvas.selection.big_bounding_rectangle = project.get_selection_rectangle( - project.selection_bitmap - ) + project.selection_map = selection_map_copy + Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect() else: if !cleared: Global.canvas.selection.clear_selection() @@ -104,17 +102,17 @@ func apply_selection(_position) -> void: _last_position = Vector2.INF -func lasso_selection(bitmap: BitMap, points: PoolVector2Array) -> void: +func lasso_selection(selection_map: SelectionMap, points: PoolVector2Array) -> void: var project: Project = Global.current_project - var size := bitmap.get_size() + var size := selection_map.get_size() for point in points: if point.x < 0 or point.y < 0 or point.x >= size.x or point.y >= size.y: continue if _intersect: - if project.selection_bitmap.get_bit(point): - bitmap.set_bit(point, true) + if project.selection_map.is_pixel_selected(point): + selection_map.select_pixel(point, true) else: - bitmap.set_bit(point, !_subtract) + selection_map.select_pixel(point, !_subtract) var v := Vector2() var image_size: Vector2 = project.size @@ -124,10 +122,10 @@ func lasso_selection(bitmap: BitMap, points: PoolVector2Array) -> void: v.y = y if Geometry.is_point_in_polygon(v, points): if _intersect: - if project.selection_bitmap.get_bit(v): - bitmap.set_bit(v, true) + if project.selection_map.is_pixel_selected(v): + selection_map.select_pixel(v, true) else: - bitmap.set_bit(v, !_subtract) + selection_map.select_pixel(v, !_subtract) # Bresenham's Algorithm diff --git a/src/Tools/SelectionTools/MagicWand.gd b/src/Tools/SelectionTools/MagicWand.gd index e4e43e785..cf3310847 100644 --- a/src/Tools/SelectionTools/MagicWand.gd +++ b/src/Tools/SelectionTools/MagicWand.gd @@ -8,37 +8,38 @@ var _allegro_image_segments: Array func apply_selection(position: Vector2) -> void: var project: Project = Global.current_project + var size: Vector2 = project.size + if position.x < 0 or position.y < 0 or position.x >= size.x or position.y >= size.y: + return if !_add and !_subtract and !_intersect: Global.canvas.selection.clear_selection() - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) if _intersect: - var full_rect = Rect2(Vector2.ZERO, selection_bitmap_copy.get_size()) - selection_bitmap_copy.set_bit_rect(full_rect, false) + selection_map_copy.clear() var cel_image := Image.new() cel_image.copy_from(_get_draw_image()) cel_image.lock() - _flood_fill(position, cel_image, selection_bitmap_copy) + _flood_fill(position, cel_image, selection_map_copy) # Handle mirroring if Tools.horizontal_mirror: var mirror_x := position mirror_x.x = Global.current_project.x_symmetry_point - position.x - _flood_fill(mirror_x, cel_image, selection_bitmap_copy) + _flood_fill(mirror_x, cel_image, selection_map_copy) if Tools.vertical_mirror: var mirror_xy := mirror_x mirror_xy.y = Global.current_project.y_symmetry_point - position.y - _flood_fill(mirror_xy, cel_image, selection_bitmap_copy) + _flood_fill(mirror_xy, cel_image, selection_map_copy) if Tools.vertical_mirror: var mirror_y := position mirror_y.y = Global.current_project.y_symmetry_point - position.y - _flood_fill(mirror_y, cel_image, selection_bitmap_copy) + _flood_fill(mirror_y, cel_image, selection_map_copy) cel_image.unlock() - project.selection_bitmap = selection_bitmap_copy - Global.canvas.selection.big_bounding_rectangle = project.get_selection_rectangle( - project.selection_bitmap - ) + project.selection_map = selection_map_copy + Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect() Global.canvas.selection.commit_undo("Select", undo_data) @@ -128,7 +129,7 @@ func _check_flooded_segment( return ret -func _flood_fill(position: Vector2, image: Image, bitmap: BitMap) -> void: +func _flood_fill(position: Vector2, image: Image, selection_map: SelectionMap) -> void: # implements the floodfill routine by Shawn Hargreaves # from https://www1.udel.edu/CIS/software/dist/allegro-4.2.1/src/flood.c var project: Project = Global.current_project @@ -139,7 +140,7 @@ func _flood_fill(position: Vector2, image: Image, bitmap: BitMap) -> void: _compute_segments_for_image(position, project, image, color) # now actually color the image: since we have already checked a few things for the points # we'll process here, we're going to skip a bunch of safety checks to speed things up. - _select_segments(bitmap) + _select_segments(selection_map) func _compute_segments_for_image( @@ -171,18 +172,18 @@ func _compute_segments_for_image( done = false -func _select_segments(bitmap: BitMap) -> void: +func _select_segments(selection_map: SelectionMap) -> void: # short circuit for flat colors for c in _allegro_image_segments.size(): var p = _allegro_image_segments[c] for px in range(p.left_position, p.right_position + 1): # We don't have to check again whether the point being processed is within the bounds - _set_bit(Vector2(px, p.y), bitmap) + _set_bit(Vector2(px, p.y), selection_map) -func _set_bit(p: Vector2, bitmap: BitMap) -> void: +func _set_bit(p: Vector2, selection_map: SelectionMap) -> void: var project: Project = Global.current_project if _intersect: - bitmap.set_bit(p, project.selection_bitmap.get_bit(p)) + selection_map.select_pixel(p, project.selection_map.is_pixel_selected(p)) else: - bitmap.set_bit(p, !_subtract) + selection_map.select_pixel(p, !_subtract) diff --git a/src/Tools/SelectionTools/PolygonSelect.gd b/src/Tools/SelectionTools/PolygonSelect.gd index 961cf354f..8093f7ab9 100644 --- a/src/Tools/SelectionTools/PolygonSelect.gd +++ b/src/Tools/SelectionTools/PolygonSelect.gd @@ -113,24 +113,22 @@ func apply_selection(_position) -> void: cleared = true Global.canvas.selection.clear_selection() if _draw_points.size() > 3: - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() - var bitmap_size: Vector2 = selection_bitmap_copy.get_size() + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) if _intersect: - selection_bitmap_copy.set_bit_rect(Rect2(Vector2.ZERO, bitmap_size), false) - lasso_selection(selection_bitmap_copy, _draw_points) + selection_map_copy.clear() + lasso_selection(selection_map_copy, _draw_points) # Handle mirroring if Tools.horizontal_mirror: - lasso_selection(selection_bitmap_copy, mirror_array(_draw_points, true, false)) + lasso_selection(selection_map_copy, mirror_array(_draw_points, true, false)) if Tools.vertical_mirror: - lasso_selection(selection_bitmap_copy, mirror_array(_draw_points, true, true)) + lasso_selection(selection_map_copy, mirror_array(_draw_points, true, true)) if Tools.vertical_mirror: - lasso_selection(selection_bitmap_copy, mirror_array(_draw_points, false, true)) + lasso_selection(selection_map_copy, mirror_array(_draw_points, false, true)) - project.selection_bitmap = selection_bitmap_copy - Global.canvas.selection.big_bounding_rectangle = project.get_selection_rectangle( - project.selection_bitmap - ) + project.selection_map = selection_map_copy + Global.canvas.selection.big_bounding_rectangle = project.selection_map.get_used_rect() else: if !cleared: Global.canvas.selection.clear_selection() @@ -142,17 +140,17 @@ func apply_selection(_position) -> void: Global.canvas.previews.update() -func lasso_selection(bitmap: BitMap, points: PoolVector2Array) -> void: +func lasso_selection(selection_map: SelectionMap, points: PoolVector2Array) -> void: var project: Project = Global.current_project - var size := bitmap.get_size() + var size := selection_map.get_size() for point in points: if point.x < 0 or point.y < 0 or point.x >= size.x or point.y >= size.y: continue if _intersect: - if project.selection_bitmap.get_bit(point): - bitmap.set_bit(point, true) + if project.selection_map.is_pixel_selected(point): + selection_map.select_pixel(point, true) else: - bitmap.set_bit(point, !_subtract) + selection_map.select_pixel(point, !_subtract) var v := Vector2() var image_size: Vector2 = project.size @@ -162,10 +160,10 @@ func lasso_selection(bitmap: BitMap, points: PoolVector2Array) -> void: v.y = y if Geometry.is_point_in_polygon(v, points): if _intersect: - if project.selection_bitmap.get_bit(v): - bitmap.set_bit(v, true) + if project.selection_map.is_pixel_selected(v): + selection_map.select_pixel(v, true) else: - bitmap.set_bit(v, !_subtract) + selection_map.select_pixel(v, !_subtract) # Bresenham's Algorithm diff --git a/src/Tools/SelectionTools/RectSelect.gd b/src/Tools/SelectionTools/RectSelect.gd index 18097f75e..d26bc9a65 100644 --- a/src/Tools/SelectionTools/RectSelect.gd +++ b/src/Tools/SelectionTools/RectSelect.gd @@ -87,49 +87,39 @@ func draw_preview() -> void: canvas.draw_set_transform(canvas.position, canvas.rotation, canvas.scale) -func apply_selection(_position) -> void: +func apply_selection(_position: Vector2) -> void: + var project: Project = Global.current_project if !_add and !_subtract and !_intersect: Global.canvas.selection.clear_selection() - if _rect.size == Vector2.ZERO and Global.current_project.has_selection: + if _rect.size == Vector2.ZERO and project.has_selection: Global.canvas.selection.commit_undo("Select", undo_data) - if _rect.size != Vector2.ZERO: - var operation := 0 - if _subtract: - operation = 1 - elif _intersect: - operation = 2 - Global.canvas.selection.select_rect(_rect, operation) + if _rect.size == Vector2.ZERO: + return + var operation := 0 + if _subtract: + operation = 1 + elif _intersect: + operation = 2 + Global.canvas.selection.select_rect(_rect, operation) - # Handle mirroring - if Tools.horizontal_mirror: - var mirror_x_rect := _rect - mirror_x_rect.position.x = ( - Global.current_project.x_symmetry_point - - _rect.position.x - + 1 - ) - mirror_x_rect.end.x = Global.current_project.x_symmetry_point - _rect.end.x + 1 - Global.canvas.selection.select_rect(mirror_x_rect.abs(), operation) - if Tools.vertical_mirror: - var mirror_xy_rect := mirror_x_rect - mirror_xy_rect.position.y = ( - Global.current_project.y_symmetry_point - - _rect.position.y - + 1 - ) - mirror_xy_rect.end.y = Global.current_project.y_symmetry_point - _rect.end.y + 1 - Global.canvas.selection.select_rect(mirror_xy_rect.abs(), operation) + # Handle mirroring + if Tools.horizontal_mirror: + var mirror_x_rect := _rect + mirror_x_rect.position.x = project.x_symmetry_point - _rect.position.x + 1 + mirror_x_rect.end.x = project.x_symmetry_point - _rect.end.x + 1 + Global.canvas.selection.select_rect(mirror_x_rect.abs(), operation) if Tools.vertical_mirror: - var mirror_y_rect := _rect - mirror_y_rect.position.y = ( - Global.current_project.y_symmetry_point - - _rect.position.y - + 1 - ) - mirror_y_rect.end.y = Global.current_project.y_symmetry_point - _rect.end.y + 1 - Global.canvas.selection.select_rect(mirror_y_rect.abs(), operation) + var mirror_xy_rect := mirror_x_rect + mirror_xy_rect.position.y = project.y_symmetry_point - _rect.position.y + 1 + mirror_xy_rect.end.y = project.y_symmetry_point - _rect.end.y + 1 + Global.canvas.selection.select_rect(mirror_xy_rect.abs(), operation) + if Tools.vertical_mirror: + var mirror_y_rect := _rect + mirror_y_rect.position.y = project.y_symmetry_point - _rect.position.y + 1 + mirror_y_rect.end.y = project.y_symmetry_point - _rect.end.y + 1 + Global.canvas.selection.select_rect(mirror_y_rect.abs(), operation) - Global.canvas.selection.commit_undo("Select", undo_data) + Global.canvas.selection.commit_undo("Select", undo_data) # Given an origin point and destination point, returns a rect representing diff --git a/src/Tools/SelectionTools/SelectionTool.gd b/src/Tools/SelectionTools/SelectionTool.gd index 34719f861..594a37af8 100644 --- a/src/Tools/SelectionTools/SelectionTool.gd +++ b/src/Tools/SelectionTools/SelectionTool.gd @@ -66,7 +66,7 @@ func draw_start(position: Vector2) -> void: if ( offsetted_pos.x >= 0 and offsetted_pos.y >= 0 - and project.selection_bitmap.get_bit(offsetted_pos) + and project.selection_map.is_pixel_selected(offsetted_pos) and (!_add and !_subtract and !_intersect or quick_copy) and !_ongoing_selection ): @@ -81,14 +81,15 @@ func draw_start(position: Vector2) -> void: image.blit_rect_mask( selection_node.preview_image, selection_node.preview_image, - Rect2(Vector2.ZERO, project.selection_bitmap.get_size()), + Rect2(Vector2.ZERO, project.selection_map.get_size()), selection_node.big_bounding_rectangle.position ) - var selected_bitmap_copy = project.selection_bitmap.duplicate() - project.move_bitmap_values(selected_bitmap_copy) + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) + selection_map_copy.move_bitmap_values(project) - project.selection_bitmap = selected_bitmap_copy + project.selection_map = selection_map_copy selection_node.commit_undo("Move Selection", selection_node.undo_data) selection_node.undo_data = selection_node.get_undo_data(true) else: @@ -98,7 +99,7 @@ func draw_start(position: Vector2) -> void: image.blit_rect_mask( selection_node.preview_image, selection_node.preview_image, - Rect2(Vector2.ZERO, project.selection_bitmap.get_size()), + Rect2(Vector2.ZERO, project.selection_map.get_size()), selection_node.big_bounding_rectangle.position ) Global.canvas.update_selected_cels_textures() @@ -190,10 +191,11 @@ func _on_XSpinBox_value_changed(value: float) -> void: timer.start() selection_node.big_bounding_rectangle.position.x = value - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() - project.move_bitmap_values(selection_bitmap_copy) - project.selection_bitmap = selection_bitmap_copy - project.selection_bitmap_changed() + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) + selection_map_copy.move_bitmap_values(project) + project.selection_map = selection_map_copy + project.selection_map_changed() func _on_YSpinBox_value_changed(value: float) -> void: @@ -205,10 +207,11 @@ func _on_YSpinBox_value_changed(value: float) -> void: timer.start() selection_node.big_bounding_rectangle.position.y = value - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() - project.move_bitmap_values(selection_bitmap_copy) - project.selection_bitmap = selection_bitmap_copy - project.selection_bitmap_changed() + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) + selection_map_copy.move_bitmap_values(project) + project.selection_map = selection_map_copy + project.selection_map_changed() func _on_WSpinBox_value_changed(value: float) -> void: @@ -243,9 +246,9 @@ func _on_HSpinBox_value_changed(value: float) -> void: func resize_selection() -> void: var project: Project = Global.current_project - var bitmap: BitMap = project.selection_bitmap + var image: SelectionMap = project.selection_map if selection_node.is_moving_content: - bitmap = selection_node.original_bitmap + image = selection_node.original_bitmap var preview_image: Image = selection_node.preview_image preview_image.copy_from(selection_node.original_preview_image) preview_image.resize( @@ -255,12 +258,13 @@ func resize_selection() -> void: ) selection_node.preview_image_texture.create_from_image(preview_image, 0) - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() - selection_bitmap_copy = project.resize_bitmap_values( - bitmap, selection_node.big_bounding_rectangle.size, false, false + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(image) + selection_map_copy.resize_bitmap_values( + project, selection_node.big_bounding_rectangle.size, false, false ) - project.selection_bitmap = selection_bitmap_copy - project.selection_bitmap_changed() + project.selection_map = selection_map_copy + project.selection_map_changed() func _on_Timer_timeout() -> void: diff --git a/src/UI/Canvas/Selection.gd b/src/UI/Canvas/Selection.gd index 6677739c0..f78952598 100644 --- a/src/UI/Canvas/Selection.gd +++ b/src/UI/Canvas/Selection.gd @@ -10,14 +10,14 @@ var is_pasting := false var big_bounding_rectangle := Rect2() setget _big_bounding_rectangle_changed var temp_rect := Rect2() -var temp_bitmap := BitMap.new() +var temp_bitmap := SelectionMap.new() var rect_aspect_ratio := 0.0 var temp_rect_size := Vector2.ZERO var temp_rect_pivot := Vector2.ZERO var original_big_bounding_rectangle := Rect2() var original_preview_image := Image.new() -var original_bitmap := BitMap.new() +var original_bitmap := SelectionMap.new() var original_offset := Vector2.ZERO var preview_image := Image.new() @@ -114,7 +114,7 @@ func _input(event: InputEvent) -> void: if Input.is_action_pressed("transform_move_selection_only"): undo_data = get_undo_data(false) temp_rect = big_bounding_rectangle - temp_bitmap = Global.current_project.selection_bitmap + temp_bitmap = Global.current_project.selection_map else: transform_content_start() Global.current_project.selection_offset = Vector2.ZERO @@ -279,8 +279,8 @@ func _update_gizmos() -> void: func update_on_zoom(zoom: float) -> void: var size := max( - Global.current_project.selection_bitmap.get_size().x, - Global.current_project.selection_bitmap.get_size().y + Global.current_project.selection_map.get_size().x, + Global.current_project.selection_map.get_size().y ) marching_ants_outline.material.set_shader_param("width", zoom) marching_ants_outline.material.set_shader_param("frequency", (1.0 / zoom) * 10 * size / 64) @@ -351,10 +351,14 @@ func _gizmo_resize() -> void: if temp_rect.size.y < 0: preview_image.flip_y() preview_image_texture.create_from_image(preview_image, 0) - Global.current_project.selection_bitmap = Global.current_project.resize_bitmap_values( - temp_bitmap, size, temp_rect.size.x < 0, temp_rect.size.y < 0 + + var temp_bitmap_copy := SelectionMap.new() + temp_bitmap_copy.copy_from(temp_bitmap) + temp_bitmap_copy.resize_bitmap_values( + Global.current_project, size, temp_rect.size.x < 0, temp_rect.size.y < 0 ) - Global.current_project.selection_bitmap_changed() + Global.current_project.selection_map = temp_bitmap_copy + Global.current_project.selection_map_changed() update() @@ -400,21 +404,22 @@ func _gizmo_rotate() -> void: # Does not work properly yet DrawingAlgos.nn_rotate(preview_image, angle, pivot) preview_image_texture.create_from_image(preview_image, 0) - var bitmap_image = Global.current_project.bitmap_to_image(original_bitmap) + var bitmap_image := original_bitmap var bitmap_pivot = ( original_big_bounding_rectangle.position + ((original_big_bounding_rectangle.end - original_big_bounding_rectangle.position) / 2) ) DrawingAlgos.nn_rotate(bitmap_image, angle, bitmap_pivot) - Global.current_project.selection_bitmap.create_from_image_alpha(bitmap_image) - Global.current_project.selection_bitmap_changed() + Global.current_project.selection_map = bitmap_image + Global.current_project.selection_map_changed() self.big_bounding_rectangle = bitmap_image.get_used_rect() update() func select_rect(rect: Rect2, operation: int = SelectionOperation.ADD) -> void: var project: Project = Global.current_project - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) # Used only if the selection is outside of the canvas boundaries, # on the left and/or above (negative coords) var offset_position := Vector2.ZERO @@ -427,28 +432,27 @@ func select_rect(rect: Rect2, operation: int = SelectionOperation.ADD) -> void: if offset_position != Vector2.ZERO: big_bounding_rectangle.position -= offset_position - project.move_bitmap_values(selection_bitmap_copy) + selection_map_copy.move_bitmap_values(project) if operation == SelectionOperation.ADD: - selection_bitmap_copy.set_bit_rect(rect, true) + selection_map_copy.fill_rect(rect, Color(1, 1, 1, 1)) elif operation == SelectionOperation.SUBTRACT: - selection_bitmap_copy.set_bit_rect(rect, false) + selection_map_copy.fill_rect(rect, Color(0)) elif operation == SelectionOperation.INTERSECT: - var full_rect = Rect2(Vector2.ZERO, selection_bitmap_copy.get_size()) - selection_bitmap_copy.set_bit_rect(full_rect, false) + selection_map_copy.clear() for x in range(rect.position.x, rect.end.x): for y in range(rect.position.y, rect.end.y): var pos := Vector2(x, y) - if !Rect2(Vector2.ZERO, selection_bitmap_copy.get_size()).has_point(pos): + if !Rect2(Vector2.ZERO, selection_map_copy.get_size()).has_point(pos): continue - selection_bitmap_copy.set_bit(pos, project.selection_bitmap.get_bit(pos)) - big_bounding_rectangle = project.get_selection_rectangle(selection_bitmap_copy) + selection_map_copy.select_pixel(pos, project.selection_map.is_pixel_selected(pos)) + big_bounding_rectangle = selection_map_copy.get_used_rect() if offset_position != Vector2.ZERO: big_bounding_rectangle.position += offset_position - project.move_bitmap_values(selection_bitmap_copy) + selection_map_copy.move_bitmap_values(project) - project.selection_bitmap = selection_bitmap_copy + project.selection_map = selection_map_copy self.big_bounding_rectangle = big_bounding_rectangle # call getter method @@ -465,14 +469,15 @@ func move_borders(move: Vector2) -> void: func move_borders_end() -> void: - var selected_bitmap_copy: BitMap = Global.current_project.selection_bitmap.duplicate() - Global.current_project.move_bitmap_values(selected_bitmap_copy) + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(Global.current_project.selection_map) + selection_map_copy.move_bitmap_values(Global.current_project) - Global.current_project.selection_bitmap = selected_bitmap_copy + Global.current_project.selection_map = selection_map_copy if !is_moving_content: commit_undo("Select", undo_data) else: - Global.current_project.selection_bitmap_changed() + Global.current_project.selection_map_changed() update() @@ -480,13 +485,13 @@ func transform_content_start() -> void: if !is_moving_content: undo_data = get_undo_data(true) temp_rect = big_bounding_rectangle - temp_bitmap = Global.current_project.selection_bitmap + temp_bitmap = Global.current_project.selection_map _get_preview_image() if original_preview_image.is_empty(): undo_data = get_undo_data(false) return is_moving_content = true - original_bitmap = Global.current_project.selection_bitmap.duplicate() + original_bitmap.copy_from(Global.current_project.selection_map) original_big_bounding_rectangle = big_bounding_rectangle original_offset = Global.current_project.selection_offset update() @@ -525,17 +530,18 @@ func transform_content_confirm() -> void: cel_image.blit_rect_mask( src, src, - Rect2(Vector2.ZERO, project.selection_bitmap.get_size()), + Rect2(Vector2.ZERO, project.selection_map.get_size()), big_bounding_rectangle.position ) - var selected_bitmap_copy = project.selection_bitmap.duplicate() - project.move_bitmap_values(selected_bitmap_copy) - project.selection_bitmap = selected_bitmap_copy + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) + selection_map_copy.move_bitmap_values(project) + project.selection_map = selection_map_copy commit_undo("Move Selection", undo_data) original_preview_image = Image.new() preview_image = Image.new() - original_bitmap = BitMap.new() + original_bitmap = SelectionMap.new() is_moving_content = false is_pasting = false clear_in_selected_cels = true @@ -550,21 +556,21 @@ func transform_content_cancel() -> void: is_moving_content = false self.big_bounding_rectangle = original_big_bounding_rectangle - project.selection_bitmap = original_bitmap - project.selection_bitmap_changed() + project.selection_map = original_bitmap + project.selection_map_changed() preview_image = original_preview_image if !is_pasting: var cel_image: Image = project.frames[project.current_frame].cels[project.current_layer].image cel_image.blit_rect_mask( preview_image, preview_image, - Rect2(Vector2.ZERO, Global.current_project.selection_bitmap.get_size()), + Rect2(Vector2.ZERO, Global.current_project.selection_map.get_size()), big_bounding_rectangle.position ) Global.canvas.update_texture(project.current_layer) original_preview_image = Image.new() preview_image = Image.new() - original_bitmap = BitMap.new() + original_bitmap = SelectionMap.new() is_pasting = false update() @@ -578,15 +584,13 @@ func commit_undo(action: String, undo_data_tmp: Dictionary) -> void: project.undos += 1 project.undo_redo.create_action(action) - project.undo_redo.add_do_property(project, "selection_bitmap", redo_data["selection_bitmap"]) + project.undo_redo.add_do_property(project, "selection_map", redo_data["selection_map"]) project.undo_redo.add_do_property( self, "big_bounding_rectangle", redo_data["big_bounding_rectangle"] ) project.undo_redo.add_do_property(project, "selection_offset", redo_data["outline_offset"]) - project.undo_redo.add_undo_property( - project, "selection_bitmap", undo_data_tmp["selection_bitmap"] - ) + project.undo_redo.add_undo_property(project, "selection_map", undo_data_tmp["selection_map"]) project.undo_redo.add_undo_property( self, "big_bounding_rectangle", undo_data_tmp["big_bounding_rectangle"] ) @@ -605,9 +609,9 @@ func commit_undo(action: String, undo_data_tmp: Dictionary) -> void: continue project.undo_redo.add_undo_property(image, "data", undo_data_tmp[image]) project.undo_redo.add_do_method(Global, "undo_or_redo", false) - project.undo_redo.add_do_method(project, "selection_bitmap_changed") + project.undo_redo.add_do_method(project, "selection_map_changed") project.undo_redo.add_undo_method(Global, "undo_or_redo", true) - project.undo_redo.add_undo_method(project, "selection_bitmap_changed") + project.undo_redo.add_undo_method(project, "selection_map_changed") project.undo_redo.commit_action() undo_data.clear() @@ -616,7 +620,7 @@ func commit_undo(action: String, undo_data_tmp: Dictionary) -> void: func get_undo_data(undo_image: bool) -> Dictionary: var data := {} var project: Project = Global.current_project - data["selection_bitmap"] = project.selection_bitmap + data["selection_map"] = project.selection_map data["big_bounding_rectangle"] = big_bounding_rectangle data["outline_offset"] = Global.current_project.selection_offset data["undo_image"] = undo_image @@ -651,7 +655,7 @@ func cut() -> void: func copy() -> void: var project: Project = Global.current_project var cl_image := Image.new() - var cl_selection_bitmap = BitMap.new() + var cl_selection_map := SelectionMap.new() var cl_big_bounding_rectangle := Rect2() var cl_selection_offset := Vector2.ZERO @@ -661,9 +665,10 @@ func copy() -> void: var to_copy := Image.new() if is_moving_content: to_copy.copy_from(preview_image) - var selected_bitmap_copy := project.selection_bitmap.duplicate() - project.move_bitmap_values(selected_bitmap_copy, false) - cl_selection_bitmap = selected_bitmap_copy + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) + selection_map_copy.move_bitmap_values(project, false) + cl_selection_map = selection_map_copy else: to_copy = image.get_rect(big_bounding_rectangle) to_copy.lock() @@ -676,22 +681,22 @@ func copy() -> void: offset_pos.x = 0 if offset_pos.y < 0: offset_pos.y = 0 - if not project.selection_bitmap.get_bit(pos + offset_pos): + if not project.selection_map.is_pixel_selected(pos + offset_pos): to_copy.set_pixelv(pos, Color(0)) to_copy.unlock() - cl_selection_bitmap = project.selection_bitmap.duplicate() + cl_selection_map.copy_from(project.selection_map) cl_image = to_copy cl_big_bounding_rectangle = big_bounding_rectangle cl_selection_offset = project.selection_offset - var transfer_clipboard = { + var transfer_clipboard := { "image": cl_image, - "selection_bitmap": cl_selection_bitmap, + "selection_map": cl_selection_map.data, "big_bounding_rectangle": cl_big_bounding_rectangle, "selection_offset": cl_selection_offset, } # Store to ".clipboard.txt" file - var clipboard_file = File.new() + var clipboard_file := File.new() clipboard_file.open("user://clipboard.txt", File.WRITE) clipboard_file.store_var(transfer_clipboard, true) clipboard_file.close() @@ -707,7 +712,7 @@ func copy() -> void: func paste() -> void: # Read from the ".clipboard.txt" file - var clipboard_file = File.new() + var clipboard_file := File.new() if !clipboard_file.file_exists("user://clipboard.txt"): return clipboard_file.open("user://clipboard.txt", File.READ) @@ -717,7 +722,7 @@ func paste() -> void: if typeof(clipboard) == TYPE_DICTIONARY: # A sanity check if not clipboard.has_all( - ["image", "selection_bitmap", "big_bounding_rectangle", "selection_offset"] + ["image", "selection_map", "big_bounding_rectangle", "selection_offset"] ): return @@ -727,21 +732,23 @@ func paste() -> void: undo_data = get_undo_data(true) var project: Project = Global.current_project - original_bitmap = project.selection_bitmap.duplicate() + original_bitmap.copy_from(project.selection_map) original_big_bounding_rectangle = big_bounding_rectangle original_offset = project.selection_offset - var clip_bitmap: BitMap = clipboard.selection_bitmap.duplicate() + var clip_map := SelectionMap.new() + clip_map.data = clipboard.selection_map var max_size := Vector2( - max(clip_bitmap.get_size().x, project.selection_bitmap.get_size().x), - max(clip_bitmap.get_size().y, project.selection_bitmap.get_size().y) + max(clip_map.get_size().x, project.selection_map.get_size().x), + max(clip_map.get_size().y, project.selection_map.get_size().y) ) - project.selection_bitmap = Global.current_project.resize_bitmap(clip_bitmap, max_size) + project.selection_map = clip_map + project.selection_map.crop(max_size.x, max_size.y) self.big_bounding_rectangle = clipboard.big_bounding_rectangle project.selection_offset = clipboard.selection_offset - temp_bitmap = project.selection_bitmap + temp_bitmap = project.selection_map temp_rect = big_bounding_rectangle is_moving_content = true is_pasting = true @@ -749,7 +756,7 @@ func paste() -> void: preview_image.copy_from(original_preview_image) preview_image_texture.create_from_image(preview_image, 0) - project.selection_bitmap_changed() + project.selection_map_changed() func delete(selected_cels := true) -> void: @@ -762,7 +769,7 @@ func delete(selected_cels := true) -> void: is_moving_content = false original_preview_image = Image.new() preview_image = Image.new() - original_bitmap = BitMap.new() + original_bitmap = SelectionMap.new() is_pasting = false update() commit_undo("Draw", undo_data) @@ -793,16 +800,17 @@ func new_brush() -> void: var brush := Image.new() if is_moving_content: brush.copy_from(preview_image) - var selected_bitmap_copy := project.selection_bitmap.duplicate() - project.move_bitmap_values(selected_bitmap_copy, false) + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) + selection_map_copy.move_bitmap_values(project, false) var clipboard = str2var(OS.get_clipboard()) if typeof(clipboard) == TYPE_DICTIONARY: # A sanity check if not clipboard.has_all( - ["image", "selection_bitmap", "big_bounding_rectangle", "selection_offset"] + ["image", "selection_map", "big_bounding_rectangle", "selection_offset"] ): return - clipboard.selection_bitmap = selected_bitmap_copy + clipboard.selection_map = selection_map_copy else: brush = image.get_rect(big_bounding_rectangle) brush.lock() @@ -815,7 +823,7 @@ func new_brush() -> void: offset_pos.x = 0 if offset_pos.y < 0: offset_pos.y = 0 - if not project.selection_bitmap.get_bit(pos + offset_pos): + if not project.selection_map.is_pixel_selected(pos + offset_pos): brush.set_pixelv(pos, Color(0)) brush.unlock() @@ -838,12 +846,13 @@ func invert() -> void: transform_content_confirm() var project: Project = Global.current_project var undo_data_tmp = get_undo_data(false) - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() - selection_bitmap_copy = project.resize_bitmap(selection_bitmap_copy, project.size) - project.invert_bitmap(selection_bitmap_copy) - project.selection_bitmap = selection_bitmap_copy - project.selection_bitmap_changed() - self.big_bounding_rectangle = project.get_selection_rectangle(selection_bitmap_copy) + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) + selection_map_copy.crop(project.size.x, project.size.y) + selection_map_copy.invert() + project.selection_map = selection_map_copy + project.selection_map_changed() + self.big_bounding_rectangle = selection_map_copy.get_used_rect() project.selection_offset = Vector2.ZERO commit_undo("Select", undo_data_tmp) @@ -854,11 +863,11 @@ func clear_selection(use_undo := false) -> void: return transform_content_confirm() var undo_data_tmp = get_undo_data(false) - var selection_bitmap_copy: BitMap = project.selection_bitmap.duplicate() - selection_bitmap_copy = project.resize_bitmap(selection_bitmap_copy, project.size) - var full_rect = Rect2(Vector2.ZERO, selection_bitmap_copy.get_size()) - selection_bitmap_copy.set_bit_rect(full_rect, false) - project.selection_bitmap = selection_bitmap_copy + var selection_map_copy := SelectionMap.new() + selection_map_copy.copy_from(project.selection_map) + selection_map_copy.crop(project.size.x, project.size.y) + selection_map_copy.clear() + project.selection_map = selection_map_copy self.big_bounding_rectangle = Rect2() project.selection_offset = Vector2.ZERO @@ -898,7 +907,7 @@ func _get_preview_image() -> void: cel_image.blit_rect_mask( clear_image, original_preview_image, - Rect2(Vector2.ZERO, Global.current_project.selection_bitmap.get_size()), + Rect2(Vector2.ZERO, Global.current_project.selection_map.get_size()), big_bounding_rectangle.position ) Global.canvas.update_texture(project.current_layer) @@ -930,7 +939,7 @@ func _get_selected_image(cel_image: Image, clear := true) -> Image: cel_image.blit_rect_mask( clear_image, image, - Rect2(Vector2.ZERO, Global.current_project.selection_bitmap.get_size()), + Rect2(Vector2.ZERO, Global.current_project.selection_map.get_size()), original_big_bounding_rectangle.position ) Global.canvas.update_texture(project.current_layer) diff --git a/src/UI/Dialogs/ImageEffects/DesaturateDialog.gd b/src/UI/Dialogs/ImageEffects/DesaturateDialog.gd index 7b14b1333..292fb89ed 100644 --- a/src/UI/Dialogs/ImageEffects/DesaturateDialog.gd +++ b/src/UI/Dialogs/ImageEffects/DesaturateDialog.gd @@ -23,8 +23,7 @@ func set_nodes() -> void: func commit_action(cel: Image, project: Project = Global.current_project) -> void: var selection_tex := ImageTexture.new() if selection_checkbox.pressed and project.has_selection: - var selection: Image = project.bitmap_to_image(project.selection_bitmap) - selection_tex.create_from_image(selection, 0) + selection_tex.create_from_image(project.selection_map, 0) var params := { "red": red, diff --git a/src/UI/Dialogs/ImageEffects/DropShadowDialog.gd b/src/UI/Dialogs/ImageEffects/DropShadowDialog.gd index 8cb04fda6..72ab29ba8 100644 --- a/src/UI/Dialogs/ImageEffects/DropShadowDialog.gd +++ b/src/UI/Dialogs/ImageEffects/DropShadowDialog.gd @@ -26,8 +26,7 @@ func set_nodes() -> void: func commit_action(cel: Image, project: Project = Global.current_project) -> void: var selection_tex := ImageTexture.new() if selection_checkbox.pressed and project.has_selection: - var selection: Image = project.bitmap_to_image(project.selection_bitmap) - selection_tex.create_from_image(selection, 0) + selection_tex.create_from_image(project.selection_map, 0) var params := { "shadow_offset": offset, diff --git a/src/UI/Dialogs/ImageEffects/FlipImageDialog.gd b/src/UI/Dialogs/ImageEffects/FlipImageDialog.gd index 8cbce5f79..cdaacd860 100644 --- a/src/UI/Dialogs/ImageEffects/FlipImageDialog.gd +++ b/src/UI/Dialogs/ImageEffects/FlipImageDialog.gd @@ -33,7 +33,7 @@ func _flip_image(cel: Image, affect_selection: bool, project: Project) -> void: var selected := Image.new() var rectangle: Rect2 = Global.canvas.selection.big_bounding_rectangle if project != Global.current_project: - rectangle = project.get_selection_rectangle() + rectangle = project.selection_map.get_used_rect() selected = cel.get_rect(rectangle) selected.lock() cel.lock() @@ -61,9 +61,9 @@ func _commit_undo(action: String, undo_data: Dictionary, project: Project) -> vo var redo_data := _get_undo_data(project) project.undos += 1 project.undo_redo.create_action(action) - project.undo_redo.add_do_property(project, "selection_bitmap", redo_data["selection_bitmap"]) + project.undo_redo.add_do_property(project, "selection_map", redo_data["selection_map"]) project.undo_redo.add_do_property(project, "selection_offset", redo_data["outline_offset"]) - project.undo_redo.add_undo_property(project, "selection_bitmap", undo_data["selection_bitmap"]) + project.undo_redo.add_undo_property(project, "selection_map", undo_data["selection_map"]) project.undo_redo.add_undo_property(project, "selection_offset", undo_data["outline_offset"]) for image in redo_data: @@ -76,15 +76,17 @@ func _commit_undo(action: String, undo_data: Dictionary, project: Project) -> vo continue project.undo_redo.add_undo_property(image, "data", undo_data[image]) project.undo_redo.add_do_method(Global, "undo_or_redo", false, -1, -1, project) - project.undo_redo.add_do_method(project, "selection_bitmap_changed") + project.undo_redo.add_do_method(project, "selection_map_changed") project.undo_redo.add_undo_method(Global, "undo_or_redo", true, -1, -1, project) - project.undo_redo.add_undo_method(project, "selection_bitmap_changed") + project.undo_redo.add_undo_method(project, "selection_map_changed") project.undo_redo.commit_action() func _get_undo_data(project: Project) -> Dictionary: + var bitmap_image := SelectionMap.new() + bitmap_image.copy_from(project.selection_map) var data := {} - data["selection_bitmap"] = project.selection_bitmap.duplicate() + data["selection_map"] = bitmap_image data["outline_offset"] = project.selection_offset var images := _get_selected_draw_images(project) @@ -99,7 +101,8 @@ func _flip_selection(project: Project = Global.current_project) -> void: if !(selection_checkbox.pressed and project.has_selection): return - var bitmap_image: Image = project.bitmap_to_image(project.selection_bitmap) + var bitmap_image := SelectionMap.new() + bitmap_image.copy_from(project.selection_map) var selection_rect := bitmap_image.get_used_rect() var smaller_bitmap_image := bitmap_image.get_rect(selection_rect) @@ -114,6 +117,4 @@ func _flip_selection(project: Project = Global.current_project) -> void: Rect2(Vector2.ZERO, smaller_bitmap_image.get_size()), selection_rect.position ) - var bitmap_copy: BitMap = project.selection_bitmap.duplicate() - bitmap_copy.create_from_image_alpha(bitmap_image) - project.selection_bitmap = bitmap_copy + project.selection_map = bitmap_image diff --git a/src/UI/Dialogs/ImageEffects/GradientDialog.gd b/src/UI/Dialogs/ImageEffects/GradientDialog.gd index 09350ee0c..81bf8c1af 100644 --- a/src/UI/Dialogs/ImageEffects/GradientDialog.gd +++ b/src/UI/Dialogs/ImageEffects/GradientDialog.gd @@ -65,7 +65,7 @@ func commit_action(cel: Image, project: Project = Global.current_project) -> voi var selection: Image var selection_tex := ImageTexture.new() if selection_checkbox.pressed and project.has_selection: - selection = project.bitmap_to_image(project.selection_bitmap) + selection = project.selection_map else: # This is needed to prevent a weird bug with the dithering shaders and GLES2 selection = Image.new() selection.create(project.size.x, project.size.y, false, Image.FORMAT_L8) diff --git a/src/UI/Dialogs/ImageEffects/GradientMapDialog.gd b/src/UI/Dialogs/ImageEffects/GradientMapDialog.gd index dbc09590d..2794f3070 100644 --- a/src/UI/Dialogs/ImageEffects/GradientMapDialog.gd +++ b/src/UI/Dialogs/ImageEffects/GradientMapDialog.gd @@ -18,8 +18,7 @@ func set_nodes() -> void: func commit_action(cel: Image, project: Project = Global.current_project) -> void: var selection_tex := ImageTexture.new() if selection_checkbox.pressed and project.has_selection: - var selection: Image = project.bitmap_to_image(project.selection_bitmap) - selection_tex.create_from_image(selection, 0) + selection_tex.create_from_image(project.selection_map, 0) var params := {"selection": selection_tex, "map": $VBoxContainer/GradientEdit.texture} diff --git a/src/UI/Dialogs/ImageEffects/HSVDialog.gd b/src/UI/Dialogs/ImageEffects/HSVDialog.gd index 576a79c6b..798920b75 100644 --- a/src/UI/Dialogs/ImageEffects/HSVDialog.gd +++ b/src/UI/Dialogs/ImageEffects/HSVDialog.gd @@ -35,8 +35,7 @@ func set_nodes() -> void: func commit_action(cel: Image, project: Project = Global.current_project) -> void: var selection_tex := ImageTexture.new() if selection_checkbox.pressed and project.has_selection: - var selection: Image = project.bitmap_to_image(project.selection_bitmap) - selection_tex.create_from_image(selection, 0) + selection_tex.create_from_image(project.selection_map, 0) var params := { "hue_shift_amount": hue_slider.value / 360, diff --git a/src/UI/Dialogs/ImageEffects/InvertColorsDialog.gd b/src/UI/Dialogs/ImageEffects/InvertColorsDialog.gd index bb44bcfbf..bed9530ce 100644 --- a/src/UI/Dialogs/ImageEffects/InvertColorsDialog.gd +++ b/src/UI/Dialogs/ImageEffects/InvertColorsDialog.gd @@ -23,8 +23,7 @@ func set_nodes() -> void: func commit_action(cel: Image, project: Project = Global.current_project) -> void: var selection_tex := ImageTexture.new() if selection_checkbox.pressed and project.has_selection: - var selection: Image = project.bitmap_to_image(project.selection_bitmap) - selection_tex.create_from_image(selection, 0) + selection_tex.create_from_image(project.selection_map, 0) var params := { "red": red, diff --git a/src/UI/Dialogs/ImageEffects/OutlineDialog.gd b/src/UI/Dialogs/ImageEffects/OutlineDialog.gd index c036ae1e9..3502c8301 100644 --- a/src/UI/Dialogs/ImageEffects/OutlineDialog.gd +++ b/src/UI/Dialogs/ImageEffects/OutlineDialog.gd @@ -36,8 +36,7 @@ func commit_action(cel: Image, project: Project = Global.current_project) -> voi var selection_tex := ImageTexture.new() if selection_checkbox.pressed and project.has_selection: - var selection: Image = project.bitmap_to_image(project.selection_bitmap) - selection_tex.create_from_image(selection, 0) + selection_tex.create_from_image(project.selection_map, 0) var params := { "color": color, diff --git a/src/UI/Dialogs/ImageEffects/RotateImage.gd b/src/UI/Dialogs/ImageEffects/RotateImage.gd index 2f1e7a5f9..5791bff17 100644 --- a/src/UI/Dialogs/ImageEffects/RotateImage.gd +++ b/src/UI/Dialogs/ImageEffects/RotateImage.gd @@ -61,7 +61,7 @@ func decide_pivot() -> void: pivot.y -= 0.5 if Global.current_project.has_selection and selection_checkbox.pressed: - var selection_rectangle: Rect2 = Global.current_project.get_selection_rectangle() + var selection_rectangle: Rect2 = Global.current_project.selection_map.get_used_rect() pivot = ( selection_rectangle.position + ((selection_rectangle.end - selection_rectangle.position) / 2) @@ -86,10 +86,10 @@ func commit_action(cel: Image, _project: Project = Global.current_project) -> vo var image := Image.new() image.copy_from(cel) if _project.has_selection and selection_checkbox.pressed: - var selection_rectangle: Rect2 = _project.get_selection_rectangle() + var selection_rectangle: Rect2 = _project.selection_map.get_used_rect() selection_size = selection_rectangle.size - var selection: Image = _project.bitmap_to_image(_project.selection_bitmap) + var selection: Image = _project.selection_map selection_tex.create_from_image(selection, 0) if !_type_is_shader():