improved performance, fixed mouse out of canvas in local coords, fixed loading image with x and y switched, removed pixels member from GELayer

This commit is contained in:
cobrapitz 2020-11-09 12:53:55 +01:00
parent 93610d2f9c
commit 8a8d776e3e
71 changed files with 313 additions and 247 deletions

13
README.md Normal file
View File

@ -0,0 +1,13 @@
# Godoxel (image Editor) v0.1
###### Godot Pixel Editor
Godoxel is an image editor for Godot, that can be used inside the editor.
## Features
* Has basic pixel editor functionality
* Save/Load
* Multiple layers (can be locked/hidden)
* Tools: Pencil, lighten/darken, rectangle/line, fill, ...

View File

@ -383,11 +383,14 @@ func hide_grid():
func select_color(x, y):
print("???")
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)
for x in range(active_layer.layer_width):
for y in range(active_layer.layer_height):
var pixel_color = active_layer.get_pixel(x, y)
if pixel_color == color:
same_color_pixels.append(color)
return same_color_pixels

View File

@ -26,4 +26,6 @@ func draw_outline_box(pos, size, color, width):
func _process(delta):
if not is_visible_in_tree():
return
update()

View File

@ -22,7 +22,7 @@ var canvas_background: TextureRect
var grids_node
var colors_grid
var selected_color = Color(1, 1, 1, 1) setget set_selected_color
var util = preload("res://addons/graphics_editor/Util.gd")
var util = preload("res://addons/Godoxel/Util.gd")
var textinfo
var allow_drawing = true
@ -54,6 +54,8 @@ var _actions_history = [] # for undo
var _redo_history = []
var _current_action
var _last_mouse_pos_canvas_area = Vector2.ZERO
var _picked_color = false
var mouse_position = Vector2()
@ -162,7 +164,6 @@ func _process(delta):
return
if paint_canvas_container_node == null or paint_canvas == null:
return
if is_mouse_in_canvas():
_handle_scroll()
@ -176,14 +177,19 @@ func _process(delta):
cell_color = paint_canvas.get_pixel(cell_mouse_position.x, cell_mouse_position.y)
update_text_info()
if not is_mouse_in_canvas():
paint_canvas.tool_layer.clear()
paint_canvas.update()
paint_canvas.tool_layer.update_texture()
else:
# if not is_mouse_in_canvas():
# paint_canvas.tool_layer.clear()
# paint_canvas.update()
# paint_canvas.tool_layer.update_texture()
# else:
if is_mouse_in_canvas():
if not paint_canvas.is_active_layer_locked():
if is_position_in_canvas(last_cell_mouse_position) or is_position_in_canvas(cell_mouse_position):
if is_position_in_canvas(paint_canvas_container_node.get_local_mouse_position()) or \
is_position_in_canvas(_last_mouse_pos_canvas_area):
brush_process()
else:
print(cell_mouse_position, " not in ", paint_canvas_container_node.rect_size)
print("not in canvas")
_draw_tool_brush()
@ -193,6 +199,7 @@ func _process(delta):
last_canvas_mouse_position = canvas_mouse_position
last_cell_mouse_position = cell_mouse_position
last_cell_color = cell_color
_last_mouse_pos_canvas_area = paint_canvas_container_node.get_local_mouse_position()
func _draw_tool_brush():
@ -219,7 +226,7 @@ func _draw_tool_brush():
_:
paint_canvas._set_pixel(paint_canvas.tool_layer,
cell_mouse_position.x, cell_mouse_position.y, selected_color)
paint_canvas.update()
#TODO add here brush prefab drawing
paint_canvas.tool_layer.update_texture()
@ -659,11 +666,21 @@ func _on_Button_pressed():
func _on_PaintCanvasContainer_mouse_entered():
if mouse_on_top == true:
return
mouse_on_top = true
paint_canvas.tool_layer.clear()
paint_canvas.update()
paint_canvas.tool_layer.update_texture()
func _on_PaintCanvasContainer_mouse_exited():
if mouse_on_top == false:
return
mouse_on_top = false
paint_canvas.tool_layer.clear()
paint_canvas.update()
paint_canvas.tool_layer.update_texture()
func _on_ColorPicker_popup_closed():

File diff suppressed because one or more lines are too long

View File

@ -3,8 +3,8 @@ class_name GELayer
var name
var pixels # array of pixels (colors), idx repressents x and y
var layer_width
var layer_height
var visible = true setget set_visible
var locked = false
@ -15,15 +15,13 @@ var texture_rect_ref
func _init():
texture = ImageTexture.new()
pixels = []
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
layer_height = height
image = Image.new()
image.create(width, height, false, Image.FORMAT_RGBA8)
@ -31,34 +29,33 @@ func create(texture_rect_ref, width: int, height: int):
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]
])
var pixel_colors = []
var prev_width = layer_width
var prev_height = layer_height
image.lock()
for y in range(prev_height):
for x in range(prev_width):
pixel_colors.append(image.get_pixel(x, y))
image.unlock()
layer_width = width
pixels.clear()
pixels.resize(width * height)
layer_height = height
image.create(width, height, false, Image.FORMAT_RGBA8)
for i in range(height * width):
pixels[i] = Color.transparent
image.lock()
for x in range(prev_width):
for y in range(prev_height):
if x >= width or y >= height:
continue
image.set_pixel(x, y, pixel_colors[GEUtils.to_1D(x, y, prev_width)])
image.unlock()
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()
@ -74,11 +71,7 @@ func get_pixel(x: int, y: int):
func clear():
for idx in range(pixels.size()):
if pixels[idx] != Color.transparent:
pixels[idx] = Color.transparent
var pos = GEUtils.to_2D(idx, layer_width)
set_pixel(pos.x, pos.y, Color.transparent)
image.fill(Color.transparent)
update_texture()

View File

@ -1,11 +1,12 @@
[gd_scene load_steps=11 format=2]
[ext_resource path="res://addons/graphics_editor/assets/minidotta_invis.png" type="Texture" id=1]
[ext_resource path="res://addons/graphics_editor/assets/minidotta.png" type="Texture" id=2]
[ext_resource path="res://addons/graphics_editor/assets/arrow_down.png" type="Texture" id=3]
[ext_resource path="res://addons/graphics_editor/assets/arrow_up.png" type="Texture" id=4]
[ext_resource path="res://addons/graphics_editor/assets/lock_layer_1.png" type="Texture" id=5]
[ext_resource path="res://addons/graphics_editor/assets/unlock_layer.png" type="Texture" id=6]
[ext_resource path="res://addons/Godoxel/assets/minidotta_invis.png" type="Texture" id=1]
[ext_resource path="res://addons/Godoxel/assets/minidotta.png" type="Texture" id=2]
[ext_resource path="res://addons/Godoxel/assets/arrow_down.png" type="Texture" id=3]
[ext_resource path="res://addons/Godoxel/assets/arrow_up.png" type="Texture" id=4]
[ext_resource path="res://addons/Godoxel/assets/lock_layer_1.png" type="Texture" id=5]
[ext_resource path="res://addons/Godoxel/assets/unlock_layer.png" type="Texture" id=6]
[sub_resource type="StyleBoxFlat" id=4]
bg_color = Color( 0.180392, 0.176471, 0.176471, 1 )

View File

@ -141,7 +141,7 @@ func toggle_layer_visibility(layer_name):
#print("Layer: ", layer_name, " is now: ", layers[layer_name].chunks.visible)
var util = preload("res://addons/graphics_editor/Util.gd")
var util = preload("res://addons/Godoxel/Util.gd")
func _on_mouse_entered():
@ -179,7 +179,7 @@ func generate_chunks():
for x in maxium_chunk_size.x:
for y in maxium_chunk_size.y:
var paint_canvas_chunk = load("res://addons/graphics_editor/PaintCanvasChunk.tscn").instance()
var paint_canvas_chunk = load("res://addons/Godoxel/PaintCanvasChunk.tscn").instance()
paint_canvas_chunk.setup(region_size)
paint_canvas_chunk.name = "C-%s-%s" % [x, y]
paint_canvas_chunk.rect_position = Vector2(x * (grid_size * region_size), y * (grid_size * region_size))

View File

@ -1,6 +1,7 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/graphics_editor/PaintCanvas.gd" type="Script" id=1]
[ext_resource path="res://addons/Godoxel/PaintCanvas.gd" type="Script" id=1]
[node name="PaintCanvas" type="Control"]
anchor_right = 1.0

View File

@ -1,6 +1,7 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/graphics_editor/PaintCanvasChunk.gd" type="Script" id=1]
[ext_resource path="res://addons/Godoxel/PaintCanvasChunk.gd" type="Script" id=1]
[node name="PaintCanvasChunk" type="TextureRect"]
margin_right = 10.0

View File

@ -44,16 +44,15 @@ func save_file():
var idx = 0
if not layer.visible:
continue
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)
for x in range(layer.layer_width):
for y in range(layer.layer_height):
var color = layer.get_pixel(x, y)
var image_color = image.get_pixel(x, y)
if color.a != 0:
image.set_pixel(x, y, image_color.blend(color))
else:
image.set_pixel(x, y, color)
image.unlock()
var dir = Directory.new()

View File

@ -1,6 +1,7 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/graphics_editor/Settings.gd" type="Script" id=1]
[ext_resource path="res://addons/Godoxel/Settings.gd" type="Script" id=1]
[node name="Settings" type="WindowDialog"]
visible = true

View File

@ -1,6 +1,7 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/graphics_editor/VisualGrid.gd" type="Script" id=1]
[ext_resource path="res://addons/Godoxel/VisualGrid.gd" type="Script" id=1]
[node name="VisualGrid" type="Control"]
anchor_right = 1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/Godoxel_Preview.png-e30103581d3fc0ed2a2c92cdf72b5c70.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Godoxel/assets/Godoxel_Preview.png"
dest_files=[ "res://.import/Godoxel_Preview.png-e30103581d3fc0ed2a2c92cdf72b5c70.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=true
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

Before

Width:  |  Height:  |  Size: 562 B

After

Width:  |  Height:  |  Size: 562 B

View File

@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/arrow_down.png-6353fddfb758b7080149cf1c92b356e5.stex"
path="res://.import/arrow_down.png-d2bd93428c0bc172a28a43c55aac576e.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/graphics_editor/assets/arrow_down.png"
dest_files=[ "res://.import/arrow_down.png-6353fddfb758b7080149cf1c92b356e5.stex" ]
source_file="res://addons/Godoxel/assets/arrow_down.png"
dest_files=[ "res://.import/arrow_down.png-d2bd93428c0bc172a28a43c55aac576e.stex" ]
[params]

View File

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 565 B

View File

@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/arrow_up.png-5a32daf21cc72903f29e9dc2d45d90bf.stex"
path="res://.import/arrow_up.png-2598e148d1b795a628ce80a4fd5cf401.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/graphics_editor/assets/arrow_up.png"
dest_files=[ "res://.import/arrow_up.png-5a32daf21cc72903f29e9dc2d45d90bf.stex" ]
source_file="res://addons/Godoxel/assets/arrow_up.png"
dest_files=[ "res://.import/arrow_up.png-2598e148d1b795a628ce80a4fd5cf401.stex" ]
[params]

View File

@ -1,8 +1,8 @@
[InternetShortcut]
URL=http://www.all-free-download.com/
IDList=
HotKey=0
IconFile=C:\WINDOWS\system32\SHELL32.dll
IconIndex=23
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
[InternetShortcut]
URL=http://www.all-free-download.com/
IDList=
HotKey=0
IconFile=C:\WINDOWS\system32\SHELL32.dll
IconIndex=23
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2

View File

Before

Width:  |  Height:  |  Size: 148 B

After

Width:  |  Height:  |  Size: 148 B

View File

@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/grid.png-74a92f0786b49dae0c01bd21c08c941f.stex"
path="res://.import/grid.png-e3d637acacdb891e09f422df261dbd1e.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/graphics_editor/assets/grid.png"
dest_files=[ "res://.import/grid.png-74a92f0786b49dae0c01bd21c08c941f.stex" ]
source_file="res://addons/Godoxel/assets/grid.png"
dest_files=[ "res://.import/grid.png-e3d637acacdb891e09f422df261dbd1e.stex" ]
[params]

View File

Before

Width:  |  Height:  |  Size: 251 B

After

Width:  |  Height:  |  Size: 251 B

View File

@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/lock_layer.png-33f1e8f880088be39b50ce41c8568529.stex"
path="res://.import/lock_layer.png-076954b389746de9e13c853ed5d9ba59.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/graphics_editor/assets/lock_layer.png"
dest_files=[ "res://.import/lock_layer.png-33f1e8f880088be39b50ce41c8568529.stex" ]
source_file="res://addons/Godoxel/assets/lock_layer.png"
dest_files=[ "res://.import/lock_layer.png-076954b389746de9e13c853ed5d9ba59.stex" ]
[params]

View File

Before

Width:  |  Height:  |  Size: 242 B

After

Width:  |  Height:  |  Size: 242 B

View File

@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/lock_layer_1.png-c7f56bc948259e1b922d48c7fca34e93.stex"
path="res://.import/lock_layer_1.png-4848d5f2cd0f48c68b880712b6b38776.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/graphics_editor/assets/lock_layer_1.png"
dest_files=[ "res://.import/lock_layer_1.png-c7f56bc948259e1b922d48c7fca34e93.stex" ]
source_file="res://addons/Godoxel/assets/lock_layer_1.png"
dest_files=[ "res://.import/lock_layer_1.png-4848d5f2cd0f48c68b880712b6b38776.stex" ]
[params]

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/minidotta.png-0170a8b64a557748e03bc1c7c0cbfd33.stex"
path="res://.import/minidotta.png-adac81df344972ef82e2499656aa288e.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/graphics_editor/assets/minidotta.png"
dest_files=[ "res://.import/minidotta.png-0170a8b64a557748e03bc1c7c0cbfd33.stex" ]
source_file="res://addons/Godoxel/assets/minidotta.png"
dest_files=[ "res://.import/minidotta.png-adac81df344972ef82e2499656aa288e.stex" ]
[params]

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/minidotta_invis.png-5232a113bb226997ae55212b2aa90bd4.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/Godoxel/assets/minidotta_invis.png"
dest_files=[ "res://.import/minidotta_invis.png-5232a113bb226997ae55212b2aa90bd4.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

Before

Width:  |  Height:  |  Size: 240 B

After

Width:  |  Height:  |  Size: 240 B

View File

@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/unlock_layer.png-fc0ace243eb1581f930731b96b257e04.stex"
path="res://.import/unlock_layer.png-ae7c97a04fb889522c7c466fdc9dd8f6.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/graphics_editor/assets/unlock_layer.png"
dest_files=[ "res://.import/unlock_layer.png-fc0ace243eb1581f930731b96b257e04.stex" ]
source_file="res://addons/Godoxel/assets/unlock_layer.png"
dest_files=[ "res://.import/unlock_layer.png-ae7c97a04fb889522c7c466fdc9dd8f6.stex" ]
[params]

View File

@ -1,6 +1,6 @@
[plugin]
name="GraphicsEditor"
name="Godoxel - Pixel Image Editor"
description=""
author=""
version=""

View File

@ -1,7 +1,7 @@
tool
extends EditorPlugin
var editor_scene = load("res://addons/graphics_editor/Editor.tscn").instance()
var editor_scene = load("res://addons/Godoxel/Editor.tscn").instance()
func _enter_tree():
editor_scene.name = "Editor"
@ -29,7 +29,7 @@ func make_visible(visible):
func get_plugin_name():
return "Image Editor"
return "Godoxel"
func get_plugin_icon():

View File

@ -1,34 +0,0 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/minidotta_invis.png-ec3aa0ca68f47f1c02c9ad632b063555.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/graphics_editor/assets/minidotta_invis.png"
dest_files=[ "res://.import/minidotta_invis.png-ec3aa0ca68f47f1c02c9ad632b063555.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

@ -12,77 +12,77 @@ _global_script_classes=[ {
"base": "Reference",
"class": "BrushPrefabs",
"language": "GDScript",
"path": "res://addons/graphics_editor/BrushPrefabs.gd"
"path": "res://addons/Godoxel/BrushPrefabs.gd"
}, {
"base": "Node",
"class": "GEAction",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Action.gd"
"path": "res://addons/Godoxel/actions/Action.gd"
}, {
"base": "GEAction",
"class": "GEBrighten",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Brighten.gd"
"path": "res://addons/Godoxel/actions/Brighten.gd"
}, {
"base": "GEAction",
"class": "GEBrush",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Brush.gd"
"path": "res://addons/Godoxel/actions/Brush.gd"
}, {
"base": "GEAction",
"class": "GEBucket",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Bucket.gd"
"path": "res://addons/Godoxel/actions/Bucket.gd"
}, {
"base": "Control",
"class": "GECanvas",
"language": "GDScript",
"path": "res://addons/graphics_editor/Canvas.gd"
"path": "res://addons/Godoxel/Canvas.gd"
}, {
"base": "GEAction",
"class": "GECut",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Cut.gd"
"path": "res://addons/Godoxel/actions/Cut.gd"
}, {
"base": "GEAction",
"class": "GEDarken",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Darken.gd"
"path": "res://addons/Godoxel/actions/Darken.gd"
}, {
"base": "Reference",
"class": "GELayer",
"language": "GDScript",
"path": "res://addons/graphics_editor/Layer.gd"
"path": "res://addons/Godoxel/Layer.gd"
}, {
"base": "GEAction",
"class": "GELine",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Line.gd"
"path": "res://addons/Godoxel/actions/Line.gd"
}, {
"base": "GEAction",
"class": "GEPasteCut",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/PasteCut.gd"
"path": "res://addons/Godoxel/actions/PasteCut.gd"
}, {
"base": "GEAction",
"class": "GEPencil",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Pencil.gd"
"path": "res://addons/Godoxel/actions/Pencil.gd"
}, {
"base": "GEAction",
"class": "GERainbow",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Rainbow.gd"
"path": "res://addons/Godoxel/actions/Rainbow.gd"
}, {
"base": "GEAction",
"class": "GERect",
"language": "GDScript",
"path": "res://addons/graphics_editor/actions/Rect.gd"
"path": "res://addons/Godoxel/actions/Rect.gd"
}, {
"base": "Node",
"class": "GEUtils",
"language": "GDScript",
"path": "res://addons/graphics_editor/Util.gd"
"path": "res://addons/Godoxel/Util.gd"
} ]
_global_script_class_icons={
"BrushPrefabs": "",
@ -104,12 +104,12 @@ _global_script_class_icons={
[application]
config/name="Image Editor"
config/name="Godoxel - Image Editor"
config/icon="res://icon.png"
[editor_plugins]
enabled=PoolStringArray( "godot-plugin-refresher", "graphics_editor" )
enabled=PoolStringArray( "Godoxel", "godot-plugin-refresher" )
[rendering]