mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-02-20 12:33:14 +00:00
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
This commit is contained in:
parent
b4a5bf4dd0
commit
41ccc704c2
28 changed files with 478 additions and 423 deletions
|
@ -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": "",
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
105
src/Classes/SelectionMap.gd
Normal file
105
src/Classes/SelectionMap.gd
Normal file
|
@ -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)
|
29
src/Shaders/ColorSelect.gdshader
Normal file
29
src/Shaders/ColorSelect.gdshader
Normal file
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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():
|
||||
|
|
Loading…
Add table
Reference in a new issue