mirror of
https://github.com/Relintai/GraphicsEditor.git
synced 2024-11-12 08:15:17 +01:00
Huge update!
This commit is contained in:
parent
174a3aa450
commit
d2002543da
13
README.md
13
README.md
@ -3,16 +3,9 @@
|
|||||||
Made by Flairieve!
|
Made by Flairieve!
|
||||||
|
|
||||||
## About
|
## About
|
||||||
This plugin was built in Godot v3.1 and is currently in alpha so it doesn't work fully and it's not finished!
|
This plugin was built in Godot v3.1.2 and is currently in alpha so it doesn't work fully and it's not finished!
|
||||||
|
Please give credit if you fork and use any code from this project!
|
||||||
Right now it can create basic images in a 100x100 resolution.
|
|
||||||
It is using a chunk system to keep rendering optmized!
|
|
||||||
|
|
||||||
### Stuff that's still WIP and are not finished:
|
### Stuff that's still WIP and are not finished:
|
||||||
* The bucket tool lags and the selection tool doesn't work at all!
|
|
||||||
* The way in which the program saves temporary data doesn't do it in chunks yet!
|
|
||||||
* There is no custom color selection tool yet so the color picker doesn't work on it.
|
|
||||||
* All chunks are always rendered which causes lag when there is more chunks.
|
|
||||||
* There is no way to change the resolution of the image.
|
|
||||||
* Images can only save in the PNG format.
|
* Images can only save in the PNG format.
|
||||||
* You can't zoom in and out on the image! Either a Camera2D can be used or every control node can be scaled!
|
* Camera is broken when running as a plugin. Godot bug?
|
15
addons/graphics_editor/Camera2D.gd
Normal file
15
addons/graphics_editor/Camera2D.gd
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
extends Camera2D
|
||||||
|
|
||||||
|
#TODO: Make the camera movement snap to the nearest highlighted cell
|
||||||
|
|
||||||
|
var speed = 10
|
||||||
|
func _process(delta):
|
||||||
|
if Input.is_key_pressed(KEY_LEFT):
|
||||||
|
position += Vector2(-1, 0) * speed
|
||||||
|
elif Input.is_key_pressed(KEY_RIGHT):
|
||||||
|
position += Vector2(1, 0) * speed
|
||||||
|
|
||||||
|
if Input.is_key_pressed(KEY_UP):
|
||||||
|
position += Vector2(0, -1) * speed
|
||||||
|
elif Input.is_key_pressed(KEY_DOWN):
|
||||||
|
position += Vector2(0, 1) * speed
|
@ -21,4 +21,4 @@ func draw_outline_box(size, color, width):
|
|||||||
draw_line(Vector2(size.x, 0), Vector2(size.x, size.y), color, width)
|
draw_line(Vector2(size.x, 0), Vector2(size.x, size.y), color, width)
|
||||||
|
|
||||||
func _process(delta):
|
func _process(delta):
|
||||||
update()
|
update()
|
||||||
|
@ -13,8 +13,8 @@ func _ready():
|
|||||||
func _process(delta):
|
func _process(delta):
|
||||||
if color_picking and not mouse_on_top:
|
if color_picking and not mouse_on_top:
|
||||||
var editor = get_node("/root/Editor")
|
var editor = get_node("/root/Editor")
|
||||||
var paint_canvas = get_node("/root/Editor/PaintCanvasContainer/PaintCanvas")
|
var paint_canvas = get_node("/root/Editor/PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas")
|
||||||
var highlighted_color = paint_canvas.get_pixel_cell_color_v(editor.cell_mouse_position)
|
var highlighted_color = paint_canvas.get_pixel(editor.cell_mouse_position)
|
||||||
if not highlighted_color == null:
|
if not highlighted_color == null:
|
||||||
color = highlighted_color
|
color = highlighted_color
|
||||||
|
|
||||||
|
@ -2,67 +2,51 @@ tool
|
|||||||
extends Control
|
extends Control
|
||||||
|
|
||||||
onready var paint_canvas_container_node = get_node("PaintCanvasContainer")
|
onready var paint_canvas_container_node = get_node("PaintCanvasContainer")
|
||||||
onready var paint_canvas_node = paint_canvas_container_node.get_node("PaintCanvas")
|
onready var paint_canvas_node = paint_canvas_container_node.get_node("ViewportContainer/Viewport/PaintCanvas")
|
||||||
|
onready var paint_canvas_image_node = paint_canvas_node.get_node("CanvasImage")
|
||||||
|
onready var camera = paint_canvas_container_node.get_node("ViewportContainer/Viewport/Camera2D")
|
||||||
onready var grids_node = paint_canvas_node.get_node("Grids")
|
onready var grids_node = paint_canvas_node.get_node("Grids")
|
||||||
|
onready var tool_manager = get_node("ToolManager")
|
||||||
|
onready var textinfo = get_node("BottomPanel/TextInfo")
|
||||||
|
onready var layers = get_node("ToolMenu/Layers")
|
||||||
|
onready var grid_size = paint_canvas_node.grid_size
|
||||||
|
onready var chunk_size = paint_canvas_node.chunk_size
|
||||||
var selected_color = Color(1, 1, 1, 1)
|
var selected_color = Color(1, 1, 1, 1)
|
||||||
var util = preload("res://addons/graphics_editor/Util.gd")
|
var util = preload("res://addons/graphics_editor/Util.gd")
|
||||||
onready var textinfo = get_node("BottomPanel/TextInfo")
|
|
||||||
onready var grid_size = paint_canvas_node.grid_size
|
|
||||||
onready var region_size = paint_canvas_node.region_size
|
|
||||||
var allow_drawing = true
|
var allow_drawing = true
|
||||||
|
|
||||||
|
#TODO:
|
||||||
|
#Work on the brush system!
|
||||||
|
#Make a GUI Notification script!
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
|
#-----------------
|
||||||
|
#Setup active tool
|
||||||
|
#-----------------
|
||||||
|
tool_manager.set_active_tool("Pencil")
|
||||||
|
|
||||||
#---------------------------
|
#---------------------------
|
||||||
#Setup the info bottom panel
|
#Setup the info bottom panel
|
||||||
#---------------------------
|
#---------------------------
|
||||||
add_text_info_variables()
|
add_text_info_variables()
|
||||||
|
|
||||||
#--------------------
|
|
||||||
#Setup the layer tree
|
|
||||||
#--------------------
|
|
||||||
setup_layer_tree()
|
|
||||||
|
|
||||||
#------------------
|
#------------------
|
||||||
#Setup visual grids
|
#Setup visual grids
|
||||||
#------------------
|
#------------------
|
||||||
for i in grids_node.get_children():
|
paint_canvas_node.connect("grid_resized", self, "grid_resized")
|
||||||
i.rect_size = Vector2(paint_canvas_node.canvas_size.x * grid_size, paint_canvas_node.canvas_size.y * grid_size)
|
grid_resized(paint_canvas_node.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
|
#Set the selected color to what the color picker has selected as default
|
||||||
#-----------------------------------
|
#-----------------------------------------------------------------------
|
||||||
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)
|
|
||||||
|
|
||||||
#------------------------------------------------------------
|
|
||||||
#Set the selected color to what the color picker has selected
|
|
||||||
#------------------------------------------------------------
|
|
||||||
selected_color = get_node("ToolMenu/Buttons/ColorPicker").color
|
selected_color = get_node("ToolMenu/Buttons/ColorPicker").color
|
||||||
|
|
||||||
#----------------------------------------------------------------
|
|
||||||
#Setup is done so we can now allow the user to draw on the canvas
|
|
||||||
#----------------------------------------------------------------
|
|
||||||
paint_canvas_node.can_draw = true
|
|
||||||
|
|
||||||
func setup_layer_tree():
|
#TODO: Make the paint canvas chunk size not a vector2?
|
||||||
var tree = get_node("ToolMenu/Layers/Tree")
|
func grid_resized(size):
|
||||||
var root = tree.create_item()
|
grids_node.get_node("VisualGrid").rect_size = paint_canvas_node.canvas_size * size
|
||||||
tree.set_hide_root(true)
|
grids_node.get_node("VisualGrid").size = size
|
||||||
var child1 = tree.create_item(root)
|
grids_node.get_node("VisualGrid2").rect_size = paint_canvas_node.canvas_size * size
|
||||||
child1.set_text(0, "Layers")
|
grids_node.get_node("VisualGrid2").size = size * paint_canvas_node.chunk_size.x
|
||||||
child1.set_editable(0, true)
|
|
||||||
for i in paint_canvas_node.layers:
|
|
||||||
var layer_name = i.name
|
|
||||||
var subchild = tree.create_item(child1)
|
|
||||||
subchild.set_text(0, layer_name)
|
|
||||||
subchild.set_editable(0, true)
|
|
||||||
|
|
||||||
func _thread_process():
|
|
||||||
pass
|
|
||||||
|
|
||||||
var brush_mode = "paint"
|
|
||||||
|
|
||||||
var mouse_position = Vector2()
|
var mouse_position = Vector2()
|
||||||
var canvas_position = Vector2()
|
var canvas_position = Vector2()
|
||||||
@ -71,31 +55,46 @@ var cell_mouse_position = Vector2()
|
|||||||
var cell_region_position = Vector2()
|
var cell_region_position = Vector2()
|
||||||
var cell_position_in_region = Vector2()
|
var cell_position_in_region = Vector2()
|
||||||
var cell_color = Color()
|
var cell_color = Color()
|
||||||
|
func process_common_used_variables():
|
||||||
|
grid_size = paint_canvas_node.grid_size
|
||||||
|
chunk_size = paint_canvas_node.chunk_size
|
||||||
|
mouse_position = get_local_mouse_position()
|
||||||
|
canvas_mouse_position = paint_canvas_node.get_local_mouse_position()
|
||||||
|
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 / chunk_size.x), floor(cell_mouse_position.y / chunk_size.y))
|
||||||
|
cell_position_in_region = paint_canvas_node.pixel_in_canvas_region(cell_mouse_position)
|
||||||
|
cell_color = paint_canvas_node.get_pixel(cell_mouse_position)
|
||||||
|
|
||||||
var last_mouse_position = Vector2()
|
var last_mouse_position = Vector2()
|
||||||
var last_canvas_position = Vector2()
|
var last_canvas_position = Vector2()
|
||||||
var last_canvas_mouse_position = Vector2()
|
var last_canvas_mouse_position = Vector2()
|
||||||
var last_cell_mouse_position = Vector2()
|
var last_cell_mouse_position = Vector2()
|
||||||
var last_cell_color = Color()
|
var last_cell_color = Color()
|
||||||
|
func process_last_common_used_variables():
|
||||||
|
last_mouse_position = mouse_position
|
||||||
|
last_canvas_position = canvas_position
|
||||||
|
last_canvas_mouse_position = canvas_mouse_position
|
||||||
|
last_cell_mouse_position = cell_mouse_position
|
||||||
|
last_cell_color = cell_color
|
||||||
|
|
||||||
|
var active_tool
|
||||||
|
func process_active_tool():
|
||||||
|
active_tool = get_node("ToolManager").get_active_tool()
|
||||||
|
active_tool.cell_mouse_position = cell_mouse_position
|
||||||
|
active_tool.last_cell_mouse_position = last_cell_mouse_position
|
||||||
|
active_tool.selected_color = selected_color
|
||||||
|
active_tool.cell_color = cell_color
|
||||||
|
|
||||||
# warning-ignore:unused_argument
|
# warning-ignore:unused_argument
|
||||||
func _process(delta):
|
func _process(delta):
|
||||||
#It's a lot more easier to just keep updating the variables in here than just have a bunch of local variables
|
#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
|
#in every update function and make it very messy
|
||||||
if paint_canvas_node == null:
|
|
||||||
set_process(false)
|
|
||||||
return
|
|
||||||
|
|
||||||
#Update commonly used variables
|
#Update commonly used variables
|
||||||
grid_size = paint_canvas_node.grid_size
|
process_common_used_variables()
|
||||||
region_size = paint_canvas_node.region_size
|
|
||||||
mouse_position = get_local_mouse_position()
|
#Process the active tool
|
||||||
canvas_position = paint_canvas_node.rect_position + paint_canvas_container_node.rect_position
|
process_active_tool()
|
||||||
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)
|
|
||||||
|
|
||||||
#Process the brush drawing stuff
|
#Process the brush drawing stuff
|
||||||
if paint_canvas_container_node.mouse_in_region and paint_canvas_container_node.mouse_on_top:
|
if paint_canvas_container_node.mouse_in_region and paint_canvas_container_node.mouse_on_top:
|
||||||
@ -105,12 +104,12 @@ func _process(delta):
|
|||||||
update()
|
update()
|
||||||
|
|
||||||
#Canvas Shift Moving
|
#Canvas Shift Moving
|
||||||
if not mouse_position == last_mouse_position:
|
if mouse_position != last_mouse_position:
|
||||||
if paint_canvas_container_node.has_focus():
|
if paint_canvas_container_node.has_focus():
|
||||||
if Input.is_key_pressed(KEY_SHIFT):
|
if Input.is_key_pressed(KEY_SHIFT) or Input.is_mouse_button_pressed(BUTTON_MIDDLE):
|
||||||
if Input.is_mouse_button_pressed(BUTTON_LEFT):
|
if Input.is_mouse_button_pressed(BUTTON_LEFT) or Input.is_mouse_button_pressed(BUTTON_MIDDLE):
|
||||||
var relative = mouse_position - last_mouse_position
|
var relative = mouse_position - last_mouse_position
|
||||||
paint_canvas_node.rect_position += relative
|
camera.position -= relative * camera.zoom
|
||||||
allow_drawing = false
|
allow_drawing = false
|
||||||
else:
|
else:
|
||||||
allow_drawing = true
|
allow_drawing = true
|
||||||
@ -119,58 +118,26 @@ func _process(delta):
|
|||||||
update_text_info()
|
update_text_info()
|
||||||
|
|
||||||
#Update last variables with the current variables
|
#Update last variables with the current variables
|
||||||
last_mouse_position = mouse_position
|
process_last_common_used_variables()
|
||||||
last_canvas_position = canvas_position
|
|
||||||
last_canvas_mouse_position = canvas_mouse_position
|
|
||||||
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_container_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 brush_process():
|
func brush_process():
|
||||||
if Input.is_mouse_button_pressed(BUTTON_LEFT):
|
if Input.is_mouse_button_pressed(BUTTON_LEFT):
|
||||||
if allow_drawing:
|
if allow_drawing:
|
||||||
if brush_mode == "paint":
|
active_tool.on_left_mouse_click()
|
||||||
paint_canvas_node.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, selected_color)
|
|
||||||
if brush_mode == "bucket":
|
|
||||||
paint_canvas_node.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, selected_color)
|
|
||||||
if brush_mode == "rainbow":
|
|
||||||
paint_canvas_node.set_random_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
|
|
||||||
elif Input.is_mouse_button_pressed(BUTTON_RIGHT):
|
elif Input.is_mouse_button_pressed(BUTTON_RIGHT):
|
||||||
if allow_drawing:
|
if allow_drawing:
|
||||||
if brush_mode == "paint" or brush_mode == "rainbow":
|
active_tool.on_right_mouse_click()
|
||||||
paint_canvas_node.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0))
|
|
||||||
if brush_mode == "bucket":
|
var zoom_amount = 0.5
|
||||||
paint_canvas_node.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, Color(0, 0, 0, 0))
|
func _input(event):
|
||||||
|
if event is InputEventMouseButton:
|
||||||
|
if event.is_pressed():
|
||||||
|
if event.button_index == BUTTON_WHEEL_UP:
|
||||||
|
if camera.zoom - Vector2(zoom_amount, zoom_amount) > Vector2(0, 0):
|
||||||
|
camera.zoom -= Vector2(zoom_amount, zoom_amount)
|
||||||
|
elif event.button_index == BUTTON_WHEEL_DOWN:
|
||||||
|
camera.zoom += Vector2(zoom_amount, zoom_amount)
|
||||||
|
|
||||||
func add_text_info_variables():
|
func add_text_info_variables():
|
||||||
textinfo.add_text_info("FPS")
|
textinfo.add_text_info("FPS")
|
||||||
@ -193,10 +160,10 @@ func update_text_info():
|
|||||||
textinfo.update_text_info("Canvas Position", canvas_position)
|
textinfo.update_text_info("Canvas Position", canvas_position)
|
||||||
textinfo.update_text_info("Cell Position", cell_mouse_position)
|
textinfo.update_text_info("Cell Position", cell_mouse_position)
|
||||||
var cell_color_text = cell_color
|
var cell_color_text = cell_color
|
||||||
if paint_canvas_node.mouse_in_region and paint_canvas_container_node.mouse_on_top:
|
if paint_canvas_container_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 Input.is_mouse_button_pressed(BUTTON_LEFT) or Input.is_mouse_button_pressed(BUTTON_RIGHT):
|
||||||
if paint_canvas_node.last_pixel.size() > 0:
|
if paint_canvas_node.last_pixel_drawn.size() > 0:
|
||||||
cell_color_text = paint_canvas_node.last_pixel[2]
|
cell_color_text = paint_canvas_node.last_pixel_drawn[1]
|
||||||
if cell_color_text == null:
|
if cell_color_text == null:
|
||||||
cell_color_text = Color(0, 0, 0, 0)
|
cell_color_text = Color(0, 0, 0, 0)
|
||||||
textinfo.update_text_info("Cell Color", cell_color_text, "Cell Color", "color", cell_color_text)
|
textinfo.update_text_info("Cell Color", cell_color_text, "Cell Color", "color", cell_color_text)
|
||||||
@ -204,10 +171,10 @@ func update_text_info():
|
|||||||
textinfo.update_text_info("Cell Position in Region", cell_position_in_region)
|
textinfo.update_text_info("Cell Position in Region", cell_position_in_region)
|
||||||
|
|
||||||
func _on_PaintTool_pressed():
|
func _on_PaintTool_pressed():
|
||||||
brush_mode = "paint"
|
tool_manager.set_active_tool("Pencil")
|
||||||
|
|
||||||
func _on_BucketTool_pressed():
|
func _on_BucketTool_pressed():
|
||||||
brush_mode = "bucket"
|
tool_manager.set_active_tool("Bucket")
|
||||||
|
|
||||||
func _on_ColorPicker_color_changed(color):
|
func _on_ColorPicker_color_changed(color):
|
||||||
selected_color = color
|
selected_color = color
|
||||||
@ -216,4 +183,4 @@ func _on_Save_pressed():
|
|||||||
get_node("SaveFileDialog").show()
|
get_node("SaveFileDialog").show()
|
||||||
|
|
||||||
func _on_RainbowTool_pressed():
|
func _on_RainbowTool_pressed():
|
||||||
brush_mode = "rainbow"
|
tool_manager.set_active_tool("Rainbow")
|
||||||
|
@ -1,16 +1,25 @@
|
|||||||
[gd_scene load_steps=12 format=2]
|
[gd_scene load_steps=20 format=2]
|
||||||
|
|
||||||
[ext_resource path="res://addons/graphics_editor/Editor.gd" type="Script" id=1]
|
[ext_resource path="res://addons/graphics_editor/Editor.gd" type="Script" id=1]
|
||||||
[ext_resource path="res://addons/graphics_editor/PaintCanvasContainer.gd" type="Script" id=2]
|
[ext_resource path="res://addons/graphics_editor/PaintCanvasContainer.gd" type="Script" id=2]
|
||||||
[ext_resource path="res://addons/graphics_editor/PaintCanvas.tscn" type="PackedScene" id=3]
|
[ext_resource path="res://addons/graphics_editor/Camera2D.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/PaintCanvas.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/PixelCursorHighlight.gd" type="Script" id=5]
|
||||||
[ext_resource path="res://addons/graphics_editor/Navbar.gd" type="Script" id=6]
|
[ext_resource path="res://addons/graphics_editor/VisualGrid.tscn" type="PackedScene" id=6]
|
||||||
[ext_resource path="res://addons/graphics_editor/MenuButtonExtended.gd" type="Script" id=7]
|
[ext_resource path="res://addons/graphics_editor/CanvasOutline.gd" type="Script" id=7]
|
||||||
[ext_resource path="res://addons/graphics_editor/ColorPicker.gd" type="Script" id=8]
|
[ext_resource path="res://addons/graphics_editor/Navbar.gd" type="Script" id=8]
|
||||||
[ext_resource path="res://addons/graphics_editor/TextInfo.gd" type="Script" id=9]
|
[ext_resource path="res://addons/graphics_editor/MenuButtonExtended.gd" type="Script" id=9]
|
||||||
[ext_resource path="res://addons/graphics_editor/SaveFileDialog.gd" type="Script" id=10]
|
[ext_resource path="res://addons/graphics_editor/ColorPicker.gd" type="Script" id=10]
|
||||||
[ext_resource path="res://addons/graphics_editor/Settings.tscn" type="PackedScene" id=11]
|
[ext_resource path="res://addons/graphics_editor/Layers.gd" type="Script" id=11]
|
||||||
|
[ext_resource path="res://addons/graphics_editor/TextInfo.gd" type="Script" id=12]
|
||||||
|
[ext_resource path="res://addons/graphics_editor/SaveFileDialog.gd" type="Script" id=13]
|
||||||
|
[ext_resource path="res://addons/graphics_editor/Settings.tscn" type="PackedScene" id=14]
|
||||||
|
[ext_resource path="res://addons/graphics_editor/NewImage.tscn" type="PackedScene" id=15]
|
||||||
|
[ext_resource path="res://addons/graphics_editor/LoadFileDialog.gd" type="Script" id=16]
|
||||||
|
[ext_resource path="res://addons/graphics_editor/ExpandCanvas.tscn" type="PackedScene" id=17]
|
||||||
|
[ext_resource path="res://addons/graphics_editor/ToolManager.gd" type="Script" id=18]
|
||||||
|
|
||||||
|
[sub_resource type="World" id=1]
|
||||||
|
|
||||||
[node name="Editor" type="Control"]
|
[node name="Editor" type="Control"]
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
@ -18,8 +27,12 @@ anchor_bottom = 1.0
|
|||||||
rect_min_size = Vector2( 1024, 300 )
|
rect_min_size = Vector2( 1024, 300 )
|
||||||
rect_clip_content = true
|
rect_clip_content = true
|
||||||
script = ExtResource( 1 )
|
script = ExtResource( 1 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="PaintCanvasContainer" type="Control" parent="."]
|
[node name="PaintCanvasContainer" type="Control" parent="."]
|
||||||
|
editor/display_folded = true
|
||||||
show_behind_parent = true
|
show_behind_parent = true
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
@ -33,39 +46,76 @@ __meta__ = {
|
|||||||
"_edit_lock_": true
|
"_edit_lock_": true
|
||||||
}
|
}
|
||||||
|
|
||||||
[node name="PaintCanvas" parent="PaintCanvasContainer" instance=ExtResource( 3 )]
|
[node name="ViewportContainer" type="ViewportContainer" parent="PaintCanvasContainer"]
|
||||||
|
editor/display_folded = true
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
mouse_filter = 1
|
||||||
|
stretch = true
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="Viewport" type="Viewport" parent="PaintCanvasContainer/ViewportContainer"]
|
||||||
|
size = Vector2( 910, 540 )
|
||||||
|
world = SubResource( 1 )
|
||||||
|
transparent_bg = true
|
||||||
|
handle_input_locally = false
|
||||||
|
render_target_update_mode = 3
|
||||||
|
|
||||||
|
[node name="Camera2D" type="Camera2D" parent="PaintCanvasContainer/ViewportContainer/Viewport"]
|
||||||
|
anchor_mode = 0
|
||||||
|
current = true
|
||||||
|
script = ExtResource( 3 )
|
||||||
|
|
||||||
|
[node name="PaintCanvas" parent="PaintCanvasContainer/ViewportContainer/Viewport" instance=ExtResource( 4 )]
|
||||||
anchor_right = 0.0
|
anchor_right = 0.0
|
||||||
anchor_bottom = 0.0
|
anchor_bottom = 0.0
|
||||||
margin_right = 1600.0
|
margin_right = 1600.0
|
||||||
margin_bottom = 1600.0
|
margin_bottom = 1600.0
|
||||||
rect_min_size = Vector2( 1600, 1600 )
|
|
||||||
|
|
||||||
[node name="Grids" type="Control" parent="PaintCanvasContainer/PaintCanvas"]
|
[node name="PixelCursorHighlight" type="Control" parent="PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas"]
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
mouse_filter = 2
|
|
||||||
|
|
||||||
[node name="VisualGrid" parent="PaintCanvasContainer/PaintCanvas/Grids" instance=ExtResource( 4 )]
|
|
||||||
mouse_filter = 2
|
|
||||||
color = Color( 0.639216, 0.639216, 0.639216, 1 )
|
|
||||||
|
|
||||||
[node name="VisualGrid2" parent="PaintCanvasContainer/PaintCanvas/Grids" instance=ExtResource( 4 )]
|
|
||||||
mouse_filter = 2
|
|
||||||
color = Color( 1, 1, 1, 1 )
|
|
||||||
size = 160
|
|
||||||
|
|
||||||
[node name="CanvasOutline" type="Control" parent="PaintCanvasContainer/PaintCanvas"]
|
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
mouse_filter = 2
|
mouse_filter = 2
|
||||||
script = ExtResource( 5 )
|
script = ExtResource( 5 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="Grids" type="Control" parent="PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
mouse_filter = 2
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="VisualGrid" parent="PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/Grids" instance=ExtResource( 6 )]
|
||||||
|
mouse_filter = 2
|
||||||
|
color = Color( 0.639216, 0.639216, 0.639216, 1 )
|
||||||
|
|
||||||
|
[node name="VisualGrid2" parent="PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/Grids" instance=ExtResource( 6 )]
|
||||||
|
mouse_filter = 2
|
||||||
|
color = Color( 1, 1, 1, 1 )
|
||||||
|
size = 160.0
|
||||||
|
|
||||||
|
[node name="CanvasOutline" type="Control" parent="PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
mouse_filter = 2
|
||||||
|
script = ExtResource( 7 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
color = Color( 0, 1, 0, 1 )
|
color = Color( 0, 1, 0, 1 )
|
||||||
|
width = 3.0
|
||||||
|
|
||||||
[node name="Navbar" type="Control" parent="."]
|
[node name="Navbar" type="Control" parent="."]
|
||||||
editor/display_folded = true
|
editor/display_folded = true
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
margin_bottom = 20.0
|
margin_bottom = 20.0
|
||||||
script = ExtResource( 6 )
|
script = ExtResource( 8 )
|
||||||
|
|
||||||
[node name="Panel" type="Panel" parent="Navbar"]
|
[node name="Panel" type="Panel" parent="Navbar"]
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
@ -74,15 +124,21 @@ anchor_bottom = 1.0
|
|||||||
[node name="Buttons" type="Control" parent="Navbar"]
|
[node name="Buttons" type="Control" parent="Navbar"]
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="File" type="MenuButton" parent="Navbar/Buttons"]
|
[node name="File" type="MenuButton" parent="Navbar/Buttons"]
|
||||||
margin_right = 90.0
|
margin_right = 90.0
|
||||||
margin_bottom = 20.0
|
margin_bottom = 20.0
|
||||||
text = "File"
|
text = "File"
|
||||||
flat = false
|
flat = false
|
||||||
items = [ "Save", null, 0, false, false, -1, 0, null, "", false, "Quit", null, 0, false, false, -1, 0, null, "", false ]
|
items = [ "New", null, 0, false, false, 0, 0, null, "", false, "Load", null, 0, false, false, 1, 0, null, "", false, "Save", null, 0, false, false, 2, 0, null, "", false, "Quit", null, 0, false, false, 3, 0, null, "", false ]
|
||||||
switch_on_hover = true
|
switch_on_hover = true
|
||||||
script = ExtResource( 7 )
|
script = ExtResource( 9 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="Editor" type="MenuButton" parent="Navbar/Buttons"]
|
[node name="Editor" type="MenuButton" parent="Navbar/Buttons"]
|
||||||
margin_left = 90.0
|
margin_left = 90.0
|
||||||
@ -90,55 +146,119 @@ margin_right = 180.0
|
|||||||
margin_bottom = 20.0
|
margin_bottom = 20.0
|
||||||
text = "Editor"
|
text = "Editor"
|
||||||
flat = false
|
flat = false
|
||||||
items = [ "Settings", null, 0, false, false, -1, 0, null, "", false, "Reset Canvas Position", null, 0, false, false, -1, 0, null, "", false, "Toggle Grid", null, 0, false, false, -1, 0, null, "", false ]
|
items = [ "Settings", null, 0, false, false, -1, 0, null, "", false, "Reset Camera Position", null, 0, false, false, -1, 0, null, "", false, "Toggle Grid", null, 0, false, false, -1, 0, null, "", false ]
|
||||||
switch_on_hover = true
|
switch_on_hover = true
|
||||||
script = ExtResource( 7 )
|
script = ExtResource( 9 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="Image" type="MenuButton" parent="Navbar/Buttons"]
|
||||||
|
margin_left = 180.0
|
||||||
|
margin_right = 270.0
|
||||||
|
margin_bottom = 20.0
|
||||||
|
text = "Image"
|
||||||
|
flat = false
|
||||||
|
items = [ "Resize", null, 0, false, false, -1, 0, null, "", false ]
|
||||||
|
switch_on_hover = true
|
||||||
|
script = ExtResource( 9 )
|
||||||
|
|
||||||
[node name="ToolMenu" type="Control" parent="."]
|
[node name="ToolMenu" type="Control" parent="."]
|
||||||
|
editor/display_folded = true
|
||||||
anchor_left = 1.0
|
anchor_left = 1.0
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
margin_left = -114.0
|
margin_left = -114.0
|
||||||
margin_top = 20.0
|
margin_top = 20.0
|
||||||
margin_bottom = -40.0
|
margin_bottom = -40.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="Buttons" type="Control" parent="ToolMenu"]
|
[node name="Buttons" type="Control" parent="ToolMenu"]
|
||||||
|
editor/display_folded = true
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
margin_bottom = 310.0
|
margin_bottom = 310.0
|
||||||
|
|
||||||
[node name="PaintTool" type="Button" parent="ToolMenu/Buttons"]
|
[node name="PaintTool" type="Button" parent="ToolMenu/Buttons"]
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
margin_bottom = 70.0
|
margin_bottom = 70.0
|
||||||
|
focus_mode = 0
|
||||||
|
enabled_focus_mode = 0
|
||||||
text = "Paint Tool"
|
text = "Paint Tool"
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="BucketTool" type="Button" parent="ToolMenu/Buttons"]
|
[node name="BucketTool" type="Button" parent="ToolMenu/Buttons"]
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
margin_top = 70.0
|
margin_top = 70.0
|
||||||
margin_bottom = 140.0
|
margin_bottom = 140.0
|
||||||
|
focus_mode = 0
|
||||||
|
enabled_focus_mode = 0
|
||||||
text = "Bucket Tool"
|
text = "Bucket Tool"
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="RainbowTool" type="Button" parent="ToolMenu/Buttons"]
|
[node name="RainbowTool" type="Button" parent="ToolMenu/Buttons"]
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
margin_top = 140.0
|
margin_top = 140.0
|
||||||
margin_bottom = 210.0
|
margin_bottom = 210.0
|
||||||
|
focus_mode = 0
|
||||||
|
enabled_focus_mode = 0
|
||||||
text = "Rainbow Tool"
|
text = "Rainbow Tool"
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="ColorPicker" type="ColorPickerButton" parent="ToolMenu/Buttons"]
|
[node name="ColorPicker" type="ColorPickerButton" parent="ToolMenu/Buttons"]
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
margin_top = 210.0
|
margin_top = 210.0
|
||||||
margin_bottom = 240.0
|
margin_bottom = 240.0
|
||||||
script = ExtResource( 8 )
|
focus_mode = 0
|
||||||
|
enabled_focus_mode = 0
|
||||||
|
script = ExtResource( 10 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="Layers" type="Control" parent="ToolMenu"]
|
[node name="Layers" type="Control" parent="ToolMenu"]
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
margin_top = 310.0
|
margin_top = 240.0
|
||||||
|
script = ExtResource( 11 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="Tree" type="Tree" parent="ToolMenu/Layers"]
|
[node name="Panel" type="Panel" parent="ToolMenu/Layers"]
|
||||||
|
editor/display_folded = true
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
margin_top = -70.0
|
|
||||||
hide_root = true
|
[node name="ScrollContainer" type="ScrollContainer" parent="ToolMenu/Layers/Panel"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_top = 20.0
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="ToolMenu/Layers/Panel/ScrollContainer"]
|
||||||
|
margin_right = 100.0
|
||||||
|
margin_bottom = 90.0
|
||||||
|
|
||||||
|
[node name="AddLayer" type="Button" parent="ToolMenu/Layers/Panel"]
|
||||||
|
margin_left = 90.0
|
||||||
|
margin_right = 110.0
|
||||||
|
margin_bottom = 20.0
|
||||||
|
text = "+"
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="ToolMenu/Layers/Panel"]
|
||||||
|
margin_left = 4.0
|
||||||
|
margin_right = 74.0
|
||||||
|
margin_bottom = 20.0
|
||||||
|
text = "Add Layer:"
|
||||||
|
align = 1
|
||||||
|
valign = 1
|
||||||
|
|
||||||
[node name="BottomPanel" type="Panel" parent="."]
|
[node name="BottomPanel" type="Panel" parent="."]
|
||||||
editor/display_folded = true
|
editor/display_folded = true
|
||||||
@ -146,9 +266,15 @@ anchor_top = 1.0
|
|||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
margin_top = -40.0
|
margin_top = -40.0
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="TextInfo" type="Control" parent="BottomPanel"]
|
[node name="TextInfo" type="Control" parent="BottomPanel"]
|
||||||
script = ExtResource( 9 )
|
script = ExtResource( 12 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
[node name="SaveFileDialog" type="FileDialog" parent="."]
|
[node name="SaveFileDialog" type="FileDialog" parent="."]
|
||||||
anchor_left = 0.5
|
anchor_left = 0.5
|
||||||
@ -160,9 +286,9 @@ margin_top = -165.0
|
|||||||
margin_right = 340.0
|
margin_right = 340.0
|
||||||
margin_bottom = 165.0
|
margin_bottom = 165.0
|
||||||
filters = PoolStringArray( "*.png ; PNG Images" )
|
filters = PoolStringArray( "*.png ; PNG Images" )
|
||||||
script = ExtResource( 10 )
|
script = ExtResource( 13 )
|
||||||
|
|
||||||
[node name="Settings" parent="." instance=ExtResource( 11 )]
|
[node name="Settings" parent="." instance=ExtResource( 14 )]
|
||||||
anchor_left = 0.5
|
anchor_left = 0.5
|
||||||
anchor_top = 0.5
|
anchor_top = 0.5
|
||||||
anchor_right = 0.5
|
anchor_right = 0.5
|
||||||
@ -171,6 +297,46 @@ margin_left = -155.0
|
|||||||
margin_top = -150.0
|
margin_top = -150.0
|
||||||
margin_right = 155.0
|
margin_right = 155.0
|
||||||
margin_bottom = 150.0
|
margin_bottom = 150.0
|
||||||
|
|
||||||
|
[node name="NewImage" parent="." instance=ExtResource( 15 )]
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
margin_left = -145.0
|
||||||
|
margin_top = -40.0
|
||||||
|
margin_right = 145.0
|
||||||
|
margin_bottom = 40.0
|
||||||
|
|
||||||
|
[node name="LoadFileDialog" type="FileDialog" parent="."]
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
margin_left = -340.0
|
||||||
|
margin_top = -165.0
|
||||||
|
margin_right = 340.0
|
||||||
|
margin_bottom = 165.0
|
||||||
|
window_title = "Open a File"
|
||||||
|
mode = 0
|
||||||
|
filters = PoolStringArray( "*.png ; PNG Images" )
|
||||||
|
script = ExtResource( 16 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="ExpandCanvas" parent="." instance=ExtResource( 17 )]
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
margin_left = -145.0
|
||||||
|
margin_top = -40.0
|
||||||
|
margin_right = 145.0
|
||||||
|
margin_bottom = 40.0
|
||||||
|
|
||||||
|
[node name="ToolManager" type="Node" parent="."]
|
||||||
|
script = ExtResource( 18 )
|
||||||
[connection signal="mouse_entered" from="PaintCanvasContainer" to="PaintCanvasContainer" method="_on_PaintCanvasContainer_mouse_entered"]
|
[connection signal="mouse_entered" from="PaintCanvasContainer" to="PaintCanvasContainer" method="_on_PaintCanvasContainer_mouse_entered"]
|
||||||
[connection signal="mouse_exited" from="PaintCanvasContainer" to="PaintCanvasContainer" method="_on_PaintCanvasContainer_mouse_exited"]
|
[connection signal="mouse_exited" from="PaintCanvasContainer" to="PaintCanvasContainer" method="_on_PaintCanvasContainer_mouse_exited"]
|
||||||
[connection signal="pressed" from="ToolMenu/Buttons/PaintTool" to="." method="_on_PaintTool_pressed"]
|
[connection signal="pressed" from="ToolMenu/Buttons/PaintTool" to="." method="_on_PaintTool_pressed"]
|
||||||
@ -180,7 +346,12 @@ margin_bottom = 150.0
|
|||||||
[connection signal="focus_exited" from="ToolMenu/Buttons/ColorPicker" to="ToolMenu/Buttons/ColorPicker" method="_on_ColorPicker_focus_exited"]
|
[connection signal="focus_exited" from="ToolMenu/Buttons/ColorPicker" to="ToolMenu/Buttons/ColorPicker" method="_on_ColorPicker_focus_exited"]
|
||||||
[connection signal="mouse_entered" from="ToolMenu/Buttons/ColorPicker" to="ToolMenu/Buttons/ColorPicker" method="_on_ColorPicker_mouse_entered"]
|
[connection signal="mouse_entered" from="ToolMenu/Buttons/ColorPicker" to="ToolMenu/Buttons/ColorPicker" method="_on_ColorPicker_mouse_entered"]
|
||||||
[connection signal="mouse_exited" from="ToolMenu/Buttons/ColorPicker" to="ToolMenu/Buttons/ColorPicker" method="_on_ColorPicker_mouse_exited"]
|
[connection signal="mouse_exited" from="ToolMenu/Buttons/ColorPicker" to="ToolMenu/Buttons/ColorPicker" method="_on_ColorPicker_mouse_exited"]
|
||||||
|
[connection signal="pressed" from="ToolMenu/Layers/Panel/AddLayer" to="ToolMenu/Layers" method="_on_AddLayer_pressed"]
|
||||||
[connection signal="about_to_show" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_about_to_show"]
|
[connection signal="about_to_show" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_about_to_show"]
|
||||||
[connection signal="confirmed" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_confirmed"]
|
[connection signal="confirmed" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_confirmed"]
|
||||||
[connection signal="file_selected" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_file_selected"]
|
[connection signal="file_selected" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_file_selected"]
|
||||||
[connection signal="visibility_changed" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_visibility_changed"]
|
[connection signal="visibility_changed" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_visibility_changed"]
|
||||||
|
[connection signal="about_to_show" from="LoadFileDialog" to="LoadFileDialog" method="_on_LoadFileDialog_about_to_show"]
|
||||||
|
[connection signal="confirmed" from="LoadFileDialog" to="LoadFileDialog" method="_on_LoadFileDialog_confirmed"]
|
||||||
|
[connection signal="file_selected" from="LoadFileDialog" to="LoadFileDialog" method="_on_LoadFileDialog_file_selected"]
|
||||||
|
[connection signal="visibility_changed" from="LoadFileDialog" to="LoadFileDialog" method="_on_LoadFileDialog_visibility_changed"]
|
||||||
|
13
addons/graphics_editor/ExpandCanvas.gd
Normal file
13
addons/graphics_editor/ExpandCanvas.gd
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
extends WindowDialog
|
||||||
|
|
||||||
|
onready var paint_canvas = get_node("/root/Editor/PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas")
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_Ok_pressed():
|
||||||
|
var new_canvas_size = Vector2()
|
||||||
|
new_canvas_size.x = get_node("CanvasSize/SpinBox").value
|
||||||
|
new_canvas_size.y = get_node("CanvasSize/SpinBox2").value
|
||||||
|
paint_canvas.expand_canvas(new_canvas_size)
|
||||||
|
hide()
|
53
addons/graphics_editor/ExpandCanvas.tscn
Normal file
53
addons/graphics_editor/ExpandCanvas.tscn
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/graphics_editor/ExpandCanvas.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[node name="ExpandCanvas" type="WindowDialog"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_right = -734.0
|
||||||
|
margin_bottom = -520.0
|
||||||
|
window_title = "Expand Canvas"
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
|
[node name="CanvasSize" type="Control" parent="."]
|
||||||
|
margin_left = 10.0
|
||||||
|
margin_top = 10.0
|
||||||
|
margin_right = 240.0
|
||||||
|
margin_bottom = 34.0
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="CanvasSize"]
|
||||||
|
margin_right = 80.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
text = "Canvas Size:"
|
||||||
|
valign = 1
|
||||||
|
|
||||||
|
[node name="Label2" type="Label" parent="CanvasSize"]
|
||||||
|
margin_left = 170.0
|
||||||
|
margin_right = 190.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
text = "X"
|
||||||
|
align = 1
|
||||||
|
valign = 1
|
||||||
|
|
||||||
|
[node name="SpinBox" type="SpinBox" parent="CanvasSize"]
|
||||||
|
margin_left = 90.0
|
||||||
|
margin_right = 170.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
max_value = 10000.0
|
||||||
|
value = 100.0
|
||||||
|
|
||||||
|
[node name="SpinBox2" type="SpinBox" parent="CanvasSize"]
|
||||||
|
margin_left = 190.0
|
||||||
|
margin_right = 270.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
max_value = 10000.0
|
||||||
|
value = 100.0
|
||||||
|
|
||||||
|
[node name="Ok" type="Button" parent="."]
|
||||||
|
margin_left = 200.0
|
||||||
|
margin_top = 50.0
|
||||||
|
margin_right = 280.0
|
||||||
|
margin_bottom = 70.0
|
||||||
|
text = "Ok"
|
||||||
|
[connection signal="pressed" from="Ok" to="." method="_on_Ok_pressed"]
|
27
addons/graphics_editor/Layer.gd
Normal file
27
addons/graphics_editor/Layer.gd
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
tool
|
||||||
|
extends Control
|
||||||
|
var image_storage = Image.new()
|
||||||
|
#TODO: Get image preview working!
|
||||||
|
var image_preview setget set_image_preview
|
||||||
|
var layer_visible = true
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
var canvas_size = get_node("../../../../").canvas.image.get_size()
|
||||||
|
image_storage.create(canvas_size.x, canvas_size.y, true, Image.FORMAT_RGBA8)
|
||||||
|
|
||||||
|
func set_image_preview(image_data):
|
||||||
|
image_preview = image_data
|
||||||
|
var texture = ImageTexture.new()
|
||||||
|
texture.create_from_image(image_data)
|
||||||
|
texture.set_flags(0)
|
||||||
|
texture.setup_local_to_scene()
|
||||||
|
get_node("TextureRect").texture = texture
|
||||||
|
|
||||||
|
func _on_LayerButton_pressed():
|
||||||
|
get_node("../../../../").active_layer = name
|
||||||
|
|
||||||
|
func _on_Visible_pressed():
|
||||||
|
layer_visible = !layer_visible
|
||||||
|
|
||||||
|
func _on_Delete_pressed():
|
||||||
|
get_node("../../../../").remove_layer(name)
|
63
addons/graphics_editor/Layer.tscn
Normal file
63
addons/graphics_editor/Layer.tscn
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
[gd_scene load_steps=4 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/graphics_editor/Layer.gd" type="Script" id=1]
|
||||||
|
[ext_resource path="res://icon.png" type="Texture" id=2]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id=1]
|
||||||
|
bg_color = Color( 1, 1, 1, 1 )
|
||||||
|
|
||||||
|
[node name="Layer" type="Control"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_right = -924.0
|
||||||
|
margin_bottom = -510.0
|
||||||
|
rect_min_size = Vector2( 100, 90 )
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
|
[node name="Panel" type="Panel" parent="."]
|
||||||
|
modulate = Color( 0.117647, 0.117647, 0.117647, 1 )
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
custom_styles/panel = SubResource( 1 )
|
||||||
|
|
||||||
|
[node name="LayerButton" type="Button" parent="."]
|
||||||
|
modulate = Color( 1, 1, 1, 0 )
|
||||||
|
margin_right = 100.0
|
||||||
|
margin_bottom = 90.0
|
||||||
|
|
||||||
|
[node name="Name" type="Label" parent="."]
|
||||||
|
margin_left = 10.0
|
||||||
|
margin_top = 4.0
|
||||||
|
margin_right = 56.0
|
||||||
|
margin_bottom = 18.0
|
||||||
|
text = "Layer 1"
|
||||||
|
|
||||||
|
[node name="Visible" type="Button" parent="."]
|
||||||
|
margin_left = 80.0
|
||||||
|
margin_top = 20.0
|
||||||
|
margin_right = 100.0
|
||||||
|
margin_bottom = 40.0
|
||||||
|
focus_mode = 0
|
||||||
|
enabled_focus_mode = 0
|
||||||
|
text = "V"
|
||||||
|
|
||||||
|
[node name="Delete" type="Button" parent="."]
|
||||||
|
margin_left = 80.0
|
||||||
|
margin_top = 40.0
|
||||||
|
margin_right = 100.0
|
||||||
|
margin_bottom = 60.0
|
||||||
|
focus_mode = 0
|
||||||
|
enabled_focus_mode = 0
|
||||||
|
text = "X"
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="."]
|
||||||
|
margin_left = 10.0
|
||||||
|
margin_top = 20.0
|
||||||
|
margin_right = 74.0
|
||||||
|
margin_bottom = 84.0
|
||||||
|
texture = ExtResource( 2 )
|
||||||
|
expand = true
|
||||||
|
stretch_mode = 1
|
||||||
|
[connection signal="pressed" from="LayerButton" to="." method="_on_LayerButton_pressed"]
|
||||||
|
[connection signal="pressed" from="Visible" to="." method="_on_Visible_pressed"]
|
||||||
|
[connection signal="pressed" from="Delete" to="." method="_on_Delete_pressed"]
|
65
addons/graphics_editor/Layers.gd
Normal file
65
addons/graphics_editor/Layers.gd
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
tool
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
onready var canvas = get_node("../../PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas")
|
||||||
|
onready var layer_list = get_node("Panel/ScrollContainer/VBoxContainer")
|
||||||
|
var layer_scene = preload("res://addons/graphics_editor/Layer.tscn")
|
||||||
|
var active_layer setget set_active_layer
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
if layer_list.get_children().size() <= 0:
|
||||||
|
add_new_layer(true)
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
var active_node = get_node_or_null("Panel/ScrollContainer/VBoxContainer/%s" % [active_layer])
|
||||||
|
if active_node:
|
||||||
|
active_node.image_storage = canvas.image.duplicate()
|
||||||
|
canvas.image_pixel_array = get_all_layer_images()
|
||||||
|
pass
|
||||||
|
|
||||||
|
func set_active_layer(new_layer):
|
||||||
|
if active_layer:
|
||||||
|
var cur_node = get_node_or_null("Panel/ScrollContainer/VBoxContainer/%s" % [active_layer])
|
||||||
|
if cur_node:
|
||||||
|
cur_node.get_node("Panel").modulate = Color(0.117647, 0.117647, 0.117647)
|
||||||
|
active_layer = new_layer
|
||||||
|
var new_node = get_node_or_null("Panel/ScrollContainer/VBoxContainer/%s" % [new_layer])
|
||||||
|
if new_node and new_node.image_storage:
|
||||||
|
new_node.get_node("Panel").modulate = Color(0.156863, 0.156863, 0.156863)
|
||||||
|
canvas.load_image(new_node.image_storage)
|
||||||
|
|
||||||
|
func get_all_layer_images():
|
||||||
|
var array = []
|
||||||
|
for i in layer_list.get_children():
|
||||||
|
if i.layer_visible:
|
||||||
|
array.append(i.image_storage)
|
||||||
|
return array
|
||||||
|
|
||||||
|
func increase_number_string(array, name_string, cur_int = 1):
|
||||||
|
for i in array:
|
||||||
|
if i == "%s %s" % [name_string, cur_int]:
|
||||||
|
cur_int += 1
|
||||||
|
return "%s %s" % [name_string, cur_int]
|
||||||
|
|
||||||
|
func _on_AddLayer_pressed():
|
||||||
|
add_new_layer()
|
||||||
|
|
||||||
|
func add_new_layer(is_active = false):
|
||||||
|
var get_children_name = PoolStringArray()
|
||||||
|
for i in layer_list.get_children():
|
||||||
|
get_children_name.append(i.name)
|
||||||
|
var new_node_name = increase_number_string(get_children_name, "New Layer")
|
||||||
|
var new_layer_node = layer_scene.instance()
|
||||||
|
new_layer_node.get_node("Name").text = new_node_name
|
||||||
|
new_layer_node.name = new_node_name
|
||||||
|
layer_list.add_child(new_layer_node)
|
||||||
|
if is_active:
|
||||||
|
set_active_layer(new_node_name)
|
||||||
|
|
||||||
|
func remove_layer(layer_name):
|
||||||
|
if layer_list.get_children().size() <= 1:
|
||||||
|
print("There needs to be an active layer always!")
|
||||||
|
return
|
||||||
|
var node_to_remove = layer_list.get_node_or_null(layer_name)
|
||||||
|
if node_to_remove:
|
||||||
|
node_to_remove.queue_free()
|
30
addons/graphics_editor/LoadFileDialog.gd
Normal file
30
addons/graphics_editor/LoadFileDialog.gd
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
tool
|
||||||
|
extends FileDialog
|
||||||
|
|
||||||
|
onready var canvas = get_parent().get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas")
|
||||||
|
|
||||||
|
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 load_file():
|
||||||
|
canvas.load_image_from_file(file_path)
|
||||||
|
|
||||||
|
func _on_LineEdit_text_entered(text):
|
||||||
|
load_file()
|
||||||
|
|
||||||
|
func _on_LoadFileDialog_confirmed():
|
||||||
|
load_file()
|
||||||
|
|
||||||
|
func _on_LoadFileDialog_file_selected(path):
|
||||||
|
file_path = path
|
||||||
|
|
||||||
|
func _on_LoadFileDialog_about_to_show():
|
||||||
|
invalidate()
|
||||||
|
|
||||||
|
func _on_LoadFileDialog_visibility_changed():
|
||||||
|
invalidate()
|
@ -8,4 +8,4 @@ func _ready():
|
|||||||
popup.connect("id_pressed", self, "id_pressed")
|
popup.connect("id_pressed", self, "id_pressed")
|
||||||
|
|
||||||
func id_pressed(id):
|
func id_pressed(id):
|
||||||
emit_signal("item_pressed", name, popup.get_item_text(id))
|
emit_signal("item_pressed", name, popup.get_item_text(id))
|
||||||
|
@ -1,21 +1,38 @@
|
|||||||
tool
|
tool
|
||||||
extends Control
|
extends Control
|
||||||
|
|
||||||
|
#TODO: Finish the navbar system!
|
||||||
|
#Disable the quit button when running as an editor plugin!
|
||||||
|
|
||||||
|
var navbar_storage = {
|
||||||
|
"File": ["New", "Load", "Save"],
|
||||||
|
"Editor": ["Settings", "Toggle Grid", "Reset Camera Position"],
|
||||||
|
"Image": ["Resize"]
|
||||||
|
}
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
for i in get_node("Buttons").get_children():
|
for i in get_node("Buttons").get_children():
|
||||||
i.connect("item_pressed", self, "button_pressed")
|
i.connect("item_pressed", self, "button_pressed")
|
||||||
|
|
||||||
func button_pressed(button_name, button_item):
|
func button_pressed(button_name, button_item):
|
||||||
if button_name == "File":
|
if button_name == "File":
|
||||||
|
if button_item == "New":
|
||||||
|
get_parent().get_node("NewImage").show()
|
||||||
|
if button_item == "Load":
|
||||||
|
get_parent().get_node("LoadFileDialog").show()
|
||||||
if button_item == "Save":
|
if button_item == "Save":
|
||||||
get_parent().get_node("SaveFileDialog").show()
|
get_parent().get_node("SaveFileDialog").show()
|
||||||
|
|
||||||
if button_item == "Quit":
|
if button_item == "Quit":
|
||||||
get_tree().quit()
|
get_tree().quit()
|
||||||
elif button_name == "Editor":
|
elif button_name == "Editor":
|
||||||
if button_item == "Settings":
|
if button_item == "Settings":
|
||||||
get_parent().get_node("Settings").show()
|
get_parent().get_node("Settings").show()
|
||||||
elif button_item == "Toggle Grid":
|
elif button_item == "Toggle Grid":
|
||||||
var grids_node = get_parent().get_node("PaintCanvasContainer/PaintCanvas/Grids")
|
var grids_node = get_parent().get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/Grids")
|
||||||
grids_node.visible = !grids_node.visible
|
grids_node.visible = !grids_node.visible
|
||||||
elif button_item == "Reset Canvas Position":
|
elif button_item == "Reset Camera Position":
|
||||||
get_parent().paint_canvas_node.rect_position = Vector2(0, 0)
|
get_parent().camera.position = Vector2(0, 0)
|
||||||
|
elif button_name == "Image":
|
||||||
|
if button_item == "Resize":
|
||||||
|
get_parent().get_node("ExpandCanvas").show()
|
||||||
|
13
addons/graphics_editor/NewImage.gd
Normal file
13
addons/graphics_editor/NewImage.gd
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
extends WindowDialog
|
||||||
|
|
||||||
|
onready var paint_canvas = get_node("/root/Editor/PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas")
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_Ok_pressed():
|
||||||
|
var new_canvas_size = Vector2()
|
||||||
|
new_canvas_size.x = get_node("ImageSize/SpinBox").value
|
||||||
|
new_canvas_size.y = get_node("ImageSize/SpinBox2").value
|
||||||
|
paint_canvas.canvas_size = new_canvas_size
|
||||||
|
hide()
|
53
addons/graphics_editor/NewImage.tscn
Normal file
53
addons/graphics_editor/NewImage.tscn
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/graphics_editor/NewImage.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[node name="NewImage" type="WindowDialog"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_right = -734.0
|
||||||
|
margin_bottom = -520.0
|
||||||
|
window_title = "New Image"
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
|
[node name="ImageSize" type="Control" parent="."]
|
||||||
|
margin_left = 10.0
|
||||||
|
margin_top = 10.0
|
||||||
|
margin_right = 240.0
|
||||||
|
margin_bottom = 34.0
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="ImageSize"]
|
||||||
|
margin_right = 80.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
text = "Image Size:"
|
||||||
|
valign = 1
|
||||||
|
|
||||||
|
[node name="Label2" type="Label" parent="ImageSize"]
|
||||||
|
margin_left = 170.0
|
||||||
|
margin_right = 190.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
text = "X"
|
||||||
|
align = 1
|
||||||
|
valign = 1
|
||||||
|
|
||||||
|
[node name="SpinBox" type="SpinBox" parent="ImageSize"]
|
||||||
|
margin_left = 90.0
|
||||||
|
margin_right = 170.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
max_value = 10000.0
|
||||||
|
value = 100.0
|
||||||
|
|
||||||
|
[node name="SpinBox2" type="SpinBox" parent="ImageSize"]
|
||||||
|
margin_left = 190.0
|
||||||
|
margin_right = 270.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
max_value = 10000.0
|
||||||
|
value = 100.0
|
||||||
|
|
||||||
|
[node name="Ok" type="Button" parent="."]
|
||||||
|
margin_left = 200.0
|
||||||
|
margin_top = 50.0
|
||||||
|
margin_right = 280.0
|
||||||
|
margin_bottom = 70.0
|
||||||
|
text = "Ok"
|
||||||
|
[connection signal="pressed" from="Ok" to="." method="_on_Ok_pressed"]
|
@ -1,388 +1,182 @@
|
|||||||
tool
|
tool
|
||||||
extends Control
|
extends Control
|
||||||
|
|
||||||
var image = Image.new()
|
export var grid_size = 16 setget resize_grid
|
||||||
var last_pixel = []
|
export var canvas_size = Vector2(100, 100) setget resize_canvas
|
||||||
onready var canvas_image_node = get_node("CanvasImage")
|
export var chunk_size = Vector2(10, 10)
|
||||||
export var grid_size = 16
|
|
||||||
export var canvas_size = Vector2(100, 100)
|
|
||||||
export var region_size = 10
|
|
||||||
export var can_draw = true
|
export var can_draw = true
|
||||||
|
onready var canvas_node = get_node("CanvasImage")
|
||||||
|
onready var util = get_node("Util")
|
||||||
|
|
||||||
var mouse_in_region
|
var mouse_in_region
|
||||||
var mouse_on_top
|
var last_pixel_drawn = []
|
||||||
|
var image = Image.new()
|
||||||
#terms
|
var image_render = Image.new()
|
||||||
#global cell - a cell that has a global grid position on the canvas
|
var image_texture = ImageTexture.new()
|
||||||
#local cell - a cell that has a local grid position in a chunk region on the canvas
|
signal grid_resized
|
||||||
#chunk region - a set of cells contained in an even number
|
signal canvas_resized
|
||||||
|
|
||||||
#TODO: Maybe each chunk region can hold an image resource so that way the engine wouldn't lag at all when updating the canvas
|
|
||||||
|
|
||||||
var layers = [
|
|
||||||
{
|
|
||||||
"name": "Layer 1",
|
|
||||||
"data": [],
|
|
||||||
"chunks": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
var active_layer = "Layer 1"
|
|
||||||
|
|
||||||
var chunks = []
|
|
||||||
|
|
||||||
func get_layer_data(layer_name):
|
|
||||||
for layer in layers:
|
|
||||||
if layer.name == layer_name:
|
|
||||||
return layer.data
|
|
||||||
#return layer.chunks
|
|
||||||
|
|
||||||
func set_layer_data(layer_name, layer_data):
|
|
||||||
for layer in layers:
|
|
||||||
if layer.name == layer_name:
|
|
||||||
layer.data = layer_data
|
|
||||||
return
|
|
||||||
|
|
||||||
func remove_layer(layer_name):
|
|
||||||
for layer in layers:
|
|
||||||
if layer.name == layer_name:
|
|
||||||
layers[layer] = null
|
|
||||||
return
|
|
||||||
|
|
||||||
func add_layer(layer_name):
|
|
||||||
for layer in layers:
|
|
||||||
#TODO: Allow users to create layers with the same name, we can do this because of the indexes in the layer array
|
|
||||||
if layer.name == layer_name:
|
|
||||||
return false
|
|
||||||
layers.append({"name": layer_name, "data": []})
|
|
||||||
#layers.append({"name": layer_name, "chunks": []})
|
|
||||||
return true
|
|
||||||
|
|
||||||
var util = preload("res://addons/graphics_editor/Util.gd")
|
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
#canvas_image_node.rect_scale = Vector2(grid_size, grid_size)
|
image.create(canvas_size.x, canvas_size.y, true, Image.FORMAT_RGBA8)
|
||||||
#image.create(canvas_size.x, canvas_size.y, true, Image.FORMAT_RGBA8)
|
image_render.create(canvas_size.x, canvas_size.y, true, Image.FORMAT_RGBA8)
|
||||||
#image.lock()
|
rect_min_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
#print(get_maxium_filled_chunks())
|
rect_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
# for pixel_data in get_layer_data(active_layer):
|
canvas_node.rect_min_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
# var cx = pixel_data[0]
|
canvas_node.rect_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
# var cy = pixel_data[1]
|
image.lock()
|
||||||
# var ccolor = pixel_data[2]
|
image_render.lock()
|
||||||
# image.set_pixel(cx, cy, ccolor)
|
|
||||||
generate_chunks()
|
|
||||||
|
|
||||||
func _process(delta):
|
func _process(delta):
|
||||||
var mouse_position = get_local_mouse_position()
|
update_canvas()
|
||||||
var rect = Rect2(Vector2(0, 0), rect_size)
|
|
||||||
mouse_in_region = rect.has_point(mouse_position)
|
#----------------------
|
||||||
update()
|
#---SETGET FUNCTIONS---
|
||||||
#if not Engine.editor_hint:
|
#----------------------
|
||||||
# print(mouse_on_canvas, " | ", has_focus())
|
|
||||||
#draw_canvas_out just updates the image constantly
|
func resize_grid(new_size):
|
||||||
#if can_draw:
|
grid_size = new_size
|
||||||
# draw_canvas_out()
|
if canvas_node:
|
||||||
|
#generate_chunks()
|
||||||
|
rect_min_size = Vector2(canvas_size.x * new_size, canvas_size.y * new_size)
|
||||||
|
rect_size = Vector2(canvas_size.x * new_size, canvas_size.y * new_size)
|
||||||
|
canvas_node.rect_min_size = Vector2(canvas_size.x * new_size, canvas_size.y * new_size)
|
||||||
|
canvas_node.rect_size = Vector2(canvas_size.x * new_size, canvas_size.y * new_size)
|
||||||
|
emit_signal("grid_resized", new_size)
|
||||||
|
|
||||||
|
func resize_canvas(new_size):
|
||||||
|
canvas_size = new_size
|
||||||
|
if canvas_node:
|
||||||
|
image.unlock()
|
||||||
|
image = Image.new()
|
||||||
|
image.create(canvas_size.x, canvas_size.y, true, Image.FORMAT_RGBA8)
|
||||||
|
image.lock()
|
||||||
|
image_render.unlock()
|
||||||
|
image_render.create(canvas_size.x, canvas_size.y, true, Image.FORMAT_RGBA8)
|
||||||
|
image_render.lock()
|
||||||
|
rect_min_size = Vector2(new_size.x * grid_size, new_size.y * grid_size)
|
||||||
|
rect_size = Vector2(new_size.x * grid_size, new_size.y * grid_size)
|
||||||
|
canvas_node.rect_min_size = Vector2(new_size.x * grid_size, new_size.y * grid_size)
|
||||||
|
canvas_node.rect_size = Vector2(new_size.x * grid_size, new_size.y * grid_size)
|
||||||
|
emit_signal("canvas_resized", new_size)
|
||||||
|
|
||||||
|
#---------------------
|
||||||
|
#---CHUNK FUNCTIONS---
|
||||||
|
#---------------------
|
||||||
|
|
||||||
|
func spawn_chunk(pos):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func update_chunk(pos):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func get_chunk_from_pixel(pos):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func set_chunk(pos):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func remove_chunk(pos):
|
||||||
|
pass
|
||||||
|
|
||||||
func generate_chunks():
|
func generate_chunks():
|
||||||
var maxium_chunk_size = get_maxium_filled_chunks()
|
pass
|
||||||
#TODO: We probably don't need to check for x and y anymore
|
|
||||||
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()
|
|
||||||
paint_canvas_chunk.setup(region_size)
|
|
||||||
paint_canvas_chunk.name = "C-%s-%s" % [x, y]
|
|
||||||
paint_canvas_chunk.rect_position = Vector2(x * (16 * 10), y * (16 * 10))
|
|
||||||
get_node("Chunks").add_child(paint_canvas_chunk)
|
|
||||||
|
|
||||||
func get_maxium_filled_chunks():
|
#---------------------
|
||||||
return Vector2(canvas_size.x / region_size, canvas_size.y / region_size).ceil()
|
#---PIXEL FUNCTIONS---
|
||||||
|
#---------------------
|
||||||
|
|
||||||
#TODO: Remake these functions with godot's setget features
|
func get_pixel(pos):
|
||||||
#so that we don't have to call these functions
|
if not pixel_in_canvas_region(pos):
|
||||||
func resize_grid(grid):
|
|
||||||
#print(grid)
|
|
||||||
if grid <= 0:
|
|
||||||
return
|
|
||||||
grid_size = grid
|
|
||||||
canvas_image_node.rect_scale = Vector2(grid, grid)
|
|
||||||
|
|
||||||
func resize_canvas(x, y):
|
|
||||||
image.unlock()
|
|
||||||
image.create(x, y, true, Image.FORMAT_RGBA8)
|
|
||||||
canvas_size = Vector2(x, y)
|
|
||||||
#setup_all_chunks()
|
|
||||||
image.lock()
|
|
||||||
|
|
||||||
#func draw_canvas_out(a = ""):
|
|
||||||
# if canvas_image_node == null:
|
|
||||||
# return
|
|
||||||
# var image_texture = ImageTexture.new()
|
|
||||||
# image_texture.create_from_image(image)
|
|
||||||
# image_texture.set_flags(0)
|
|
||||||
# canvas_image_node.texture = image_texture
|
|
||||||
|
|
||||||
func get_wrapped_region_cell(x, y):
|
|
||||||
return Vector2(wrapi(x, 0, region_size), wrapi(y, 0, region_size))
|
|
||||||
|
|
||||||
func get_region_from_cell(x, y):
|
|
||||||
return Vector2(floor(x / region_size), floor(y / region_size))
|
|
||||||
|
|
||||||
func set_local_cell_in_chunk(chunk_x, chunk_y, local_cell_x, local_cell_y, color):
|
|
||||||
var chunk_node = get_node("Chunks").get_node_or_null("C-%s-%s" % [chunk_x, chunk_y])
|
|
||||||
if chunk_node == null:
|
|
||||||
print("Can't find chunk node!")
|
|
||||||
return
|
|
||||||
chunk_node.set_cell(local_cell_x, local_cell_y, color)
|
|
||||||
|
|
||||||
func set_global_cell_in_chunk(cell_x, cell_y, color):
|
|
||||||
var chunk = get_region_from_cell(cell_x, cell_y)
|
|
||||||
var wrapped_cell = get_wrapped_region_cell(cell_x, cell_y)
|
|
||||||
set_local_cell_in_chunk(chunk.x, chunk.y, wrapped_cell.x, wrapped_cell.y, color)
|
|
||||||
|
|
||||||
#func update_chunk_region_from_cell(x, y):
|
|
||||||
# var region_to_update = get_region_from_cell(x, y)
|
|
||||||
# update_chunk_region(region_to_update.x, region_to_update.y)
|
|
||||||
|
|
||||||
func get_pixel_cell_color(x, y):
|
|
||||||
if not cell_in_canvas_region(x, y):
|
|
||||||
return null
|
|
||||||
var pixel_cell = get_pixel_cell(x, y)
|
|
||||||
if pixel_cell == null:
|
|
||||||
#We already checked that the cell can't be out of the canvas region so we can assume the pixel cell is completely transparent if it's null
|
|
||||||
return Color(0, 0, 0, 0)
|
|
||||||
else:
|
|
||||||
return util.color_from_array(pixel_cell[2])
|
|
||||||
|
|
||||||
func get_pixel_cell_color_v(vec2):
|
|
||||||
return get_pixel_cell_color(vec2.x, vec2.y)
|
|
||||||
|
|
||||||
func get_pixel_cell(x, y):
|
|
||||||
if not cell_in_canvas_region(x, y):
|
|
||||||
return null
|
return null
|
||||||
|
|
||||||
for pixel in get_layer_data(active_layer):
|
return image.get_pixelv(pos)
|
||||||
if pixel[0] == x and pixel[1] == y:
|
|
||||||
return pixel
|
func set_pixel(pos, color):
|
||||||
|
if not pixel_in_canvas_region(pos):
|
||||||
|
return null
|
||||||
|
|
||||||
return null
|
last_pixel_drawn = [pos, color]
|
||||||
|
return image.set_pixelv(pos, color)
|
||||||
|
|
||||||
func get_pixel_cell_v(vec2):
|
func pixel_in_canvas_region(pos):
|
||||||
return get_pixel_cell(vec2.x, vec2.y)
|
if pos.x < canvas_size.x and pos.x > -1 and pos.y < canvas_size.y and pos.y > -1:
|
||||||
|
|
||||||
#func remove_pixel_cell(x, y):
|
|
||||||
# if can_draw == false:
|
|
||||||
# return false
|
|
||||||
# if not cell_in_canvas_region(x, y):
|
|
||||||
# return false
|
|
||||||
# var layer_data = get_layer_data("Layer 1")
|
|
||||||
# for pixel in range(0, layer_data.size()):
|
|
||||||
# if layer_data[pixel][0] == x and layer_data[pixel][1] == y:
|
|
||||||
# layer_data.remove(pixel)
|
|
||||||
# #update_chunk_region_from_cell(x, y)
|
|
||||||
# #TOOD: If pixel exists in temp_pool_pixels then remove it
|
|
||||||
# image.set_pixel(x, y, Color(0, 0, 0, 0))
|
|
||||||
# return true
|
|
||||||
# return false
|
|
||||||
|
|
||||||
#func remove_pixel_cell_v(vec2):
|
|
||||||
# return remove_pixel_cell(vec2.x, vec2.y)
|
|
||||||
|
|
||||||
func set_pixel_cell(x, y, color):
|
|
||||||
if can_draw == false:
|
|
||||||
return false
|
|
||||||
if not cell_in_canvas_region(x, y):
|
|
||||||
return false
|
|
||||||
var layer_data = get_layer_data(active_layer)
|
|
||||||
var index = 0
|
|
||||||
for pixel in layer_data:
|
|
||||||
#TODO: Make a better way of accessing the array because the more pixels we have, the longer it takes to
|
|
||||||
#set the pixel
|
|
||||||
if pixel[0] == x and pixel[1] == y:
|
|
||||||
#No reason to set the pixel again if the colors are the same
|
|
||||||
if pixel[2] == color:
|
|
||||||
return
|
|
||||||
#If the color we are setting is 0, 0, 0, 0 then there is no reason to keep the information about the pixel
|
|
||||||
#so we remove it from the layer data
|
|
||||||
if color == Color(0, 0, 0, 0):
|
|
||||||
layer_data.remove(index)
|
|
||||||
else:
|
|
||||||
pixel[2] = color
|
|
||||||
#TODO: The new system is going to allow chunks to each have their own TextureRect and Image
|
|
||||||
#nodes so what we are doing in here is that we are setting the local cell in the region of that image
|
|
||||||
set_global_cell_in_chunk(x, y, color)
|
|
||||||
last_pixel = [x, y, color]
|
|
||||||
return true
|
|
||||||
index += 1
|
|
||||||
#don't append any data if the color is 0, 0, 0, 0
|
|
||||||
if color != Color(0, 0, 0, 0):
|
|
||||||
#if the pixel data doesn't exist then we add it in
|
|
||||||
layer_data.append([x, y, color])
|
|
||||||
set_global_cell_in_chunk(x, y, color)
|
|
||||||
last_pixel = [x, y, color]
|
|
||||||
return true
|
|
||||||
|
|
||||||
func set_pixel_cell_v(vec2, color):
|
|
||||||
return set_pixel_cell(vec2.x, vec2.y, color)
|
|
||||||
|
|
||||||
func set_pixels_from_line(vec2_1, vec2_2, color):
|
|
||||||
var points = get_pixels_from_line(vec2_1, vec2_2)
|
|
||||||
for i in points:
|
|
||||||
set_pixel_cell_v(i, color)
|
|
||||||
|
|
||||||
func set_random_pixels_from_line(vec2_1, vec2_2):
|
|
||||||
var points = get_pixels_from_line(vec2_1, vec2_2)
|
|
||||||
for i in points:
|
|
||||||
set_pixel_cell_v(i, util.random_color_alt())
|
|
||||||
|
|
||||||
func get_pixels_from_line(vec2_1, vec2_2):
|
|
||||||
var points = PoolVector2Array()
|
|
||||||
|
|
||||||
var dx = abs(vec2_2.x - vec2_1.x)
|
|
||||||
var dy = abs(vec2_2.y - vec2_1.y)
|
|
||||||
|
|
||||||
var x = vec2_1.x
|
|
||||||
var y = vec2_1.y
|
|
||||||
|
|
||||||
var sx = 0
|
|
||||||
if vec2_1.x > vec2_2.x:
|
|
||||||
sx = -1
|
|
||||||
else:
|
|
||||||
sx = 1
|
|
||||||
|
|
||||||
var sy = 0
|
|
||||||
if vec2_1.y > vec2_2.y:
|
|
||||||
sy = -1
|
|
||||||
else:
|
|
||||||
sy = 1
|
|
||||||
|
|
||||||
if dx > dy:
|
|
||||||
var err = dx / 2
|
|
||||||
while(true):
|
|
||||||
if x == vec2_2.x:
|
|
||||||
break
|
|
||||||
points.push_back(Vector2(x, y))
|
|
||||||
|
|
||||||
err -= dy
|
|
||||||
if err < 0:
|
|
||||||
y += sy
|
|
||||||
err += dx
|
|
||||||
x += sx
|
|
||||||
else:
|
|
||||||
var err = dy / 2
|
|
||||||
while (true):
|
|
||||||
if y == vec2_2.y:
|
|
||||||
break
|
|
||||||
points.push_back(Vector2(x, y))
|
|
||||||
|
|
||||||
err -= dx
|
|
||||||
if err < 0:
|
|
||||||
x += sx
|
|
||||||
err += dy
|
|
||||||
y += sy
|
|
||||||
points.push_back(Vector2(x, y))
|
|
||||||
return points
|
|
||||||
|
|
||||||
#even though the function checks for it, we can't afford adding more functions to the call stack
|
|
||||||
#because godot has a limit until it crashes
|
|
||||||
|
|
||||||
func flood_fill(x, y, target_color, replacement_color):
|
|
||||||
var time_debug = util.time_debug.new()
|
|
||||||
time_debug.start()
|
|
||||||
flood_fill_main(x, y, target_color, replacement_color)
|
|
||||||
time_debug.end()
|
|
||||||
print("Bucket fill time passed: msec: %s | sec: %s" % [time_debug.get_time_passed(), time_debug.get_time_passed() / float(1000)])
|
|
||||||
return
|
|
||||||
|
|
||||||
var flood_fill_queue = 0
|
|
||||||
func flood_fill_main(x, y, target_color, replacement_color):
|
|
||||||
|
|
||||||
#yield(get_tree().create_timer(1), "timeout")
|
|
||||||
flood_fill_queue += 1
|
|
||||||
if not cell_in_canvas_region(x, y):
|
|
||||||
flood_fill_queue -= 1
|
|
||||||
return
|
|
||||||
if target_color == replacement_color:
|
|
||||||
flood_fill_queue -= 1
|
|
||||||
return
|
|
||||||
elif not get_pixel_cell_color(x, y) == target_color:
|
|
||||||
flood_fill_queue -= 1
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
set_pixel_cell(x, y, replacement_color)
|
|
||||||
if flood_fill_queue >= 200:
|
|
||||||
yield(get_tree().create_timer(0.01), "timeout")
|
|
||||||
#up
|
|
||||||
if get_pixel_cell_color(x, y - 1) == target_color:
|
|
||||||
flood_fill_main(x, y - 1, target_color, replacement_color)
|
|
||||||
#down
|
|
||||||
if get_pixel_cell_color(x, y + 1) == target_color:
|
|
||||||
flood_fill_main(x, y + 1, target_color, replacement_color)
|
|
||||||
#left
|
|
||||||
if get_pixel_cell_color(x - 1, y) == target_color:
|
|
||||||
flood_fill_main(x - 1, y, target_color, replacement_color)
|
|
||||||
#right
|
|
||||||
if get_pixel_cell_color(x + 1, y) == target_color:
|
|
||||||
flood_fill_main(x + 1, y, target_color, replacement_color)
|
|
||||||
flood_fill_queue -= 1
|
|
||||||
return
|
|
||||||
|
|
||||||
#func flood_fill_erase(x, y, target_color):
|
|
||||||
# yield(get_tree().create_timer(0.001), "timeout")
|
|
||||||
# if not cell_in_canvas_region(x, y):
|
|
||||||
# print("cell not in canvas")
|
|
||||||
# return
|
|
||||||
# #if target_color == replacement_color:
|
|
||||||
# # return
|
|
||||||
# elif not get_pixel_cell_color(x, y) == target_color:
|
|
||||||
# print("cell doesn't match pixel color")
|
|
||||||
# return
|
|
||||||
# elif not get_pixel_cell(x, y):
|
|
||||||
# print("cell already erased")
|
|
||||||
# return
|
|
||||||
# else:
|
|
||||||
# print("removed pixel")
|
|
||||||
# remove_pixel_cell(x, y)
|
|
||||||
# print("x: ", x, " y: ", y, " color: ", target_color)
|
|
||||||
# #up
|
|
||||||
# flood_fill_erase(x, y - 1, target_color)
|
|
||||||
# #down
|
|
||||||
# flood_fill_erase(x, y + 1, target_color)
|
|
||||||
# #left
|
|
||||||
# flood_fill_erase(x - 1, y, target_color)
|
|
||||||
# #right
|
|
||||||
# flood_fill_erase(x + 1, y, target_color)
|
|
||||||
# return
|
|
||||||
|
|
||||||
func cell_in_canvas_region(x, y):
|
|
||||||
if x > canvas_size.x - 1 or x < 0 or y > canvas_size.y - 1 or y < 0:
|
|
||||||
#out of bounds, return false
|
|
||||||
return false
|
|
||||||
else:
|
|
||||||
return true
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
#Both of these functions right now just return the starting position of the canvas and the last position of the canvas
|
#--------------------
|
||||||
func get_all_used_regions_in_canvas():
|
#--Canvas Rendering--
|
||||||
var first_used_region = get_first_used_region_in_canvas()
|
#--------------------
|
||||||
var last_used_region = get_last_used_region_in_canvas()
|
|
||||||
var chunk_pool = PoolVector2Array()
|
|
||||||
for chunk_x in range(first_used_region.x, last_used_region.x):
|
|
||||||
for chunk_y in range(first_used_region.y, last_used_region.y):
|
|
||||||
chunk_pool.append(Vector2(chunk_x, chunk_y))
|
|
||||||
return chunk_pool
|
|
||||||
|
|
||||||
func get_first_used_region_in_canvas():
|
var image_pixel_array = []
|
||||||
return get_region_from_cell(0, 0)
|
func update_canvas():
|
||||||
|
image_render.fill(Color(0, 0, 0, 0))
|
||||||
|
for i in image_pixel_array:
|
||||||
|
image_render.blend_rect(i, Rect2(Vector2.ZERO, canvas_size), Vector2.ZERO)
|
||||||
|
image_texture.create_from_image(image_render)
|
||||||
|
image_texture.set_flags(0)
|
||||||
|
if canvas_node:
|
||||||
|
canvas_node.texture = image_texture
|
||||||
|
|
||||||
func get_last_used_region_in_canvas():
|
#---------------------
|
||||||
return get_region_from_cell(canvas_size.x - 1, canvas_size.y - 1)
|
#---IMAGE FUNCTIONS---
|
||||||
|
#---------------------
|
||||||
|
|
||||||
func get_cells_in_region(x, y):
|
func load_image(image_data):
|
||||||
var start_cell = Vector2(x * region_size, y * region_size)
|
var array_data = image_data_to_array(image_data)
|
||||||
var end_cell = Vector2((x * region_size) + region_size, (y * region_size) + region_size)
|
image.unlock()
|
||||||
var cell_array = []
|
image.create(canvas_size.x, canvas_size.y, true, Image.FORMAT_RGBA8)
|
||||||
for cx in range(start_cell.x, end_cell.x):
|
image.lock()
|
||||||
for cy in range(start_cell.y, end_cell.y):
|
image_render.unlock()
|
||||||
var pixel_cell = get_pixel_cell(cx, cy)
|
image_render.create(canvas_size.x, canvas_size.y, true, Image.FORMAT_RGBA8)
|
||||||
if pixel_cell == null:
|
image_render.lock()
|
||||||
pixel_cell = [cx, cy, Color(0, 0, 0, 0)]
|
set_pixels_from_array(array_data)
|
||||||
cell_array.append(pixel_cell)
|
rect_min_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
return cell_array
|
rect_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
|
canvas_node.rect_min_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
|
canvas_node.rect_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
|
emit_signal("canvas_resized", canvas_size)
|
||||||
|
|
||||||
|
func load_image_from_file(file_path):
|
||||||
|
image.unlock()
|
||||||
|
image.load(file_path)
|
||||||
|
image.lock()
|
||||||
|
canvas_size = image.get_size()
|
||||||
|
image_render.unlock()
|
||||||
|
image_render.create(canvas_size.x, canvas_size.y, true, Image.FORMAT_RGBA8)
|
||||||
|
image_render.lock()
|
||||||
|
rect_min_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
|
rect_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
|
canvas_node.rect_min_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
|
canvas_node.rect_size = Vector2(canvas_size.x * grid_size, canvas_size.y * grid_size)
|
||||||
|
emit_signal("canvas_resized", canvas_size)
|
||||||
|
|
||||||
|
func expand_canvas(new_size):
|
||||||
|
canvas_size = new_size
|
||||||
|
if canvas_node:
|
||||||
|
var array_data = image_data_to_array(image)
|
||||||
|
image.unlock()
|
||||||
|
image.create(new_size.x, new_size.y, true, Image.FORMAT_RGBA8)
|
||||||
|
image.lock()
|
||||||
|
image_render.unlock()
|
||||||
|
image_render.create(new_size.x, new_size.y, true, Image.FORMAT_RGBA8)
|
||||||
|
image_render.lock()
|
||||||
|
set_pixels_from_array(array_data)
|
||||||
|
rect_min_size = Vector2(new_size.x * grid_size, new_size.y * grid_size)
|
||||||
|
rect_size = Vector2(new_size.x * grid_size, new_size.y * grid_size)
|
||||||
|
canvas_node.rect_min_size = Vector2(new_size.x * grid_size, new_size.y * grid_size)
|
||||||
|
canvas_node.rect_size = Vector2(new_size.x * grid_size, new_size.y * grid_size)
|
||||||
|
emit_signal("canvas_resized", new_size)
|
||||||
|
|
||||||
|
func set_pixels_from_array(array):
|
||||||
|
for i in array:
|
||||||
|
set_pixel(i[0], i[1])
|
||||||
|
|
||||||
|
func image_data_to_array(image_data):
|
||||||
|
var array = []
|
||||||
|
if image_data:
|
||||||
|
image_data.lock()
|
||||||
|
var image_data_size = image_data.get_size()
|
||||||
|
for x in image_data_size.x:
|
||||||
|
for y in image_data_size.y:
|
||||||
|
array.append([Vector2(x, y), image_data.get_pixel(x, y)])
|
||||||
|
return array
|
||||||
|
File diff suppressed because one or more lines are too long
@ -16,4 +16,4 @@ func _on_PaintCanvasContainer_mouse_entered():
|
|||||||
mouse_on_top = true
|
mouse_on_top = true
|
||||||
|
|
||||||
func _on_PaintCanvasContainer_mouse_exited():
|
func _on_PaintCanvasContainer_mouse_exited():
|
||||||
mouse_on_top = false
|
mouse_on_top = false
|
||||||
|
88
addons/graphics_editor/PaintCanvasUtil.gd
Normal file
88
addons/graphics_editor/PaintCanvasUtil.gd
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
tool
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
onready var paint_canvas = get_parent()
|
||||||
|
onready var util = preload("res://addons/graphics_editor/Util.gd")
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func set_pixels_from_line(vec2_1, vec2_2, color):
|
||||||
|
var points = get_points_from_line(vec2_1, vec2_2)
|
||||||
|
for i in points:
|
||||||
|
paint_canvas.set_pixel(i, color)
|
||||||
|
|
||||||
|
func get_points_from_line(vec2_1, vec2_2):
|
||||||
|
var points = PoolVector2Array()
|
||||||
|
|
||||||
|
var dx = abs(vec2_2.x - vec2_1.x)
|
||||||
|
var dy = abs(vec2_2.y - vec2_1.y)
|
||||||
|
|
||||||
|
var x = vec2_1.x
|
||||||
|
var y = vec2_1.y
|
||||||
|
|
||||||
|
var sx = 0
|
||||||
|
if vec2_1.x > vec2_2.x:
|
||||||
|
sx = -1
|
||||||
|
else:
|
||||||
|
sx = 1
|
||||||
|
|
||||||
|
var sy = 0
|
||||||
|
if vec2_1.y > vec2_2.y:
|
||||||
|
sy = -1
|
||||||
|
else:
|
||||||
|
sy = 1
|
||||||
|
|
||||||
|
if dx > dy:
|
||||||
|
var err = dx / 2
|
||||||
|
while(true):
|
||||||
|
if x == vec2_2.x:
|
||||||
|
break
|
||||||
|
points.push_back(Vector2(x, y))
|
||||||
|
|
||||||
|
err -= dy
|
||||||
|
if err < 0:
|
||||||
|
y += sy
|
||||||
|
err += dx
|
||||||
|
x += sx
|
||||||
|
else:
|
||||||
|
var err = dy / 2
|
||||||
|
while (true):
|
||||||
|
if y == vec2_2.y:
|
||||||
|
break
|
||||||
|
points.push_back(Vector2(x, y))
|
||||||
|
|
||||||
|
err -= dx
|
||||||
|
if err < 0:
|
||||||
|
x += sx
|
||||||
|
err += dy
|
||||||
|
y += sy
|
||||||
|
points.push_back(Vector2(x, y))
|
||||||
|
return points
|
||||||
|
|
||||||
|
#Flood fill algrorithm copied and modified from Pixeloroma!
|
||||||
|
#https://github.com/OverloadedOrama/Pixelorama/blob/master/Scripts/Canvas.gd
|
||||||
|
func flood_fill(pos, target_color, replacement_color):
|
||||||
|
if target_color == replacement_color:
|
||||||
|
return
|
||||||
|
elif paint_canvas.get_pixel(pos) != target_color:
|
||||||
|
return
|
||||||
|
elif !paint_canvas.pixel_in_canvas_region(pos):
|
||||||
|
return
|
||||||
|
var q = [pos]
|
||||||
|
for n in q:
|
||||||
|
var west = n
|
||||||
|
var east = n
|
||||||
|
while paint_canvas.get_pixel(west) == target_color:
|
||||||
|
west += Vector2.LEFT
|
||||||
|
while paint_canvas.get_pixel(east) == target_color:
|
||||||
|
east += Vector2.RIGHT
|
||||||
|
for px in range(west.x + 1, east.x):
|
||||||
|
var p = Vector2(px, n.y)
|
||||||
|
paint_canvas.set_pixel(p, replacement_color)
|
||||||
|
var north = p + Vector2.UP
|
||||||
|
var south = p + Vector2.DOWN
|
||||||
|
if paint_canvas.get_pixel(north) == target_color:
|
||||||
|
q.append(north)
|
||||||
|
if paint_canvas.get_pixel(south) == target_color:
|
||||||
|
q.append(south)
|
14
addons/graphics_editor/PixelCursorHighlight.gd
Normal file
14
addons/graphics_editor/PixelCursorHighlight.gd
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
tool
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
var cell_mouse_position = Vector2()
|
||||||
|
var grid_size = 0
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
var canvas_mouse_position = get_parent().get_local_mouse_position()
|
||||||
|
grid_size = get_parent().grid_size
|
||||||
|
cell_mouse_position = Vector2(floor(canvas_mouse_position.x / grid_size), floor(canvas_mouse_position.y / grid_size))
|
||||||
|
update()
|
||||||
|
|
||||||
|
func _draw():
|
||||||
|
draw_rect(Rect2(Vector2((cell_mouse_position.x * grid_size), (cell_mouse_position.y * grid_size)), Vector2(grid_size, grid_size)), Color(0.8, 0.8, 0.8, 0.8), true)
|
@ -1,47 +1,29 @@
|
|||||||
tool
|
tool
|
||||||
extends FileDialog
|
extends FileDialog
|
||||||
|
|
||||||
onready var canvas = get_parent().get_node("PaintCanvasContainer/PaintCanvas")
|
onready var canvas = get_parent().get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas")
|
||||||
|
|
||||||
var file_path = ""
|
var file_path = ""
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
# warning-ignore:return_value_discarded
|
|
||||||
get_line_edit().connect("text_entered", self, "_on_LineEdit_text_entered")
|
get_line_edit().connect("text_entered", self, "_on_LineEdit_text_entered")
|
||||||
invalidate()
|
invalidate()
|
||||||
clear_filters()
|
clear_filters()
|
||||||
add_filter("*.png ; PNG Images")
|
add_filter("*.png ; PNG Images")
|
||||||
|
|
||||||
func _on_SaveFileDialog_file_selected(path):
|
func save_file():
|
||||||
file_path = path
|
canvas.image.unlock()
|
||||||
|
canvas.image.save_png(file_path)
|
||||||
|
canvas.image.lock()
|
||||||
|
|
||||||
# warning-ignore:unused_argument
|
|
||||||
func _on_LineEdit_text_entered(text):
|
func _on_LineEdit_text_entered(text):
|
||||||
save_file()
|
save_file()
|
||||||
|
|
||||||
func _on_SaveFileDialog_confirmed():
|
func _on_SaveFileDialog_confirmed():
|
||||||
save_file()
|
save_file()
|
||||||
|
|
||||||
func save_file():
|
func _on_SaveFileDialog_file_selected(path):
|
||||||
var image = Image.new()
|
file_path = path
|
||||||
image.create(canvas.canvas_size.x, canvas.canvas_size.y, true, Image.FORMAT_RGBA8)
|
|
||||||
image.lock()
|
|
||||||
for i in canvas.get_node("Chunks").get_children():
|
|
||||||
var chunk_name = i.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 = i.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
|
|
||||||
image.set_pixel(global_cell_x, global_cell_y, pixel_color)
|
|
||||||
image.unlock()
|
|
||||||
image.save_png(file_path)
|
|
||||||
|
|
||||||
func _on_SaveFileDialog_about_to_show():
|
func _on_SaveFileDialog_about_to_show():
|
||||||
invalidate()
|
invalidate()
|
||||||
|
@ -2,9 +2,9 @@ tool
|
|||||||
extends Control
|
extends Control
|
||||||
|
|
||||||
onready var editor = get_parent()
|
onready var editor = get_parent()
|
||||||
onready var canvas_outline = get_parent().get_node("PaintCanvasContainer/PaintCanvas/CanvasOutline")
|
onready var canvas_outline = get_parent().get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/CanvasOutline")
|
||||||
onready var visual_grid_1 = get_parent().get_node("PaintCanvasContainer/PaintCanvas/Grids/VisualGrid")
|
onready var visual_grid_1 = get_parent().get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/Grids/VisualGrid")
|
||||||
onready var visual_grid_2 = get_parent().get_node("PaintCanvasContainer/PaintCanvas/Grids/VisualGrid2")
|
onready var visual_grid_2 = get_parent().get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/Grids/VisualGrid2")
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
#CanvasOutline settings
|
#CanvasOutline settings
|
||||||
@ -40,4 +40,4 @@ func _on_Grids_Grid2Color_value_changed(color):
|
|||||||
visual_grid_2.color = color
|
visual_grid_2.color = color
|
||||||
|
|
||||||
func _on_Grids_Grid2Size_value_changed(value):
|
func _on_Grids_Grid2Size_value_changed(value):
|
||||||
visual_grid_2.size = value
|
visual_grid_2.size = value
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
[ext_resource path="res://addons/graphics_editor/Settings.gd" type="Script" id=1]
|
[ext_resource path="res://addons/graphics_editor/Settings.gd" type="Script" id=1]
|
||||||
|
|
||||||
[node name="Settings" type="WindowDialog"]
|
[node name="Settings" type="WindowDialog"]
|
||||||
margin_top = 20.0
|
|
||||||
margin_right = 310.0
|
margin_right = 310.0
|
||||||
margin_bottom = 320.0
|
margin_bottom = 300.0
|
||||||
window_title = "Settings"
|
window_title = "Settings"
|
||||||
script = ExtResource( 1 )
|
script = ExtResource( 1 )
|
||||||
|
|
||||||
@ -161,7 +160,7 @@ valign = 1
|
|||||||
margin_left = 210.0
|
margin_left = 210.0
|
||||||
margin_right = 284.0
|
margin_right = 284.0
|
||||||
margin_bottom = 24.0
|
margin_bottom = 24.0
|
||||||
max_value = 9999.0
|
max_value = 10000.0
|
||||||
allow_greater = true
|
allow_greater = true
|
||||||
allow_lesser = true
|
allow_lesser = true
|
||||||
|
|
||||||
@ -184,7 +183,7 @@ valign = 1
|
|||||||
margin_left = 210.0
|
margin_left = 210.0
|
||||||
margin_right = 284.0
|
margin_right = 284.0
|
||||||
margin_bottom = 24.0
|
margin_bottom = 24.0
|
||||||
max_value = 9999.0
|
max_value = 10000.0
|
||||||
allow_greater = true
|
allow_greater = true
|
||||||
allow_lesser = true
|
allow_lesser = true
|
||||||
[connection signal="pressed" from="Ok" to="." method="_on_Ok_pressed"]
|
[connection signal="pressed" from="Ok" to="." method="_on_Ok_pressed"]
|
||||||
|
@ -36,4 +36,4 @@ func update_text_info(text_name, text_value = null, node = null, node_target_val
|
|||||||
if text_value == null:
|
if text_value == null:
|
||||||
text_label.text = "%s: %s" % [text_name, null]
|
text_label.text = "%s: %s" % [text_name, null]
|
||||||
else:
|
else:
|
||||||
text_label.text = "%s: %s" % [text_name, String(text_value)]
|
text_label.text = "%s: %s" % [text_name, String(text_value)]
|
||||||
|
21
addons/graphics_editor/Tool.gd
Normal file
21
addons/graphics_editor/Tool.gd
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#Main file for the graphic editor tools!
|
||||||
|
tool
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
export var keep_running = false
|
||||||
|
export var tool_name = ""
|
||||||
|
|
||||||
|
#Common variables
|
||||||
|
onready var canvas = get_node("../../../Editor/PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas")
|
||||||
|
var util = preload("res://addons/graphics_editor/Util.gd")
|
||||||
|
var cell_mouse_position = Vector2()
|
||||||
|
var last_cell_mouse_position = Vector2()
|
||||||
|
var selected_color = Color()
|
||||||
|
var cell_color = Color()
|
||||||
|
|
||||||
|
#Dummy functions
|
||||||
|
func on_left_mouse_click():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func on_right_mouse_click():
|
||||||
|
pass
|
39
addons/graphics_editor/ToolManager.gd
Normal file
39
addons/graphics_editor/ToolManager.gd
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
tool
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
var active_tool
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func set_active_tool(tool_to_use):
|
||||||
|
var tool_manager_folder = get_script().resource_path.get_base_dir()
|
||||||
|
var tool_scripts = get_files_from_path(tool_manager_folder.plus_file("Tools"))
|
||||||
|
for i in tool_scripts:
|
||||||
|
var file_name_raw = i.get_file()
|
||||||
|
var file_extension = i.get_extension()
|
||||||
|
var file_name = file_name_raw.substr(0, file_name_raw.length()-(file_extension.length()+1))
|
||||||
|
if file_name == tool_to_use:
|
||||||
|
var node = Node.new()
|
||||||
|
node.name = file_name
|
||||||
|
var script_file = load(i)
|
||||||
|
node.set_script(script_file)
|
||||||
|
add_child(node)
|
||||||
|
active_tool = node
|
||||||
|
return node
|
||||||
|
push_error("Can't find tool from script files! Either file missing or wrong name?")
|
||||||
|
|
||||||
|
func get_active_tool():
|
||||||
|
return active_tool
|
||||||
|
|
||||||
|
func get_files_from_path(path):
|
||||||
|
var script_array = PoolStringArray()
|
||||||
|
var dir = Directory.new()
|
||||||
|
if dir.open(path) == OK:
|
||||||
|
dir.list_dir_begin()
|
||||||
|
var file_name = dir.get_next()
|
||||||
|
while (file_name != ""):
|
||||||
|
if !dir.current_is_dir():
|
||||||
|
script_array.append(path.plus_file(file_name))
|
||||||
|
file_name = dir.get_next()
|
||||||
|
return script_array
|
8
addons/graphics_editor/Tools/Bucket.gd
Normal file
8
addons/graphics_editor/Tools/Bucket.gd
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
tool
|
||||||
|
extends "../Tool.gd"
|
||||||
|
|
||||||
|
func on_left_mouse_click():
|
||||||
|
canvas.util.flood_fill(cell_mouse_position, cell_color, selected_color)
|
||||||
|
|
||||||
|
func on_right_mouse_click():
|
||||||
|
canvas.util.flood_fill(cell_mouse_position, cell_color, Color(0, 0, 0, 0))
|
8
addons/graphics_editor/Tools/Pencil.gd
Normal file
8
addons/graphics_editor/Tools/Pencil.gd
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
tool
|
||||||
|
extends "../Tool.gd"
|
||||||
|
|
||||||
|
func on_left_mouse_click():
|
||||||
|
canvas.util.set_pixels_from_line(last_cell_mouse_position, cell_mouse_position, selected_color)
|
||||||
|
|
||||||
|
func on_right_mouse_click():
|
||||||
|
canvas.util.set_pixels_from_line(last_cell_mouse_position, cell_mouse_position, Color(0, 0, 0, 0))
|
11
addons/graphics_editor/Tools/Rainbow.gd
Normal file
11
addons/graphics_editor/Tools/Rainbow.gd
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
tool
|
||||||
|
extends "../Tool.gd"
|
||||||
|
|
||||||
|
func on_left_mouse_click():
|
||||||
|
if cell_mouse_position != last_cell_mouse_position:
|
||||||
|
var points = canvas.util.get_points_from_line(last_cell_mouse_position, cell_mouse_position)
|
||||||
|
for i in points:
|
||||||
|
canvas.set_pixel(i, util.random_color_alt())
|
||||||
|
|
||||||
|
func on_right_mouse_click():
|
||||||
|
canvas.util.set_pixels_from_line(last_cell_mouse_position, cell_mouse_position, Color(0, 0, 0, 0))
|
@ -30,22 +30,16 @@ static func random_color_alt():
|
|||||||
var rand = randi() % 6
|
var rand = randi() % 6
|
||||||
|
|
||||||
match rand:
|
match rand:
|
||||||
#red
|
|
||||||
0:
|
0:
|
||||||
return Color.red
|
return Color.red
|
||||||
#blue
|
|
||||||
1:
|
1:
|
||||||
return Color.blue
|
return Color.blue
|
||||||
#green
|
|
||||||
2:
|
2:
|
||||||
return Color.green
|
return Color.green
|
||||||
#orange
|
|
||||||
3:
|
3:
|
||||||
return Color.orange
|
return Color.orange
|
||||||
#yellow
|
|
||||||
4:
|
4:
|
||||||
return Color.yellow
|
return Color.yellow
|
||||||
#purple
|
|
||||||
5:
|
5:
|
||||||
return Color.purple
|
return Color.purple
|
||||||
|
|
||||||
@ -64,4 +58,4 @@ static func printv(variable):
|
|||||||
var left_p_string = line_string.right(left_p + 1)
|
var left_p_string = line_string.right(left_p + 1)
|
||||||
var right_p = left_p_string.find(")")
|
var right_p = left_p_string.find(")")
|
||||||
var variable_name = left_p_string.left(right_p)
|
var variable_name = left_p_string.left(right_p)
|
||||||
print("%s: %s" % [variable_name, variable])
|
print("%s: %s" % [variable_name, variable])
|
||||||
|
@ -13,9 +13,9 @@ func _draw():
|
|||||||
var temp_size = size + zoom
|
var temp_size = size + zoom
|
||||||
|
|
||||||
var wrap_offset = Vector2(wrapf(offset.x, 0, temp_size), wrapf(offset.y, 0, temp_size))
|
var wrap_offset = Vector2(wrapf(offset.x, 0, temp_size), wrapf(offset.y, 0, temp_size))
|
||||||
|
|
||||||
var ceil_x = ceil(rect_size.x / temp_size) + 0.01
|
var ceil_x = floor(rect_size.x / temp_size) + 0.01
|
||||||
var ceil_y = ceil(rect_size.y / temp_size) + 0.01
|
var ceil_y = floor(rect_size.y / temp_size) + 0.01
|
||||||
|
|
||||||
for i in ceil_y:
|
for i in ceil_y:
|
||||||
var start_x = Vector2(0, (i * temp_size) + wrap_offset.y)
|
var start_x = Vector2(0, (i * temp_size) + wrap_offset.y)
|
||||||
@ -28,4 +28,4 @@ func _draw():
|
|||||||
draw_line(start_y, end_y, color, 1)
|
draw_line(start_y, end_y, color, 1)
|
||||||
|
|
||||||
func _process(delta):
|
func _process(delta):
|
||||||
update()
|
update()
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
tool
|
tool
|
||||||
extends EditorPlugin
|
extends EditorPlugin
|
||||||
|
|
||||||
|
#TODO: Make a system for setting scripts as tool scripts when running as an editor plugin
|
||||||
|
|
||||||
var editor_scene = load("res://addons/graphics_editor/Editor.tscn").instance()
|
var editor_scene = load("res://addons/graphics_editor/Editor.tscn").instance()
|
||||||
|
|
||||||
func _enter_tree():
|
func _enter_tree():
|
||||||
add_control_to_bottom_panel(editor_scene, "Graphics Editor")
|
add_control_to_bottom_panel(editor_scene, "Graphics Editor")
|
||||||
|
|
||||||
func _exit_tree():
|
func _exit_tree():
|
||||||
remove_control_from_bottom_panel(editor_scene)
|
remove_control_from_bottom_panel(editor_scene)
|
||||||
|
@ -21,7 +21,7 @@ config/icon="res://icon.png"
|
|||||||
|
|
||||||
[editor_plugins]
|
[editor_plugins]
|
||||||
|
|
||||||
enabled=PoolStringArray( "graphics_editor", "scene_notes", "todo" )
|
enabled=PoolStringArray( "todo" )
|
||||||
|
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user