Huge update!

This commit is contained in:
Flairieve 2019-11-23 05:33:43 -06:00
parent 174a3aa450
commit d2002543da
34 changed files with 1053 additions and 589 deletions

View File

@ -3,16 +3,9 @@
Made by Flairieve!
## 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!
Right now it can create basic images in a 100x100 resolution.
It is using a chunk system to keep rendering optmized!
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!
### 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.
* 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?

View 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

View File

@ -21,4 +21,4 @@ func draw_outline_box(size, color, width):
draw_line(Vector2(size.x, 0), Vector2(size.x, size.y), color, width)
func _process(delta):
update()
update()

View File

@ -13,8 +13,8 @@ func _ready():
func _process(delta):
if color_picking and not mouse_on_top:
var editor = get_node("/root/Editor")
var paint_canvas = get_node("/root/Editor/PaintCanvasContainer/PaintCanvas")
var highlighted_color = paint_canvas.get_pixel_cell_color_v(editor.cell_mouse_position)
var paint_canvas = get_node("/root/Editor/PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas")
var highlighted_color = paint_canvas.get_pixel(editor.cell_mouse_position)
if not highlighted_color == null:
color = highlighted_color

View File

@ -2,67 +2,51 @@ tool
extends Control
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 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 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
#TODO:
#Work on the brush system!
#Make a GUI Notification script!
func _ready():
#-----------------
#Setup active tool
#-----------------
tool_manager.set_active_tool("Pencil")
#---------------------------
#Setup the info bottom panel
#---------------------------
add_text_info_variables()
#--------------------
#Setup the layer tree
#--------------------
setup_layer_tree()
#------------------
#Setup visual grids
#------------------
for i in grids_node.get_children():
i.rect_size = Vector2(paint_canvas_node.canvas_size.x * grid_size, paint_canvas_node.canvas_size.y * grid_size)
grids_node.get_node("VisualGrid").size = grid_size
grids_node.get_node("VisualGrid2").size = grid_size * region_size
paint_canvas_node.connect("grid_resized", self, "grid_resized")
grid_resized(paint_canvas_node.grid_size)
#-----------------------------------
#Setup canvas node size and position
#-----------------------------------
paint_canvas_node.rect_size = Vector2(paint_canvas_node.canvas_size.x * grid_size, paint_canvas_node.canvas_size.y * grid_size)
paint_canvas_node.rect_min_size = Vector2(paint_canvas_node.canvas_size.x * grid_size, paint_canvas_node.canvas_size.y * grid_size)
#------------------------------------------------------------
#Set the selected color to what the color picker has selected
#------------------------------------------------------------
#-----------------------------------------------------------------------
#Set the selected color to what the color picker has selected as default
#-----------------------------------------------------------------------
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():
var tree = get_node("ToolMenu/Layers/Tree")
var root = tree.create_item()
tree.set_hide_root(true)
var child1 = tree.create_item(root)
child1.set_text(0, "Layers")
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"
#TODO: Make the paint canvas chunk size not a vector2?
func grid_resized(size):
grids_node.get_node("VisualGrid").rect_size = paint_canvas_node.canvas_size * size
grids_node.get_node("VisualGrid").size = size
grids_node.get_node("VisualGrid2").rect_size = paint_canvas_node.canvas_size * size
grids_node.get_node("VisualGrid2").size = size * paint_canvas_node.chunk_size.x
var mouse_position = Vector2()
var canvas_position = Vector2()
@ -71,31 +55,46 @@ var cell_mouse_position = Vector2()
var cell_region_position = Vector2()
var cell_position_in_region = Vector2()
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_canvas_position = Vector2()
var last_canvas_mouse_position = Vector2()
var last_cell_mouse_position = Vector2()
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
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
#in every update function and make it very messy
if paint_canvas_node == null:
set_process(false)
return
#Update commonly used variables
grid_size = paint_canvas_node.grid_size
region_size = paint_canvas_node.region_size
mouse_position = get_local_mouse_position()
canvas_position = paint_canvas_node.rect_position + paint_canvas_container_node.rect_position
canvas_mouse_position = Vector2(mouse_position.x - canvas_position.x, mouse_position.y - canvas_position.y)
cell_mouse_position = Vector2(floor(canvas_mouse_position.x / grid_size), floor(canvas_mouse_position.y / grid_size))
cell_region_position = Vector2(floor(cell_mouse_position.x / region_size), floor(cell_mouse_position.y / region_size))
cell_position_in_region = paint_canvas_node.get_region_from_cell(cell_mouse_position.x, cell_mouse_position.y)
cell_color = paint_canvas_node.get_pixel_cell_color(cell_mouse_position.x, cell_mouse_position.y)
process_common_used_variables()
#Process the active tool
process_active_tool()
#Process the brush drawing stuff
if paint_canvas_container_node.mouse_in_region and paint_canvas_container_node.mouse_on_top:
@ -105,12 +104,12 @@ func _process(delta):
update()
#Canvas Shift Moving
if not mouse_position == last_mouse_position:
if mouse_position != last_mouse_position:
if paint_canvas_container_node.has_focus():
if Input.is_key_pressed(KEY_SHIFT):
if Input.is_mouse_button_pressed(BUTTON_LEFT):
if Input.is_key_pressed(KEY_SHIFT) or Input.is_mouse_button_pressed(BUTTON_MIDDLE):
if Input.is_mouse_button_pressed(BUTTON_LEFT) or Input.is_mouse_button_pressed(BUTTON_MIDDLE):
var relative = mouse_position - last_mouse_position
paint_canvas_node.rect_position += relative
camera.position -= relative * camera.zoom
allow_drawing = false
else:
allow_drawing = true
@ -119,58 +118,26 @@ func _process(delta):
update_text_info()
#Update last variables with the current 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 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
process_last_common_used_variables()
func brush_process():
if Input.is_mouse_button_pressed(BUTTON_LEFT):
if allow_drawing:
if brush_mode == "paint":
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)
active_tool.on_left_mouse_click()
elif Input.is_mouse_button_pressed(BUTTON_RIGHT):
if allow_drawing:
if brush_mode == "paint" or brush_mode == "rainbow":
paint_canvas_node.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0))
if brush_mode == "bucket":
paint_canvas_node.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, Color(0, 0, 0, 0))
active_tool.on_right_mouse_click()
var zoom_amount = 0.5
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():
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("Cell Position", cell_mouse_position)
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 paint_canvas_node.last_pixel.size() > 0:
cell_color_text = paint_canvas_node.last_pixel[2]
if paint_canvas_node.last_pixel_drawn.size() > 0:
cell_color_text = paint_canvas_node.last_pixel_drawn[1]
if cell_color_text == null:
cell_color_text = Color(0, 0, 0, 0)
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)
func _on_PaintTool_pressed():
brush_mode = "paint"
tool_manager.set_active_tool("Pencil")
func _on_BucketTool_pressed():
brush_mode = "bucket"
tool_manager.set_active_tool("Bucket")
func _on_ColorPicker_color_changed(color):
selected_color = color
@ -216,4 +183,4 @@ func _on_Save_pressed():
get_node("SaveFileDialog").show()
func _on_RainbowTool_pressed():
brush_mode = "rainbow"
tool_manager.set_active_tool("Rainbow")

View File

@ -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/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/VisualGrid.tscn" type="PackedScene" id=4]
[ext_resource path="res://addons/graphics_editor/CanvasOutline.gd" type="Script" id=5]
[ext_resource path="res://addons/graphics_editor/Navbar.gd" type="Script" id=6]
[ext_resource path="res://addons/graphics_editor/MenuButtonExtended.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/TextInfo.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/Settings.tscn" type="PackedScene" id=11]
[ext_resource path="res://addons/graphics_editor/Camera2D.gd" type="Script" id=3]
[ext_resource path="res://addons/graphics_editor/PaintCanvas.tscn" type="PackedScene" id=4]
[ext_resource path="res://addons/graphics_editor/PixelCursorHighlight.gd" type="Script" id=5]
[ext_resource path="res://addons/graphics_editor/VisualGrid.tscn" type="PackedScene" id=6]
[ext_resource path="res://addons/graphics_editor/CanvasOutline.gd" type="Script" id=7]
[ext_resource path="res://addons/graphics_editor/Navbar.gd" type="Script" id=8]
[ext_resource path="res://addons/graphics_editor/MenuButtonExtended.gd" type="Script" id=9]
[ext_resource path="res://addons/graphics_editor/ColorPicker.gd" type="Script" id=10]
[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"]
anchor_right = 1.0
@ -18,8 +27,12 @@ anchor_bottom = 1.0
rect_min_size = Vector2( 1024, 300 )
rect_clip_content = true
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="PaintCanvasContainer" type="Control" parent="."]
editor/display_folded = true
show_behind_parent = true
anchor_right = 1.0
anchor_bottom = 1.0
@ -33,39 +46,76 @@ __meta__ = {
"_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_bottom = 0.0
margin_right = 1600.0
margin_bottom = 1600.0
rect_min_size = Vector2( 1600, 1600 )
[node name="Grids" type="Control" parent="PaintCanvasContainer/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"]
[node name="PixelCursorHighlight" type="Control" parent="PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas"]
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
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 )
width = 3.0
[node name="Navbar" type="Control" parent="."]
editor/display_folded = true
anchor_right = 1.0
margin_bottom = 20.0
script = ExtResource( 6 )
script = ExtResource( 8 )
[node name="Panel" type="Panel" parent="Navbar"]
anchor_right = 1.0
@ -74,15 +124,21 @@ anchor_bottom = 1.0
[node name="Buttons" type="Control" parent="Navbar"]
anchor_right = 1.0
anchor_bottom = 1.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="File" type="MenuButton" parent="Navbar/Buttons"]
margin_right = 90.0
margin_bottom = 20.0
text = "File"
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
script = ExtResource( 7 )
script = ExtResource( 9 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Editor" type="MenuButton" parent="Navbar/Buttons"]
margin_left = 90.0
@ -90,55 +146,119 @@ margin_right = 180.0
margin_bottom = 20.0
text = "Editor"
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
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="."]
editor/display_folded = true
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -114.0
margin_top = 20.0
margin_bottom = -40.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Buttons" type="Control" parent="ToolMenu"]
editor/display_folded = true
anchor_right = 1.0
margin_bottom = 310.0
[node name="PaintTool" type="Button" parent="ToolMenu/Buttons"]
anchor_right = 1.0
margin_bottom = 70.0
focus_mode = 0
enabled_focus_mode = 0
text = "Paint Tool"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="BucketTool" type="Button" parent="ToolMenu/Buttons"]
anchor_right = 1.0
margin_top = 70.0
margin_bottom = 140.0
focus_mode = 0
enabled_focus_mode = 0
text = "Bucket Tool"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="RainbowTool" type="Button" parent="ToolMenu/Buttons"]
anchor_right = 1.0
margin_top = 140.0
margin_bottom = 210.0
focus_mode = 0
enabled_focus_mode = 0
text = "Rainbow Tool"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ColorPicker" type="ColorPickerButton" parent="ToolMenu/Buttons"]
anchor_right = 1.0
margin_top = 210.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"]
anchor_right = 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_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="."]
editor/display_folded = true
@ -146,9 +266,15 @@ anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_top = -40.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TextInfo" type="Control" parent="BottomPanel"]
script = ExtResource( 9 )
script = ExtResource( 12 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="SaveFileDialog" type="FileDialog" parent="."]
anchor_left = 0.5
@ -160,9 +286,9 @@ margin_top = -165.0
margin_right = 340.0
margin_bottom = 165.0
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_top = 0.5
anchor_right = 0.5
@ -171,6 +297,46 @@ margin_left = -155.0
margin_top = -150.0
margin_right = 155.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_exited" from="PaintCanvasContainer" to="PaintCanvasContainer" method="_on_PaintCanvasContainer_mouse_exited"]
[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="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="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="confirmed" from="SaveFileDialog" to="SaveFileDialog" method="_on_SaveFileDialog_confirmed"]
[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="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"]

View 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()

View 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"]

View 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)

View 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"]

View 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()

View 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()

View File

@ -8,4 +8,4 @@ func _ready():
popup.connect("id_pressed", self, "id_pressed")
func id_pressed(id):
emit_signal("item_pressed", name, popup.get_item_text(id))
emit_signal("item_pressed", name, popup.get_item_text(id))

View File

@ -1,21 +1,38 @@
tool
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():
for i in get_node("Buttons").get_children():
i.connect("item_pressed", self, "button_pressed")
func button_pressed(button_name, button_item):
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":
get_parent().get_node("SaveFileDialog").show()
if button_item == "Quit":
get_tree().quit()
elif button_name == "Editor":
if button_item == "Settings":
get_parent().get_node("Settings").show()
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
elif button_item == "Reset Canvas Position":
get_parent().paint_canvas_node.rect_position = Vector2(0, 0)
elif button_item == "Reset Camera Position":
get_parent().camera.position = Vector2(0, 0)
elif button_name == "Image":
if button_item == "Resize":
get_parent().get_node("ExpandCanvas").show()

View 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()

View 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"]

View File

@ -1,388 +1,182 @@
tool
extends Control
var image = Image.new()
var last_pixel = []
onready var canvas_image_node = get_node("CanvasImage")
export var grid_size = 16
export var canvas_size = Vector2(100, 100)
export var region_size = 10
export var grid_size = 16 setget resize_grid
export var canvas_size = Vector2(100, 100) setget resize_canvas
export var chunk_size = Vector2(10, 10)
export var can_draw = true
onready var canvas_node = get_node("CanvasImage")
onready var util = get_node("Util")
var mouse_in_region
var mouse_on_top
#terms
#global cell - a cell that has a global grid position on the canvas
#local cell - a cell that has a local grid position in a chunk region on the canvas
#chunk region - a set of cells contained in an even number
#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")
var last_pixel_drawn = []
var image = Image.new()
var image_render = Image.new()
var image_texture = ImageTexture.new()
signal grid_resized
signal canvas_resized
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.lock()
#print(get_maxium_filled_chunks())
# for pixel_data in get_layer_data(active_layer):
# var cx = pixel_data[0]
# var cy = pixel_data[1]
# var ccolor = pixel_data[2]
# image.set_pixel(cx, cy, ccolor)
generate_chunks()
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)
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)
image.lock()
image_render.lock()
func _process(delta):
var mouse_position = get_local_mouse_position()
var rect = Rect2(Vector2(0, 0), rect_size)
mouse_in_region = rect.has_point(mouse_position)
update()
#if not Engine.editor_hint:
# print(mouse_on_canvas, " | ", has_focus())
#draw_canvas_out just updates the image constantly
#if can_draw:
# draw_canvas_out()
update_canvas()
#----------------------
#---SETGET FUNCTIONS---
#----------------------
func resize_grid(new_size):
grid_size = new_size
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():
var maxium_chunk_size = get_maxium_filled_chunks()
#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)
pass
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
#so that we don't have to call these functions
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):
func get_pixel(pos):
if not pixel_in_canvas_region(pos):
return null
for pixel in get_layer_data(active_layer):
if pixel[0] == x and pixel[1] == y:
return pixel
return image.get_pixelv(pos)
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):
return get_pixel_cell(vec2.x, vec2.y)
#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:
func pixel_in_canvas_region(pos):
if pos.x < canvas_size.x and pos.x > -1 and pos.y < canvas_size.y and pos.y > -1:
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():
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
#--------------------
#--Canvas Rendering--
#--------------------
func get_first_used_region_in_canvas():
return get_region_from_cell(0, 0)
var image_pixel_array = []
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):
var start_cell = Vector2(x * region_size, y * region_size)
var end_cell = Vector2((x * region_size) + region_size, (y * region_size) + region_size)
var cell_array = []
for cx in range(start_cell.x, end_cell.x):
for cy in range(start_cell.y, end_cell.y):
var pixel_cell = get_pixel_cell(cx, cy)
if pixel_cell == null:
pixel_cell = [cx, cy, Color(0, 0, 0, 0)]
cell_array.append(pixel_cell)
return cell_array
func load_image(image_data):
var array_data = image_data_to_array(image_data)
image.unlock()
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()
set_pixels_from_array(array_data)
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 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

View File

@ -16,4 +16,4 @@ func _on_PaintCanvasContainer_mouse_entered():
mouse_on_top = true
func _on_PaintCanvasContainer_mouse_exited():
mouse_on_top = false
mouse_on_top = false

View 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)

View 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)

View File

@ -1,47 +1,29 @@
tool
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 = ""
func _ready():
# warning-ignore:return_value_discarded
get_line_edit().connect("text_entered", self, "_on_LineEdit_text_entered")
invalidate()
clear_filters()
add_filter("*.png ; PNG Images")
func _on_SaveFileDialog_file_selected(path):
file_path = path
func save_file():
canvas.image.unlock()
canvas.image.save_png(file_path)
canvas.image.lock()
# warning-ignore:unused_argument
func _on_LineEdit_text_entered(text):
save_file()
func _on_SaveFileDialog_confirmed():
save_file()
func save_file():
var image = Image.new()
image.create(canvas.canvas_size.x, canvas.canvas_size.y, true, Image.FORMAT_RGBA8)
image.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_file_selected(path):
file_path = path
func _on_SaveFileDialog_about_to_show():
invalidate()

View File

@ -2,9 +2,9 @@ tool
extends Control
onready var editor = get_parent()
onready var canvas_outline = get_parent().get_node("PaintCanvasContainer/PaintCanvas/CanvasOutline")
onready var visual_grid_1 = get_parent().get_node("PaintCanvasContainer/PaintCanvas/Grids/VisualGrid")
onready var visual_grid_2 = get_parent().get_node("PaintCanvasContainer/PaintCanvas/Grids/VisualGrid2")
onready var canvas_outline = get_parent().get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/CanvasOutline")
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/ViewportContainer/Viewport/PaintCanvas/Grids/VisualGrid2")
func _ready():
#CanvasOutline settings
@ -40,4 +40,4 @@ func _on_Grids_Grid2Color_value_changed(color):
visual_grid_2.color = color
func _on_Grids_Grid2Size_value_changed(value):
visual_grid_2.size = value
visual_grid_2.size = value

View File

@ -3,9 +3,8 @@
[ext_resource path="res://addons/graphics_editor/Settings.gd" type="Script" id=1]
[node name="Settings" type="WindowDialog"]
margin_top = 20.0
margin_right = 310.0
margin_bottom = 320.0
margin_bottom = 300.0
window_title = "Settings"
script = ExtResource( 1 )
@ -161,7 +160,7 @@ valign = 1
margin_left = 210.0
margin_right = 284.0
margin_bottom = 24.0
max_value = 9999.0
max_value = 10000.0
allow_greater = true
allow_lesser = true
@ -184,7 +183,7 @@ valign = 1
margin_left = 210.0
margin_right = 284.0
margin_bottom = 24.0
max_value = 9999.0
max_value = 10000.0
allow_greater = true
allow_lesser = true
[connection signal="pressed" from="Ok" to="." method="_on_Ok_pressed"]

View File

@ -36,4 +36,4 @@ func update_text_info(text_name, text_value = null, node = null, node_target_val
if text_value == null:
text_label.text = "%s: %s" % [text_name, null]
else:
text_label.text = "%s: %s" % [text_name, String(text_value)]
text_label.text = "%s: %s" % [text_name, String(text_value)]

View 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

View 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

View 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))

View 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))

View 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))

View File

@ -30,22 +30,16 @@ static func random_color_alt():
var rand = randi() % 6
match rand:
#red
0:
return Color.red
#blue
1:
return Color.blue
#green
2:
return Color.green
#orange
3:
return Color.orange
#yellow
4:
return Color.yellow
#purple
5:
return Color.purple
@ -64,4 +58,4 @@ static func printv(variable):
var left_p_string = line_string.right(left_p + 1)
var right_p = left_p_string.find(")")
var variable_name = left_p_string.left(right_p)
print("%s: %s" % [variable_name, variable])
print("%s: %s" % [variable_name, variable])

View File

@ -13,9 +13,9 @@ func _draw():
var temp_size = size + zoom
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_y = ceil(rect_size.y / temp_size) + 0.01
var ceil_x = floor(rect_size.x / temp_size) + 0.01
var ceil_y = floor(rect_size.y / temp_size) + 0.01
for i in ceil_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)
func _process(delta):
update()
update()

View File

@ -1,10 +1,12 @@
tool
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()
func _enter_tree():
add_control_to_bottom_panel(editor_scene, "Graphics Editor")
func _exit_tree():
remove_control_from_bottom_panel(editor_scene)
remove_control_from_bottom_panel(editor_scene)

View File

@ -21,7 +21,7 @@ config/icon="res://icon.png"
[editor_plugins]
enabled=PoolStringArray( "graphics_editor", "scene_notes", "todo" )
enabled=PoolStringArray( "todo" )
[rendering]