From c54b74f829d3ab19487b7dbeac85854817e174bb Mon Sep 17 00:00:00 2001
From: Manolis Papadeas <35376950+OverloadedOrama@users.noreply.github.com>
Date: Sun, 31 Jan 2021 15:09:54 +0200
Subject: [PATCH] Having no active selection no longer treats all the pixels of
the canvas as selected
A performance boost for when opening large images. Also fixed an issue with pixels being selected outside of the canvas boundaries, when the selection rectangle was outside the canvas and its size got reduced.
---
CHANGELOG.md | 4 +++-
src/Classes/Drawers.gd | 2 +-
src/Classes/ImageEffect.gd | 4 ++--
src/Classes/Project.gd | 5 +----
src/Palette/PaletteContainer.gd | 2 +-
src/SelectionRectangle.gd | 2 +-
src/Tools/Base.gd | 7 +++++--
src/Tools/Bucket.gd | 18 ++++++++++++++----
src/Tools/Draw.gd | 6 +++---
9 files changed, 31 insertions(+), 19 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1c85f9340..3561dcc01 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,15 +29,17 @@ Laurenz Reinthaler (Schweini07), kleonc, Variable-ind
- Frame tags can now be set for frames larger than 100. ([#408](https://github.com/Orama-Interactive/Pixelorama/pull/408))
- The "lock aspect ratio" button in the create new image dialog has been changed to a texture button.
- Improved the "Scale Image" dialog. It now automatically sets the size to the current project's size, has a button to lock aspect ratio, and resizing based on percentage.
+- Having no active selection no longer treats all the pixels of the canvas as selected. This is also a performance boost, especially for larger images, as Pixelorama no longer has to loop through all of the pixels to select them.
- Tile mode rects are now cached for a little speedup. ([#443](https://github.com/Orama-Interactive/Pixelorama/pull/443))
### Fixed
+- Fixed issue with pixels being selected outside of the canvas boundaries, when the selection rectangle was outside the canvas and its size got reduced.
- Fixed layer button textures not being updated properly when changing theme. ([#404](https://github.com/Orama-Interactive/Pixelorama/issues/404))
- Keyboard shortcut conflicts between tool shortcuts and other shortcuts that use the "Control" key, like menu shortcuts, have been resolved. ([#407](https://github.com/Orama-Interactive/Pixelorama/pull/407))
- The opacity of a cel and the tile mode opacity are now multiplicative. ([#414](https://github.com/Orama-Interactive/Pixelorama/pull/414))
- Fixed an issue where adding a new layer did not select it, rather it was selecting the above layer of the previously selected layer. ([#424](https://github.com/Orama-Interactive/Pixelorama/pull/424))
- Fixed cel opacity not always being updated on the UI. ([#420](https://github.com/Orama-Interactive/Pixelorama/pull/420))
-- Loading empty backuped projects no longer result in a crash. ([#445](https://github.com/Orama-Interactive/Pixelorama/issues/445))
+- Loading empty backed up projects no longer result in a crash. ([#445](https://github.com/Orama-Interactive/Pixelorama/issues/445))
- Fixed potential index out of bounds error when loading backup files. ([#446](https://github.com/Orama-Interactive/Pixelorama/pull/446))
diff --git a/src/Classes/Drawers.gd b/src/Classes/Drawers.gd
index 951a428c0..3be9ca9ed 100644
--- a/src/Classes/Drawers.gd
+++ b/src/Classes/Drawers.gd
@@ -75,7 +75,7 @@ func set_pixel(image: Image, position: Vector2, color: Color) -> void:
var mirror_y = project.y_symmetry_point - position.y
var mirror_x_inside : bool
var mirror_y_inside : bool
- var entire_image_selected : bool = project.selected_pixels.size() == project.size.x * project.size.y
+ var entire_image_selected : bool = project.selected_pixels.empty()
if entire_image_selected:
mirror_x_inside = mirror_x >= 0 and mirror_x < project.size.x
mirror_y_inside = mirror_y >= 0 and mirror_y < project.size.y
diff --git a/src/Classes/ImageEffect.gd b/src/Classes/ImageEffect.gd
index 6daab2e00..9f4d711b0 100644
--- a/src/Classes/ImageEffect.gd
+++ b/src/Classes/ImageEffect.gd
@@ -66,7 +66,7 @@ func _confirmed() -> void:
elif affect == ALL_PROJECTS:
for project in Global.projects:
var _pixels := []
- if selection_checkbox.pressed:
+ if selection_checkbox.pressed and project.selected_pixels:
_pixels = project.selected_pixels.duplicate()
else:
for x in project.size.x:
@@ -90,7 +90,7 @@ func set_nodes() -> void:
func _on_SelectionCheckBox_toggled(button_pressed : bool) -> void:
pixels.clear()
- if button_pressed:
+ if button_pressed and Global.current_project.selected_pixels:
pixels = Global.current_project.selected_pixels.duplicate()
else:
for x in Global.current_project.size.x:
diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd
index b313c7d62..4d7a57e78 100644
--- a/src/Classes/Project.gd
+++ b/src/Classes/Project.gd
@@ -42,7 +42,6 @@ func _init(_frames := [], _name := tr("untitled"), _size := Vector2(64, 64)) ->
name = _name
size = _size
update_tile_mode_rects()
- select_all_pixels()
undo_redo = UndoRedo.new()
@@ -295,7 +294,6 @@ func deserialize(dict : Dictionary) -> void:
size.x = dict.size_x
size.y = dict.size_y
update_tile_mode_rects()
- select_all_pixels()
if dict.has("save_path"):
OpenSave.current_save_paths[Global.projects.find(self)] = dict.save_path
if dict.has("frames"):
@@ -366,8 +364,7 @@ func name_changed(value : String) -> void:
func size_changed(value : Vector2) -> void:
size = value
update_tile_mode_rects()
- if Global.selection_rectangle._selected_rect.has_no_area():
- select_all_pixels()
+ Global.selection_rectangle.set_rect(Global.selection_rectangle.get_rect())
func frames_changed(value : Array) -> void:
diff --git a/src/Palette/PaletteContainer.gd b/src/Palette/PaletteContainer.gd
index abe3e0df6..b11f94a4c 100644
--- a/src/Palette/PaletteContainer.gd
+++ b/src/Palette/PaletteContainer.gd
@@ -204,7 +204,7 @@ func create_palette_from_sprite() -> void:
var palette : Palette = Global.palettes[current_palette]
var pixels := []
- if selection_checkbox.pressed:
+ if selection_checkbox.pressed and current_project.selected_pixels:
pixels = current_project.selected_pixels.duplicate()
else:
for x in current_project.size.x:
diff --git a/src/SelectionRectangle.gd b/src/SelectionRectangle.gd
index 06000ea87..479c4536d 100644
--- a/src/SelectionRectangle.gd
+++ b/src/SelectionRectangle.gd
@@ -39,7 +39,7 @@ func set_rect(rect : Rect2) -> void:
var project : Project = Global.current_project
if rect.has_no_area():
- project.select_all_pixels()
+ project.selected_pixels = []
else:
project.clear_selection()
for x in range(rect.position.x, rect.end.x):
diff --git a/src/Tools/Base.gd b/src/Tools/Base.gd
index b6364d3f8..2eac06798 100644
--- a/src/Tools/Base.gd
+++ b/src/Tools/Base.gd
@@ -77,8 +77,11 @@ func draw_indicator() -> void:
func _get_draw_rect() -> Rect2:
- var selected_pixels = Global.current_project.selected_pixels
- return Rect2(selected_pixels[0].x, selected_pixels[0].y, selected_pixels[-1].x - selected_pixels[0].x + 1, selected_pixels[-1].y - selected_pixels[0].y + 1)
+ if Global.current_project.selected_pixels.empty():
+ return Global.current_project.tile_mode_rects[Global.TileMode.NONE]
+ else:
+ var selected_pixels = Global.current_project.selected_pixels
+ return Rect2(selected_pixels[0].x, selected_pixels[0].y, selected_pixels[-1].x - selected_pixels[0].x + 1, selected_pixels[-1].y - selected_pixels[0].y + 1)
func _get_draw_image() -> Image:
diff --git a/src/Tools/Bucket.gd b/src/Tools/Bucket.gd
index 11d56521a..aff4522f1 100644
--- a/src/Tools/Bucket.gd
+++ b/src/Tools/Bucket.gd
@@ -94,7 +94,9 @@ func update_pattern() -> void:
func draw_start(position : Vector2) -> void:
- if not position in Global.current_project.selected_pixels or Global.current_project.layers[Global.current_project.current_layer].locked:
+ if Global.current_project.layers[Global.current_project.current_layer].locked or !Global.current_project.tile_mode_rects[Global.TileMode.NONE].has_point(position):
+ return
+ if Global.current_project.selected_pixels and not position in Global.current_project.selected_pixels:
return
var undo_data = _get_undo_data()
if _fill_area == 0:
@@ -121,7 +123,15 @@ func fill_in_color(position : Vector2) -> void:
return
image.lock()
- for i in project.selected_pixels:
+ var pixels := []
+ if project.selected_pixels:
+ pixels = project.selected_pixels.duplicate()
+ else:
+ for x in Global.current_project.size.x:
+ for y in Global.current_project.size.y:
+ pixels.append(Vector2(x, y))
+
+ for i in pixels:
if image.get_pixelv(i).is_equal_approx(color):
_set_pixel(image, i.x, i.y, tool_slot.color)
@@ -135,7 +145,7 @@ func fill_in_area(position : Vector2) -> void:
var mirror_y = project.y_symmetry_point - position.y
var mirror_x_inside : bool
var mirror_y_inside : bool
- var entire_image_selected : bool = project.selected_pixels.size() == project.size.x * project.size.y
+ var entire_image_selected : bool = project.selected_pixels.empty()
if entire_image_selected:
mirror_x_inside = mirror_x >= 0 and mirror_x < project.size.x
mirror_y_inside = mirror_y >= 0 and mirror_y < project.size.y
@@ -192,7 +202,7 @@ func _flood_fill(position : Vector2) -> void:
func _set_pixel(image : Image, x : int, y : int, color : Color) -> void:
var project : Project = Global.current_project
- var entire_image_selected : bool = project.selected_pixels.size() == project.size.x * project.size.y
+ var entire_image_selected : bool = project.selected_pixels.empty()
if entire_image_selected:
if not _get_draw_rect().has_point(Vector2(x, y)):
return
diff --git a/src/Tools/Draw.gd b/src/Tools/Draw.gd
index 24091068c..47a776543 100644
--- a/src/Tools/Draw.gd
+++ b/src/Tools/Draw.gd
@@ -281,7 +281,7 @@ func draw_tool_brush(position : Vector2) -> void:
var mirror_y = (project.y_symmetry_point + 1) - dst.y - src_rect.size.y
var mirror_x_inside : bool
var mirror_y_inside : bool
- var entire_image_selected : bool = project.selected_pixels.size() == project.size.x * project.size.y
+ var entire_image_selected : bool = project.selected_pixels.empty()
if entire_image_selected:
mirror_x_inside = mirror_x >= 0 and mirror_x < project.size.x
mirror_y_inside = mirror_y >= 0 and mirror_y < project.size.y
@@ -307,7 +307,7 @@ func draw_indicator() -> void:
draw_indicator_at(_cursor, Vector2.ZERO, Color.blue)
if Global.current_project.tile_mode and Global.current_project.get_tile_mode_rect().has_point(_cursor):
var tile := _line_start if _draw_line else _cursor
- if not tile in Global.current_project.selected_pixels:
+ if not Global.current_project.tile_mode_rects[Global.TileMode.NONE].has_point(tile):
var offset := tile - tile.posmodv(Global.current_project.size)
draw_indicator_at(_cursor, offset, Color.green)
@@ -339,7 +339,7 @@ func _set_pixel(position : Vector2) -> void:
if project.tile_mode and project.get_tile_mode_rect().has_point(position):
position = position.posmodv(project.size)
- var entire_image_selected : bool = project.selected_pixels.size() == project.size.x * project.size.y
+ var entire_image_selected : bool = project.selected_pixels.empty()
if entire_image_selected:
if not _get_draw_rect().has_point(position):
return