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