mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-18 17:19:50 +00:00
Replaced the _min and _max Project variables with Project.selected_pixels
This will allow us to create more selection tools in the future, that aren't necessarily rectangular (See #129) and even enhance the current rectangle selection tool (See #56) Current issues spotted so far: Drawing is slower for large images, and bucket filling is also considerably slower even on a 64x64 image. Optimizations are required.
This commit is contained in:
parent
8c965c1858
commit
0f82be765e
|
@ -455,17 +455,12 @@ 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)
|
||||
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
|
||||
|
||||
|
@ -474,24 +469,22 @@ func adjust_hsv(img: Image, id : int, delta : float) -> void:
|
|||
while(hue < -180):
|
||||
hue += 360
|
||||
c.h = range_lerp(hue,-180,180,0,1)
|
||||
img.set_pixel(i,j,c)
|
||||
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)
|
||||
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_pixel(i,j,c)
|
||||
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)
|
||||
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)
|
||||
|
@ -499,7 +492,7 @@ func adjust_hsv(img: Image, id : int, delta : float) -> void:
|
|||
val = range_lerp(delta,-100,0,0,c.v)
|
||||
|
||||
c.v = val
|
||||
img.set_pixel(i,j,c)
|
||||
img.set_pixelv(i,c)
|
||||
|
||||
img.unlock()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue