diff --git a/src/Autoload/DrawingAlgos.gd b/src/Autoload/DrawingAlgos.gd index d33f8c8b9..32dcfb7e9 100644 --- a/src/Autoload/DrawingAlgos.gd +++ b/src/Autoload/DrawingAlgos.gd @@ -455,51 +455,44 @@ func generate_outline(image : Image, outline_color : Color, thickness : int, dia func adjust_hsv(img: Image, id : int, delta : float) -> void: - var x_min = Global.current_project.x_min - var x_max = Global.current_project.x_max - var y_min = Global.current_project.y_min - var y_max = Global.current_project.y_max img.lock() match id: 0: # Hue - for i in range(x_min, x_max): - for j in range(y_min, y_max): - var c : Color = img.get_pixel(i,j) - var hue = range_lerp(c.h,0,1,-180,180) - hue = hue + delta + for i in Global.current_project.selected_pixels: + var c : Color = img.get_pixelv(i) + var hue = range_lerp(c.h,0,1,-180,180) + hue = hue + delta - while(hue >= 180): - hue -= 360 - while(hue < -180): - hue += 360 - c.h = range_lerp(hue,-180,180,0,1) - img.set_pixel(i,j,c) + while(hue >= 180): + hue -= 360 + while(hue < -180): + hue += 360 + c.h = range_lerp(hue,-180,180,0,1) + img.set_pixelv(i,c) 1: # Saturation - for i in range(x_min, x_max): - for j in range(y_min, y_max): - var c : Color = img.get_pixel(i,j) - var sat = c.s - if delta > 0: - sat = range_lerp(delta,0,100,c.s,1) - elif delta < 0: - sat = range_lerp(delta,-100,0,0,c.s) - c.s = sat - img.set_pixel(i,j,c) + for i in Global.current_project.selected_pixels: + var c : Color = img.get_pixelv(i) + var sat = c.s + if delta > 0: + sat = range_lerp(delta,0,100,c.s,1) + elif delta < 0: + sat = range_lerp(delta,-100,0,0,c.s) + c.s = sat + img.set_pixelv(i,c) 2: # Value - for i in range(x_min, x_max): - for j in range(y_min, y_max): - var c : Color = img.get_pixel(i,j) - var val = c.v - if delta > 0: - val = range_lerp(delta,0,100,c.v,1) - elif delta < 0: - val = range_lerp(delta,-100,0,0,c.v) + for i in Global.current_project.selected_pixels: + var c : Color = img.get_pixelv(i) + var val = c.v + if delta > 0: + val = range_lerp(delta,0,100,c.v,1) + elif delta < 0: + val = range_lerp(delta,-100,0,0,c.v) - c.v = val - img.set_pixel(i,j,c) + c.v = val + img.set_pixelv(i,c) img.unlock() diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index c627ff6d3..775692e91 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -322,10 +322,9 @@ func save_pxo_file(path : String, autosave : bool, use_zstd_compression := true, func open_image_as_new_tab(path : String, image : Image) -> void: - var project = Project.new([], path.get_file()) + var project = Project.new([], path.get_file(), image.get_size()) project.layers.append(Layer.new()) Global.projects.append(project) - project.size = image.get_size() var frame := Frame.new() image.convert(Image.FORMAT_RGBA8) diff --git a/src/Canvas.gd b/src/Canvas.gd index 94d9127dd..ec8cab003 100644 --- a/src/Canvas.gd +++ b/src/Canvas.gd @@ -68,15 +68,6 @@ func _input(event : InputEvent) -> void: sprite_changed_this_frame = false var current_project : Project = Global.current_project - current_project.x_min = location.x - current_project.x_max = location.x + current_project.size.x - current_project.y_min = location.y - current_project.y_max = location.y + current_project.size.y - if not current_project.selected_rect.has_no_area(): - current_project.x_min = max(current_project.x_min, current_project.selected_rect.position.x) - current_project.x_max = min(current_project.x_max, current_project.selected_rect.end.x) - current_project.y_min = max(current_project.y_min, current_project.selected_rect.position.y) - current_project.y_max = min(current_project.y_max, current_project.selected_rect.end.y) if Global.has_focus: if !cursor_image_has_changed: diff --git a/src/Classes/Drawers.gd b/src/Classes/Drawers.gd index 967181619..a89a4ea2e 100644 --- a/src/Classes/Drawers.gd +++ b/src/Classes/Drawers.gd @@ -71,8 +71,14 @@ func set_pixel(image: Image, position: Vector2, color: Color) -> void: var mirror_x = project.x_symmetry_point - position.x var mirror_y = project.y_symmetry_point - position.y - var mirror_x_inside : bool = mirror_x >= project.x_min and mirror_x <= project.x_max - 1 - var mirror_y_inside : bool = mirror_y >= project.y_min and mirror_y <= project.y_max - 1 + var selected_pixels_x := [] + var selected_pixels_y := [] + for i in project.selected_pixels: + selected_pixels_x.append(i.x) + selected_pixels_y.append(i.y) + + var mirror_x_inside : bool = mirror_x in selected_pixels_x + var mirror_y_inside : bool = mirror_y in selected_pixels_y drawers[0].set_pixel(image, position, color, color_op) if horizontal_mirror and mirror_x_inside: diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 4cee8602a..7c6f7f118 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -3,7 +3,7 @@ class_name Project extends Reference var name := "" setget name_changed -var size := Vector2(64, 64) +var size : Vector2 setget size_changed var undo_redo : UndoRedo var undos := 0 # The number of times we added undo properties var has_changed := false setget has_changed_changed @@ -16,15 +16,12 @@ var guides := [] # Array of Guides var brushes := [] # Array of Images -var x_symmetry_point := size.x / 2 + 1 -var y_symmetry_point := size.y / 2 + 1 +var x_symmetry_point +var y_symmetry_point var x_symmetry_axis : SymmetryGuide var y_symmetry_axis : SymmetryGuide -var x_min := 0 -var x_max := 64 -var y_min := 0 -var y_max := 64 +var selected_pixels := [] var selected_rect := Rect2(0, 0, 0, 0) setget _set_selected_rect # For every camera (currently there are 3) @@ -32,17 +29,21 @@ var cameras_zoom := [Vector2(0.15, 0.15), Vector2(0.15, 0.15), Vector2(0.15, 0.1 var cameras_offset := [Vector2.ZERO, Vector2.ZERO, Vector2.ZERO] # Array of Vector2 -func _init(_frames := [], _name := tr("untitled")) -> void: +func _init(_frames := [], _name := tr("untitled"), _size := Vector2(64, 64)) -> void: frames = _frames name = _name - x_max = size.x - y_max = size.y + size = _size + select_all_pixels() + undo_redo = UndoRedo.new() Global.tabs.add_tab(name) OpenSave.current_save_paths.append("") OpenSave.backup_save_paths.append("") + x_symmetry_point = size.x / 2 + 1 + y_symmetry_point = size.y / 2 + 1 + if !x_symmetry_axis: x_symmetry_axis = SymmetryGuide.new() x_symmetry_axis.type = x_symmetry_axis.Types.HORIZONTAL @@ -60,6 +61,17 @@ func _init(_frames := [], _name := tr("untitled")) -> void: Global.canvas.add_child(y_symmetry_axis) +func select_all_pixels() -> void: + clear_selection() + for x in size.x: + for y in size.y: + selected_pixels.append(Vector2(x, y)) + + +func clear_selection() -> void: + selected_pixels.clear() + + func _set_selected_rect(value : Rect2) -> void: selected_rect = value Global.selection_rectangle.set_rect(value) @@ -290,6 +302,12 @@ func name_changed(value : String) -> void: Global.tabs.set_tab_title(Global.tabs.current_tab, name) +func size_changed(value : Vector2) -> void: + size = value + if Global.selection_rectangle._selected_rect.has_no_area(): + select_all_pixels() + + func frames_changed(value : Array) -> void: frames = value remove_cel_buttons() diff --git a/src/SelectionRectangle.gd b/src/SelectionRectangle.gd index 7e82e793e..817130c8b 100644 --- a/src/SelectionRectangle.gd +++ b/src/SelectionRectangle.gd @@ -28,6 +28,7 @@ func has_point(position : Vector2) -> bool: func get_rect() -> Rect2: return _selected_rect + func set_rect(rect : Rect2) -> void: _selected_rect = rect polygon[0] = rect.position @@ -36,6 +37,19 @@ func set_rect(rect : Rect2) -> void: polygon[3] = Vector2(rect.position.x, rect.end.y) visible = not rect.has_no_area() + var project : Project = Global.current_project + if rect.has_no_area(): + project.select_all_pixels() + else: + project.clear_selection() + for x in range(rect.position.x, rect.end.x): + for y in range(rect.position.y, rect.end.y): + if x < 0 or x >= project.size.x: + continue + if y < 0 or y >= project.size.y: + continue + project.selected_pixels.append(Vector2(x, y)) + func move_rect(move : Vector2) -> void: _selected_rect.position += move diff --git a/src/Tools/Base.gd b/src/Tools/Base.gd index f281dc120..cbd868d7f 100644 --- a/src/Tools/Base.gd +++ b/src/Tools/Base.gd @@ -77,11 +77,8 @@ func draw_indicator() -> void: func _get_draw_rect() -> Rect2: - var x_min : int = Global.current_project.x_min - var x_max : int = Global.current_project.x_max - var y_min : int = Global.current_project.y_min - var y_max : int = Global.current_project.y_max - return Rect2(x_min, y_min, x_max - x_min, y_max - y_min) + 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_tile_mode_rect() -> Rect2: diff --git a/src/Tools/Bucket.gd b/src/Tools/Bucket.gd index 92a066e0a..61ad677b2 100644 --- a/src/Tools/Bucket.gd +++ b/src/Tools/Bucket.gd @@ -94,7 +94,7 @@ func update_pattern() -> void: func draw_start(position : Vector2) -> void: - if not _get_draw_rect().has_point(position): + if not position in Global.current_project.selected_pixels: return var undo_data = _get_undo_data() if _fill_area == 0: @@ -121,18 +121,23 @@ func fill_in_color(position : Vector2) -> void: return image.lock() - for y in range(project.y_min, project.y_max): - for x in range(project.x_min, project.x_max): - if image.get_pixel(x, y).is_equal_approx(color): - _set_pixel(image, x, y, tool_slot.color) + for i in project.selected_pixels: + if image.get_pixelv(i).is_equal_approx(color): + _set_pixel(image, i.x, i.y, tool_slot.color) func fill_in_area(position : Vector2) -> void: var project : Project = Global.current_project var mirror_x = project.x_symmetry_point - position.x var mirror_y = project.y_symmetry_point - position.y - var mirror_x_inside : bool = mirror_x >= project.x_min and mirror_x <= project.x_max - 1 - var mirror_y_inside : bool = mirror_y >= project.y_min and mirror_y <= project.y_max - 1 + var selected_pixels_x := [] + var selected_pixels_y := [] + for i in project.selected_pixels: + selected_pixels_x.append(i.x) + selected_pixels_y.append(i.y) + + var mirror_x_inside : bool = mirror_x in selected_pixels_x + var mirror_y_inside : bool = mirror_y in selected_pixels_y _flood_fill(position) if tool_slot.horizontal_mirror and mirror_x_inside: @@ -160,9 +165,9 @@ func _flood_fill(position : Vector2) -> void: continue var west : Vector2 = n var east : Vector2 = n - while west.x >= project.x_min && image.get_pixelv(west).is_equal_approx(color): + while west in project.selected_pixels && image.get_pixelv(west).is_equal_approx(color): west += Vector2.LEFT - while east.x < project.x_max && image.get_pixelv(east).is_equal_approx(color): + while east in project.selected_pixels && image.get_pixelv(east).is_equal_approx(color): east += Vector2.RIGHT for px in range(west.x + 1, east.x): var p := Vector2(px, n.y) @@ -170,9 +175,9 @@ func _flood_fill(position : Vector2) -> void: processed.set_bit(p, true) var north := p + Vector2.UP var south := p + Vector2.DOWN - if north.y >= project.y_min && image.get_pixelv(north).is_equal_approx(color): + if north in project.selected_pixels && image.get_pixelv(north).is_equal_approx(color): q.append(north) - if south.y < project.y_max && image.get_pixelv(south).is_equal_approx(color): + if south in project.selected_pixels && image.get_pixelv(south).is_equal_approx(color): q.append(south) diff --git a/src/Tools/Draw.gd b/src/Tools/Draw.gd index dde73ac05..7749e4cae 100644 --- a/src/Tools/Draw.gd +++ b/src/Tools/Draw.gd @@ -271,8 +271,14 @@ func draw_tool_brush(position : Vector2) -> void: var project : Project = Global.current_project var mirror_x = (project.x_symmetry_point + 1) - dst.x - src_rect.size.x var mirror_y = (project.y_symmetry_point + 1) - dst.y - src_rect.size.y - var mirror_x_inside : bool = mirror_x >= project.x_min and mirror_x <= project.x_max - 1 - var mirror_y_inside : bool = mirror_y >= project.y_min and mirror_y <= project.y_max - 1 + var selected_pixels_x := [] + var selected_pixels_y := [] + for i in project.selected_pixels: + selected_pixels_x.append(i.x) + selected_pixels_y.append(i.y) + + var mirror_x_inside : bool = mirror_x in selected_pixels_x + var mirror_y_inside : bool = mirror_y in selected_pixels_y _draw_brush_image(_brush_image, src_rect, dst) if tool_slot.horizontal_mirror and mirror_x_inside: @@ -287,7 +293,7 @@ func draw_indicator() -> void: draw_indicator_at(_cursor, Vector2.ZERO, Color.blue) if Global.tile_mode and _get_tile_mode_rect().has_point(_cursor): var tile := _line_start if _draw_line else _cursor - if not _get_draw_rect().has_point(tile): + if not tile in Global.current_project.selected_pixels: var offset := tile - tile.posmodv(Global.current_project.size) draw_indicator_at(_cursor, offset, Color.green) @@ -316,7 +322,7 @@ func _set_pixel(position : Vector2) -> void: if Global.tile_mode and _get_tile_mode_rect().has_point(position): position = position.posmodv(Global.current_project.size) - if not _get_draw_rect().has_point(position): + if not position in Global.current_project.selected_pixels: return var image := _get_draw_image() diff --git a/src/UI/Dialogs/CreateNewImage.gd b/src/UI/Dialogs/CreateNewImage.gd index baaa16945..9a24f8ab6 100644 --- a/src/UI/Dialogs/CreateNewImage.gd +++ b/src/UI/Dialogs/CreateNewImage.gd @@ -80,11 +80,10 @@ func _on_CreateNewImage_confirmed() -> void: Global.canvas.fill_color = fill_color var frame : Frame = Global.canvas.new_empty_frame(false, true, Vector2(width, height)) - var new_project := Project.new([frame]) + var new_project := Project.new([frame], tr("untitled"), Vector2(width, height).floor()) new_project.layers.append(Layer.new()) Global.projects.append(new_project) Global.tabs.current_tab = Global.tabs.get_tab_count() - 1 - Global.current_project.size = Vector2(width, height).floor() Global.canvas.camera_zoom()