mirror of
https://github.com/Relintai/GraphicsEditor.git
synced 2025-04-19 10:43:13 +02:00
reimplemented tools, implmemented undo, reimplemented layers
This commit is contained in:
parent
f1787477fc
commit
af82266561
@ -12,7 +12,7 @@ export var can_draw = true
|
||||
var mouse_in_region
|
||||
var mouse_on_top
|
||||
|
||||
var layers = {} # Key: layer_name, val: GELayer
|
||||
var layers : Array = [] # Key: layer_name, val: GELayer
|
||||
var active_layer: GELayer
|
||||
var preview_layer: GELayer
|
||||
|
||||
@ -31,24 +31,20 @@ func _enter_tree():
|
||||
grid = find_node("Grid")
|
||||
big_grid = find_node("BigGrid")
|
||||
|
||||
|
||||
#-------------------------------
|
||||
# setup layers and canvas
|
||||
#-------------------------------
|
||||
connect("mouse_entered", self, "_on_mouse_entered")
|
||||
connect("mouse_exited", self, "_on_mouse_exited")
|
||||
|
||||
|
||||
#-------------------------------
|
||||
# setup layers and canvas
|
||||
#-------------------------------
|
||||
#canvas_size = Vector2(int(rect_size.x / grid_size), int(rect_size.y / grid_size))
|
||||
#pixel_size = canvas_size
|
||||
|
||||
preview_layer = add_new_layer("Preview")
|
||||
active_layer = add_new_layer("Layer1")
|
||||
|
||||
active_layer.set_pixel(10, 10, Color.blue)
|
||||
preview_layer = add_new_layer("Preview")
|
||||
|
||||
set_process(true)
|
||||
|
||||
@ -63,13 +59,21 @@ func _process(delta):
|
||||
|
||||
|
||||
func _draw():
|
||||
for layer_name in layers:
|
||||
var layer = layers[layer_name]
|
||||
for layer in layers:
|
||||
if not layer.visible:
|
||||
continue
|
||||
var idx = 0
|
||||
for color in layer.pixels:
|
||||
var p = GEUtils.to_2D(idx, canvas_width)
|
||||
draw_rect(Rect2(p.x * pixel_size, p.y * pixel_size, pixel_size, pixel_size), color)
|
||||
idx += 1
|
||||
|
||||
var idx = 0
|
||||
for color in preview_layer.pixels:
|
||||
var p = GEUtils.to_2D(idx, canvas_width)
|
||||
draw_rect(Rect2(p.x * pixel_size, p.y * pixel_size, pixel_size, pixel_size), color)
|
||||
idx += 1
|
||||
|
||||
|
||||
|
||||
#-------------------------------
|
||||
@ -121,62 +125,107 @@ func get_preview_layer():
|
||||
|
||||
|
||||
func clear_active_layer():
|
||||
clear_layer(active_layer.name)
|
||||
active_layer.clear()
|
||||
|
||||
|
||||
func clear_preview_layer():
|
||||
clear_layer(preview_layer.name)
|
||||
preview_layer.clear()
|
||||
|
||||
|
||||
func clear_layer(layer_name: String):
|
||||
for layer in layers:
|
||||
layer.pixels.clear()
|
||||
if layer.name == layer_name:
|
||||
layer.clear()
|
||||
break
|
||||
|
||||
|
||||
func remove_layer(layer_name: String):
|
||||
if not layer_name in layers:
|
||||
return null
|
||||
|
||||
# change current layer if the active layer is removed
|
||||
if active_layer.name == layer_name:
|
||||
var del_layer = find_layer_by_name(layer_name)
|
||||
del_layer.clear()
|
||||
if del_layer == active_layer:
|
||||
for layer in layers:
|
||||
if layer == preview_layer:
|
||||
if layer == preview_layer or layer == active_layer:
|
||||
continue
|
||||
active_layer = layer
|
||||
break
|
||||
|
||||
find_node("Layers").remove_child(layers[layer_name])
|
||||
layers[layer_name].queue_free()
|
||||
layers.erase(layer_name)
|
||||
|
||||
# return new active layer ?
|
||||
layers.erase(del_layer)
|
||||
return active_layer
|
||||
|
||||
|
||||
func add_new_layer(layer_name):
|
||||
if layer_name in layers:
|
||||
return
|
||||
func add_new_layer(layer_name: String):
|
||||
for layer in layers:
|
||||
if layer.name == layer_name:
|
||||
return
|
||||
var layer = GELayer.new()
|
||||
layer.name = layer_name
|
||||
layer.resize(canvas_width, canvas_height)
|
||||
layers[layer_name] = layer
|
||||
return layers[layer_name]
|
||||
if layer_name != "Preview":
|
||||
layers.append(layer)
|
||||
return layer
|
||||
|
||||
|
||||
func duplicate_layer(layer_name: String, new_layer_name: String):
|
||||
if not layer_name in layers or new_layer_name in layers:
|
||||
return
|
||||
var layer = add_new_layer(new_layer_name)
|
||||
layer.pixels = layers[layer_name].pixels.duplicate()
|
||||
for layer in layers:
|
||||
if layer.name == new_layer_name:
|
||||
return
|
||||
|
||||
var dup_layer
|
||||
for layer in layers:
|
||||
if layer.name == layer_name:
|
||||
dup_layer = layer
|
||||
break
|
||||
|
||||
var layer :GELayer = add_new_layer(new_layer_name)
|
||||
layer.pixels = dup_layer.pixels.duplicate()
|
||||
layer.name = new_layer_name
|
||||
return layer
|
||||
|
||||
|
||||
func toggle_layer_visibility(layer_name: String):
|
||||
if not layer_name in layers:
|
||||
return
|
||||
layers[layer_name].visible = not layers[layer_name].visible
|
||||
for layer in layers:
|
||||
if layer.name == layer_name:
|
||||
layer.visible = not layer.visible
|
||||
|
||||
|
||||
func find_layer_by_name(layer_name: String):
|
||||
for layer in layers:
|
||||
if layer.name == layer_name:
|
||||
return layer
|
||||
return null
|
||||
|
||||
|
||||
func move_layer_forward(layer_name: String):
|
||||
var remove_pos = -1
|
||||
var layer
|
||||
for i in range(layers.size()):
|
||||
if layers[i].name == layer_name:
|
||||
remove_pos = i
|
||||
layer = layers[i]
|
||||
print("from: ", i)
|
||||
break
|
||||
layers.erase(layer)
|
||||
print("forw to: ", max(remove_pos - 1, 0))
|
||||
layers.insert(max(remove_pos - 1, 0), layer)
|
||||
|
||||
|
||||
func move_layer_back(layer_name: String):
|
||||
var remove_pos = -1
|
||||
var layer
|
||||
for i in range(layers.size()):
|
||||
if layers[i].name == layer_name:
|
||||
remove_pos = i
|
||||
layer = layers[i]
|
||||
print("from: ", i)
|
||||
break
|
||||
layers.erase(layer)
|
||||
print("back to: ", min(remove_pos + 1, layers.size()))
|
||||
layers.insert(min(remove_pos + 1, layers.size()), layer)
|
||||
|
||||
|
||||
func select_layer(layer_name: String):
|
||||
active_layer = find_layer_by_name(layer_name)
|
||||
|
||||
|
||||
#-------------------------------
|
||||
# Check
|
||||
@ -235,7 +284,30 @@ func get_pixel(x: int, y: int):
|
||||
if active_layer:
|
||||
if active_layer.pixels.size() <= idx:
|
||||
return null
|
||||
return active_layer.pixels[idx]
|
||||
return active_layer.pixels[idx]
|
||||
return null
|
||||
|
||||
|
||||
func set_preview_pixel_v(pos: Vector2, color: Color):
|
||||
set_preview_pixel(pos.x, pos.y, color)
|
||||
|
||||
|
||||
func set_preview_pixel(x:int, y: int, color: Color):
|
||||
if not is_inside_canvas(x, y):
|
||||
return
|
||||
preview_layer.set_pixel(x, y, color)
|
||||
|
||||
|
||||
func get_preview_pixel_v(pos: Vector2):
|
||||
return get_preview_pixel(pos.x, pos.y)
|
||||
|
||||
|
||||
func get_preview_pixel(x: int, y: int):
|
||||
var idx = GEUtils.to_1D(x, y, canvas_width)
|
||||
if preview_layer:
|
||||
if preview_layer.pixels.size() <= idx:
|
||||
return null
|
||||
return preview_layer.pixels[idx]
|
||||
|
||||
|
||||
#-------------------------------
|
||||
@ -252,7 +324,7 @@ func select_color(x, y):
|
||||
return same_color_pixels
|
||||
|
||||
|
||||
func select_neighbouring_color(x, y):
|
||||
func select_same_color(x, y):
|
||||
return get_neighbouring_pixels(x, y)
|
||||
|
||||
|
||||
@ -262,14 +334,21 @@ func select_neighbouring_color(x, y):
|
||||
func get_neighbouring_pixels(pos_x: int, pos_y: int) -> Array:
|
||||
var pixels = []
|
||||
|
||||
var check_queue = []
|
||||
var to_check_queue = []
|
||||
var checked_queue = []
|
||||
|
||||
check_queue.append(Vector2(pos_x, pos_y))
|
||||
to_check_queue.append(GEUtils.to_1D(pos_x, pos_y, canvas_width))
|
||||
|
||||
var color = get_pixel(pos_x, pos_y)
|
||||
|
||||
while not check_queue.empty():
|
||||
var p = check_queue.pop_front()
|
||||
while not to_check_queue.empty():
|
||||
var idx = to_check_queue.pop_front()
|
||||
var p = GEUtils.to_2D(idx, canvas_width)
|
||||
|
||||
if idx in checked_queue:
|
||||
continue
|
||||
|
||||
checked_queue.append(idx)
|
||||
|
||||
if get_pixel(p.x, p.y) != color:
|
||||
continue
|
||||
@ -280,22 +359,25 @@ func get_neighbouring_pixels(pos_x: int, pos_y: int) -> Array:
|
||||
# check neighbours
|
||||
var x = p.x - 1
|
||||
var y = p.y
|
||||
|
||||
if not p in pixels and is_inside_canvas(x, y):
|
||||
check_queue.append(Vector2(x, y))
|
||||
if is_inside_canvas(x, y):
|
||||
idx = GEUtils.to_1D(x, y, canvas_width)
|
||||
to_check_queue.append(idx)
|
||||
|
||||
x = p.x + 1
|
||||
if not p in pixels and is_inside_canvas(x, y):
|
||||
check_queue.append(Vector2(x, y))
|
||||
if is_inside_canvas(x, y):
|
||||
idx = GEUtils.to_1D(x, y, canvas_width)
|
||||
to_check_queue.append(idx)
|
||||
|
||||
x = p.x
|
||||
y = p.y - 1
|
||||
if not p in pixels and is_inside_canvas(x, y):
|
||||
check_queue.append(Vector2(x, y))
|
||||
if is_inside_canvas(x, y):
|
||||
idx = GEUtils.to_1D(x, y, canvas_width)
|
||||
to_check_queue.append(idx)
|
||||
|
||||
y = p.y + 1
|
||||
if not p in pixels and is_inside_canvas(x, y):
|
||||
check_queue.append(Vector2(x, y))
|
||||
if is_inside_canvas(x, y):
|
||||
idx = GEUtils.to_1D(x, y, canvas_width)
|
||||
to_check_queue.append(idx)
|
||||
|
||||
return pixels
|
||||
|
||||
|
@ -14,8 +14,9 @@ enum Tools {
|
||||
CUT,
|
||||
}
|
||||
|
||||
var layer_buttons: Control
|
||||
var paint_canvas_container_node
|
||||
var paint_canvas
|
||||
var paint_canvas: GECanvas
|
||||
var grids_node
|
||||
var colors_grid
|
||||
var selected_color = Color(1, 1, 1, 1)
|
||||
@ -34,7 +35,10 @@ var _total_added_layers = 1
|
||||
var selected_brush_prefab = 0
|
||||
var _last_drawn_pixel = Vector2.ZERO
|
||||
var _last_preview_draw_cell_pos = Vector2.ZERO
|
||||
var _selection = []
|
||||
|
||||
var _selection_cells = []
|
||||
var _selection_colors = []
|
||||
|
||||
var _just_cut = false
|
||||
var _show_cut = false
|
||||
var _cut_pos = Vector2.ZERO
|
||||
@ -44,9 +48,6 @@ var _actions_history = [] # for undo
|
||||
var _redo_history = []
|
||||
var _current_action
|
||||
|
||||
enum Action {
|
||||
PAINT,
|
||||
}
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
@ -58,7 +59,8 @@ func _enter_tree():
|
||||
selected_color = find_node("ColorPicker").color
|
||||
colors_grid = find_node("Colors")
|
||||
paint_canvas = get_node("Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/Canvas")
|
||||
print(paint_canvas)
|
||||
layer_buttons = find_node("LayerButtons")
|
||||
|
||||
set_process(true)
|
||||
|
||||
#--------------------
|
||||
@ -73,6 +75,8 @@ func _enter_tree():
|
||||
|
||||
func _ready():
|
||||
set_brush(Tools.PAINT)
|
||||
_layer_button_ref[layer_buttons.get_child(0).name] = layer_buttons.get_child(0) #ugly
|
||||
_connect_layer_buttons()
|
||||
|
||||
|
||||
func _input(event):
|
||||
@ -81,6 +85,15 @@ func _input(event):
|
||||
elif Input.is_key_pressed(KEY_Y):
|
||||
print("Y")
|
||||
|
||||
if (paint_canvas.mouse_in_region and paint_canvas.mouse_on_top):
|
||||
match brush_mode:
|
||||
Tools.BUCKET:
|
||||
if _current_action == null:
|
||||
_current_action = get_action()
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == BUTTON_LEFT:
|
||||
if event.pressed:
|
||||
do_action([cell_mouse_position, last_cell_mouse_position, selected_color])
|
||||
|
||||
|
||||
var brush_mode
|
||||
@ -141,31 +154,38 @@ func _process(delta):
|
||||
last_cell_color = cell_color
|
||||
|
||||
|
||||
func _reset_cut_tool():
|
||||
_just_cut = false
|
||||
_show_cut = false
|
||||
_selection_cells.clear()
|
||||
_selection_colors.clear()
|
||||
|
||||
|
||||
func _handle_cut():
|
||||
if Input.is_mouse_button_pressed(BUTTON_RIGHT):
|
||||
_just_cut = false
|
||||
_show_cut = false
|
||||
paint_canvas.clear_preview_layer()
|
||||
brush_mode = _previous_tool
|
||||
_selection = []
|
||||
_reset_cut_tool()
|
||||
set_brush(_previous_tool)
|
||||
return
|
||||
|
||||
# if Input.is_mouse_button_pressed(BUTTON_LEFT):
|
||||
# for pixel_pos in paint_canvas.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position):
|
||||
# for pixel in _selection:
|
||||
# var pos = pixel[0]
|
||||
# pos -= _cut_pos
|
||||
# pos += pixel_pos
|
||||
# paint_canvas.set_pixel_v(pos, pixel[1])
|
||||
if Input.is_mouse_button_pressed(BUTTON_LEFT):
|
||||
for pixel_pos in GEUtils.get_pixels_in_line(cell_mouse_position, last_cell_mouse_position):
|
||||
for idx in range(_selection_cells.size()):
|
||||
var pixel = _selection_cells[idx]
|
||||
var color = _selection_colors[idx]
|
||||
pixel -= _cut_pos
|
||||
pixel += pixel_pos
|
||||
paint_canvas.set_pixel_v(pixel, color)
|
||||
else:
|
||||
if _last_preview_draw_cell_pos == cell_mouse_position:
|
||||
return
|
||||
paint_canvas.clear_preview_layer()
|
||||
for pixel in _selection:
|
||||
var pos = pixel[0]
|
||||
pos -= _cut_pos
|
||||
pos += cell_mouse_position
|
||||
paint_canvas.set_pixel_v(pos, pixel[1])
|
||||
for idx in range(_selection_cells.size()):
|
||||
var pixel = _selection_cells[idx]
|
||||
var color = _selection_colors[idx]
|
||||
pixel -= _cut_pos
|
||||
pixel += cell_mouse_position
|
||||
paint_canvas.set_preview_pixel_v(pixel, color)
|
||||
_last_preview_draw_cell_pos = cell_mouse_position
|
||||
|
||||
|
||||
@ -175,10 +195,6 @@ func brush_process():
|
||||
return
|
||||
|
||||
if Input.is_mouse_button_pressed(BUTTON_LEFT):
|
||||
# var arr = GEUtils.get_pixels_in_line(cell_mouse_position, last_cell_mouse_position)
|
||||
# paint_canvas.set_pixel_arr(arr, selected_color)
|
||||
|
||||
|
||||
if _current_action == null:
|
||||
_current_action = get_action()
|
||||
|
||||
@ -187,172 +203,34 @@ func brush_process():
|
||||
do_action([cell_mouse_position, last_cell_mouse_position, selected_color])
|
||||
Tools.BRUSH:
|
||||
do_action([cell_mouse_position, last_cell_mouse_position, selected_color, selected_brush_prefab])
|
||||
return
|
||||
else:
|
||||
if _current_action and _current_action.can_commit():
|
||||
commit_action()
|
||||
|
||||
return
|
||||
if Input.is_mouse_button_pressed(BUTTON_LEFT):
|
||||
match brush_mode:
|
||||
Tools.PAINT:
|
||||
paint_canvas.set_pixel_arr(GEUtils.get_pixels_in_line(cell_mouse_position, last_cell_mouse_position), selected_color)
|
||||
Tools.BRUSH:
|
||||
for pixel_pos in GEUtils.get_pixels_in_line(cell_mouse_position, last_cell_mouse_position):
|
||||
for off in BrushPrefabs.list[selected_brush_prefab]:
|
||||
paint_canvas.set_pixel_v(pixel_pos + off, selected_color)
|
||||
Tools.LINE:
|
||||
if _left_mouse_pressed_start_pos == Vector2.ZERO:
|
||||
_left_mouse_pressed_start_pos = cell_mouse_position
|
||||
paint_canvas.clear_preview_layer()
|
||||
paint_canvas.set_pixels_from_line(
|
||||
cell_mouse_position, _left_mouse_pressed_start_pos, selected_color)
|
||||
|
||||
do_action([cell_mouse_position, last_cell_mouse_position, selected_color])
|
||||
Tools.RECT:
|
||||
if _left_mouse_pressed_start_pos == Vector2.ZERO:
|
||||
_left_mouse_pressed_start_pos = cell_mouse_position
|
||||
paint_canvas.clear_preview_layer()
|
||||
|
||||
var p = _left_mouse_pressed_start_pos
|
||||
var s = cell_mouse_position - _left_mouse_pressed_start_pos
|
||||
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p, p + Vector2(s.x, 0), selected_color)
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p, p + Vector2(0, s.y), selected_color)
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p + s, p + s + Vector2(0, -s.y), selected_color)
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p + s, p + s + Vector2(-s.x, 0), selected_color)
|
||||
|
||||
do_action([cell_mouse_position, last_cell_mouse_position, selected_color])
|
||||
Tools.DARKEN:
|
||||
var pixels = paint_canvas.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
|
||||
var val = 0.9
|
||||
for pixel in pixels:
|
||||
if _last_drawn_pixel == pixel:
|
||||
continue
|
||||
_last_drawn_pixel = pixel
|
||||
|
||||
var new_color = paint_canvas.get_pixel_cell_color(pixel.x, pixel.y)
|
||||
new_color.r *= val
|
||||
new_color.g *= val
|
||||
new_color.b *= val
|
||||
paint_canvas.set_pixel_v(pixel, new_color)
|
||||
|
||||
do_action([cell_mouse_position, last_cell_mouse_position, selected_color])
|
||||
Tools.BRIGHTEN:
|
||||
var pixels = paint_canvas.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
|
||||
var val = 1.1
|
||||
for pixel in pixels:
|
||||
if _last_drawn_pixel == pixel:
|
||||
continue
|
||||
_last_drawn_pixel = pixel
|
||||
|
||||
var new_color = paint_canvas.get_pixel_cell_color(pixel.x, pixel.y)
|
||||
new_color.r *= val
|
||||
new_color.g *= val
|
||||
new_color.b *= val
|
||||
paint_canvas.set_pixel_v(pixel, new_color)
|
||||
|
||||
do_action([cell_mouse_position, last_cell_mouse_position, selected_color])
|
||||
Tools.COLORPICKER:
|
||||
change_color(paint_canvas.get_pixel_cell_color(cell_mouse_position.x, cell_mouse_position.y))
|
||||
|
||||
change_color(paint_canvas.get_pixel(cell_mouse_position.x, cell_mouse_position.y))
|
||||
Tools.CUT:
|
||||
if _left_mouse_pressed_start_pos == Vector2.ZERO:
|
||||
_left_mouse_pressed_start_pos = cell_mouse_position
|
||||
paint_canvas.clear_preview_layer()
|
||||
|
||||
var p = _left_mouse_pressed_start_pos
|
||||
var s = cell_mouse_position - _left_mouse_pressed_start_pos
|
||||
|
||||
var selection_color = Color(0.8, 0.8, 0.8, 0.5)
|
||||
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p, p + Vector2(s.x, 0), selection_color)
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p, p + Vector2(0, s.y), selection_color)
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p + s, p + s + Vector2(0, -s.y), selection_color)
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p + s, p + s + Vector2(-s.x, 0), selection_color)
|
||||
|
||||
Tools.BUCKET:
|
||||
paint_canvas.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, selected_color)
|
||||
do_action([cell_mouse_position, last_cell_mouse_position, selected_color])
|
||||
Tools.RAINBOW:
|
||||
paint_canvas.set_random_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
|
||||
_:
|
||||
print("no brush selected")
|
||||
# paint_canvas.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, selected_color)
|
||||
|
||||
do_action([cell_mouse_position, last_cell_mouse_position])
|
||||
else:
|
||||
if _current_action and _current_action.can_commit():
|
||||
commit_action()
|
||||
|
||||
if Input.is_mouse_button_pressed(BUTTON_RIGHT):
|
||||
return
|
||||
if _current_action == null:
|
||||
_current_action = get_action()
|
||||
|
||||
match brush_mode:
|
||||
Tools.PAINT:
|
||||
paint_canvas.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0))
|
||||
# Tools.BUCKET:
|
||||
# paint_canvas.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, Color(0, 0, 0, 0))
|
||||
do_action([cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0)])
|
||||
Tools.BRUSH:
|
||||
for pixel_pos in paint_canvas.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position):
|
||||
for off in BrushPrefabs.list[selected_brush_prefab]:
|
||||
paint_canvas.set_pixel_v(pixel_pos + off, Color(0, 0, 0, 0))
|
||||
Tools.RAINBOW:
|
||||
paint_canvas.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0))
|
||||
_:
|
||||
paint_canvas.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0))
|
||||
|
||||
if not Input.is_mouse_button_pressed(BUTTON_LEFT):
|
||||
match brush_mode:
|
||||
Tools.LINE:
|
||||
paint_canvas.clear_preview_layer()
|
||||
paint_canvas.set_pixels_from_line(
|
||||
cell_mouse_position, _left_mouse_pressed_start_pos, selected_color)
|
||||
_left_mouse_pressed_start_pos = Vector2.ZERO
|
||||
|
||||
Tools.RECT:
|
||||
paint_canvas.clear_preview_layer()
|
||||
|
||||
var p = _left_mouse_pressed_start_pos
|
||||
var s = cell_mouse_position - _left_mouse_pressed_start_pos
|
||||
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p, p + Vector2(s.x, 0), selected_color)
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p, p + Vector2(0, s.y), selected_color)
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p + s, p + s + Vector2(0, -s.y), selected_color)
|
||||
paint_canvas.set_pixels_from_line(
|
||||
p + s, p + s + Vector2(-s.x, 0), selected_color)
|
||||
_left_mouse_pressed_start_pos = Vector2.ZERO
|
||||
|
||||
Tools.CUT:
|
||||
paint_canvas.clear_preview_layer()
|
||||
|
||||
var p = _left_mouse_pressed_start_pos
|
||||
var s = cell_mouse_position - _left_mouse_pressed_start_pos
|
||||
_cut_pos = p + s / 2
|
||||
_cut_size = s
|
||||
|
||||
for x in range(abs(s.x)+1):
|
||||
for y in range(abs(s.y)+1):
|
||||
var px = x
|
||||
var py = y
|
||||
if s.x < 0:
|
||||
px *= -1
|
||||
if s.y < 0:
|
||||
py *= -1
|
||||
|
||||
var pos = p + Vector2(px, py)
|
||||
var color = paint_canvas.get_pixel_cell_color(pos.x, pos.y)
|
||||
if color.a == 0:
|
||||
continue
|
||||
_selection.append([pos, color])
|
||||
paint_canvas.set_pixel_v(pos, Color.transparent)
|
||||
_left_mouse_pressed_start_pos = Vector2.ZERO
|
||||
_just_cut = true
|
||||
do_action([cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0), selected_brush_prefab])
|
||||
|
||||
|
||||
func update_text_info():
|
||||
@ -379,10 +257,6 @@ func update_text_info():
|
||||
find_node("DebugTextDisplay").display_text(text)
|
||||
|
||||
|
||||
func select_layer(layer_name: String):
|
||||
print("select layer: ", layer_name)
|
||||
|
||||
|
||||
func _on_Save_pressed():
|
||||
get_node("SaveFileDialog").show()
|
||||
|
||||
@ -404,10 +278,22 @@ func commit_action():
|
||||
return
|
||||
|
||||
print("commit action")
|
||||
_current_action.commit_action(paint_canvas)
|
||||
var commit_data = _current_action.commit_action(paint_canvas)
|
||||
var action = get_action()
|
||||
action.action_data = _current_action.action_data.duplicate(true)
|
||||
|
||||
_actions_history.push_back(action)
|
||||
|
||||
match brush_mode:
|
||||
Tools.CUT:
|
||||
if _just_cut:
|
||||
continue
|
||||
_cut_pos = _current_action.mouse_start_pos
|
||||
_cut_size = _current_action.mouse_end_pos - _current_action.mouse_start_pos
|
||||
_selection_cells = _current_action.action_data.do.cells.duplicate()
|
||||
_selection_colors = _current_action.action_data.do.colors.duplicate()
|
||||
_just_cut = true
|
||||
|
||||
_current_action = null
|
||||
return
|
||||
action.action_data = _current_action.action_data
|
||||
@ -435,6 +321,20 @@ func get_action():
|
||||
return GEPencil.new()
|
||||
Tools.BRUSH:
|
||||
return GEBrush.new()
|
||||
Tools.LINE:
|
||||
return GELine.new()
|
||||
Tools.RAINBOW:
|
||||
return GERainbow.new()
|
||||
Tools.BUCKET:
|
||||
return GEBucket.new()
|
||||
Tools.RECT:
|
||||
return GERect.new()
|
||||
Tools.DARKEN:
|
||||
return GEDarken.new()
|
||||
Tools.BRIGHTEN:
|
||||
return GEBrighten.new()
|
||||
Tools.CUT:
|
||||
return GECut.new()
|
||||
_:
|
||||
print("no tool!")
|
||||
return null
|
||||
@ -449,6 +349,14 @@ func set_brush(new_mode):
|
||||
return
|
||||
_previous_tool = brush_mode
|
||||
brush_mode = new_mode
|
||||
|
||||
match _previous_tool:
|
||||
Tools.CUT:
|
||||
paint_canvas.clear_preview_layer()
|
||||
_just_cut = false
|
||||
Tools.BUCKET:
|
||||
_current_action = null
|
||||
print("Selected: ", Tools.keys()[brush_mode])
|
||||
|
||||
|
||||
func change_color(new_color):
|
||||
@ -463,11 +371,11 @@ func _on_ColorPicker_color_changed(color):
|
||||
|
||||
|
||||
func _on_PaintTool_pressed():
|
||||
brush_mode = Tools.PAINT
|
||||
set_brush(Tools.PAINT)
|
||||
|
||||
|
||||
func _on_BucketTool_pressed():
|
||||
brush_mode = Tools.BUCKET
|
||||
set_brush(Tools.BUCKET)
|
||||
|
||||
|
||||
func _on_RainbowTool_pressed():
|
||||
@ -514,91 +422,97 @@ func _on_Editor_visibility_changed():
|
||||
pause_mode = not visible
|
||||
|
||||
|
||||
func _connect_layer_buttons():
|
||||
for layer_btn in get_tree().get_nodes_in_group("layer"):
|
||||
if layer_btn.is_connected("pressed", self, "select_layer"):
|
||||
continue
|
||||
layer_btn.connect("pressed", self, "select_layer", [get_layer_by_button_name(layer_btn.name)])
|
||||
layer_btn.find_node("Visible").connect("pressed", self, "toggle_layer_visibility",
|
||||
[layer_btn.find_node("Visible"), get_layer_by_button_name(layer_btn.name)])
|
||||
layer_btn.find_node("Up").connect("pressed", self, "move_up", [layer_btn])
|
||||
layer_btn.find_node("Down").connect("pressed", self, "move_down", [layer_btn])
|
||||
|
||||
#---------------------------------------
|
||||
# Layer
|
||||
#---------------------------------------
|
||||
|
||||
func toggle_layer_visibility(button, layer_name: String):
|
||||
print("toggling: ", layer_name)
|
||||
print(paint_canvas.layers.keys())
|
||||
paint_canvas.toggle_layer_visibility(layer_name)
|
||||
|
||||
|
||||
func select_layer(layer_name: String):
|
||||
print("select layer: ", layer_name)
|
||||
paint_canvas.select_layer(layer_name)
|
||||
|
||||
|
||||
func add_new_layer():
|
||||
var layers = get_tree().get_nodes_in_group("layer")
|
||||
var new_layer = layers.back().duplicate()
|
||||
find_node("Layers").add_child_below_node(layers.back(), new_layer, true)
|
||||
var new_layer = layer_buttons.get_child(0).duplicate()
|
||||
layer_buttons.add_child_below_node(layer_buttons.get_child(layer_buttons.get_child_count() - 1), new_layer, true)
|
||||
_total_added_layers += 1
|
||||
new_layer.text = "Layer " + str(_total_added_layers)
|
||||
|
||||
var new_layer_name = paint_canvas.add_new_layer(new_layer.name)
|
||||
var layer: GELayer = paint_canvas.add_new_layer(new_layer.name)
|
||||
|
||||
_layer_button_ref[new_layer_name] = new_layer
|
||||
_layer_button_ref[new_layer.name] = new_layer
|
||||
|
||||
_connect_layer_buttons()
|
||||
|
||||
print("added layer: ", new_layer_name, "(total:", layers.size(), ")")
|
||||
print("added layer: ", layer.name)
|
||||
|
||||
|
||||
func remove_active_layer():
|
||||
if _layer_button_ref.size() < 2:
|
||||
if layer_buttons.get_child_count() <= 1:
|
||||
return
|
||||
var layer_name = paint_canvas.active_layer.name
|
||||
paint_canvas.remove_layer(layer_name)
|
||||
layer_buttons.remove_child(_layer_button_ref[layer_name])
|
||||
_layer_button_ref[layer_name].queue_free()
|
||||
_layer_button_ref.erase(layer_name)
|
||||
|
||||
_layer_button_ref[paint_canvas.active_layer].get_parent().remove_child(_layer_button_ref[paint_canvas.active_layer])
|
||||
_layer_button_ref[paint_canvas.active_layer].queue_free()
|
||||
_layer_button_ref.erase(paint_canvas.active_layer)
|
||||
paint_canvas.remove_layer(paint_canvas.active_layer)
|
||||
|
||||
|
||||
func duplicate_active_layer():
|
||||
# copy the last layer button (or the initial one)
|
||||
var layer_buttons = get_tree().get_nodes_in_group("layer")
|
||||
var new_layer_button = layer_buttons.back().duplicate()
|
||||
find_node("Layers").add_child_below_node(layer_buttons.back(), new_layer_button, true)
|
||||
|
||||
var new_layer_button = layer_buttons.get_child(0).duplicate()
|
||||
layer_buttons.add_child_below_node(
|
||||
layer_buttons.get_child(layer_buttons.get_child_count() - 1), new_layer_button, true)
|
||||
|
||||
_total_added_layers += 1 # for keeping track...
|
||||
new_layer_button.text = "Layer " + str(_total_added_layers)
|
||||
|
||||
var new_layer_name = paint_canvas.duplicate_layer(paint_canvas.active_layer, new_layer_button.name)
|
||||
var new_layer = paint_canvas.duplicate_layer(paint_canvas.active_layer.name, new_layer_button.name)
|
||||
|
||||
_layer_button_ref[new_layer_name] = new_layer_button
|
||||
_layer_button_ref[new_layer.name] = new_layer_button
|
||||
|
||||
_connect_layer_buttons()
|
||||
new_layer_button.disconnect("pressed", self, "select_layer")
|
||||
new_layer_button.find_node("Visible").disconnect("pressed", self, "toggle_layer_visibility")
|
||||
new_layer_button.find_node("Up").disconnect("pressed", self, "move_down")
|
||||
new_layer_button.find_node("Down").disconnect("pressed", self, "move_up")
|
||||
|
||||
print("added layer: ", new_layer_name, " (total:", layer_buttons.size(), ")")
|
||||
new_layer_button.connect("pressed", self, "select_layer", [new_layer_button.name])
|
||||
new_layer_button.find_node("Visible").connect("pressed", self, "toggle_layer_visibility",
|
||||
[new_layer_button.find_node("Visible"), new_layer_button.name])
|
||||
new_layer_button.find_node("Up").connect("pressed", self, "move_down", [new_layer_button])
|
||||
new_layer_button.find_node("Down").connect("pressed", self, "move_up", [new_layer_button])
|
||||
|
||||
print("added layer: ", new_layer.name, " (total:", layer_buttons.size(), ")")
|
||||
|
||||
|
||||
func get_layer_by_button_name(button_name: String):
|
||||
for layer_name in _layer_button_ref:
|
||||
var button = _layer_button_ref[layer_name]
|
||||
if button.name == button_name:
|
||||
return layer_name
|
||||
return null
|
||||
func move_up(layer_btn):
|
||||
var new_idx = min(layer_btn.get_index() + 1, layer_buttons.get_child_count())
|
||||
print("move_down: ", layer_btn.name, " from ", layer_btn.get_index(), " to ", new_idx)
|
||||
layer_buttons.move_child(layer_btn, new_idx)
|
||||
paint_canvas.move_layer_back(layer_btn.name)
|
||||
|
||||
|
||||
func move_down(layer_btn, button_name: String):
|
||||
print("move_up: ", button_name)
|
||||
var layer_name = get_layer_by_button_name(button_name)
|
||||
var chunk_node = paint_canvas.layers[layer_name].chunks
|
||||
chunk_node.get_parent().move_child(chunk_node, max(chunk_node.get_index() + 1, 0))
|
||||
layer_btn.get_parent().move_child(layer_btn, max(layer_btn.get_index() + 1, 0))
|
||||
func move_down(layer_btn):
|
||||
var new_idx = max(layer_btn.get_index() - 1, 0)
|
||||
print("move_up: ", layer_btn.name, " from ", layer_btn.get_index(), " to ", new_idx)
|
||||
layer_buttons.move_child(layer_btn, new_idx)
|
||||
paint_canvas.move_layer_forward(layer_btn.name)
|
||||
|
||||
|
||||
func move_up(layer_btn, button_name: String):
|
||||
print("move_up: ", button_name)
|
||||
var layer_name = get_layer_by_button_name(button_name)
|
||||
var chunk_node = paint_canvas.layers[layer_name].chunks
|
||||
chunk_node.get_parent().move_child(chunk_node,
|
||||
min(chunk_node.get_index() - 1, chunk_node.get_parent().get_child_count() - 1))
|
||||
layer_btn.get_parent().move_child(layer_btn,
|
||||
min(layer_btn.get_index() - 1, layer_btn.get_parent().get_child_count() - 1))
|
||||
func _connect_layer_buttons():
|
||||
for layer_btn in layer_buttons.get_children():
|
||||
if layer_btn.is_connected("pressed", self, "select_layer"):
|
||||
continue
|
||||
layer_btn.connect("pressed", self, "select_layer", [layer_btn.name])
|
||||
layer_btn.find_node("Visible").connect("pressed", self, "toggle_layer_visibility",
|
||||
[layer_btn.find_node("Visible"), layer_btn.name])
|
||||
layer_btn.find_node("Up").connect("pressed", self, "move_down", [layer_btn])
|
||||
layer_btn.find_node("Down").connect("pressed", self, "move_up", [layer_btn])
|
||||
|
||||
|
||||
func _on_Button_pressed():
|
||||
|
@ -26,76 +26,76 @@ corner_radius_bottom_right = 2
|
||||
corner_radius_bottom_left = 2
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=27]
|
||||
bg_color = Color( 0.213659, 0.765351, 0.325763, 1 )
|
||||
bg_color = Color( 0.103793, 0.952543, 0.558178, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=28]
|
||||
bg_color = Color( 0.176073, 0.806619, 0.967443, 1 )
|
||||
bg_color = Color( 0.68094, 0.136103, 0.784658, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=29]
|
||||
bg_color = Color( 0.46115, 0.389032, 0.649624, 1 )
|
||||
bg_color = Color( 0.565245, 0.950216, 0.525136, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=30]
|
||||
bg_color = Color( 0.415833, 0.965657, 0.678807, 1 )
|
||||
bg_color = Color( 0.840295, 0.689674, 0.146119, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=31]
|
||||
bg_color = Color( 0.95106, 0.531613, 0.0362836, 1 )
|
||||
bg_color = Color( 0.170796, 0.863757, 0.940376, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=32]
|
||||
bg_color = Color( 0.414718, 0.156676, 0.927291, 1 )
|
||||
bg_color = Color( 0.989842, 0.167318, 0.759568, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=33]
|
||||
bg_color = Color( 0.904518, 0.341891, 0.208397, 1 )
|
||||
bg_color = Color( 0.424938, 0.286666, 0.207677, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=34]
|
||||
bg_color = Color( 0.532053, 0.87726, 0.342851, 1 )
|
||||
bg_color = Color( 0.470532, 0.276365, 0.490264, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=35]
|
||||
bg_color = Color( 0.933623, 0.443817, 0.855431, 1 )
|
||||
bg_color = Color( 0.479465, 0.612879, 0.603754, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=36]
|
||||
bg_color = Color( 0.79689, 0.333745, 0.615167, 1 )
|
||||
bg_color = Color( 0.66582, 0.937007, 0.078631, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=37]
|
||||
bg_color = Color( 0.399027, 0.806071, 0.516829, 1 )
|
||||
bg_color = Color( 0.969678, 0.463082, 0.741374, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=38]
|
||||
bg_color = Color( 0.513829, 0.820974, 0.0806655, 1 )
|
||||
bg_color = Color( 0.748974, 0.911029, 0.0970848, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=39]
|
||||
bg_color = Color( 0.576046, 0.303465, 0.354421, 1 )
|
||||
bg_color = Color( 0.0446367, 0.149028, 0.965347, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=40]
|
||||
bg_color = Color( 0.0409532, 0.831937, 0.447566, 1 )
|
||||
bg_color = Color( 0.652305, 0.82955, 0.449331, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=41]
|
||||
bg_color = Color( 0.641815, 0.654958, 0.623856, 1 )
|
||||
bg_color = Color( 0.858449, 0.143876, 0.556734, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=42]
|
||||
bg_color = Color( 0.16782, 0.641056, 0.625732, 1 )
|
||||
bg_color = Color( 0.885448, 0.997685, 0.776802, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=43]
|
||||
bg_color = Color( 0.797095, 0.50587, 0.280019, 1 )
|
||||
bg_color = Color( 0.404004, 0.65451, 0.498103, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=44]
|
||||
bg_color = Color( 0.691959, 0.511673, 0.985569, 1 )
|
||||
bg_color = Color( 0.0711977, 0.735235, 0.953192, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=45]
|
||||
bg_color = Color( 0.610537, 0.592647, 0.539142, 1 )
|
||||
bg_color = Color( 0.696129, 0.303368, 0.559114, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=46]
|
||||
bg_color = Color( 0.263664, 0.636201, 0.25046, 1 )
|
||||
bg_color = Color( 0.16818, 0.0828524, 0.104581, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=47]
|
||||
bg_color = Color( 0.49156, 0.696528, 0.836079, 1 )
|
||||
bg_color = Color( 0.388226, 0.400829, 0.895155, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=48]
|
||||
bg_color = Color( 0.402661, 0.715784, 0.995676, 1 )
|
||||
bg_color = Color( 0.381586, 0.871279, 0.0388422, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=49]
|
||||
bg_color = Color( 0.694132, 0.532637, 0.466888, 1 )
|
||||
bg_color = Color( 0.0975624, 0.683663, 0.768315, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=50]
|
||||
bg_color = Color( 0.120597, 0.37573, 0.24552, 1 )
|
||||
bg_color = Color( 0.125084, 0.498048, 0.0623495, 1 )
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=26]
|
||||
bg_color = Color( 0.156863, 0.156863, 0.156863, 1 )
|
||||
@ -702,23 +702,30 @@ margin_right = 114.0
|
||||
margin_bottom = 501.0
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Layers" type="VBoxContainer" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Control"]
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Control"]
|
||||
margin_right = 114.0
|
||||
margin_bottom = 67.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="LayerButtons" type="VBoxContainer" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Control/VBoxContainer"]
|
||||
margin_right = 114.0
|
||||
margin_bottom = 38.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Layer1" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Control/Layers" instance=ExtResource( 12 )]
|
||||
[node name="Layer1" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Control/VBoxContainer/LayerButtons" instance=ExtResource( 12 )]
|
||||
margin_bottom = 32.0
|
||||
|
||||
[node name="Button" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Control/Layers"]
|
||||
margin_top = 36.0
|
||||
[node name="Button" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Control/VBoxContainer"]
|
||||
margin_top = 42.0
|
||||
margin_right = 114.0
|
||||
margin_bottom = 61.0
|
||||
margin_bottom = 67.0
|
||||
rect_min_size = Vector2( 0, 25 )
|
||||
size_flags_horizontal = 3
|
||||
text = "+"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
@ -736,7 +743,7 @@ custom_styles/panel = SubResource( 26 )
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
text = "FPS 60 Mouse Position (0, 0) Canvas Mouse Position (0, 0) Canvas Position (0, 0)
|
||||
Cell Position (0, 0) Cell Color 0,0,0,0 Cell Region (0, 0) Cell Position (0, 0) "
|
||||
Cell Position (0, 0) Cell Color 0,0,0,0 "
|
||||
scroll_active = false
|
||||
script = ExtResource( 11 )
|
||||
__meta__ = {
|
||||
@ -777,7 +784,7 @@ mouse_filter = 1
|
||||
[connection signal="pressed" from="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Tools/ColorPickerTool" to="." method="_on_ColorPickerTool_pressed"]
|
||||
[connection signal="pressed" from="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Tools/CutTool" to="." method="_on_CutTool_pressed"]
|
||||
[connection signal="color_changed" from="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Tools/ColorPicker" to="." method="_on_ColorPicker_color_changed"]
|
||||
[connection signal="pressed" from="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Control/Layers/Button" to="." method="_on_Button_pressed"]
|
||||
[connection signal="pressed" from="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Control/VBoxContainer/Button" to="." method="_on_Button_pressed"]
|
||||
[connection signal="about_to_show" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_about_to_show"]
|
||||
[connection signal="confirmed" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_confirmed"]
|
||||
[connection signal="file_selected" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_file_selected"]
|
||||
|
@ -5,6 +5,7 @@ class_name GELayer
|
||||
var name
|
||||
var pixels # array of pixels (colors), idx repressents x and y
|
||||
var layer_width
|
||||
var visible = true
|
||||
|
||||
|
||||
func _init():
|
||||
@ -25,3 +26,9 @@ func set_pixel(x, y, color):
|
||||
|
||||
func get_pixel(x: int, y: int):
|
||||
return pixels[x + y * layer_width]
|
||||
|
||||
|
||||
func clear():
|
||||
for idx in range(pixels.size()):
|
||||
if pixels[idx] != Color.transparent:
|
||||
pixels[idx] = Color.transparent
|
||||
|
@ -9,7 +9,7 @@
|
||||
bg_color = Color( 0.25098, 0.25098, 0.25098, 1 )
|
||||
|
||||
[node name="Layer1" type="Button" groups=[
|
||||
"layer",
|
||||
"layer_button",
|
||||
]]
|
||||
margin_right = 114.0
|
||||
margin_bottom = 20.0
|
||||
|
@ -36,8 +36,7 @@ func save_file():
|
||||
image.create(canvas.canvas_width, canvas.canvas_height, true, Image.FORMAT_RGBA8)
|
||||
image.lock()
|
||||
|
||||
for layer_name in canvas.layers:
|
||||
var layer = canvas.layers[layer_name]
|
||||
for layer in canvas.layers:
|
||||
var idx = 0
|
||||
for color in layer.pixels:
|
||||
var pos = GEUtils.to_2D(idx, canvas.canvas_width)
|
||||
|
@ -37,7 +37,7 @@ static func to_1D(x, y, w) -> int:
|
||||
|
||||
static func to_2D(idx, w) -> Vector2:
|
||||
var p = Vector2()
|
||||
p.x = idx % int(w)
|
||||
p.x = int(idx) % int(w)
|
||||
p.y = int(idx / w)
|
||||
return p
|
||||
|
||||
|
@ -8,14 +8,30 @@ var action_data = {}
|
||||
func _init():
|
||||
action_data["do"] = {}
|
||||
action_data["undo"] = {}
|
||||
action_data["preview"] = {}
|
||||
|
||||
|
||||
func do_action(canvas, data: Array):
|
||||
print("NO IMPL do_action")
|
||||
if not "cells" in action_data.do:
|
||||
action_data.do["cells"] = []
|
||||
action_data.do["colors"] = []
|
||||
|
||||
if not "cells" in action_data.undo:
|
||||
action_data.undo["cells"] = []
|
||||
action_data.undo["colors"] = []
|
||||
|
||||
if not "cells" in action_data.preview:
|
||||
action_data.preview["cells"] = []
|
||||
action_data.preview["colors"] = []
|
||||
|
||||
if "layer" in action_data.do:
|
||||
action_data.do["layer"] = canvas.active_layer
|
||||
action_data.undo["layer"] = canvas.active_layer
|
||||
|
||||
|
||||
func commit_action(canvas):
|
||||
print("NO IMPL commit_action ")
|
||||
return []
|
||||
|
||||
|
||||
func undo_action(canvas):
|
||||
|
43
addons/graphics_editor/actions/Brighten.gd
Normal file
43
addons/graphics_editor/actions/Brighten.gd
Normal file
@ -0,0 +1,43 @@
|
||||
extends GEAction
|
||||
class_name GEBrighten
|
||||
|
||||
|
||||
const brighten_color = 0.1
|
||||
|
||||
|
||||
func do_action(canvas, data: Array):
|
||||
.do_action(canvas, data)
|
||||
|
||||
var pixels = GEUtils.get_pixels_in_line(data[0], data[1])
|
||||
for pixel in pixels:
|
||||
if pixel in action_data.undo.cells:
|
||||
var brightened_color = canvas.get_pixel_v(pixel).lightened(0.1)
|
||||
canvas.set_pixel_v(pixel, brightened_color)
|
||||
|
||||
action_data.do.cells.append(pixel)
|
||||
action_data.do.colors.append(brightened_color)
|
||||
continue
|
||||
|
||||
action_data.undo.colors.append(canvas.get_pixel_v(pixel))
|
||||
action_data.undo.cells.append(pixel)
|
||||
var brightened_color = canvas.get_pixel_v(pixel).lightened(0.1)
|
||||
canvas.set_pixel_v(pixel, brightened_color)
|
||||
|
||||
action_data.do.cells.append(pixel)
|
||||
action_data.do.colors.append(brightened_color)
|
||||
|
||||
|
||||
func commit_action(canvas):
|
||||
var cells = action_data.do.cells
|
||||
var colors = action_data.do.colors
|
||||
return []
|
||||
|
||||
|
||||
func undo_action(canvas):
|
||||
var cells = action_data.undo.cells
|
||||
var colors = action_data.undo.colors
|
||||
for idx in range(cells.size()):
|
||||
canvas.set_pixel_v(cells[idx], colors[idx])
|
||||
|
||||
|
||||
|
@ -3,17 +3,7 @@ class_name GEBrush
|
||||
|
||||
|
||||
func do_action(canvas: GECanvas, data: Array):
|
||||
if not "cells" in action_data.do:
|
||||
action_data.do["cells"] = []
|
||||
action_data.do["colors"] = []
|
||||
|
||||
if not "cells" in action_data.undo:
|
||||
action_data.undo["cells"] = []
|
||||
action_data.undo["colors"] = []
|
||||
|
||||
if "layer" in action_data.do:
|
||||
action_data.do["layer"] = canvas.active_layer
|
||||
action_data.undo["layer"] = canvas.active_layer
|
||||
.do_action(canvas, data)
|
||||
|
||||
for pixel in GEUtils.get_pixels_in_line(data[0], data[1]):
|
||||
for off in BrushPrefabs.list[data[3]]:
|
||||
@ -34,6 +24,7 @@ func do_action(canvas: GECanvas, data: Array):
|
||||
func commit_action(canvas):
|
||||
var cells = action_data.do.cells
|
||||
var colors = action_data.do.colors
|
||||
return []
|
||||
|
||||
|
||||
func undo_action(canvas):
|
||||
|
39
addons/graphics_editor/actions/Bucket.gd
Normal file
39
addons/graphics_editor/actions/Bucket.gd
Normal file
@ -0,0 +1,39 @@
|
||||
extends GEAction
|
||||
class_name GEBucket
|
||||
|
||||
|
||||
|
||||
func do_action(canvas, data: Array):
|
||||
.do_action(canvas, data)
|
||||
|
||||
if canvas.get_pixel_v(data[0]) == data[2]:
|
||||
return
|
||||
var pixels = canvas.select_same_color(data[0].x, data[0].y)
|
||||
|
||||
for pixel in pixels:
|
||||
if pixel in action_data.undo.cells:
|
||||
continue
|
||||
|
||||
action_data.undo.colors.append(canvas.get_pixel_v(pixel))
|
||||
action_data.undo.cells.append(pixel)
|
||||
|
||||
canvas.set_pixel_v(pixel, data[2])
|
||||
|
||||
action_data.do.cells.append(pixel)
|
||||
action_data.do.colors.append(data[2])
|
||||
|
||||
|
||||
func commit_action(canvas):
|
||||
var cells = action_data.preview.cells
|
||||
var colors = action_data.preview.colors
|
||||
return []
|
||||
|
||||
|
||||
func undo_action(canvas):
|
||||
var cells = action_data.undo.cells
|
||||
var colors = action_data.undo.colors
|
||||
for idx in range(cells.size()):
|
||||
canvas.set_pixel_v(cells[idx], colors[idx])
|
||||
|
||||
|
||||
|
70
addons/graphics_editor/actions/Cut.gd
Normal file
70
addons/graphics_editor/actions/Cut.gd
Normal file
@ -0,0 +1,70 @@
|
||||
extends GEAction
|
||||
class_name GECut
|
||||
|
||||
const selection_color = Color(0.8, 0.8, 0.8, 0.5)
|
||||
var mouse_start_pos = null
|
||||
var mouse_end_pos = null
|
||||
|
||||
func do_action(canvas, data: Array):
|
||||
.do_action(canvas, data)
|
||||
|
||||
if not mouse_start_pos:
|
||||
mouse_start_pos = data[0]
|
||||
mouse_end_pos = data[0]
|
||||
|
||||
action_data.preview.cells.clear()
|
||||
action_data.preview.colors.clear()
|
||||
canvas.clear_preview_layer()
|
||||
|
||||
var p = mouse_start_pos
|
||||
var s = mouse_end_pos - mouse_start_pos
|
||||
|
||||
var pixels = GEUtils.get_pixels_in_line(p, p + Vector2(s.x, 0))
|
||||
pixels += GEUtils.get_pixels_in_line(p, p + Vector2(0, s.y))
|
||||
pixels += GEUtils.get_pixels_in_line(p + s, p + s + Vector2(0, -s.y))
|
||||
pixels += GEUtils.get_pixels_in_line(p + s, p + s + Vector2(-s.x, 0))
|
||||
|
||||
for pixel in pixels:
|
||||
canvas.set_preview_pixel_v(pixel, selection_color)
|
||||
action_data.preview.cells.append(pixel)
|
||||
action_data.preview.colors.append(selection_color)
|
||||
|
||||
|
||||
func commit_action(canvas):
|
||||
canvas.clear_preview_layer()
|
||||
var p = mouse_start_pos
|
||||
var s = mouse_end_pos - mouse_start_pos
|
||||
|
||||
for x in range(abs(s.x)+1):
|
||||
for y in range(abs(s.y)+1):
|
||||
var px = x
|
||||
var py = y
|
||||
if s.x < 0:
|
||||
px *= -1
|
||||
if s.y < 0:
|
||||
py *= -1
|
||||
|
||||
var pos = p + Vector2(px, py)
|
||||
var color = canvas.get_pixel(pos.x, pos.y)
|
||||
|
||||
if color == Color.transparent:
|
||||
continue
|
||||
|
||||
action_data.do.cells.append(pos)
|
||||
action_data.do.colors.append(canvas.get_pixel_v(pos))
|
||||
|
||||
canvas.set_pixel_v(pos, Color.transparent)
|
||||
|
||||
action_data.undo.cells.append(pos)
|
||||
action_data.undo.colors.append(Color.transparent)
|
||||
return []
|
||||
|
||||
|
||||
func undo_action(canvas):
|
||||
var cells = action_data.undo.cells
|
||||
var colors = action_data.undo.colors
|
||||
for idx in range(cells.size()):
|
||||
canvas.set_pixel_v(cells[idx], colors[idx])
|
||||
|
||||
|
||||
|
42
addons/graphics_editor/actions/Darken.gd
Normal file
42
addons/graphics_editor/actions/Darken.gd
Normal file
@ -0,0 +1,42 @@
|
||||
extends GEAction
|
||||
class_name GEDarken
|
||||
|
||||
const dark_factor = 0.1
|
||||
|
||||
|
||||
func do_action(canvas, data: Array):
|
||||
.do_action(canvas, data)
|
||||
|
||||
var pixels = GEUtils.get_pixels_in_line(data[0], data[1])
|
||||
for pixel in pixels:
|
||||
if pixel in action_data.undo.cells:
|
||||
var darkened_color = canvas.get_pixel_v(pixel).darkened(dark_factor)
|
||||
canvas.set_pixel_v(pixel, darkened_color)
|
||||
|
||||
action_data.do.cells.append(pixel)
|
||||
action_data.do.colors.append(darkened_color)
|
||||
continue
|
||||
|
||||
action_data.undo.colors.append(canvas.get_pixel_v(pixel))
|
||||
action_data.undo.cells.append(pixel)
|
||||
var darkened_color = canvas.get_pixel_v(pixel).darkened(dark_factor)
|
||||
canvas.set_pixel_v(pixel, darkened_color)
|
||||
|
||||
action_data.do.cells.append(pixel)
|
||||
action_data.do.colors.append(darkened_color)
|
||||
|
||||
|
||||
func commit_action(canvas):
|
||||
var cells = action_data.do.cells
|
||||
var colors = action_data.do.colors
|
||||
return []
|
||||
|
||||
|
||||
func undo_action(canvas):
|
||||
var cells = action_data.undo.cells
|
||||
var colors = action_data.undo.colors
|
||||
for idx in range(cells.size()):
|
||||
canvas.set_pixel_v(cells[idx], colors[idx])
|
||||
|
||||
|
||||
|
47
addons/graphics_editor/actions/Line.gd
Normal file
47
addons/graphics_editor/actions/Line.gd
Normal file
@ -0,0 +1,47 @@
|
||||
extends GEAction
|
||||
class_name GELine
|
||||
|
||||
|
||||
var mouse_start_pos = null
|
||||
|
||||
func do_action(canvas, data: Array):
|
||||
.do_action(canvas, data)
|
||||
|
||||
if mouse_start_pos == null:
|
||||
mouse_start_pos = data[0]
|
||||
|
||||
action_data.preview.cells.clear()
|
||||
action_data.preview.colors.clear()
|
||||
canvas.clear_preview_layer()
|
||||
|
||||
var pixels = GEUtils.get_pixels_in_line(data[0], mouse_start_pos)
|
||||
for pixel in pixels:
|
||||
canvas.set_preview_pixel_v(pixel, data[2])
|
||||
action_data.preview.cells.append(pixel)
|
||||
action_data.preview.colors.append(data[2])
|
||||
|
||||
|
||||
func commit_action(canvas):
|
||||
canvas.clear_preview_layer()
|
||||
var cells = action_data.preview.cells
|
||||
var colors = action_data.preview.colors
|
||||
for idx in range(cells.size()):
|
||||
action_data.undo.cells.append(cells[idx])
|
||||
action_data.undo.colors.append(canvas.get_pixel_v(cells[idx]))
|
||||
|
||||
canvas.set_pixel_v(cells[idx], colors[idx])
|
||||
|
||||
action_data.do.cells.append(cells[idx])
|
||||
action_data.do.colors.append(colors[idx])
|
||||
mouse_start_pos = null
|
||||
return []
|
||||
|
||||
|
||||
func undo_action(canvas):
|
||||
var cells = action_data.undo.cells
|
||||
var colors = action_data.undo.colors
|
||||
for idx in range(cells.size()):
|
||||
canvas.set_pixel_v(cells[idx], colors[idx])
|
||||
|
||||
|
||||
|
@ -3,31 +3,26 @@ class_name GEPencil
|
||||
|
||||
|
||||
func do_action(canvas, data: Array):
|
||||
if not "cells" in action_data.do:
|
||||
action_data.do["cells"] = []
|
||||
action_data.do["colors"] = []
|
||||
|
||||
if not "cells" in action_data.undo:
|
||||
action_data.undo["cells"] = []
|
||||
action_data.undo["colors"] = []
|
||||
|
||||
if "layer" in action_data.do:
|
||||
action_data.do["layer"] = canvas.active_layer
|
||||
action_data.undo["layer"] = canvas.active_layer
|
||||
.do_action(canvas, data)
|
||||
|
||||
var pixels = GEUtils.get_pixels_in_line(data[0], data[1])
|
||||
for pixel in pixels:
|
||||
canvas.set_pixel_v(pixel, data[2])
|
||||
action_data.do.cells.append(pixel)
|
||||
if pixel in action_data.undo.cells:
|
||||
continue
|
||||
|
||||
action_data.undo.colors.append(canvas.get_pixel_v(pixel))
|
||||
action_data.undo.cells.append(pixel)
|
||||
|
||||
canvas.set_pixel_v(pixel, data[2])
|
||||
|
||||
action_data.do.cells.append(pixel)
|
||||
action_data.do.colors.append(data[2])
|
||||
action_data.undo.colors.append(Color.transparent)
|
||||
|
||||
|
||||
func commit_action(canvas):
|
||||
var cells = action_data.do.cells
|
||||
var colors = action_data.do.colors
|
||||
return []
|
||||
|
||||
|
||||
func undo_action(canvas):
|
||||
|
45
addons/graphics_editor/actions/Rainbow.gd
Normal file
45
addons/graphics_editor/actions/Rainbow.gd
Normal file
@ -0,0 +1,45 @@
|
||||
extends GEAction
|
||||
class_name GERainbow
|
||||
|
||||
|
||||
func do_action(canvas, data: Array):
|
||||
.do_action(canvas, data)
|
||||
|
||||
var pixels = GEUtils.get_pixels_in_line(data[0], data[1])
|
||||
for pixel in pixels:
|
||||
if pixel in action_data.undo.cells:
|
||||
var color = GEUtils.random_color()
|
||||
canvas.set_pixel_v(pixel, color)
|
||||
|
||||
var idx = action_data.do.cells.find(pixel)
|
||||
action_data.do.cells.remove(idx)
|
||||
action_data.do.colors.remove(idx)
|
||||
|
||||
action_data.do.cells.append(pixel)
|
||||
action_data.do.colors.append(color)
|
||||
continue
|
||||
|
||||
action_data.undo.colors.append(canvas.get_pixel_v(pixel))
|
||||
action_data.undo.cells.append(pixel)
|
||||
|
||||
var color = GEUtils.random_color()
|
||||
canvas.set_pixel_v(pixel, color)
|
||||
|
||||
action_data.do.cells.append(pixel)
|
||||
action_data.do.colors.append(color)
|
||||
|
||||
|
||||
func commit_action(canvas):
|
||||
var cells = action_data.do.cells
|
||||
var colors = action_data.do.colors
|
||||
return []
|
||||
|
||||
|
||||
func undo_action(canvas):
|
||||
var cells = action_data.undo.cells
|
||||
var colors = action_data.undo.colors
|
||||
for idx in range(cells.size()):
|
||||
canvas.set_pixel_v(cells[idx], colors[idx])
|
||||
|
||||
|
||||
|
57
addons/graphics_editor/actions/Rect.gd
Normal file
57
addons/graphics_editor/actions/Rect.gd
Normal file
@ -0,0 +1,57 @@
|
||||
extends GEAction
|
||||
class_name GERect
|
||||
|
||||
|
||||
var mouse_start_pos = null
|
||||
|
||||
func do_action(canvas, data: Array):
|
||||
.do_action(canvas, data)
|
||||
|
||||
if mouse_start_pos == null:
|
||||
mouse_start_pos = data[0]
|
||||
print("init:", mouse_start_pos)
|
||||
|
||||
|
||||
action_data.undo.cells.clear()
|
||||
action_data.undo.colors.clear()
|
||||
action_data.preview.cells.clear()
|
||||
action_data.preview.colors.clear()
|
||||
canvas.clear_preview_layer()
|
||||
|
||||
var p = mouse_start_pos
|
||||
var s = data[0] - mouse_start_pos
|
||||
var pixels = GEUtils.get_pixels_in_line(p, p + Vector2(s.x, 0))
|
||||
pixels += GEUtils.get_pixels_in_line(p, p + Vector2(0, s.y))
|
||||
pixels += GEUtils.get_pixels_in_line(p + s, p + s + Vector2(0, -s.y))
|
||||
pixels += GEUtils.get_pixels_in_line(p + s, p + s + Vector2(-s.x, 0))
|
||||
|
||||
for pixel in pixels:
|
||||
canvas.set_preview_pixel_v(pixel, data[2])
|
||||
action_data.undo.cells.append(pixel)
|
||||
action_data.undo.colors.append(canvas.get_pixel_v(pixel))
|
||||
action_data.preview.cells.append(pixel)
|
||||
action_data.preview.colors.append(data[2])
|
||||
|
||||
|
||||
func commit_action(canvas):
|
||||
canvas.clear_preview_layer()
|
||||
var cells = action_data.preview.cells
|
||||
var colors = action_data.preview.colors
|
||||
for idx in range(cells.size()):
|
||||
|
||||
canvas.set_pixel_v(cells[idx], colors[idx])
|
||||
|
||||
action_data.do.cells.append(cells[idx])
|
||||
action_data.do.colors.append(colors[idx])
|
||||
mouse_start_pos = null
|
||||
return []
|
||||
|
||||
|
||||
func undo_action(canvas):
|
||||
var cells = action_data.undo.cells
|
||||
var colors = action_data.undo.colors
|
||||
for idx in range(cells.size()):
|
||||
canvas.set_pixel_v(cells[idx], colors[idx])
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@ _global_script_classes=[ {
|
||||
"base": "Reference",
|
||||
"class": "BrushPrefabs",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/Brush.gd"
|
||||
"path": "res://addons/graphics_editor/BrushPrefabs.gd"
|
||||
}, {
|
||||
"base": "Node",
|
||||
"class": "GEAction",
|
||||
@ -20,25 +20,60 @@ _global_script_classes=[ {
|
||||
"path": "res://addons/graphics_editor/actions/Action.gd"
|
||||
}, {
|
||||
"base": "GEAction",
|
||||
"class": "GEBrighten",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/actions/Brighten.gd"
|
||||
}, {
|
||||
"base": "GEAction",
|
||||
"class": "GEBrush",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/actions/Brush.gd"
|
||||
}, {
|
||||
"base": "GEAction",
|
||||
"class": "GEBucket",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/actions/Bucket.gd"
|
||||
}, {
|
||||
"base": "Control",
|
||||
"class": "GECanvas",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/Canvas.gd"
|
||||
}, {
|
||||
"base": "GEAction",
|
||||
"class": "GECut",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/actions/Cut.gd"
|
||||
}, {
|
||||
"base": "GEAction",
|
||||
"class": "GEDarken",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/actions/Darken.gd"
|
||||
}, {
|
||||
"base": "Reference",
|
||||
"class": "GELayer",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/Layer.gd"
|
||||
}, {
|
||||
"base": "GEAction",
|
||||
"class": "GELine",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/actions/Line.gd"
|
||||
}, {
|
||||
"base": "GEAction",
|
||||
"class": "GEPencil",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/actions/Pencil.gd"
|
||||
}, {
|
||||
"base": "GEAction",
|
||||
"class": "GERainbow",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/actions/Rainbow.gd"
|
||||
}, {
|
||||
"base": "GEAction",
|
||||
"class": "GERect",
|
||||
"language": "GDScript",
|
||||
"path": "res://addons/graphics_editor/actions/Rect.gd"
|
||||
}, {
|
||||
"base": "Node",
|
||||
"class": "GEUtils",
|
||||
"language": "GDScript",
|
||||
@ -47,10 +82,17 @@ _global_script_classes=[ {
|
||||
_global_script_class_icons={
|
||||
"BrushPrefabs": "",
|
||||
"GEAction": "",
|
||||
"GEBrighten": "",
|
||||
"GEBrush": "",
|
||||
"GEBucket": "",
|
||||
"GECanvas": "",
|
||||
"GECut": "",
|
||||
"GEDarken": "",
|
||||
"GELayer": "",
|
||||
"GELine": "",
|
||||
"GEPencil": "",
|
||||
"GERainbow": "",
|
||||
"GERect": "",
|
||||
"GEUtils": ""
|
||||
}
|
||||
|
||||
@ -59,12 +101,6 @@ _global_script_class_icons={
|
||||
config/name="TestGDNative"
|
||||
config/icon="res://icon.png"
|
||||
|
||||
[autoload]
|
||||
|
||||
Gdtest="*res://gdtest.gdns"
|
||||
IconLoader="*res://addons/file-editor/scripts/IconLoader.gd"
|
||||
LastOpenedFiles="*res://addons/file-editor/scripts/LastOpenedFiles.gd"
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PoolStringArray( "godot-plugin-refresher", "graphics_editor" )
|
||||
|
Loading…
Reference in New Issue
Block a user