added resize, toggle grid, fix mouse interacting with canvas outside of window, improved performance, only render when changed, using TextureRects' set_pixel instead of drawing rects, canvas size can be changed, load file added ( loadfile and save file might be broken due to change of layer rendering/data structure change)

This commit is contained in:
cobrapitz 2020-10-30 12:32:04 +01:00
parent af82266561
commit e51ae47bcf
39 changed files with 1210 additions and 643 deletions

View File

@ -1,3 +0,0 @@
source_md5="f2446c62da0093ebbc5c6a4c629e95fa"
dest_md5="f805a61fa71cdc48cc5f45a98dfd4332"

View File

@ -1,3 +0,0 @@
source_md5="4adc812d45f40a06b9b2ca01cf81ae95"
dest_md5="d6d99a1c7f42a184a39920f8abb2e0b4"

View File

@ -1,3 +0,0 @@
source_md5="bec155c5904394450131d27b462c96e4"
dest_md5="71febc6938a68e205920ca412ebaf71d"

View File

@ -1,3 +0,0 @@
source_md5="f6bdc4cf50b93bf6accef209602404a3"
dest_md5="8102e795bd6d15849efc2870c51252b9"

View File

@ -1,3 +0,0 @@
source_md5="3503838b09b288e7ba25eda91156f748"
dest_md5="707338f082324b175177059fbd3c6032"

View File

@ -1,3 +0,0 @@
source_md5="16749baf6a306a99dc4e80eee2abefbf"
dest_md5="55aba65ce681911f66cffde93b5491ea"

View File

@ -1,3 +0,0 @@
source_md5="d7a9507fc7dbc1dcf4fcba5f438d20d3"
dest_md5="9b21ddc79734d495f2bcc94862d43b43"

View File

@ -1,3 +0,0 @@
source_md5="976b0714fcbc434f323dad76d3b5bf36"
dest_md5="0f5e8acf1d61ab0711f44f75905e5a8a"

View File

@ -1,3 +0,0 @@
source_md5="06f1cb8e512e5adfad002ef0338a818e"
dest_md5="87b2e06d78c49f4dc5456f18656eb3d3"

View File

@ -1,3 +0,0 @@
source_md5="2d4a406047a743eb20e0ce47be843558"
dest_md5="86808acdf32b0015647e3b12e728ce0a"

View File

@ -1,3 +0,0 @@
source_md5="c576029f055c5661a5ab02e79f718143"
dest_md5="03d4d90c298c894e9d624b48ca00b128"

View File

@ -1,3 +0,0 @@
source_md5="4440cfb0f469fe68adca066948bc8183"
dest_md5="da9faa3bbd2610755b629238ae47dc44"

View File

@ -15,6 +15,7 @@ var mouse_on_top
var layers : Array = [] # Key: layer_name, val: GELayer
var active_layer: GELayer
var preview_layer: GELayer
var canvas_layers: Control
var canvas
var grid
@ -30,6 +31,7 @@ func _enter_tree():
canvas = find_node("Canvas")
grid = find_node("Grid")
big_grid = find_node("BigGrid")
canvas_layers = find_node("CanvasLayers")
#-------------------------------
# setup layers and canvas
@ -50,29 +52,34 @@ func _enter_tree():
func _process(delta):
if active_layer == null:
if not Engine.is_editor_hint():
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():
if not Engine.is_editor_hint():
return
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
layer.update_texture()
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
preview_layer.update_texture()
func resize(width: int, height: int):
if width < 0:
width = 1
if height < 0:
height = 1
set_canvas_width(width)
set_canvas_height(height)
preview_layer.resize(width, height)
for layer in layers:
layer.resize(width, height)
@ -86,6 +93,13 @@ func set_pixel_size(size: int):
set_big_grid_size(big_grid_size)
set_canvas_width(canvas_width)
set_canvas_height(canvas_height)
return
if preview_layer == null:
return
preview_layer.resize(canvas_width, canvas_height)
for layer in layers:
layer.resize(canvas_width, canvas_height)
func set_grid_size(size):
@ -159,7 +173,17 @@ func add_new_layer(layer_name: String):
return
var layer = GELayer.new()
layer.name = layer_name
layer.resize(canvas_width, canvas_height)
var texture_rect = TextureRect.new()
canvas_layers.add_child(texture_rect)
texture_rect.expand = true
texture_rect.anchor_right = 1
texture_rect.anchor_bottom = 1
texture_rect.margin_right = 0
texture_rect.margin_bottom = 0
texture_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
layer.create(texture_rect, canvas_width, canvas_height)
if layer_name != "Preview":
layers.append(layer)
return layer
@ -282,7 +306,7 @@ func get_pixel_v(pos: Vector2):
func get_pixel(x: int, y: int):
var idx = GEUtils.to_1D(x, y, canvas_width)
if active_layer:
if active_layer.pixels.size() <= idx:
if idx >= 0 and active_layer.pixels.size() <= idx:
return null
return active_layer.pixels[idx]
return null
@ -310,6 +334,27 @@ func get_preview_pixel(x: int, y: int):
return preview_layer.pixels[idx]
#-------------------------------
# Grid
#-------------------------------
func toggle_grid():
$BigGrid.visible = not $BigGrid.visible
$Grid.visible = not $Grid.visible
func show_grid():
$BigGrid.show()
$Grid.show()
func hide_grid():
$BigGrid.hide()
$Grid.hide()
#-------------------------------
# Handy tools
#-------------------------------

View File

@ -17,6 +17,7 @@ enum Tools {
var layer_buttons: Control
var paint_canvas_container_node
var paint_canvas: GECanvas
var canvas_background: TextureRect
var grids_node
var colors_grid
var selected_color = Color(1, 1, 1, 1)
@ -24,7 +25,12 @@ var util = preload("res://addons/graphics_editor/Util.gd")
var textinfo
var allow_drawing = true
var mouse_in_region = false
var mouse_on_top = false
var _middle_mouse_pressed_pos = null
var _middle_mouse_pressed_start_pos = null
var _left_mouse_pressed_start_pos = Vector2()
var _previous_tool
@ -58,8 +64,9 @@ func _enter_tree():
textinfo = find_node("DebugTextDisplay")
selected_color = find_node("ColorPicker").color
colors_grid = find_node("Colors")
paint_canvas = get_node("Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/Canvas")
paint_canvas = paint_canvas_container_node.find_node("Canvas")
layer_buttons = find_node("LayerButtons")
canvas_background = find_node("CanvasBackground")
set_process(true)
@ -80,12 +87,25 @@ func _ready():
func _input(event):
if not Engine.is_editor_hint():
return
if Rect2(Vector2(), paint_canvas_container_node.rect_size).has_point(
paint_canvas_container_node.get_local_mouse_position()):
mouse_in_region = true
elif mouse_in_region:
mouse_in_region = false
if not mouse_on_top or not mouse_in_region:
return
if Input.is_key_pressed(KEY_Z):
undo_action()
elif Input.is_key_pressed(KEY_Y):
print("Y")
pass
if (paint_canvas.mouse_in_region and paint_canvas.mouse_on_top):
_handle_zoom(event)
if paint_canvas and (paint_canvas.mouse_in_region and paint_canvas.mouse_on_top):
match brush_mode:
Tools.BUCKET:
if _current_action == null:
@ -113,6 +133,10 @@ var last_cell_color = Color()
# warning-ignore:unused_argument
func _process(delta):
if not Engine.is_editor_hint():
return
if not mouse_on_top or not mouse_in_region:
return
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
@ -121,6 +145,10 @@ func _process(delta):
set_process(false)
return
if mouse_on_top and mouse_in_region:
_handle_scroll()
#Update commonly used variables
var grid_size = paint_canvas.pixel_size
mouse_position = paint_canvas.get_local_mouse_position()
@ -133,7 +161,7 @@ func _process(delta):
brush_process()
#Render the highlighting stuff
update()
#Canvas Shift Moving
if not mouse_position == last_mouse_position:
@ -154,6 +182,42 @@ func _process(delta):
last_cell_color = cell_color
func _handle_scroll():
if Input.is_mouse_button_pressed(BUTTON_MIDDLE):
if _middle_mouse_pressed_start_pos == null:
_middle_mouse_pressed_start_pos = paint_canvas.rect_position
_middle_mouse_pressed_pos = get_global_mouse_position()
paint_canvas.rect_position = _middle_mouse_pressed_start_pos
paint_canvas.rect_position += get_global_mouse_position() - _middle_mouse_pressed_pos
elif _middle_mouse_pressed_start_pos != null:
_middle_mouse_pressed_start_pos = null
const max_zoom_out = 1
const max_zoom_in = 50
func _handle_zoom(event):
if not event is InputEventMouseButton:
return
if event.is_pressed():
if event.button_index == BUTTON_WHEEL_UP:
paint_canvas.set_pixel_size(min(paint_canvas.pixel_size * 2, max_zoom_in))
return
if paint_canvas.pixel_size != max_zoom_in:
paint_canvas.rect_global_position -= Vector2(
paint_canvas.canvas_width / 2,
paint_canvas.canvas_height / 2)
elif event.button_index == BUTTON_WHEEL_DOWN:
paint_canvas.set_pixel_size(max(paint_canvas.pixel_size / 2.0, max_zoom_out))
return
if paint_canvas.pixel_size != max_zoom_out:
paint_canvas.rect_global_position += Vector2(
paint_canvas.canvas_width / 2,
paint_canvas.canvas_height / 2)
func _reset_cut_tool():
_just_cut = false
_show_cut = false
@ -192,9 +256,13 @@ func _handle_cut():
func brush_process():
if _just_cut:
_handle_cut()
update()
paint_canvas.update()
return
if Input.is_mouse_button_pressed(BUTTON_LEFT):
update()
paint_canvas.update()
if _current_action == null:
_current_action = get_action()
@ -217,12 +285,10 @@ func brush_process():
do_action([cell_mouse_position, last_cell_mouse_position, selected_color])
Tools.RAINBOW:
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
elif Input.is_mouse_button_pressed(BUTTON_RIGHT):
update()
paint_canvas.update()
if _current_action == null:
_current_action = get_action()
@ -231,6 +297,11 @@ func brush_process():
do_action([cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0)])
Tools.BRUSH:
do_action([cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0), selected_brush_prefab])
else:
if _current_action and _current_action.can_commit():
commit_action()
update()
paint_canvas.update()
func update_text_info():
@ -312,6 +383,8 @@ func undo_action():
if not action:
return
action.undo_action(paint_canvas)
update()
paint_canvas.update()
print("undo action")
@ -437,18 +510,21 @@ func select_layer(layer_name: String):
func add_new_layer():
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)
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
new_layer.text = "Layer " + str(_total_added_layers)
new_layer_button.text = "Layer " + str(_total_added_layers)
var layer: GELayer = paint_canvas.add_new_layer(new_layer.name)
var layer: GELayer = paint_canvas.add_new_layer(new_layer_button.name)
_layer_button_ref[new_layer.name] = new_layer
_layer_button_ref[new_layer_button.name] = new_layer_button
_connect_layer_buttons()
print("added layer: ", layer.name)
return layer
func remove_active_layer():
@ -520,3 +596,9 @@ func _on_Button_pressed():
func _on_PaintCanvasContainer_mouse_entered():
mouse_on_top = true
func _on_PaintCanvasContainer_mouse_exited():
mouse_on_top = false

File diff suppressed because it is too large Load Diff

View File

@ -5,23 +5,62 @@ class_name GELayer
var name
var pixels # array of pixels (colors), idx repressents x and y
var layer_width
var visible = true
var visible = true setget set_visible
var texture: ImageTexture
var image: Image
var texture_rect_ref
func _init():
texture = ImageTexture.new()
pixels = []
func resize(width: int, height: int):
func create(texture_rect_ref, width: int, height: int):
self.texture_rect_ref = texture_rect_ref
pixels = []
for i in range(height * width):
pixels.append(Color.transparent)
layer_width = width
image = Image.new()
image.create(width, height, false, Image.FORMAT_RGBA8)
update_texture()
func resize(width: int, height: int):
var pixels_and_colors = []
for i in range(pixels.size()):
pixels_and_colors.append([
GEUtils.to_2D(i, layer_width),
pixels[i]
])
layer_width = width
pixels.clear()
pixels.resize(width * height)
image.create(width, height, false, Image.FORMAT_RGBA8)
for i in range(height * width):
pixels[i] = Color.transparent
for i in range(pixels_and_colors.size()):
var pos = pixels_and_colors[i][0]
var color = pixels_and_colors[i][1]
if pos.x >= width or pos.y >= height:
continue
set_pixel(pos.x, pos.y, color)
update_texture()
func set_pixel(x, y, color):
# print("setting pixel: (", x, ", ", y, ") with ", color)
pixels[GEUtils.to_1D(x, y, layer_width)] = color
image.lock()
image.set_pixel(x, y, color)
image.unlock()
func get_pixel(x: int, y: int):
@ -32,3 +71,16 @@ func clear():
for idx in range(pixels.size()):
if pixels[idx] != Color.transparent:
pixels[idx] = Color.transparent
func update_texture():
texture.create_from_image(image, 0)
texture_rect_ref.texture = texture
texture_rect_ref.margin_right = 0
texture_rect_ref.margin_bottom = 0
func set_visible(vis: bool):
visible = vis
texture_rect_ref.visible = visible

View File

@ -36,6 +36,10 @@ func handle_file_menu(pressed_item: String):
match pressed_item:
"Save":
owner.get_node("SaveFileDialog").show()
"Load":
owner.get_node("LoadFileDialog").show()
"New":
owner.get_node("ConfirmationDialog").show()
func handle_edit_menu(pressed_item: String):
@ -46,8 +50,8 @@ func handle_edit_menu(pressed_item: String):
func handle_canvas_menu(pressed_item: String):
match pressed_item:
"Add Layer":
editor.add_new_layer()
"Change Size":
owner.get_node("ChangeCanvasSize").show()
func handle_layer_menu(pressed_item: String):
@ -62,8 +66,10 @@ func handle_layer_menu(pressed_item: String):
func handle_grid_menu(pressed_item: String):
match pressed_item:
"Add Layer":
editor.add_new_layer()
"Change Grid Size":
owner.get_node("ChangeGridSizeDialog").show()
"Toggle Grid":
owner.paint_canvas.toggle_grid()
func handle_magic_menu(pressed_item: String):

View File

@ -7,7 +7,7 @@ var file_path = ""
func _enter_tree():
canvas = get_parent().get_node("Panel/VBoxContainer/HBoxContainer/PaintCanvasContainer/Canvas")
canvas = get_parent().find_node("Canvas")
func _ready():

View File

@ -3,6 +3,7 @@
[ext_resource path="res://addons/graphics_editor/Settings.gd" type="Script" id=1]
[node name="Settings" type="WindowDialog"]
visible = true
margin_top = 20.0
margin_right = 300.0
margin_bottom = 120.0

View File

@ -1,8 +1,6 @@
extends ViewportContainer
tool
func _ready():
print(name)
pass
get_child(0).size = rect_size
func _notification(what):
pass

View File

@ -7,7 +7,7 @@ func do_action(canvas, data: Array):
var pixels = GEUtils.get_pixels_in_line(data[0], data[1])
for pixel in pixels:
if pixel in action_data.undo.cells:
if pixel in action_data.undo.cells or canvas.get_pixel_v(pixel) == null:
continue
action_data.undo.colors.append(canvas.get_pixel_v(pixel))

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/grid.png-74a92f0786b49dae0c01bd21c08c941f.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/graphics_editor/assets/grid.png"
dest_files=[ "res://.import/grid.png-74a92f0786b49dae0c01bd21c08c941f.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View File

@ -0,0 +1,27 @@
extends AcceptDialog
tool
func _ready():
find_node("GridValue").value = owner.paint_canvas.grid_size
find_node("BigGridValue").value = owner.paint_canvas.big_grid_size
func _on_ChangeGridSizeDialog_confirmed():
var grid_size = find_node("GridValue").value
var big_grid_size = find_node("BigGridValue").value
owner.paint_canvas.grid_size = grid_size
owner.paint_canvas.big_grid_size = big_grid_size
func _on_GridValue_value_changed(value):
var grid_size = value
owner.paint_canvas.grid_size = grid_size
func _on_BigGridValue_value_changed(value):
var big_grid_size = value
owner.paint_canvas.big_grid_size = big_grid_size
func _on_ChangeGridSizeDialog_visibility_changed():
pass # Replace with function body.

View File

@ -0,0 +1,19 @@
extends ConfirmationDialog
tool
func _ready():
find_node("Width").value = owner.paint_canvas.canvas_width
find_node("Height").value = owner.paint_canvas.canvas_height
func _on_ConfirmationDialog_confirmed():
var width = find_node("Width").value
var height = find_node("Height").value
print("change canvas size: ", width, " ", height)
owner.paint_canvas.resize(width, height)
func _on_ChangeCanvasSize_visibility_changed():
if visible:
find_node("Width").value = owner.paint_canvas.canvas_width
find_node("Height").value = owner.paint_canvas.canvas_height

View File

@ -0,0 +1,57 @@
tool
extends FileDialog
var canvas: GECanvas
var file_path = ""
func _ready():
get_line_edit().connect("text_entered", self, "_on_LineEdit_text_entered")
invalidate()
clear_filters()
add_filter("*.png ; PNG Images")
func _on_LineEdit_text_entered(_text):
print(_text)
#load_img()
print("hsadfasd")
func _on_LoadFileDialog_file_selected(path):
file_path = path
print("1ere")
load_img()
func _on_LoadFileDialog_confirmed():
print("ere")
#load_img()
func load_img():
var image = Image.new()
if image.load(file_path) != OK:
print("couldn't load image!")
return
var image_data = image.get_data()
var layer: GELayer = owner.add_new_layer()
for i in range(image_data.size() / 4):
var color = Color(image_data[i*4], image_data[i*4+1], image_data[i*4+2], image_data[i*4+3])
var pos = GEUtils.to_2D(i, image.get_width())
if pos.x > layer.layer_width:
continue
layer.set_pixel(pos.x, pos.y, color)
func _on_LoadFileDialog_about_to_show():
invalidate()
func _on_LoadFileDialog_visibility_changed():
invalidate()

View File

@ -0,0 +1,22 @@
[gd_scene load_steps=2 format=2]
[sub_resource type="GDScript" id=1]
script/source = "extends ConfirmationDialog
func _ready():
get_ok().connect(\"pressed\", self, \"hide\")
get_cancel().connect(\"pressed\", self, \"hide\")
"
[node name="LoadFileDialog" type="FileDialog"]
margin_right = 604.0
margin_bottom = 367.0
window_title = "Open a File"
mode = 0
access = 2
current_dir = "/Projects/BitBucket/GraphicsEditor"
current_path = "/Projects/BitBucket/GraphicsEditor/"
script = SubResource( 1 )