reimplementd how pixels are drawn, not suing texture but hte draw_rect method which shouldn't take that much performance, also acxcessing the pxiels per idx (1D) with x_pos + y_pos * canvas_width = idx

This commit is contained in:
cobrapitz 2020-10-26 17:01:31 +01:00
parent 6ca768ee8e
commit cfd5d9e6ba
14 changed files with 751 additions and 414 deletions

View File

@ -1,3 +1,3 @@
source_md5="9898b4b50cf2b080d5c106e39863f916"
dest_md5="64289bfd5608e896cab1ef7ed48d84e6"
source_md5="f2446c62da0093ebbc5c6a4c629e95fa"
dest_md5="f805a61fa71cdc48cc5f45a98dfd4332"

View File

@ -0,0 +1,300 @@
extends Control
tool
export var pixel_size: int = 16 setget set_pixel_size
export(int, 1, 2500) var canvas_width = 48 setget set_canvas_width # == pixels
export(int, 1, 2500) var canvas_height = 28 setget set_canvas_height # == pixels
export var grid_size = 16 setget set_grid_size
export var big_grid_size = 10 setget set_big_grid_size
export var can_draw = true
var mouse_in_region
var mouse_on_top
var layers = {} # Key: layer_name, val: GELayer
var active_layer: GELayer
var preview_layer: GELayer
var canvas
var grid
var big_grid
var selected_pixels = []
func _enter_tree():
#-------------------------------
# Set nodes
#-------------------------------
canvas = find_node("Canvas")
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)
set_process(true)
func _process(delta):
if active_layer == null:
return
var mouse_position = get_local_mouse_position()
var rect = Rect2(Vector2(0, 0), rect_size)
mouse_in_region = rect.has_point(mouse_position)
update()
func _draw():
for layer_name in layers:
var layer = layers[layer_name]
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
#-------------------------------
# Export
#-------------------------------
func set_pixel_size(size: int):
pixel_size = size
set_grid_size(grid_size)
set_big_grid_size(big_grid_size)
set_canvas_width(canvas_width)
set_canvas_height(canvas_height)
func set_grid_size(size):
grid_size = size
if not find_node("Grid"):
return
find_node("Grid").size = size * pixel_size
func set_big_grid_size(size):
big_grid_size = size
if not find_node("BigGrid"):
return
find_node("BigGrid").size = size * pixel_size
func set_canvas_width(val: int):
canvas_width = val
rect_size.x = canvas_width * pixel_size
func set_canvas_height(val: int):
canvas_height = val
rect_size.y = canvas_height * pixel_size
#-------------------------------
# Layer
#-------------------------------
func get_active_layer():
return active_layer
func get_preview_layer():
return preview_layer
func clear_active_layer():
clear_layer(active_layer.name)
func clear_preview_layer():
clear_layer(preview_layer.name)
func clear_layer(layer_name: String):
for layer in layers:
layer.pixels.clear()
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:
for layer in layers:
if layer == preview_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 ?
return active_layer
func add_new_layer(layer_name):
if layer_name in layers:
return
var layer = GELayer.new()
layer.name = layer_name
layer.resize(canvas_width, canvas_height)
layers[layer_name] = layer
return layers[layer_name]
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()
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
#-------------------------------
# Check
#-------------------------------
func _on_mouse_entered():
mouse_on_top = true
func _on_mouse_exited():
mouse_on_top = false
func is_inside_canvas(x, y):
if x < 0 or y < 0:
return false
if x >= canvas_width or y >= canvas_height:
return false
return true
#-------------------------------
# Basic pixel-layer options
#-------------------------------
#Note: Arrays are always passed by reference. To get a copy of an array which
# can be modified independently of the original array, use duplicate.
# (https://docs.godotengine.org/en/stable/classes/class_array.html)
func set_pixel_arr(pixels: Array, color: Color):
for pixel in pixels:
_set_pixel(active_layer, pixel.x, pixel.y, color)
func set_pixel_v(pos: Vector2, color: Color):
set_pixel(pos.x, pos.y, color)
func set_pixel(x: int, y: int, color: Color):
_set_pixel(active_layer, x, y, color)
func _set_pixel(layer: GELayer, x: int, y: int, color: Color):
if not is_inside_canvas(x, y):
return
layer.set_pixel(x, y, color)
func get_pixel_v(pos: Vector2):
return get_pixel(pos.x, pos.y)
func get_pixel(x: int, y: int):
var idx = GEUtils.to_1D(x, y, canvas_width)
if active_layer:
if not active_layer.pixels.has(idx):
return null
return active_layer.pixels[idx]
#-------------------------------
# Handy tools
#-------------------------------
func select_color(x, y):
var same_color_pixels = []
var color = get_pixel(x, y)
for pixel_color in active_layer.pixels:
if pixel_color == color:
same_color_pixels.append(color)
return same_color_pixels
func select_neighbouring_color(x, y):
return get_neighbouring_pixels(x, y)
# returns array of Vector2
# yoinked from
# https://www.geeksforgeeks.org/flood-fill-algorithm-implement-fill-paint/
func get_neighbouring_pixels(pos_x: int, pos_y: int) -> Array:
var pixels = []
var check_queue = []
check_queue.append(Vector2(pos_x, pos_y))
var color = get_pixel(pos_x, pos_y)
while not check_queue.empty():
var p = check_queue.pop_front()
if get_pixel(p.x, p.y) != color:
continue
# add to result
pixels.append(p)
# 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))
x = p.x + 1
if not p in pixels and is_inside_canvas(x, y):
check_queue.append(Vector2(x, y))
x = p.x
y = p.y - 1
if not p in pixels and is_inside_canvas(x, y):
check_queue.append(Vector2(x, y))
y = p.y + 1
if not p in pixels and is_inside_canvas(x, y):
check_queue.append(Vector2(x, y))
return pixels

View File

@ -3,18 +3,19 @@ extends Control
export var color = Color()
func _ready():
pass
func _draw():
var size = get_parent().get_node("Grids").rect_size
var pos = get_parent().get_node("Grids").rect_position
var size = get_parent().rect_size
var pos = Vector2.ZERO #get_parent().rect_global_position
draw_outline_box(pos, size, color, 1)
func draw_outline_box(pos, size, color, width):
#Top line
pos -= Vector2(0, 0)
size += Vector2(0, 0)
draw_line(pos, pos + Vector2(size.x, 0), color, width)
#Left line
draw_line(pos, pos + Vector2(0, size.y), color, width)
@ -23,5 +24,6 @@ func draw_outline_box(pos, size, color, width):
#Right line
draw_line(pos + Vector2(size.x, 0), pos + Vector2(size.x, size.y), color, width)
func _process(delta):
update()

View File

@ -15,14 +15,12 @@ enum Tools {
}
var paint_canvas_container_node
var paint_canvas_node
var paint_canvas
var grids_node
var colors_grid
var selected_color = Color(1, 1, 1, 1)
var util = preload("res://addons/graphics_editor/Util.gd")
var textinfo
onready var grid_size = paint_canvas_node.grid_size
onready var region_size = paint_canvas_node.region_size
var allow_drawing = true
@ -44,9 +42,10 @@ var _cut_size = Vector2.ZERO
var _actions_history = [] # for undo
var _redo_history = []
var _current_action
var Actions = {
Tools.PAINT: load("res://addons/graphics_editor/actions/Pencil.gd").new(),
enum Action {
PAINT,
}
@ -55,18 +54,12 @@ func _enter_tree():
#Setup nodes
#--------------------
paint_canvas_container_node = find_node("PaintCanvasContainer")
paint_canvas_node = paint_canvas_container_node.find_node("PaintCanvas")
grids_node = paint_canvas_node.find_node("Grids")
textinfo = find_node("DebugTextDisplay")
selected_color = find_node("ColorPicker").color
colors_grid = find_node("Colors")
paint_canvas = get_node("Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/Canvas")
print(paint_canvas)
set_process(true)
#--------------------
# Setup Actions
#--------------------
for key in Actions:
Actions[key].painter = paint_canvas_node
#--------------------
#connect nodes
@ -76,58 +69,15 @@ func _enter_tree():
if not is_connected("visibility_changed", self, "_on_Editor_visibility_changed"):
connect("visibility_changed", self, "_on_Editor_visibility_changed")
#--------------------
#Setup the layer
#--------------------
var layer_container = find_node("Layers")
for child in layer_container.get_children():
if child.name == "Layer1" or child.name == "Button":
continue
print("too many children: ", child.name)
# child.queue_free()
#------------------
#Setup visual grids
#------------------
# for i in grids_node.get_children():
# i.rect_size = Vector2(paint_canvas_node.canvas_size.x * grid_size, paint_canvas_node.canvas_size.y * grid_size)
# grids_node.get_node("VisualGrid").size = grid_size
# grids_node.get_node("VisualGrid2").size = grid_size * region_size
#-----------------------------------
#Setup canvas node size and position
#-----------------------------------
# paint_canvas_node.rect_size = Vector2(paint_canvas_node.canvas_size.x * grid_size,
# paint_canvas_node.canvas_size.y * grid_size)
# paint_canvas_node.rect_min_size = Vector2(paint_canvas_node.canvas_size.x * grid_size,
# paint_canvas_node.canvas_size.y * grid_size)
#----------------------------------------------------------------
#Setup is done so we can now allow the user to draw on the canvas
#----------------------------------------------------------------
paint_canvas_node.can_draw = true
func _ready():
_add_init_layers()
func _add_init_layers():
var i = 0
for layer in paint_canvas_node.layers:
if layer == paint_canvas_node.preview_layer:
continue
_layer_button_ref[layer] = find_node("Layers").get_child(i)
print("layer: ", layer, " is ", find_node("Layers").get_child(i).name)
i += 1
_connect_layer_buttons()
return
func _input(event):
if Input.is_key_pressed(KEY_Z):
print("Z")
undo_action()
elif Input.is_key_pressed(KEY_Y):
print("Y")
@ -139,8 +89,6 @@ var mouse_position = Vector2()
var canvas_position = Vector2()
var canvas_mouse_position = Vector2()
var cell_mouse_position = Vector2()
var cell_region_position = Vector2()
var cell_position_in_region = Vector2()
var cell_color = Color()
var last_mouse_position = Vector2()
@ -155,25 +103,20 @@ func _process(delta):
update_text_info()
#It's a lot more easier to just keep updating the variables in here than just have a bunch of local variables
#in every update function and make it very messy
if paint_canvas_node == null:
if paint_canvas == null:
#_check_variables()
set_process(false)
return
#Update commonly used variables
grid_size = paint_canvas_node.grid_size
region_size = paint_canvas_node.region_size
mouse_position = paint_canvas_node.get_local_mouse_position()
var grid_size = paint_canvas.pixel_size
mouse_position = paint_canvas.get_local_mouse_position()
canvas_position = paint_canvas_container_node.rect_position
canvas_mouse_position = Vector2(mouse_position.x - canvas_position.x, mouse_position.y - canvas_position.y)
cell_mouse_position = Vector2(floor(canvas_mouse_position.x / grid_size), floor(canvas_mouse_position.y / grid_size))
cell_region_position = Vector2(floor(cell_mouse_position.x / region_size), floor(cell_mouse_position.y / region_size))
cell_position_in_region = paint_canvas_node.get_region_from_cell(cell_mouse_position.x, cell_mouse_position.y)
cell_color = paint_canvas_node.get_pixel_cell_color(cell_mouse_position.x, cell_mouse_position.y)
cell_color = paint_canvas.get_pixel(cell_mouse_position.x, cell_mouse_position.y)
#Process the brush drawing stuff
if (paint_canvas_node.mouse_in_region and paint_canvas_node.mouse_on_top) \
or paint_canvas_node.preview_enabled:
if (paint_canvas.mouse_in_region and paint_canvas.mouse_on_top):
brush_process()
#Render the highlighting stuff
@ -181,11 +124,11 @@ func _process(delta):
#Canvas Shift Moving
if not mouse_position == last_mouse_position:
if paint_canvas_node.has_focus():
if paint_canvas.has_focus():
if Input.is_key_pressed(KEY_SHIFT):
if Input.is_mouse_button_pressed(BUTTON_LEFT):
var relative = mouse_position - last_mouse_position
paint_canvas_node.rect_position += relative
paint_canvas.rect_position += relative
allow_drawing = false
else:
allow_drawing = true
@ -197,253 +140,215 @@ func _process(delta):
last_cell_mouse_position = cell_mouse_position
last_cell_color = cell_color
var currently_selecting = false
func _draw():
if paint_canvas_node == null:
return
if paint_canvas_node.mouse_in_region and paint_canvas_node.mouse_in_region:
#draw cell_mouse_position
if paint_canvas_node.cell_in_canvas_region(cell_mouse_position.x, cell_mouse_position.y):
draw_rect(Rect2(Vector2(
(cell_mouse_position.x * grid_size) + canvas_position.x,
(cell_mouse_position.y * grid_size) + canvas_position.y),
Vector2(grid_size, grid_size)), Color(0.8, 0.8, 0.8, 0.8), true)
func draw_outline_box(pos, size, color, width):
#Top line
draw_line(Vector2(0 + 1 + pos.x, 0 + pos.y), Vector2(pos.x + size.x, 0 + pos.y), color, width)
#Left line
draw_line(Vector2(0 + 1 + pos.x, 0 + pos.y), Vector2(0 + pos.x, pos.y + size.y), color, width)
#Bottom line
draw_line(Vector2(0 + 1 + pos.x, pos.y + size.y), Vector2(pos.x + size.x, pos.y + size.y), color, width)
#Right line
draw_line(Vector2(pos.x + size.x, 0 + pos.y), Vector2(pos.x + size.x, pos.y + size.y), color, width)
func pool_vector2_array_append_new_value(vec2array, vec2):
for i in vec2array:
if i == vec2:
return
vec2array.append(vec2)
func custom_rect_size_brush(x, y, color, size):
for cx in range(x, x + size):
for cy in range(y, y + size):
paint_canvas_node.set_pixel_cell(cx, cy, color)
pass
func _handle_cut():
if Input.is_mouse_button_pressed(BUTTON_RIGHT):
_just_cut = false
_show_cut = false
paint_canvas_node.preview_enabled = true
paint_canvas_node.clear_layer("preview")
paint_canvas.clear_preview_layer()
brush_mode = _previous_tool
paint_canvas_node.preview_enabled = false
_selection = []
return
if Input.is_mouse_button_pressed(BUTTON_LEFT):
for pixel_pos in paint_canvas_node.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_node.set_pixel_cell_v(pos, pixel[1])
# 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])
else:
if _last_preview_draw_cell_pos == cell_mouse_position:
return
paint_canvas_node.preview_enabled = true
paint_canvas_node.clear_layer("preview")
paint_canvas.clear_preview_layer()
for pixel in _selection:
var pos = pixel[0]
pos -= _cut_pos
pos += cell_mouse_position
paint_canvas_node.set_pixel_cell_v(pos, pixel[1])
paint_canvas_node.preview_enabled = false
paint_canvas.set_pixel_v(pos, pixel[1])
_last_preview_draw_cell_pos = cell_mouse_position
func brush_process():
if not allow_drawing:
return
if _just_cut:
_handle_cut()
return
if Input.is_mouse_button_pressed(BUTTON_LEFT):
do_action(Actions[brush_mode], [cell_mouse_position, last_cell_mouse_position, selected_color])
# var arr = GEUtils.get_pixels_in_line(cell_mouse_position, last_cell_mouse_position)
# paint_canvas.set_pixel_arr(arr, selected_color)
do_action([cell_mouse_position, last_cell_mouse_position, selected_color])
return
else:
commit_action()
return
if Input.is_mouse_button_pressed(BUTTON_LEFT):
match brush_mode:
Tools.PAINT:
paint_canvas_node.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, selected_color)
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 paint_canvas_node.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position):
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_node.set_pixel_cell_v(pixel_pos + off, selected_color)
paint_canvas.set_pixel_v(pixel_pos + off, selected_color)
Tools.LINE:
paint_canvas_node.preview_enabled = true
if _left_mouse_pressed_start_pos == Vector2.ZERO:
_left_mouse_pressed_start_pos = cell_mouse_position
paint_canvas_node.clear_layer("preview")
paint_canvas_node.set_pixels_from_line(
paint_canvas.clear_preview_layer()
paint_canvas.set_pixels_from_line(
cell_mouse_position, _left_mouse_pressed_start_pos, selected_color)
Tools.RECT:
paint_canvas_node.preview_enabled = true
if _left_mouse_pressed_start_pos == Vector2.ZERO:
_left_mouse_pressed_start_pos = cell_mouse_position
paint_canvas_node.clear_layer("preview")
paint_canvas.clear_preview_layer()
var p = _left_mouse_pressed_start_pos
var s = cell_mouse_position - _left_mouse_pressed_start_pos
paint_canvas_node.set_pixels_from_line(
paint_canvas.set_pixels_from_line(
p, p + Vector2(s.x, 0), selected_color)
paint_canvas_node.set_pixels_from_line(
paint_canvas.set_pixels_from_line(
p, p + Vector2(0, s.y), selected_color)
paint_canvas_node.set_pixels_from_line(
paint_canvas.set_pixels_from_line(
p + s, p + s + Vector2(0, -s.y), selected_color)
paint_canvas_node.set_pixels_from_line(
paint_canvas.set_pixels_from_line(
p + s, p + s + Vector2(-s.x, 0), selected_color)
Tools.DARKEN:
var pixels = paint_canvas_node.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
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_node.get_pixel_cell_color(pixel.x, pixel.y)
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_node.set_pixel_cell_v(pixel, new_color)
paint_canvas.set_pixel_v(pixel, new_color)
Tools.BRIGHTEN:
var pixels = paint_canvas_node.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
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_node.get_pixel_cell_color(pixel.x, pixel.y)
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_node.set_pixel_cell_v(pixel, new_color)
paint_canvas.set_pixel_v(pixel, new_color)
Tools.COLORPICKER:
change_color(paint_canvas_node.get_pixel_cell_color(cell_mouse_position.x, cell_mouse_position.y))
change_color(paint_canvas.get_pixel_cell_color(cell_mouse_position.x, cell_mouse_position.y))
Tools.CUT:
paint_canvas_node.preview_enabled = true
if _left_mouse_pressed_start_pos == Vector2.ZERO:
_left_mouse_pressed_start_pos = cell_mouse_position
paint_canvas_node.clear_layer("preview")
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_node.set_pixels_from_line(
paint_canvas.set_pixels_from_line(
p, p + Vector2(s.x, 0), selection_color)
paint_canvas_node.set_pixels_from_line(
paint_canvas.set_pixels_from_line(
p, p + Vector2(0, s.y), selection_color)
paint_canvas_node.set_pixels_from_line(
paint_canvas.set_pixels_from_line(
p + s, p + s + Vector2(0, -s.y), selection_color)
paint_canvas_node.set_pixels_from_line(
paint_canvas.set_pixels_from_line(
p + s, p + s + Vector2(-s.x, 0), selection_color)
Tools.BUCKET:
paint_canvas_node.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, selected_color)
paint_canvas.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, selected_color)
Tools.RAINBOW:
paint_canvas_node.set_random_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
paint_canvas.set_random_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
_:
print("no brush selected")
# paint_canvas_node.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, selected_color)
elif Input.is_mouse_button_pressed(BUTTON_RIGHT):
# paint_canvas.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, selected_color)
else:
if _current_action and _current_action.can_commit():
commit_action()
if Input.is_mouse_button_pressed(BUTTON_RIGHT):
return
match brush_mode:
Tools.PAINT:
paint_canvas_node.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))
# Tools.BUCKET:
# paint_canvas_node.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, Color(0, 0, 0, 0))
# paint_canvas.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, Color(0, 0, 0, 0))
Tools.BRUSH:
for pixel_pos in paint_canvas_node.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position):
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_node.set_pixel_cell_v(pixel_pos + off, Color(0, 0, 0, 0))
paint_canvas.set_pixel_v(pixel_pos + off, Color(0, 0, 0, 0))
Tools.RAINBOW:
paint_canvas_node.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))
_:
paint_canvas_node.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 paint_canvas_node.preview_enabled:
if not Input.is_mouse_button_pressed(BUTTON_LEFT):
match brush_mode:
Tools.LINE:
paint_canvas_node.clear_layer("preview")
paint_canvas_node.preview_enabled = false
paint_canvas_node.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_node.clear_layer("preview")
paint_canvas_node.preview_enabled = false
var p = _left_mouse_pressed_start_pos
var s = cell_mouse_position - _left_mouse_pressed_start_pos
paint_canvas_node.set_pixels_from_line(
p, p + Vector2(s.x, 0), selected_color)
paint_canvas_node.set_pixels_from_line(
p, p + Vector2(0, s.y), selected_color)
paint_canvas_node.set_pixels_from_line(
p + s, p + s + Vector2(0, -s.y), selected_color)
paint_canvas_node.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_node.clear_layer("preview")
paint_canvas_node.preview_enabled = false
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_node.get_pixel_cell_color(pos.x, pos.y)
if color.a == 0:
continue
_selection.append([pos, color])
paint_canvas_node.set_pixel_cell_v(pos, Color.transparent)
_left_mouse_pressed_start_pos = Vector2.ZERO
_just_cut = true
paint_canvas_node.preview_enabled = true
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
func update_text_info():
var text = ""
var cell_color_text = cell_color
# if paint_canvas_node.mouse_in_region and paint_canvas_container_node.mouse_on_top:
# if Input.is_mouse_button_pressed(BUTTON_LEFT) or Input.is_mouse_button_pressed(BUTTON_RIGHT):
# if paint_canvas_node.last_pixel.size() > 0:
# cell_color_text = paint_canvas_node.last_pixel[2]
cell_color_text = Color(0, 0, 0, 0)
text += \
@ -452,17 +357,13 @@ func update_text_info():
"Canvas Mouse Position %s \t" + \
"Canvas Position %s\t\n" + \
"Cell Position %s \t" + \
"Cell Color %s\t" + \
"Cell Region %s \t" + \
"Cell Position %s\t") % [
"Cell Color %s\t") % [
str(Engine.get_frames_per_second()),
str(mouse_position),
str(canvas_mouse_position),
str(canvas_position),
str(cell_mouse_position),
str(cell_color_text),
str(cell_region_position),
str(cell_position_in_region),
]
find_node("DebugTextDisplay").display_text(text)
@ -470,7 +371,6 @@ func update_text_info():
func select_layer(layer_name: String):
print("select layer: ", layer_name)
paint_canvas_node.active_layer = layer_name
func _on_Save_pressed():
@ -483,10 +383,32 @@ func _on_Save_pressed():
#---------------------------------------
func do_action(action, data: Array):
func get_action():
match brush_mode:
Tools.PAINT:
return GEPencil.new()
return null
func do_action(data: Array):
if _current_action == null:
_redo_history.clear()
_current_action = GEPencil.new()
_current_action.do_action(paint_canvas, data)
func commit_action():
if not _current_action:
return
var action = GEPencil.new()
action.action_data = _current_action.action_data
if not "action_data" in action:
print(action.get_class())
return
action.action_data = _current_action.action_data.duplicate(true)
_actions_history.push_back(action)
action.do_action(data)
_redo_history.clear()
_current_action.commit_action(paint_canvas)
_current_action = null
func redo_action():
@ -495,8 +417,9 @@ func redo_action():
func undo_action():
var action = _actions_history.pop_back()
_redo_history.append(action)
action.undo_action()
if not action:
return
action.undo_action(paint_canvas)
#---------------------------------------
@ -587,8 +510,8 @@ func _connect_layer_buttons():
func toggle_layer_visibility(button, layer_name: String):
print("toggling: ", layer_name)
print(paint_canvas_node.layers.keys())
paint_canvas_node.toggle_layer_visibility(layer_name)
print(paint_canvas.layers.keys())
paint_canvas.toggle_layer_visibility(layer_name)
func add_new_layer():
@ -598,7 +521,7 @@ func add_new_layer():
_total_added_layers += 1
new_layer.text = "Layer " + str(_total_added_layers)
var new_layer_name = paint_canvas_node.add_new_layer(new_layer.name)
var new_layer_name = paint_canvas.add_new_layer(new_layer.name)
_layer_button_ref[new_layer_name] = new_layer
@ -611,10 +534,10 @@ func remove_active_layer():
if _layer_button_ref.size() < 2:
return
_layer_button_ref[paint_canvas_node.active_layer].get_parent().remove_child(_layer_button_ref[paint_canvas_node.active_layer])
_layer_button_ref[paint_canvas_node.active_layer].queue_free()
_layer_button_ref.erase(paint_canvas_node.active_layer)
paint_canvas_node.remove_layer(paint_canvas_node.active_layer)
_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():
@ -626,7 +549,7 @@ func duplicate_active_layer():
_total_added_layers += 1 # for keeping track...
new_layer_button.text = "Layer " + str(_total_added_layers)
var new_layer_name = paint_canvas_node.duplicate_layer(paint_canvas_node.active_layer, new_layer_button.name)
var new_layer_name = paint_canvas.duplicate_layer(paint_canvas.active_layer, new_layer_button.name)
_layer_button_ref[new_layer_name] = new_layer_button
@ -646,7 +569,7 @@ func get_layer_by_button_name(button_name: String):
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_node.layers[layer_name].chunks
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))
@ -654,7 +577,7 @@ func move_down(layer_btn, button_name: String):
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_node.layers[layer_name].chunks
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,

View File

@ -1,7 +1,7 @@
[gd_scene load_steps=38 format=2]
[gd_scene load_steps=39 format=2]
[ext_resource path="res://addons/graphics_editor/Editor.gd" type="Script" id=1]
[ext_resource path="res://addons/graphics_editor/PaintCanvas.tscn" type="PackedScene" id=3]
[ext_resource path="res://addons/graphics_editor/Canvas.gd" type="Script" id=3]
[ext_resource path="res://addons/graphics_editor/VisualGrid.tscn" type="PackedScene" id=4]
[ext_resource path="res://addons/graphics_editor/CanvasOutline.gd" type="Script" id=5]
[ext_resource path="res://addons/graphics_editor/Navbar.gd" type="Script" id=6]
@ -11,6 +11,7 @@
[ext_resource path="res://addons/graphics_editor/Settings.tscn" type="PackedScene" id=10]
[ext_resource path="res://addons/graphics_editor/DebugTextDisplay.gd" type="Script" id=11]
[ext_resource path="res://addons/graphics_editor/LayerButton.tscn" type="PackedScene" id=12]
[ext_resource path="res://icon.png" type="Texture" id=13]
[sub_resource type="StyleBoxFlat" id=1]
bg_color = Color( 0.75, 0.75, 0.75, 1 )
@ -24,77 +25,77 @@ corner_radius_top_right = 2
corner_radius_bottom_right = 2
corner_radius_bottom_left = 2
[sub_resource type="StyleBoxFlat" id=2]
bg_color = Color( 0.452144, 0.397716, 0.0538159, 1 )
[sub_resource type="StyleBoxFlat" id=27]
bg_color = Color( 0.213659, 0.765351, 0.325763, 1 )
[sub_resource type="StyleBoxFlat" id=3]
bg_color = Color( 0.114134, 0.989919, 0.990908, 1 )
[sub_resource type="StyleBoxFlat" id=28]
bg_color = Color( 0.176073, 0.806619, 0.967443, 1 )
[sub_resource type="StyleBoxFlat" id=4]
bg_color = Color( 0.315986, 0.563746, 0.536825, 1 )
[sub_resource type="StyleBoxFlat" id=29]
bg_color = Color( 0.46115, 0.389032, 0.649624, 1 )
[sub_resource type="StyleBoxFlat" id=5]
bg_color = Color( 0.218219, 0.336323, 0.0659741, 1 )
[sub_resource type="StyleBoxFlat" id=30]
bg_color = Color( 0.415833, 0.965657, 0.678807, 1 )
[sub_resource type="StyleBoxFlat" id=6]
bg_color = Color( 0.163289, 0.240192, 0.37346, 1 )
[sub_resource type="StyleBoxFlat" id=31]
bg_color = Color( 0.95106, 0.531613, 0.0362836, 1 )
[sub_resource type="StyleBoxFlat" id=7]
bg_color = Color( 0.330661, 0.369256, 0.97379, 1 )
[sub_resource type="StyleBoxFlat" id=32]
bg_color = Color( 0.414718, 0.156676, 0.927291, 1 )
[sub_resource type="StyleBoxFlat" id=8]
bg_color = Color( 0.216537, 0.755049, 0.491349, 1 )
[sub_resource type="StyleBoxFlat" id=33]
bg_color = Color( 0.904518, 0.341891, 0.208397, 1 )
[sub_resource type="StyleBoxFlat" id=9]
bg_color = Color( 0.826652, 0.848742, 0.0115273, 1 )
[sub_resource type="StyleBoxFlat" id=34]
bg_color = Color( 0.532053, 0.87726, 0.342851, 1 )
[sub_resource type="StyleBoxFlat" id=10]
bg_color = Color( 0.122094, 0.920589, 0.44931, 1 )
[sub_resource type="StyleBoxFlat" id=35]
bg_color = Color( 0.933623, 0.443817, 0.855431, 1 )
[sub_resource type="StyleBoxFlat" id=11]
bg_color = Color( 0.150271, 0.325517, 0.694568, 1 )
[sub_resource type="StyleBoxFlat" id=36]
bg_color = Color( 0.79689, 0.333745, 0.615167, 1 )
[sub_resource type="StyleBoxFlat" id=12]
bg_color = Color( 0.703849, 0.926427, 0.334865, 1 )
[sub_resource type="StyleBoxFlat" id=37]
bg_color = Color( 0.399027, 0.806071, 0.516829, 1 )
[sub_resource type="StyleBoxFlat" id=13]
bg_color = Color( 0.471709, 0.00867083, 0.188914, 1 )
[sub_resource type="StyleBoxFlat" id=38]
bg_color = Color( 0.513829, 0.820974, 0.0806655, 1 )
[sub_resource type="StyleBoxFlat" id=14]
bg_color = Color( 0.300704, 0.501144, 0.687167, 1 )
[sub_resource type="StyleBoxFlat" id=39]
bg_color = Color( 0.576046, 0.303465, 0.354421, 1 )
[sub_resource type="StyleBoxFlat" id=15]
bg_color = Color( 0.52919, 0.953225, 0.374313, 1 )
[sub_resource type="StyleBoxFlat" id=40]
bg_color = Color( 0.0409532, 0.831937, 0.447566, 1 )
[sub_resource type="StyleBoxFlat" id=16]
bg_color = Color( 0.443307, 0.0121565, 0.599621, 1 )
[sub_resource type="StyleBoxFlat" id=41]
bg_color = Color( 0.641815, 0.654958, 0.623856, 1 )
[sub_resource type="StyleBoxFlat" id=17]
bg_color = Color( 0.868357, 0.245633, 0.583044, 1 )
[sub_resource type="StyleBoxFlat" id=42]
bg_color = Color( 0.16782, 0.641056, 0.625732, 1 )
[sub_resource type="StyleBoxFlat" id=18]
bg_color = Color( 0.20955, 0.510868, 0.721501, 1 )
[sub_resource type="StyleBoxFlat" id=43]
bg_color = Color( 0.797095, 0.50587, 0.280019, 1 )
[sub_resource type="StyleBoxFlat" id=19]
bg_color = Color( 0.544154, 0.786819, 0.162435, 1 )
[sub_resource type="StyleBoxFlat" id=44]
bg_color = Color( 0.691959, 0.511673, 0.985569, 1 )
[sub_resource type="StyleBoxFlat" id=20]
bg_color = Color( 0.309762, 0.772837, 0.467272, 1 )
[sub_resource type="StyleBoxFlat" id=45]
bg_color = Color( 0.610537, 0.592647, 0.539142, 1 )
[sub_resource type="StyleBoxFlat" id=21]
bg_color = Color( 0.0682784, 0.753402, 0.362869, 1 )
[sub_resource type="StyleBoxFlat" id=46]
bg_color = Color( 0.263664, 0.636201, 0.25046, 1 )
[sub_resource type="StyleBoxFlat" id=22]
bg_color = Color( 0.343818, 0.0699588, 0.589297, 1 )
[sub_resource type="StyleBoxFlat" id=47]
bg_color = Color( 0.49156, 0.696528, 0.836079, 1 )
[sub_resource type="StyleBoxFlat" id=23]
bg_color = Color( 0.290648, 0.443224, 0.249702, 1 )
[sub_resource type="StyleBoxFlat" id=48]
bg_color = Color( 0.402661, 0.715784, 0.995676, 1 )
[sub_resource type="StyleBoxFlat" id=24]
bg_color = Color( 0.838284, 0.660357, 0.11075, 1 )
[sub_resource type="StyleBoxFlat" id=49]
bg_color = Color( 0.694132, 0.532637, 0.466888, 1 )
[sub_resource type="StyleBoxFlat" id=25]
bg_color = Color( 0.876227, 0.296861, 0.400053, 1 )
[sub_resource type="StyleBoxFlat" id=50]
bg_color = Color( 0.120597, 0.37573, 0.24552, 1 )
[sub_resource type="StyleBoxFlat" id=26]
bg_color = Color( 0.156863, 0.156863, 0.156863, 1 )
@ -168,7 +169,7 @@ script = ExtResource( 7 )
[node name="Edit" type="MenuButton" parent="Panel/VBoxContainer/Navbar/Buttons"]
margin_left = 93.0
margin_right = 166.0
margin_right = 167.0
margin_bottom = 25.0
size_flags_horizontal = 3
size_flags_vertical = 3
@ -179,8 +180,8 @@ switch_on_hover = true
script = ExtResource( 7 )
[node name="Canvas" type="MenuButton" parent="Panel/VBoxContainer/Navbar/Buttons"]
margin_left = 186.0
margin_right = 259.0
margin_left = 187.0
margin_right = 260.0
margin_bottom = 25.0
size_flags_horizontal = 3
size_flags_vertical = 3
@ -191,8 +192,8 @@ switch_on_hover = true
script = ExtResource( 7 )
[node name="Layer" type="MenuButton" parent="Panel/VBoxContainer/Navbar/Buttons"]
margin_left = 279.0
margin_right = 352.0
margin_left = 280.0
margin_right = 354.0
margin_bottom = 25.0
size_flags_horizontal = 3
size_flags_vertical = 3
@ -203,8 +204,8 @@ switch_on_hover = true
script = ExtResource( 7 )
[node name="Grid" type="MenuButton" parent="Panel/VBoxContainer/Navbar/Buttons"]
margin_left = 372.0
margin_right = 445.0
margin_left = 374.0
margin_right = 447.0
margin_bottom = 25.0
size_flags_horizontal = 3
size_flags_vertical = 3
@ -215,8 +216,8 @@ switch_on_hover = true
script = ExtResource( 7 )
[node name="Magic" type="MenuButton" parent="Panel/VBoxContainer/Navbar/Buttons"]
margin_left = 465.0
margin_right = 538.0
margin_left = 467.0
margin_right = 541.0
margin_bottom = 25.0
size_flags_horizontal = 3
size_flags_vertical = 3
@ -227,7 +228,7 @@ switch_on_hover = true
script = ExtResource( 7 )
[node name="Editor" type="MenuButton" parent="Panel/VBoxContainer/Navbar/Buttons"]
margin_left = 558.0
margin_left = 561.0
margin_right = 635.0
margin_bottom = 25.0
size_flags_horizontal = 3
@ -262,45 +263,63 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="PaintCanvas" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer" instance=ExtResource( 3 )]
[node name="Canvas" type="Control" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -384.0
margin_top = -240.0
margin_top = -192.0
margin_right = 384.0
margin_bottom = 208.0
mouse_filter = 1
canvas_size = Vector2( 48, 28 )
margin_bottom = 192.0
script = ExtResource( 3 )
__meta__ = {
"_edit_group_": true,
"_edit_use_anchors_": false
}
canvas_height = 24
grid_size = 1
big_grid_size = 8
[node name="Grids" type="Control" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/PaintCanvas"]
[node name="Grid" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/Canvas" instance=ExtResource( 4 )]
mouse_filter = 2
color = Color( 1, 1, 1, 0.266667 )
[node name="BigGrid" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/Canvas" instance=ExtResource( 4 )]
mouse_filter = 2
color = Color( 1, 1, 1, 1 )
size = 128
[node name="CanvasLayers" type="Control" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/Canvas"]
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
__meta__ = {
"_edit_lock_": true,
"_edit_use_anchors_": false
}
[node name="VisualGrid" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/PaintCanvas/Grids" instance=ExtResource( 4 )]
mouse_filter = 2
color = Color( 1, 1, 1, 0.121569 )
[node name="VisualGrid2" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/PaintCanvas/Grids" instance=ExtResource( 4 )]
mouse_filter = 2
color = Color( 1, 1, 1, 1 )
size = 160
[node name="CanvasOutline" type="Control" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/PaintCanvas"]
[node name="CanvasOutline" type="Control" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/Canvas"]
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
script = ExtResource( 5 )
__meta__ = {
"_edit_lock_": true,
"_edit_use_anchors_": false
}
color = Color( 0, 1, 0, 1 )
[node name="Image" type="TextureRect" parent="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/Canvas"]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
texture = ExtResource( 13 )
expand = true
__meta__ = {
"_edit_lock_": true
}
[node name="ScrollContainer" type="ScrollContainer" parent="Panel/VBoxContainer/HBoxContainer"]
margin_left = 910.0
margin_right = 1024.0
@ -453,7 +472,7 @@ margin_bottom = 25.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 2 )
custom_styles/normal = SubResource( 27 )
[node name="Button2" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 29.0
@ -462,7 +481,7 @@ margin_bottom = 25.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 3 )
custom_styles/normal = SubResource( 28 )
[node name="Button3" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 58.0
@ -471,7 +490,7 @@ margin_bottom = 25.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 4 )
custom_styles/normal = SubResource( 29 )
[node name="Button4" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 87.0
@ -480,7 +499,7 @@ margin_bottom = 25.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 5 )
custom_styles/normal = SubResource( 30 )
[node name="Button5" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_top = 29.0
@ -489,7 +508,7 @@ margin_bottom = 54.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 6 )
custom_styles/normal = SubResource( 31 )
[node name="Button6" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 29.0
@ -499,7 +518,7 @@ margin_bottom = 54.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 7 )
custom_styles/normal = SubResource( 32 )
[node name="Button7" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 58.0
@ -509,7 +528,7 @@ margin_bottom = 54.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 8 )
custom_styles/normal = SubResource( 33 )
[node name="Button8" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 87.0
@ -519,7 +538,7 @@ margin_bottom = 54.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 9 )
custom_styles/normal = SubResource( 34 )
[node name="Button9" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_top = 58.0
@ -528,7 +547,7 @@ margin_bottom = 83.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 10 )
custom_styles/normal = SubResource( 35 )
[node name="Button10" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 29.0
@ -538,7 +557,7 @@ margin_bottom = 83.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 11 )
custom_styles/normal = SubResource( 36 )
[node name="Button11" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 58.0
@ -548,7 +567,7 @@ margin_bottom = 83.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 12 )
custom_styles/normal = SubResource( 37 )
[node name="Button12" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 87.0
@ -558,7 +577,7 @@ margin_bottom = 83.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 13 )
custom_styles/normal = SubResource( 38 )
[node name="Button13" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_top = 87.0
@ -567,7 +586,7 @@ margin_bottom = 112.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 14 )
custom_styles/normal = SubResource( 39 )
[node name="Button14" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 29.0
@ -577,7 +596,7 @@ margin_bottom = 112.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 15 )
custom_styles/normal = SubResource( 40 )
[node name="Button15" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 58.0
@ -587,7 +606,7 @@ margin_bottom = 112.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 16 )
custom_styles/normal = SubResource( 41 )
[node name="Button16" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 87.0
@ -597,7 +616,7 @@ margin_bottom = 112.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 17 )
custom_styles/normal = SubResource( 42 )
[node name="Button17" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_top = 116.0
@ -606,7 +625,7 @@ margin_bottom = 141.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 18 )
custom_styles/normal = SubResource( 43 )
[node name="Button18" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 29.0
@ -616,7 +635,7 @@ margin_bottom = 141.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 19 )
custom_styles/normal = SubResource( 44 )
[node name="Button19" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 58.0
@ -626,7 +645,7 @@ margin_bottom = 141.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 20 )
custom_styles/normal = SubResource( 45 )
[node name="Button20" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 87.0
@ -636,7 +655,7 @@ margin_bottom = 141.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 21 )
custom_styles/normal = SubResource( 46 )
[node name="Button21" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_top = 145.0
@ -645,7 +664,7 @@ margin_bottom = 170.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 22 )
custom_styles/normal = SubResource( 47 )
[node name="Button22" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 29.0
@ -655,7 +674,7 @@ margin_bottom = 170.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 23 )
custom_styles/normal = SubResource( 48 )
[node name="Button23" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 58.0
@ -665,7 +684,7 @@ margin_bottom = 170.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 24 )
custom_styles/normal = SubResource( 49 )
[node name="Button24" type="Button" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Colors"]
margin_left = 87.0
@ -675,7 +694,7 @@ margin_bottom = 170.0
rect_min_size = Vector2( 25, 25 )
size_flags_horizontal = 3
size_flags_vertical = 3
custom_styles/normal = SubResource( 25 )
custom_styles/normal = SubResource( 50 )
[node name="Control" type="ScrollContainer" parent="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu"]
margin_top = 434.0
@ -716,7 +735,7 @@ custom_styles/panel = SubResource( 26 )
[node name="DebugTextDisplay" type="RichTextLabel" parent="Panel/VBoxContainer/BottomPanel"]
anchor_right = 1.0
anchor_bottom = 1.0
text = "FPS 145 Mouse Position (0, 0) Canvas Mouse Position (0, 0) Canvas Position (0, 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) "
scroll_active = false
script = ExtResource( 11 )
@ -733,6 +752,7 @@ margin_left = -340.0
margin_top = -165.0
margin_right = 340.0
margin_bottom = 165.0
mouse_filter = 1
filters = PoolStringArray( "*.png ; PNG Images" )
script = ExtResource( 9 )
@ -745,8 +765,7 @@ margin_left = -150.0
margin_top = -50.0
margin_right = 150.0
margin_bottom = 50.0
[connection signal="mouse_entered" from="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/PaintCanvas" to="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/PaintCanvas" method="_on_mouse_entered"]
[connection signal="mouse_exited" from="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/PaintCanvas" to="Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/PaintCanvas" method="_on_mouse_exited"]
mouse_filter = 1
[connection signal="pressed" from="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Tools/PaintTool" to="." method="_on_PaintTool_pressed"]
[connection signal="pressed" from="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Tools/BrushTool" to="." method="_on_BrushTool_pressed"]
[connection signal="pressed" from="Panel/VBoxContainer/HBoxContainer/ScrollContainer/ToolMenu/Tools/BucketTool" to="." method="_on_BucketTool_pressed"]

View File

@ -0,0 +1,27 @@
extends Reference
class_name GELayer
var name
var pixels # array of pixels (colors), idx repressents x and y
var layer_width
func _init():
pixels = []
func resize(width: int, height: int):
pixels = []
for i in range(height * width):
pixels.append(Color.transparent)
layer_width = width
func set_pixel(x, y, color):
# print("setting pixel: (", x, ", ", y, ") with ", color)
pixels[GEUtils.to_1D(x, y, layer_width)] = color
func get_pixel(x: int, y: int):
return pixels[x + y * layer_width]

View File

@ -27,7 +27,6 @@ var preview_enabled = false
func _enter_tree():
#----------------------
# init Layer
#----------------------

View File

@ -7,7 +7,7 @@ var file_path = ""
func _enter_tree():
canvas = get_parent().find_node("PaintCanvas")
canvas = get_parent().get_node("Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/Canvas")
func _ready():
@ -21,63 +21,41 @@ func _ready():
func _on_SaveFileDialog_file_selected(path):
file_path = path
# warning-ignore:unused_argument
func _on_LineEdit_text_entered(text):
save_file()
func _on_SaveFileDialog_confirmed():
save_file()
func save_file():
var image = Image.new()
image.create(canvas.canvas_size.x, canvas.canvas_size.y, true, Image.FORMAT_RGBA8)
image.create(canvas.canvas_width, canvas.canvas_height, true, Image.FORMAT_RGBA8)
image.lock()
var preview_layer_chunk_node = canvas.get_preview_layer().chunks
for chunks_node in canvas.get_node("ChunkNodes").get_children():
if chunks_node.name == preview_layer_chunk_node.name:
continue
if not chunks_node.visible:
continue
for chunk in chunks_node.get_children():
var chunk_name = chunk.name
var chunk_name_split = chunk_name.split("-")
var chunk_x = int(chunk_name_split[1])
var chunk_y = int(chunk_name_split[2])
var chunk_image = chunk.image.duplicate()
chunk_image.lock()
var chunk_image_size = chunk_image.get_size()
for x in chunk_image_size.x:
for y in chunk_image_size.y:
var pixel_color = chunk_image.get_pixel(x, y)
var global_cell_x = (chunk_x * canvas.region_size) + x
var global_cell_y = (chunk_y * canvas.region_size) + y
if image.get_height() <= global_cell_y:
continue
if image.get_width() <= global_cell_x:
continue
if global_cell_x > canvas.canvas_size.x:
continue
if global_cell_y > canvas.canvas_size.y:
continue
image.lock()
var current_color = image.get_pixel(global_cell_x, global_cell_y)
if current_color.a != 0:
image.set_pixel(global_cell_x, global_cell_y, current_color.blend(pixel_color))
else:
image.set_pixel(global_cell_x, global_cell_y, pixel_color)
for layer_name in canvas.layers:
var layer = canvas.layers[layer_name]
var idx = 0
for color in layer.pixels:
var pos = GEUtils.to_2D(idx, canvas.canvas_width)
idx += 1
image.lock()
var current_color = image.get_pixel(pos.x, pos.y)
if current_color.a != 0:
image.set_pixel(pos.x, pos.y, current_color.blend(color))
else:
image.set_pixel(pos.x, pos.y, color)
image.unlock()
image.save_png(file_path)
func _on_SaveFileDialog_about_to_show():
invalidate()
func _on_SaveFileDialog_visibility_changed():
invalidate()

View File

@ -1,5 +1,47 @@
tool
extends Node
class_name GEUtils
static func get_pixels_in_line(from: Vector2, to: Vector2):
var dx = to[0] - from[0]
var dy = to[1] - from[1]
var nx = abs(dx)
var ny = abs(dy)
var signX = sign(dx)
var signY = sign(dy)
var p = from
var points : Array = [p]
var ix = 0
var iy = 0
while ix < nx || iy < ny:
if (1 + (ix << 1)) * ny < (1 + (iy << 1)) * nx:
p[0] += signX
ix +=1
else:
p[1] += signY
iy += 1
points.append(p)
return points
static func to_1D_v(p, w) -> int:
return p.x + p.y * w
static func to_1D(x, y, w) -> int:
return x + y * w
static func to_2D(idx, w) -> Vector2:
var p = Vector2()
p.x = idx % int(w)
p.y = int(idx / w)
return p
static func color_from_array(color_array):
var r = color_array[0]

View File

@ -2,7 +2,7 @@ tool
extends Control
export var color = Color()
export var size = 16
export var size:int = 16
export var zoom = 0
export var offset = Vector2(0, 0)

View File

@ -1,17 +1,28 @@
extends Reference
extends Node
class_name GEAction
var action_data = {}
var painter
func _init():
pass
action_data["do"] = {}
action_data["undo"] = {}
func do_action(data: Array):
pass
func do_action(canvas, data: Array):
print("NO IMPL do_action")
func commit_action(canvas):
print("NO IMPL commit_action ")
func undo_action(canvas):
print("NO IMPL undo_action ")
func can_commit() -> bool:
return not action_data.do.empty()
func undo_action(data: Array):
pass

View File

@ -1,25 +1,37 @@
extends "res://addons/graphics_editor/actions/Action.gd"
extends GEAction
class_name GEPencil
func do_action(data: Array):
action_data["do"] = {
"cell_position": data[0],
"last_cell_position": data[1],
"color": data[2],
}
func do_action(canvas, data: Array):
if not "cells" in action_data.do:
action_data.do["cells"] = []
action_data.do["colors"] = []
action_data["undo"] = {
"cell_position": data[0],
"last_cell_position": data[1],
"color": get("painter").get_pixel_cell_color_v(action_data.do.cell_position),
}
if not "cells" in action_data.undo:
action_data.undo["cells"] = []
action_data.undo["colors"] = []
get("painter").set_pixels_from_line(action_data.do.cell_position, action_data.do.last_cell_position, action_data.do.color)
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)
action_data.undo.cells.append(pixel)
action_data.do.colors.append(data[2])
action_data.undo.colors.append(Color.transparent)
func undo_action(data: Array):
get("painter").set_pixels_from_line(action_data.undo.cell_position, action_data.undo.last_cell_position, action_data.undo.color)
func commit_action(canvas):
var cells = action_data.do.cells
var colors = action_data.do.colors
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])

View File

@ -13,9 +13,33 @@ _global_script_classes=[ {
"class": "BrushPrefabs",
"language": "GDScript",
"path": "res://addons/graphics_editor/Brush.gd"
}, {
"base": "Node",
"class": "GEAction",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Action.gd"
}, {
"base": "Reference",
"class": "GELayer",
"language": "GDScript",
"path": "res://addons/graphics_editor/Layer.gd"
}, {
"base": "GEAction",
"class": "GEPencil",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Pencil.gd"
}, {
"base": "Node",
"class": "GEUtils",
"language": "GDScript",
"path": "res://addons/graphics_editor/Util.gd"
} ]
_global_script_class_icons={
"BrushPrefabs": ""
"BrushPrefabs": "",
"GEAction": "",
"GELayer": "",
"GEPencil": "",
"GEUtils": ""
}
[application]