changed editor to tab editor, ......

This commit is contained in:
cobrapitz 2020-10-25 18:39:10 +01:00
parent 5d231a2153
commit 6ca768ee8e
117 changed files with 3014 additions and 1684 deletions

21
.gitignore vendored
View File

@ -1,14 +1,11 @@
\exports/
\.import/
.import/
export.cfg
export_presets.cfg
addons/*
# Imported translations (automatically generated from CSV files)
*.translation
!addons/graphics_editor
scene-notes\.ini
todo\.cache\.ini
todo\.config\.ini
export_presets\.cfg
# Mono-specific ignores
.mono/
data_*/

View File

@ -0,0 +1,3 @@
source_md5="7ba250dc0369bd9ea174a98fa96fd159"
dest_md5="592d848ccf689082959787d416db762f"

View File

@ -0,0 +1,3 @@
source_md5="2117353e2e3a97b4461460d303806021"
dest_md5="35ac6bd3dfff4656d63f0245d37ed74e"

View File

@ -0,0 +1,3 @@
source_md5="47313fa4c47a9963fddd764e1ec6e4a8"
dest_md5="2ded9e7f9060e2b530aab678b135fc5b"

Binary file not shown.

View File

@ -0,0 +1,3 @@
source_md5="adad2e5a70e96772dddf92b495d1e0ed"
dest_md5="9b6188fa4147bfc4b5e5977abb8469af"

Binary file not shown.

View File

@ -0,0 +1,3 @@
source_md5="4e6da06002747457d0e002efd2f49ef8"
dest_md5="46ed73e9c81c4cac671c27036b30b777"

Binary file not shown.

View File

@ -0,0 +1,3 @@
source_md5="c4ed68c81275539e6cbf8391d88276c2"
dest_md5="f55ead5c7be937b3aacf4e61f3f1603b"

View File

@ -0,0 +1,3 @@
source_md5="7c09c98e65f6ff015128c19855d2f7fb"
dest_md5="40c2029dc0099f4030c789a32e7b84ad"

View File

@ -0,0 +1,3 @@
source_md5="99c754b29181eaddbf4461e2954e265f"
dest_md5="5771e849f36b5516b53bbbef9ceef73a"

View File

@ -0,0 +1,3 @@
source_md5="e0848eef5591cbefcdd580e2266df32a"
dest_md5="b383e9e9635223c43c25b6c9c30e158d"

View File

@ -0,0 +1,3 @@
source_md5="ed7ea9ed6750cf2fbe5141c6745f1a80"
dest_md5="b53ed83de9acfb64b40bb7e19266a861"

View File

@ -0,0 +1 @@
source_md5="be8428ecca46883304ee0a8437c6b2cc"

View File

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

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,22 +0,0 @@
The MIT License (MIT)
Copyright (c) 2019 Flairieve
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,11 +0,0 @@
# GraphicsEditor
Made by Flairieve!
## About
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:
* Images can only save in the PNG format.
* Camera is broken when running as a plugin. Godot bug?

View File

@ -0,0 +1,7 @@
[plugin]
name="Godot Plugin Refresher"
description="A toolbar addition to facilitate toggling off/on a selected plugin."
author="willnationsdev"
version="1.0"
script="plugin_refresher_plugin.gd"

View File

@ -0,0 +1,53 @@
tool
extends HBoxContainer
signal request_refresh_plugin(p_name)
signal confirm_refresh_plugin(p_name)
onready var options = $OptionButton
func _ready():
$RefreshButton.icon = get_icon('Reload', 'EditorIcons')
func update_items(p_plugins):
if not options:
return
options.clear()
var plugin_dirs = p_plugins.keys()
for idx in plugin_dirs.size():
var plugin_dirname = plugin_dirs[idx]
var plugin_name = p_plugins[plugin_dirname]
options.add_item(plugin_name, idx)
options.set_item_metadata(idx, plugin_dirname)
func select_plugin(p_name):
if not options:
return
if p_name == null or p_name.empty():
return
for idx in options.get_item_count():
var plugin = options.get_item_metadata(idx)
if plugin == p_name:
options.selected = options.get_item_id(idx)
break
func _on_RefreshButton_pressed():
if options.selected == -1:
return # nothing selected
var plugin = options.get_item_metadata(options.selected)
if not plugin or plugin.empty():
return
emit_signal("request_refresh_plugin", plugin)
func show_warning(p_name):
$ConfirmationDialog.dialog_text = """
Plugin `%s` is currently disabled.\n
Do you want to enable it now?
""" % [p_name]
$ConfirmationDialog.popup_centered()
func _on_ConfirmationDialog_confirmed():
var plugin = options.get_item_metadata(options.selected)
emit_signal('confirm_refresh_plugin', plugin)

View File

@ -0,0 +1,32 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/godot-plugin-refresher/plugin_refresher.gd" type="Script" id=1]
[node name="HBoxContainer" type="HBoxContainer"]
margin_right = 40.0
margin_bottom = 40.0
script = ExtResource( 1 )
[node name="VSeparator" type="VSeparator" parent="."]
margin_right = 4.0
margin_bottom = 40.0
[node name="OptionButton" type="OptionButton" parent="."]
margin_left = 8.0
margin_right = 158.0
margin_bottom = 40.0
rect_min_size = Vector2( 150, 0 )
[node name="RefreshButton" type="ToolButton" parent="."]
margin_left = 162.0
margin_right = 174.0
margin_bottom = 40.0
[node name="ConfirmationDialog" type="ConfirmationDialog" parent="."]
margin_right = 278.0
margin_bottom = 110.0
rect_min_size = Vector2( 300, 70 )
window_title = "Plugin Refresher"
dialog_autowrap = true
[connection signal="pressed" from="RefreshButton" to="." method="_on_RefreshButton_pressed"]
[connection signal="confirmed" from="ConfirmationDialog" to="." method="_on_ConfirmationDialog_confirmed"]

View File

@ -0,0 +1,125 @@
tool
extends EditorPlugin
const ADDONS_PATH = "res://addons/"
const PLUGIN_CONFIG_DIR = 'plugins/plugin_refresher'
const PLUGIN_CONFIG = 'settings.cfg'
const SETTINGS = 'settings'
const SETTING_RECENT = 'recently_used'
var plugin_config = ConfigFile.new()
var refresher
func _enter_tree():
refresher = preload("plugin_refresher.tscn").instance()
add_control_to_container(CONTAINER_TOOLBAR, refresher)
# Watch whether any plugin is changed, added or removed on the filesystem
var efs = get_editor_interface().get_resource_filesystem()
efs.connect("filesystem_changed", self, "_on_filesystem_changed")
refresher.connect("request_refresh_plugin", self, "_on_request_refresh_plugin")
refresher.connect("confirm_refresh_plugin", self, "_on_confirm_refresh_plugin")
_reload_plugins_list()
_load_settings()
func _exit_tree():
remove_control_from_container(CONTAINER_TOOLBAR, refresher)
refresher.free()
func _reload_plugins_list():
var refresher_dir = get_plugin_path().get_file()
var plugins = {}
var origins = {}
var dir = Directory.new()
dir.open(ADDONS_PATH)
dir.list_dir_begin(true, true)
var file = dir.get_next()
while file:
var addon_dir = ADDONS_PATH.plus_file(file)
if dir.dir_exists(addon_dir) and file != refresher_dir:
var display_name = file
var plugin_config_path = addon_dir.plus_file("plugin.cfg")
if not dir.file_exists(plugin_config_path):
continue # not a plugin
var plugin_cfg = ConfigFile.new()
plugin_cfg.load(plugin_config_path)
display_name = plugin_cfg.get_value("plugin", "name", file)
if not display_name in origins:
origins[display_name] = [file]
else:
origins[display_name].append(file)
plugins[file] = display_name
file = dir.get_next()
# Specify the exact plugin name in parenthesis in case of naming collisions.
for display_name in origins:
var plugin_names = origins[display_name]
if plugin_names.size() > 1:
for n in plugin_names:
plugins[n] = "%s (%s)" % [display_name, n]
refresher.update_items(plugins)
func _load_settings():
var path = get_config_path()
var fs = Directory.new()
if not fs.file_exists(path):
# Create new if running for the first time
var config = ConfigFile.new()
fs.make_dir_recursive(path.get_base_dir())
config.save(path)
else:
plugin_config.load(path)
func _save_settings():
plugin_config.save(get_config_path())
func get_config_path():
var dir = get_editor_interface().get_editor_settings().get_project_settings_dir()
var home = dir.plus_file(PLUGIN_CONFIG_DIR)
var path = home.plus_file(PLUGIN_CONFIG)
return path
func _on_filesystem_changed():
if refresher:
_reload_plugins_list()
refresher.select_plugin(get_recent_plugin())
func get_recent_plugin():
if not plugin_config.has_section_key(SETTINGS, SETTING_RECENT):
return null # not saved yet
var recent = plugin_config.get_value(SETTINGS, SETTING_RECENT)
return recent
func _on_request_refresh_plugin(p_name):
assert(not p_name.empty())
var disabled = not get_editor_interface().is_plugin_enabled(p_name)
if disabled:
refresher.show_warning(p_name)
else:
refresh_plugin(p_name)
func _on_confirm_refresh_plugin(p_name):
refresh_plugin(p_name)
func get_plugin_path():
return get_script().resource_path.get_base_dir()
func refresh_plugin(p_name):
print("Refreshing plugin: ", p_name)
var enabled = get_editor_interface().is_plugin_enabled(p_name)
if enabled: # can only disable an active plugin
get_editor_interface().set_plugin_enabled(p_name, false)
get_editor_interface().set_plugin_enabled(p_name, true)
plugin_config.set_value(SETTINGS, SETTING_RECENT, p_name)
_save_settings()

View File

@ -1,8 +1,21 @@
extends Node
class_name BrushPrefabs
func _ready():
print("test")
pass
func draw_pixel():
print("Drawed pixel!")
const list = [
[ Vector2(0, -1),
Vector2(-1, 0), Vector2(0, 0), Vector2(1, 0),
Vector2(0, 1)
],
[Vector2(-1, -1), Vector2(0, -1), Vector2(1, -1),
Vector2(-1, 0), Vector2(0, 0), Vector2(1, 0),
Vector2(-1, 1), Vector2(0, 1), Vector2(1, 1),
],
[
Vector2(-1, 0), Vector2(0, 0), Vector2(1, 0),
],
[ Vector2(0, -1),
Vector2(0, 0),
Vector2(0, 1)
]
]

View File

@ -1,16 +0,0 @@
#This script isn't a tool script because you can accidently move the camera while trying to edit the scene
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

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

View File

@ -1,34 +0,0 @@
tool
extends ColorPickerButton
var color_picking = false
var mouse_on_top = false
func _ready():
var color_picker = get_picker()
var color_picker_popup = get_popup()
var color_picker_button = color_picker.get_children()[0].get_children()[1]
color_picker_popup.connect("popup_hide", self, "color_picker_popup_hide")
color_picker_button.disconnect("pressed", color_picker, "_screen_pick_pressed")
color_picker_button.connect("pressed", self, "color_picker_button_pressed")
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/ViewportContainer/Viewport/PaintCanvas")
var highlighted_color = paint_canvas.get_pixel(editor.cell_mouse_position)
if not highlighted_color == null:
color = highlighted_color
func color_picker_button_pressed():
if not color_picking:
color_picking = true
func color_picker_popup_hide():
color_picking = false
func _on_ColorPicker_mouse_entered():
mouse_on_top = true
func _on_ColorPicker_mouse_exited():
mouse_on_top = false

View File

@ -0,0 +1,23 @@
tool
extends GridContainer
signal color_change_request
func _enter_tree():
for child in get_children():
child.set("custom_styles/normal", StyleBoxFlat.new())
child.get("custom_styles/normal").set("bg_color", Color(randf(), randf(), randf()))
for child in get_children():
if child.is_connected("pressed", self, "change_color_to"):
return
child.connect("pressed", self, "change_color_to", [child.get("custom_styles/normal").bg_color])
func change_color_to(color):
emit_signal("color_change_request", color)

View File

@ -0,0 +1,9 @@
extends RichTextLabel
tool
func _ready():
pass
func display_text(text):
self.text = text

View File

@ -1,21 +0,0 @@
extends Control
var util = preload("res://addons/graphics_editor/Util.gd")
func _ready():
var dialog_folder = get_script().resource_path.get_base_dir()
var files = util.get_files_from_path(dialog_folder.plus_file("Dialogs"))
for i in files:
var file_name = util.get_file_name(i)
if i.get_extension() == "tscn":
var new_scene = load(i).instance()
add_child(new_scene)
func show_dialog(dialog_name):
var dialog_node = get_node_or_null(dialog_name)
if dialog_node:
dialog_node.set_anchors_preset(PRESET_CENTER)
dialog_node.rect_position = Vector2((rect_size.x / 2) - (dialog_node.rect_size.x / 2), (rect_size.y / 2) - (dialog_node.rect_size.y / 2))
dialog_node.show()
else:
push_error("Can't load dialog! Either missing node or file?")

View File

@ -1,13 +0,0 @@
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

@ -1,53 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/graphics_editor/Dialogs/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

@ -1,30 +0,0 @@
tool
extends FileDialog
onready var canvas = get_parent().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

@ -1,13 +0,0 @@
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

@ -1,54 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/graphics_editor/Dialogs/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,32 +0,0 @@
tool
extends FileDialog
onready var canvas = get_parent().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 save_file():
canvas.image.unlock()
canvas.image.save_png(file_path)
canvas.image.lock()
func _on_LineEdit_text_entered(text):
save_file()
func _on_SaveFileDialog_confirmed():
save_file()
func _on_SaveFileDialog_file_selected(path):
file_path = path
func _on_SaveFileDialog_about_to_show():
invalidate()
func _on_SaveFileDialog_visibility_changed():
invalidate()

View File

@ -1,196 +0,0 @@
tool
extends Control
#TODO: Make the settings auto generate!
onready var editor = get_parent().get_parent()
onready var canvas_outline = editor.get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/CanvasOutline")
onready var visual_grid_1 = editor.get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/Grids/VisualGrid")
onready var visual_grid_2 = editor.get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/Grids/VisualGrid2")
onready var scroll_container = get_node("ScrollContainer")
#{
# "CATEGORY": {
# "SETTINGNAME": {
# "node": "PATHTONODE",
# "valueMod": "VALUETOMODIFY",
# "setterType": "SETTERTYPE"
# }
# }
#}
#ValueSetterType List:
#ColorPicker
#CheckButton
#SpinBox
var setting_storage = {
"Canvas Outline": {
"Enabled": {
"node": canvas_outline,
"valueMod": "visible",
"setterType": "CheckBox"
},
"Color": {
"node": canvas_outline,
"valueMod": "color",
"setterType": "ColorPicker"
},
"Width": {
"node": canvas_outline,
"valueMod": "width",
"setterType": "SpinBox"
}
},
"Grids": {
"Grid1_Color": {
"node": visual_grid_1,
"valueMod": "color",
"setterType": "ColorPicker"
},
"Grid1_Size": {
"node": visual_grid_1,
"valueMod": "grid_size",
"setterType": "SpinBox"
},
"Grid2_Color": {
"node": visual_grid_2,
"valueMod": "color",
"setterType": "ColorPicker"
},
"Grid2_Size": {
"node": visual_grid_2,
"valueMod": "grid_size",
"setterType": "SpinBox"
},
}
}
#TODO: Instead of this current system, we can make a function type of system instead like this
#generate_category(name)
#generate_property(category_name, node, valueMod) # setterType is automatically detected from the property it gets from the node
func _ready():
generate_category_container("Canvas Outline")
generate_property_container("Canvas Outline", canvas_outline, "Enabled", "visible")
generate_property_container("Canvas Outline", canvas_outline, "Color", "color")
generate_property_container("Canvas Outline", canvas_outline, "Width", "width")
generate_category_container("Grids")
generate_property_container("Grids", visual_grid_1, "Grid1 Enabled", "visible")
generate_property_container("Grids", visual_grid_1, "Grid1 Color", "color")
generate_property_container("Grids", visual_grid_1, "Grid1 Size", "size")
generate_property_container("Grids", visual_grid_2, "Grid2 Enabled", "visible")
generate_property_container("Grids", visual_grid_2, "Grid2 Color", "color")
generate_property_container("Grids", visual_grid_2, "Grid2 Size", "size")
func generate_settings():
for i in setting_storage:
generate_category_container(i)
for j in setting_storage[i]:
var valuemod = setting_storage[i][j]["valueMod"]
var settertype = setting_storage[i][j]["setterType"]
generate_property_container(i, j, valuemod, settertype)
func generate_category_container(category):
var vboxContainer = VBoxContainer.new()
vboxContainer.name = category
var label = Label.new()
label.text = category + ":"
label.valign = Label.ALIGN_CENTER
vboxContainer.add_child(label)
var vboxPropertiesContainer = VBoxContainer.new()
vboxPropertiesContainer.name = "VBoxContainer"
vboxContainer.add_child(vboxPropertiesContainer)
get_node("ScrollContainer/VBoxContainer").add_child(vboxContainer)
func generate_property_container(category, node, propertyname, valuemod):
var hbox = HBoxContainer.new()
hbox.rect_min_size = Vector2(scroll_container.rect_size.x, 20)
hbox.name = propertyname
hbox.add_constant_override("separation", 0)
var label = Label.new()
label.rect_min_size = Vector2(scroll_container.rect_size.x / 2, 20)
label.text = propertyname.capitalize()
label.align = Label.ALIGN_CENTER
label.valign = Label.ALIGN_CENTER
var settertypenode
var get_value = node.get(valuemod)
match typeof(get_value):
TYPE_INT:
settertypenode = SpinBox.new()
settertypenode.max_value = 9999
settertypenode.value = get_value
settertypenode.connect("value_changed", self, "on_setting_changed", [node, valuemod, settertypenode, "value"])
pass
TYPE_REAL:
settertypenode = SpinBox.new()
settertypenode.max_value = 9999
settertypenode.value = get_value
settertypenode.connect("value_changed", self, "on_setting_changed", [node, valuemod, settertypenode, "value"])
pass
TYPE_COLOR:
settertypenode = ColorPickerButton.new()
settertypenode.color = get_value
settertypenode.connect("color_changed", self, "on_setting_changed", [node, valuemod, settertypenode, "color"])
pass
TYPE_VECTOR2:
pass
TYPE_BOOL:
settertypenode = CheckBox.new()
settertypenode.text = "On"
settertypenode.pressed = get_value
var styleboxflat = StyleBoxFlat.new()
styleboxflat.bg_color = Color(0.254902, 0.254902, 0.254902)
settertypenode.add_stylebox_override("normal", styleboxflat)
settertypenode.add_stylebox_override("hover", styleboxflat)
settertypenode.add_stylebox_override("pressed", styleboxflat)
settertypenode.connect("pressed", self, "on_setting_changed", [null, node, valuemod, settertypenode, "pressed"])
pass
# match settertype:
# "ColorPicker":
# settertypenode = ColorPickerButton.new()
# "CheckBox":
# settertypenode = CheckBox.new()
# settertypenode.text = "On"
# var styleboxflat = StyleBoxFlat.new()
# styleboxflat.bg_color = Color(0.254902, 0.254902, 0.254902)
# settertypenode.add_stylebox_override("normal", styleboxflat)
# settertypenode.add_stylebox_override("hover", styleboxflat)
# settertypenode.add_stylebox_override("pressed", styleboxflat)
# "SpinBox":
# settertypenode = SpinBox.new()
if settertypenode == null:
push_error("Setter type not found! Returning! DEBUG_INFO: %s | %s | %s" % [node, node.name, typeof(get_value)])
return
settertypenode.rect_min_size = Vector2(scroll_container.rect_size.x / 2, 20)
hbox.add_child(label)
hbox.add_child(settertypenode)
get_node("ScrollContainer/VBoxContainer/%s/VBoxContainer" % [category]).add_child(hbox)
func _on_Ok_pressed():
hide()
func on_setting_changed(default_signal, node, value_to_get, setter, value_setter_get):
var setter_new_value = setter.get(value_setter_get)
node.set(value_to_get, setter_new_value)
func _on_CanvasOutline_Enabled_value_changed(button_pressed):
canvas_outline.visible = button_pressed
func _on_CanvasOutline_Color_value_changed(color):
canvas_outline.color = color
func _on_CanvasOutline_SpinBox_value_changed(value):
canvas_outline.width = value
func _on_Grids_Grid1Color_value_changed(color):
visual_grid_1.color = color
func _on_Grids_Grid1Size_value_changed(value):
visual_grid_1.size = value
func _on_Grids_Grid2Color_value_changed(color):
visual_grid_2.color = color
func _on_Grids_Grid2Size_value_changed(value):
visual_grid_2.size = value

View File

@ -1,35 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/graphics_editor/Dialogs/Settings.gd" type="Script" id=1]
[node name="Settings" type="WindowDialog"]
margin_top = 20.0
margin_right = 250.0
margin_bottom = 270.0
popup_exclusive = true
window_title = "Settings"
script = ExtResource( 1 )
[node name="Ok" type="Button" parent="."]
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -90.0
margin_top = -30.0
margin_right = -10.0
margin_bottom = -10.0
text = "Ok"
[node name="ScrollContainer" type="ScrollContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_right = -12.0
margin_bottom = -40.0
scroll_horizontal_enabled = false
[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"]
margin_right = 100.0
margin_bottom = 36.0
custom_constants/separation = 0
[connection signal="pressed" from="Ok" to="." method="_on_Ok_pressed"]

View File

@ -1,52 +1,139 @@
tool
extends Control
onready var paint_canvas_container_node = get_node("PaintCanvasContainer")
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
enum Tools {
PAINT,
BRUSH,
BUCKET,
RAINBOW,
LINE,
RECT,
DARKEN,
BRIGHTEN
COLORPICKER,
CUT,
}
var paint_canvas_container_node
var paint_canvas_node
var grids_node
var colors_grid
var selected_color = Color(1, 1, 1, 1)
var util = preload("res://addons/graphics_editor/Util.gd")
var textinfo
onready var grid_size = paint_canvas_node.grid_size
onready var region_size = paint_canvas_node.region_size
var allow_drawing = true
#TODO:
#Work on the brush system!
#Make a GUI Notification script!
func _ready():
#-----------------
#Setup active tool
#-----------------
tool_manager.set_active_tool("Pencil")
var _left_mouse_pressed_start_pos = Vector2()
var _previous_tool
var _layer_button_ref = {}
var _total_added_layers = 1
var selected_brush_prefab = 0
var _last_drawn_pixel = Vector2.ZERO
var _last_preview_draw_cell_pos = Vector2.ZERO
var _selection = []
var _just_cut = false
var _show_cut = false
var _cut_pos = Vector2.ZERO
var _cut_size = Vector2.ZERO
var _actions_history = [] # for undo
var _redo_history = []
var Actions = {
Tools.PAINT: load("res://addons/graphics_editor/actions/Pencil.gd").new(),
}
func _enter_tree():
#--------------------
#Setup nodes
#--------------------
paint_canvas_container_node = find_node("PaintCanvasContainer")
paint_canvas_node = paint_canvas_container_node.find_node("PaintCanvas")
grids_node = paint_canvas_node.find_node("Grids")
textinfo = find_node("DebugTextDisplay")
selected_color = find_node("ColorPicker").color
colors_grid = find_node("Colors")
#---------------------------
#Setup the info bottom panel
#---------------------------
add_text_info_variables()
set_process(true)
#--------------------
# Setup Actions
#--------------------
for key in Actions:
Actions[key].painter = paint_canvas_node
#--------------------
#connect nodes
#--------------------
if not colors_grid.is_connected("color_change_request", self, "change_color"):
colors_grid.connect("color_change_request", self, "change_color")
if not is_connected("visibility_changed", self, "_on_Editor_visibility_changed"):
connect("visibility_changed", self, "_on_Editor_visibility_changed")
#--------------------
#Setup the layer
#--------------------
var layer_container = find_node("Layers")
for child in layer_container.get_children():
if child.name == "Layer1" or child.name == "Button":
continue
print("too many children: ", child.name)
# child.queue_free()
#------------------
#Setup visual grids
#------------------
paint_canvas_node.connect("grid_resized", self, "grid_resized")
grid_resized(paint_canvas_node.grid_size)
# 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
#-----------------------------------------------------------------------
#Set the selected color to what the color picker has selected as default
#-----------------------------------------------------------------------
selected_color = get_node("ToolMenu/Buttons/ColorPicker").color
#-----------------------------------
#Setup canvas node size and position
#-----------------------------------
# paint_canvas_node.rect_size = Vector2(paint_canvas_node.canvas_size.x * grid_size,
# paint_canvas_node.canvas_size.y * grid_size)
# paint_canvas_node.rect_min_size = Vector2(paint_canvas_node.canvas_size.x * grid_size,
# paint_canvas_node.canvas_size.y * grid_size)
#----------------------------------------------------------------
#Setup is done so we can now allow the user to draw on the canvas
#----------------------------------------------------------------
paint_canvas_node.can_draw = true
#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
func _ready():
_add_init_layers()
func _add_init_layers():
var i = 0
for layer in paint_canvas_node.layers:
if layer == paint_canvas_node.preview_layer:
continue
_layer_button_ref[layer] = find_node("Layers").get_child(i)
print("layer: ", layer, " is ", find_node("Layers").get_child(i).name)
i += 1
_connect_layer_buttons()
func _input(event):
if Input.is_key_pressed(KEY_Z):
print("Z")
elif Input.is_key_pressed(KEY_Y):
print("Y")
var brush_mode = Tools.PAINT
var mouse_position = Vector2()
var canvas_position = Vector2()
@ -55,133 +142,527 @@ 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):
update_text_info()
#It's a lot more easier to just keep updating the variables in here than just have a bunch of local variables
#in every update function and make it very messy
#Update commonly used variables
process_common_used_variables()
if paint_canvas_node == null:
#_check_variables()
set_process(false)
return
#Process the active tool
process_active_tool()
#Update commonly used variables
grid_size = paint_canvas_node.grid_size
region_size = paint_canvas_node.region_size
mouse_position = paint_canvas_node.get_local_mouse_position()
canvas_position = paint_canvas_container_node.rect_position
canvas_mouse_position = Vector2(mouse_position.x - canvas_position.x, mouse_position.y - canvas_position.y)
cell_mouse_position = Vector2(floor(canvas_mouse_position.x / grid_size), floor(canvas_mouse_position.y / grid_size))
cell_region_position = Vector2(floor(cell_mouse_position.x / region_size), floor(cell_mouse_position.y / region_size))
cell_position_in_region = paint_canvas_node.get_region_from_cell(cell_mouse_position.x, cell_mouse_position.y)
cell_color = paint_canvas_node.get_pixel_cell_color(cell_mouse_position.x, cell_mouse_position.y)
#Process the brush drawing stuff
if paint_canvas_container_node.mouse_in_region and paint_canvas_container_node.mouse_on_top:
if (paint_canvas_node.mouse_in_region and paint_canvas_node.mouse_on_top) \
or paint_canvas_node.preview_enabled:
brush_process()
#Render the highlighting stuff
update()
#Canvas Shift Moving
if mouse_position != last_mouse_position:
if paint_canvas_container_node.has_focus():
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):
if not mouse_position == last_mouse_position:
if paint_canvas_node.has_focus():
if Input.is_key_pressed(KEY_SHIFT):
if Input.is_mouse_button_pressed(BUTTON_LEFT):
var relative = mouse_position - last_mouse_position
camera.position -= relative * camera.zoom
paint_canvas_node.rect_position += relative
allow_drawing = false
else:
allow_drawing = true
#Update text info
update_text_info()
#Update last variables with the current variables
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 currently_selecting = false
func _draw():
if paint_canvas_node == null:
return
if paint_canvas_node.mouse_in_region and paint_canvas_node.mouse_in_region:
#draw cell_mouse_position
if paint_canvas_node.cell_in_canvas_region(cell_mouse_position.x, cell_mouse_position.y):
draw_rect(Rect2(Vector2(
(cell_mouse_position.x * grid_size) + canvas_position.x,
(cell_mouse_position.y * grid_size) + canvas_position.y),
Vector2(grid_size, grid_size)), Color(0.8, 0.8, 0.8, 0.8), true)
func draw_outline_box(pos, size, color, width):
#Top line
draw_line(Vector2(0 + 1 + pos.x, 0 + pos.y), Vector2(pos.x + size.x, 0 + pos.y), color, width)
#Left line
draw_line(Vector2(0 + 1 + pos.x, 0 + pos.y), Vector2(0 + pos.x, pos.y + size.y), color, width)
#Bottom line
draw_line(Vector2(0 + 1 + pos.x, pos.y + size.y), Vector2(pos.x + size.x, pos.y + size.y), color, width)
#Right line
draw_line(Vector2(pos.x + size.x, 0 + pos.y), Vector2(pos.x + size.x, pos.y + size.y), color, width)
func pool_vector2_array_append_new_value(vec2array, vec2):
for i in vec2array:
if i == vec2:
return
vec2array.append(vec2)
func custom_rect_size_brush(x, y, color, size):
for cx in range(x, x + size):
for cy in range(y, y + size):
paint_canvas_node.set_pixel_cell(cx, cy, color)
pass
func _handle_cut():
if Input.is_mouse_button_pressed(BUTTON_RIGHT):
_just_cut = false
_show_cut = false
paint_canvas_node.preview_enabled = true
paint_canvas_node.clear_layer("preview")
brush_mode = _previous_tool
paint_canvas_node.preview_enabled = false
_selection = []
return
if Input.is_mouse_button_pressed(BUTTON_LEFT):
for pixel_pos in paint_canvas_node.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position):
for pixel in _selection:
var pos = pixel[0]
pos -= _cut_pos
pos += pixel_pos
paint_canvas_node.set_pixel_cell_v(pos, pixel[1])
else:
if _last_preview_draw_cell_pos == cell_mouse_position:
return
paint_canvas_node.preview_enabled = true
paint_canvas_node.clear_layer("preview")
for pixel in _selection:
var pos = pixel[0]
pos -= _cut_pos
pos += cell_mouse_position
paint_canvas_node.set_pixel_cell_v(pos, pixel[1])
paint_canvas_node.preview_enabled = false
_last_preview_draw_cell_pos = cell_mouse_position
func brush_process():
if not allow_drawing:
return
if _just_cut:
_handle_cut()
return
if Input.is_mouse_button_pressed(BUTTON_LEFT):
if allow_drawing:
active_tool.on_left_mouse_click()
do_action(Actions[brush_mode], [cell_mouse_position, last_cell_mouse_position, selected_color])
return
match brush_mode:
Tools.PAINT:
paint_canvas_node.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, selected_color)
Tools.BRUSH:
for pixel_pos in paint_canvas_node.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position):
for off in BrushPrefabs.list[selected_brush_prefab]:
paint_canvas_node.set_pixel_cell_v(pixel_pos + off, selected_color)
Tools.LINE:
paint_canvas_node.preview_enabled = true
if _left_mouse_pressed_start_pos == Vector2.ZERO:
_left_mouse_pressed_start_pos = cell_mouse_position
paint_canvas_node.clear_layer("preview")
paint_canvas_node.set_pixels_from_line(
cell_mouse_position, _left_mouse_pressed_start_pos, selected_color)
Tools.RECT:
paint_canvas_node.preview_enabled = true
if _left_mouse_pressed_start_pos == Vector2.ZERO:
_left_mouse_pressed_start_pos = cell_mouse_position
paint_canvas_node.clear_layer("preview")
var p = _left_mouse_pressed_start_pos
var s = cell_mouse_position - _left_mouse_pressed_start_pos
paint_canvas_node.set_pixels_from_line(
p, p + Vector2(s.x, 0), selected_color)
paint_canvas_node.set_pixels_from_line(
p, p + Vector2(0, s.y), selected_color)
paint_canvas_node.set_pixels_from_line(
p + s, p + s + Vector2(0, -s.y), selected_color)
paint_canvas_node.set_pixels_from_line(
p + s, p + s + Vector2(-s.x, 0), selected_color)
Tools.DARKEN:
var pixels = paint_canvas_node.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
var val = 0.9
for pixel in pixels:
if _last_drawn_pixel == pixel:
continue
_last_drawn_pixel = pixel
var new_color = paint_canvas_node.get_pixel_cell_color(pixel.x, pixel.y)
new_color.r *= val
new_color.g *= val
new_color.b *= val
paint_canvas_node.set_pixel_cell_v(pixel, new_color)
Tools.BRIGHTEN:
var pixels = paint_canvas_node.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
var val = 1.1
for pixel in pixels:
if _last_drawn_pixel == pixel:
continue
_last_drawn_pixel = pixel
var new_color = paint_canvas_node.get_pixel_cell_color(pixel.x, pixel.y)
new_color.r *= val
new_color.g *= val
new_color.b *= val
paint_canvas_node.set_pixel_cell_v(pixel, new_color)
Tools.COLORPICKER:
change_color(paint_canvas_node.get_pixel_cell_color(cell_mouse_position.x, cell_mouse_position.y))
Tools.CUT:
paint_canvas_node.preview_enabled = true
if _left_mouse_pressed_start_pos == Vector2.ZERO:
_left_mouse_pressed_start_pos = cell_mouse_position
paint_canvas_node.clear_layer("preview")
var p = _left_mouse_pressed_start_pos
var s = cell_mouse_position - _left_mouse_pressed_start_pos
var selection_color = Color(0.8, 0.8, 0.8, 0.5)
paint_canvas_node.set_pixels_from_line(
p, p + Vector2(s.x, 0), selection_color)
paint_canvas_node.set_pixels_from_line(
p, p + Vector2(0, s.y), selection_color)
paint_canvas_node.set_pixels_from_line(
p + s, p + s + Vector2(0, -s.y), selection_color)
paint_canvas_node.set_pixels_from_line(
p + s, p + s + Vector2(-s.x, 0), selection_color)
Tools.BUCKET:
paint_canvas_node.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, selected_color)
Tools.RAINBOW:
paint_canvas_node.set_random_pixels_from_line(cell_mouse_position, last_cell_mouse_position)
_:
print("no brush selected")
# paint_canvas_node.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, selected_color)
elif Input.is_mouse_button_pressed(BUTTON_RIGHT):
if allow_drawing:
active_tool.on_right_mouse_click()
match brush_mode:
Tools.PAINT:
paint_canvas_node.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0))
# Tools.BUCKET:
# paint_canvas_node.flood_fill(cell_mouse_position.x, cell_mouse_position.y, cell_color, Color(0, 0, 0, 0))
Tools.BRUSH:
for pixel_pos in paint_canvas_node.get_pixels_from_line(cell_mouse_position, last_cell_mouse_position):
for off in BrushPrefabs.list[selected_brush_prefab]:
paint_canvas_node.set_pixel_cell_v(pixel_pos + off, Color(0, 0, 0, 0))
Tools.RAINBOW:
paint_canvas_node.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0))
_:
paint_canvas_node.set_pixels_from_line(cell_mouse_position, last_cell_mouse_position, Color(0, 0, 0, 0))
if paint_canvas_node.preview_enabled:
if not Input.is_mouse_button_pressed(BUTTON_LEFT):
match brush_mode:
Tools.LINE:
paint_canvas_node.clear_layer("preview")
paint_canvas_node.preview_enabled = false
paint_canvas_node.set_pixels_from_line(
cell_mouse_position, _left_mouse_pressed_start_pos, selected_color)
_left_mouse_pressed_start_pos = Vector2.ZERO
Tools.RECT:
paint_canvas_node.clear_layer("preview")
paint_canvas_node.preview_enabled = false
var p = _left_mouse_pressed_start_pos
var s = cell_mouse_position - _left_mouse_pressed_start_pos
paint_canvas_node.set_pixels_from_line(
p, p + Vector2(s.x, 0), selected_color)
paint_canvas_node.set_pixels_from_line(
p, p + Vector2(0, s.y), selected_color)
paint_canvas_node.set_pixels_from_line(
p + s, p + s + Vector2(0, -s.y), selected_color)
paint_canvas_node.set_pixels_from_line(
p + s, p + s + Vector2(-s.x, 0), selected_color)
_left_mouse_pressed_start_pos = Vector2.ZERO
Tools.CUT:
paint_canvas_node.clear_layer("preview")
paint_canvas_node.preview_enabled = false
var p = _left_mouse_pressed_start_pos
var s = cell_mouse_position - _left_mouse_pressed_start_pos
_cut_pos = p + s / 2
_cut_size = s
for x in range(abs(s.x)+1):
for y in range(abs(s.y)+1):
var px = x
var py = y
if s.x < 0:
px *= -1
if s.y < 0:
py *= -1
var pos = p + Vector2(px, py)
var color = paint_canvas_node.get_pixel_cell_color(pos.x, pos.y)
if color.a == 0:
continue
_selection.append([pos, color])
paint_canvas_node.set_pixel_cell_v(pos, Color.transparent)
_left_mouse_pressed_start_pos = Vector2.ZERO
_just_cut = true
paint_canvas_node.preview_enabled = true
var zoom_amount = 0.5
func _input(event):
if event is InputEventMouseButton:
if event.is_pressed():
if paint_canvas_container_node.mouse_in_region and paint_canvas_container_node.mouse_on_top:
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")
textinfo.add_text_info("Mouse Position")
textinfo.add_text_info("Canvas Mouse Position")
textinfo.add_text_info("Canvas Position")
textinfo.add_text_info("Cell Position")
var cell_color_texture_rect = ColorRect.new()
cell_color_texture_rect.name = "Cell Color"
cell_color_texture_rect.rect_size = Vector2(14, 14)
cell_color_texture_rect.rect_position.x = 120
textinfo.add_text_info("Cell Color", cell_color_texture_rect)
textinfo.add_text_info("Cell Region")
textinfo.add_text_info("Cell Position in Region")
func update_text_info():
textinfo.update_text_info("FPS", Engine.get_frames_per_second())
textinfo.update_text_info("Mouse Position", mouse_position)
textinfo.update_text_info("Canvas Mouse Position", canvas_mouse_position)
textinfo.update_text_info("Canvas Position", canvas_position)
textinfo.update_text_info("Cell Position", cell_mouse_position)
var text = ""
var cell_color_text = cell_color
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_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)
textinfo.update_text_info("Cell Region", cell_region_position)
textinfo.update_text_info("Cell Position in Region", cell_position_in_region)
# if paint_canvas_node.mouse_in_region and paint_canvas_container_node.mouse_on_top:
# if Input.is_mouse_button_pressed(BUTTON_LEFT) or Input.is_mouse_button_pressed(BUTTON_RIGHT):
# if paint_canvas_node.last_pixel.size() > 0:
# cell_color_text = paint_canvas_node.last_pixel[2]
cell_color_text = Color(0, 0, 0, 0)
text += \
str("FPS %s\t" + \
"Mouse Position %s\t" + \
"Canvas Mouse Position %s \t" + \
"Canvas Position %s\t\n" + \
"Cell Position %s \t" + \
"Cell Color %s\t" + \
"Cell Region %s \t" + \
"Cell Position %s\t") % [
str(Engine.get_frames_per_second()),
str(mouse_position),
str(canvas_mouse_position),
str(canvas_position),
str(cell_mouse_position),
str(cell_color_text),
str(cell_region_position),
str(cell_position_in_region),
]
find_node("DebugTextDisplay").display_text(text)
func _on_PaintTool_pressed():
tool_manager.set_active_tool("Pencil")
func _on_BucketTool_pressed():
tool_manager.set_active_tool("Bucket")
func select_layer(layer_name: String):
print("select layer: ", layer_name)
paint_canvas_node.active_layer = layer_name
func _on_ColorPicker_color_changed(color):
selected_color = color
func _on_Save_pressed():
get_node("SaveFileDialog").show()
#---------------------------------------
# Actions
#---------------------------------------
func do_action(action, data: Array):
_actions_history.push_back(action)
action.do_action(data)
_redo_history.clear()
func redo_action():
pass
func undo_action():
var action = _actions_history.pop_back()
_redo_history.append(action)
action.undo_action()
#---------------------------------------
# Brushes
#---------------------------------------
func set_brush(new_mode):
if brush_mode == new_mode:
return
_previous_tool = brush_mode
brush_mode = new_mode
func change_color(new_color):
if new_color.a == 0:
return
selected_color = new_color
find_node("ColorPicker").color = selected_color
func _on_ColorPicker_color_changed(color):
selected_color = color
func _on_PaintTool_pressed():
brush_mode = Tools.PAINT
func _on_BucketTool_pressed():
brush_mode = Tools.BUCKET
func _on_RainbowTool_pressed():
tool_manager.set_active_tool("Rainbow")
set_brush(Tools.RAINBOW)
func _on_BrushTool_pressed():
var prev_mode = brush_mode
set_brush(Tools.BRUSH)
if prev_mode != brush_mode:
return
selected_brush_prefab += 1
selected_brush_prefab = selected_brush_prefab % BrushPrefabs.list.size()
var value = float(selected_brush_prefab) / BrushPrefabs.list.size()
find_node("BrushTool").get("custom_styles/normal").set("bg_color", Color(value, value, value, 1.0))
func _on_LineTool_pressed():
set_brush(Tools.LINE)
func _on_RectTool_pressed():
set_brush(Tools.RECT)
func _on_DarkenTool_pressed():
set_brush(Tools.DARKEN)
func _on_BrightenTool_pressed():
set_brush(Tools.BRIGHTEN)
func _on_ColorPickerTool_pressed():
set_brush(Tools.COLORPICKER)
func _on_CutTool_pressed():
set_brush(Tools.CUT)
func _on_Editor_visibility_changed():
pause_mode = not visible
func _connect_layer_buttons():
for layer_btn in get_tree().get_nodes_in_group("layer"):
if layer_btn.is_connected("pressed", self, "select_layer"):
continue
layer_btn.connect("pressed", self, "select_layer", [get_layer_by_button_name(layer_btn.name)])
layer_btn.find_node("Visible").connect("pressed", self, "toggle_layer_visibility",
[layer_btn.find_node("Visible"), get_layer_by_button_name(layer_btn.name)])
layer_btn.find_node("Up").connect("pressed", self, "move_up", [layer_btn])
layer_btn.find_node("Down").connect("pressed", self, "move_down", [layer_btn])
func toggle_layer_visibility(button, layer_name: String):
print("toggling: ", layer_name)
print(paint_canvas_node.layers.keys())
paint_canvas_node.toggle_layer_visibility(layer_name)
func add_new_layer():
var layers = get_tree().get_nodes_in_group("layer")
var new_layer = layers.back().duplicate()
find_node("Layers").add_child_below_node(layers.back(), new_layer, true)
_total_added_layers += 1
new_layer.text = "Layer " + str(_total_added_layers)
var new_layer_name = paint_canvas_node.add_new_layer(new_layer.name)
_layer_button_ref[new_layer_name] = new_layer
_connect_layer_buttons()
print("added layer: ", new_layer_name, "(total:", layers.size(), ")")
func remove_active_layer():
if _layer_button_ref.size() < 2:
return
_layer_button_ref[paint_canvas_node.active_layer].get_parent().remove_child(_layer_button_ref[paint_canvas_node.active_layer])
_layer_button_ref[paint_canvas_node.active_layer].queue_free()
_layer_button_ref.erase(paint_canvas_node.active_layer)
paint_canvas_node.remove_layer(paint_canvas_node.active_layer)
func duplicate_active_layer():
# copy the last layer button (or the initial one)
var layer_buttons = get_tree().get_nodes_in_group("layer")
var new_layer_button = layer_buttons.back().duplicate()
find_node("Layers").add_child_below_node(layer_buttons.back(), new_layer_button, true)
_total_added_layers += 1 # for keeping track...
new_layer_button.text = "Layer " + str(_total_added_layers)
var new_layer_name = paint_canvas_node.duplicate_layer(paint_canvas_node.active_layer, new_layer_button.name)
_layer_button_ref[new_layer_name] = new_layer_button
_connect_layer_buttons()
print("added layer: ", new_layer_name, " (total:", layer_buttons.size(), ")")
func get_layer_by_button_name(button_name: String):
for layer_name in _layer_button_ref:
var button = _layer_button_ref[layer_name]
if button.name == button_name:
return layer_name
return null
func move_down(layer_btn, button_name: String):
print("move_up: ", button_name)
var layer_name = get_layer_by_button_name(button_name)
var chunk_node = paint_canvas_node.layers[layer_name].chunks
chunk_node.get_parent().move_child(chunk_node, max(chunk_node.get_index() + 1, 0))
layer_btn.get_parent().move_child(layer_btn, max(layer_btn.get_index() + 1, 0))
func move_up(layer_btn, button_name: String):
print("move_up: ", button_name)
var layer_name = get_layer_by_button_name(button_name)
var chunk_node = paint_canvas_node.layers[layer_name].chunks
chunk_node.get_parent().move_child(chunk_node,
min(chunk_node.get_index() - 1, chunk_node.get_parent().get_child_count() - 1))
layer_btn.get_parent().move_child(layer_btn,
min(layer_btn.get_index() - 1, layer_btn.get_parent().get_child_count() - 1))
func _on_Button_pressed():
add_new_layer()

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +0,0 @@
tool
extends Control
onready var layers = get_node("../../../../")
onready var canvas = layers.canvas
var image_storage = Image.new() setget set_image_storage
var layer_visible = true setget set_layer_visible
func _ready():
var canvas_size = canvas.image.get_size()
image_storage.create(canvas_size.x, canvas_size.y, true, Image.FORMAT_RGBA8)
func set_image_storage(image_data):
image_storage = image_data
var texture = ImageTexture.new()
texture.create_from_image(image_data)
texture.set_flags(0)
texture.setup_local_to_scene()
get_node("LayerPreview/TextureRect").texture = texture
func set_layer_visible(value):
layer_visible = value
if layer_visible:
get_node("Visible").modulate = Color(1, 1, 1)
else:
get_node("Visible").modulate = Color(0.572549, 0.572549, 0.572549)
func _on_LayerButton_pressed():
layers.active_layer = name
func _on_Visible_pressed():
set_layer_visible(!layer_visible)
func _on_Delete_pressed():
layers.remove_layer(name)

View File

@ -1,68 +0,0 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://addons/graphics_editor/Layer.gd" type="Script" id=1]
[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="LayerPreview" type="ColorRect" parent="."]
margin_left = 10.0
margin_top = 20.0
margin_right = 74.0
margin_bottom = 84.0
mouse_filter = 2
color = Color( 0.329412, 0.329412, 0.329412, 1 )
[node name="TextureRect" type="TextureRect" parent="LayerPreview"]
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 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,70 @@
[gd_scene load_steps=6 format=2]
[ext_resource path="res://addons/graphics_editor/assets/minidotta_invis.png" type="Texture" id=1]
[ext_resource path="res://addons/graphics_editor/assets/minidotta.png" type="Texture" id=2]
[ext_resource path="res://addons/graphics_editor/assets/arrow_down.png" type="Texture" id=3]
[ext_resource path="res://addons/graphics_editor/assets/arrow_up.png" type="Texture" id=4]
[sub_resource type="StyleBoxFlat" id=1]
bg_color = Color( 0.25098, 0.25098, 0.25098, 1 )
[node name="Layer1" type="Button" groups=[
"layer",
]]
margin_right = 114.0
margin_bottom = 20.0
rect_min_size = Vector2( 0, 32 )
custom_styles/hover = SubResource( 1 )
custom_styles/pressed = SubResource( 1 )
custom_styles/focus = SubResource( 1 )
custom_styles/disabled = SubResource( 1 )
custom_styles/normal = SubResource( 1 )
text = "Layer 1"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Visible" type="CheckButton" parent="."]
anchor_top = 0.5
anchor_bottom = 0.5
margin_top = -12.0
margin_right = 28.0
margin_bottom = 12.0
custom_icons/off = ExtResource( 1 )
custom_icons/on = ExtResource( 2 )
pressed = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="VBoxContainer" type="VBoxContainer" parent="."]
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -20.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Up" type="TextureButton" parent="VBoxContainer"]
margin_right = 20.0
margin_bottom = 14.0
rect_min_size = Vector2( 20, 0 )
size_flags_horizontal = 3
size_flags_vertical = 3
texture_normal = ExtResource( 4 )
texture_pressed = ExtResource( 2 )
expand = true
stretch_mode = 3
[node name="Down" type="TextureButton" parent="VBoxContainer"]
margin_top = 18.0
margin_right = 20.0
margin_bottom = 32.0
rect_min_size = Vector2( 20, 0 )
size_flags_horizontal = 3
size_flags_vertical = 3
texture_normal = ExtResource( 3 )
texture_pressed = ExtResource( 2 )
expand = true
stretch_mode = 3

View File

@ -1,70 +0,0 @@
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()
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
var num_increase = 1
func increase_number_string(array, name_string):
var name_to_return = "%s %s" % [name_string, num_increase]
num_increase += 1
return name_to_return
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):
var layer_children = layer_list.get_children()
if layer_children.size() <= 1:
print("There needs to be an active layer always!")
return
for i in layer_children.size():
if layer_children[i].name == layer_name:
if layer_children[i].name == active_layer:
if layer_children.size() != i+1:
set_active_layer(layer_children[i+1].name)
else:
set_active_layer(layer_children[i-1].name)
layer_children[i].queue_free()

View File

@ -9,3 +9,5 @@ func _ready():
func id_pressed(id):
emit_signal("item_pressed", name, popup.get_item_text(id))

View File

@ -1,66 +1,84 @@
tool
extends Control
var navbar_storage = {
"File": {
"items": ["New", "Load", "Save", "Quit"],
"export_only": ["Quit"]
},
"Editor": {
"items": ["Settings", "Toggle Grid", "Reset Camera Position"],
},
"Image": {
"items": ["Resize"]
}
}
onready var dialogs = get_parent().get_node("Dialogs")
var editor
var paint_canvas
func _ready():
var x_to_add = 0
var menu_button_script = load("res://addons/graphics_editor/MenuButtonExtended.gd")
for i in navbar_storage:
var menu_button = MenuButton.new()
menu_button.name = i
menu_button.rect_size = Vector2(90, 20)
menu_button.rect_position = Vector2(x_to_add, 0)
x_to_add += menu_button.rect_size.x
menu_button.switch_on_hover = true
menu_button.flat = false
menu_button.text = i
menu_button.set_script(menu_button_script)
var items_to_remove = []
if Engine.editor_hint:
if navbar_storage[i].get("export_only"):
for j in navbar_storage[i]["export_only"]:
items_to_remove.append(j)
if navbar_storage[i].get("items"):
for j in navbar_storage[i]["items"]:
var item_index = items_to_remove.find(j)
if item_index == -1:
menu_button.get_popup().add_item(j)
get_node("Buttons").add_child(menu_button)
editor = owner
paint_canvas = editor.find_node("PaintCanvas")
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":
dialogs.show_dialog("NewImage")
if button_item == "Load":
dialogs.show_dialog("LoadFileDialog")
if button_item == "Save":
dialogs.show_dialog("SaveFileDialog")
if button_item == "Quit":
get_tree().quit()
elif button_name == "Editor":
if button_item == "Settings":
dialogs.show_dialog("Settings")
elif button_item == "Toggle Grid":
var grids_node = get_parent().get_node("PaintCanvasContainer/ViewportContainer/Viewport/PaintCanvas/Grids")
print("pressed: ", button_name)
print("pressed item is: '%s'" % button_item)
match button_name:
"File":
handle_file_menu(button_item)
"Edit":
handle_edit_menu(button_item)
"Canvas":
handle_canvas_menu(button_item)
"Layer":
handle_layer_menu(button_item)
"Grid":
handle_grid_menu(button_item)
"Magic":
handle_magic_menu(button_item)
"Editor":
handle_editor_menu(button_item)
func handle_file_menu(pressed_item: String):
match pressed_item:
"Save":
owner.get_node("SaveFileDialog").show()
func handle_edit_menu(pressed_item: String):
match pressed_item:
"Add Layer":
editor.add_new_layer()
func handle_canvas_menu(pressed_item: String):
match pressed_item:
"Add Layer":
editor.add_new_layer()
func handle_layer_menu(pressed_item: String):
match pressed_item:
"Add Layer":
editor.add_new_layer()
"Delete Layer":
editor.remove_active_layer()
"Duplicate Layer":
editor.duplicate_active_layer()
func handle_grid_menu(pressed_item: String):
match pressed_item:
"Add Layer":
editor.add_new_layer()
func handle_magic_menu(pressed_item: String):
match pressed_item:
"Add Layer":
editor.add_new_layer()
func handle_editor_menu(pressed_item: String):
match pressed_item:
"Settings":
owner.get_node("Settings").show()
"Toggle Grid":
var grids_node = owner.find_node("Grids")
grids_node.visible = !grids_node.visible
elif button_item == "Reset Camera Position":
get_parent().camera.position = Vector2(0, 0)
elif button_name == "Image":
if button_item == "Resize":
dialogs.show_dialog("ExpandCanvas")
"Reset Canvas Position":
owner.paint_canvas_node.rect_position = Vector2(0, 0)

View File

@ -1,14 +0,0 @@
extends Control
var message
var time
func _ready():
get_node("Label").text = message
get_node("Timer").start(time)
func _on_Timer_timeout():
queue_free()
func _on_Button_pressed():
queue_free()

View File

@ -1,38 +0,0 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/graphics_editor/Notification.gd" type="Script" id=1]
[node name="Notification" type="Control"]
margin_right = 200.0
margin_bottom = 100.0
rect_min_size = Vector2( 0, 100 )
mouse_filter = 2
script = ExtResource( 1 )
[node name="Panel" type="ColorRect" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
mouse_filter = 2
color = Color( 0.501961, 0.501961, 0.501961, 0.27451 )
[node name="Label" type="Label" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 10.0
margin_top = 10.0
margin_right = -40.0
margin_bottom = -10.0
text = "Notifcation Test!"
[node name="Button" type="Button" parent="."]
anchor_left = 1.0
anchor_right = 1.0
margin_left = -30.0
margin_top = 10.0
margin_right = -10.0
margin_bottom = 30.0
text = "X"
[node name="Timer" type="Timer" parent="."]
one_shot = true
[connection signal="pressed" from="Button" to="." method="_on_Button_pressed"]

View File

@ -1,22 +0,0 @@
extends Control
var limit = 3
var notification_storage = []
func create(message, time):
var msg_scene = load("res://addons/graphics_editor/Notification.tscn").instance()
msg_scene.message = message
msg_scene.time = time
if get_node("VBoxContainer").get_children().size() >= limit:
notification_storage.push_back([message, time])
return
msg_scene.connect("tree_exited", self, "notification_deleted")
get_node("VBoxContainer").add_child(msg_scene)
get_node("VBoxContainer").move_child(msg_scene, 0)
func notification_deleted():
if get_node("VBoxContainer").get_children().size() <= limit:
if notification_storage.size() > 0:
create(notification_storage[0][0], notification_storage[0][1])
notification_storage.remove(0)

View File

@ -1,182 +1,490 @@
tool
extends Control
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)
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(48, 28)
export var region_size = 10
export var can_draw = true
onready var canvas_node = get_node("CanvasImage")
onready var util = get_node("Util")
var mouse_in_region
var last_pixel_drawn = []
var image = Image.new()
var image_render = Image.new()
var image_texture = ImageTexture.new()
signal grid_resized
signal canvas_resized
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 = {}
var active_layer
var preview_layer = "preview"
var preview_enabled = false
func _enter_tree():
#----------------------
# init Layer
#----------------------
layers[preview_layer] = {
"layer": null,
"data": [],
"chunks": null,
}
canvas_size = Vector2(int(rect_size.x / grid_size), int(rect_size.y / grid_size))
print("canvas_size: ", canvas_size)
func _ready():
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()
active_layer = add_existing_layer(get_tree().get_nodes_in_group("layer")[0])
print("active Layer: ", active_layer)
func get_layer_data(layer_name):
return layers[layer_name]
func get_active_layer():
return layers[active_layer]
func get_preview_layer():
return layers[preview_layer]
func clear_active_layer():
for pixel in layers[active_layer].data:
set_global_cell_in_chunk(pixel[0], pixel[1], Color(0,0,0,0))
func clear_layer(layer_name: String):
for pixel in layers[layer_name].data:
set_global_cell_in_chunk(pixel[0], pixel[1], Color(0,0,0,0))
func clear_preview_layer():
for pixel in layers["preview"].data:
set_global_cell_in_chunk(pixel[0], pixel[1], Color(0,0,0,0))
func remove_layer(layer_name):
get_node("ChunkNodes").remove_child(layers[layer_name].chunks)
layers[layer_name].chunks.queue_free()
layers.erase(layer_name)
if active_layer == layer_name:
for layer in layers:
if layer == preview_layer:
continue
active_layer = layer
break
return active_layer
# only needed for init
func add_existing_layer(layer):
layers[layer.name] = {
"layer": layer,
"data": [],
"chunks": null,
}
generate_chunks()
return layer.name
func add_new_layer(layer_name):
layers[layer_name] = {
"layer": null,
"data": [],
"chunks": null,
}
generate_chunks()
return layer_name
func duplicate_layer(layer: String, neu_layer_name: String):
var _preview = preview_enabled
preview_enabled = false
var _temp = active_layer
active_layer = neu_layer_name
layers[neu_layer_name] = {
"layer": null,
"data": layers[layer].data.duplicate(true),
"chunks": null,
}
generate_chunks()
# get_node("ChunkNodes").remove_child(layers[neu_layer_name].chunks)
# get_node("ChunkNodes").add_child_below_node(layers[layer].chunks, layers[neu_layer_name].chunks, true)
for pixel in layers[neu_layer_name].data:
set_pixel_cell(pixel[0], pixel[1], pixel[2])
active_layer = _temp
preview_enabled = _preview
return neu_layer_name
func toggle_layer_visibility(layer_name):
layers[layer_name].chunks.visible = not layers[layer_name].chunks.visible
print("Layer: ", layer_name, " is now: ", layers[layer_name].chunks.visible)
var util = preload("res://addons/graphics_editor/Util.gd")
func _on_mouse_entered():
mouse_on_top = true
func _on_mouse_exited():
mouse_on_top = false
func _process(delta):
update_canvas()
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()
#----------------------
#---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():
pass
var maxium_chunk_size = get_maxium_filled_chunks()
#TODO: We probably don't need to check for x and y anymore
for key in layers:
if layers[key].chunks != null:
continue
var chunk_node = Control.new()
get_node("ChunkNodes").add_child(chunk_node)
chunk_node.owner = self
layers[key].chunks = chunk_node
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 * (grid_size * region_size), y * (grid_size * region_size))
layers[key].chunks.add_child(paint_canvas_chunk)
#---------------------
#---PIXEL FUNCTIONS---
#---------------------
func get_pixel(pos):
if not pixel_in_canvas_region(pos):
func get_maxium_filled_chunks():
return Vector2(canvas_size.x / region_size, canvas_size.y / region_size).ceil()
#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
if preview_enabled:
chunk_node = layers.preview.chunks.get_node_or_null("C-%s-%s" % [chunk_x, chunk_y])
else:
chunk_node = layers[active_layer].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 active_layer == null:
return
if not cell_in_canvas_region(x, y):
return null
return image.get_pixelv(pos)
func set_pixel(pos, color):
if not pixel_in_canvas_region(pos):
return null
for pixel in get_active_layer().data:
if pixel[0] == x and pixel[1] == y:
return pixel
last_pixel_drawn = [pos, color]
return image.set_pixelv(pos, color)
return null
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:
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
if preview_enabled:
layer = get_preview_layer()
else:
layer = get_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 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
var flood_fill_queue = 0
func flood_fill(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 >= 500:
print(flood_fill_queue)
yield(get_tree().create_timer(0.01), "timeout")
#up
if get_pixel_cell_color(x, y - 1) == target_color:
flood_fill(x, y - 1, target_color, replacement_color)
#down
if get_pixel_cell_color(x, y + 1) == target_color:
flood_fill(x, y + 1, target_color, replacement_color)
#left
if get_pixel_cell_color(x - 1, y) == target_color:
flood_fill(x - 1, y, target_color, replacement_color)
#right
if get_pixel_cell_color(x + 1, y) == target_color:
flood_fill(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 false
#--------------------
#--Canvas Rendering--
#--------------------
#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
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_first_used_region_in_canvas():
return get_region_from_cell(0, 0)
#---------------------
#---IMAGE FUNCTIONS---
#---------------------
func get_last_used_region_in_canvas():
return get_region_from_cell(canvas_size.x - 1, canvas_size.y - 1)
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
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

File diff suppressed because one or more lines are too long

View File

@ -20,11 +20,8 @@ func set_cell(x, y, color):
image.set_pixel(x, y, color)
update_chunk()
func get_cell(x, y):
return image.get_pixel(x, y)
func _on_VisibilityNotifier2D_screen_entered():
visible = true
func _on_VisibilityNotifier2D_screen_exited():
visible = false
visible = false

View File

@ -1,19 +1,2 @@
tool
extends Control
var mouse_in_region
var mouse_on_top
func _ready():
pass
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)
func _on_PaintCanvasContainer_mouse_entered():
mouse_on_top = true
func _on_PaintCanvasContainer_mouse_exited():
mouse_on_top = false

View File

@ -1,88 +0,0 @@
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

@ -1,14 +0,0 @@
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

@ -0,0 +1,83 @@
tool
extends FileDialog
var canvas
var file_path = ""
func _enter_tree():
canvas = get_parent().find_node("PaintCanvas")
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
# 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()
var preview_layer_chunk_node = canvas.get_preview_layer().chunks
for chunks_node in canvas.get_node("ChunkNodes").get_children():
if chunks_node.name == preview_layer_chunk_node.name:
continue
if not chunks_node.visible:
continue
for chunk in chunks_node.get_children():
var chunk_name = chunk.name
var chunk_name_split = chunk_name.split("-")
var chunk_x = int(chunk_name_split[1])
var chunk_y = int(chunk_name_split[2])
var chunk_image = chunk.image.duplicate()
chunk_image.lock()
var chunk_image_size = chunk_image.get_size()
for x in chunk_image_size.x:
for y in chunk_image_size.y:
var pixel_color = chunk_image.get_pixel(x, y)
var global_cell_x = (chunk_x * canvas.region_size) + x
var global_cell_y = (chunk_y * canvas.region_size) + y
if image.get_height() <= global_cell_y:
continue
if image.get_width() <= global_cell_x:
continue
if global_cell_x > canvas.canvas_size.x:
continue
if global_cell_y > canvas.canvas_size.y:
continue
image.lock()
var current_color = image.get_pixel(global_cell_x, global_cell_y)
if current_color.a != 0:
image.set_pixel(global_cell_x, global_cell_y, current_color.blend(pixel_color))
else:
image.set_pixel(global_cell_x, global_cell_y, pixel_color)
image.unlock()
image.save_png(file_path)
func _on_SaveFileDialog_about_to_show():
invalidate()
func _on_SaveFileDialog_visibility_changed():
invalidate()

View File

@ -21,4 +21,4 @@ func draw_outline_box(size, color, width):
#Bottom line
draw_line(Vector2(0 + 1, size.y), Vector2(size.x, size.y), color, width)
#Right line
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)

View File

@ -0,0 +1,36 @@
tool
extends Control
var editor
var canvas_outline
var start_time
var end_time
func _enter_tree():
canvas_outline = get_parent().find_node("CanvasOutline")
editor = get_parent()
func _ready():
#start_time = OS.get_ticks_msec()
return
get_node("CanvasOutlineToggle/CheckButton").pressed = canvas_outline.visible
get_node("CanvasOutlineColor/ColorPickerButton").color = canvas_outline.color
func _process(delta):
# if get_parent().paint_canvas_node != null:
# canvas_outline = get_parent().paint_canvas_node.get_node("CanvasOutline")
# end_time = OS.get_ticks_msec()
# print("[Settings] Found Editor node in %s seconds!" % [(end_time - start_time) / float(1000)])
# set_process(false)
pass
func _on_ColorPickerButton_color_changed(color):
canvas_outline.color = color
func _on_CheckButton_toggled(button_pressed):
canvas_outline.visible = button_pressed
func _on_Ok_pressed():
hide()

View File

@ -0,0 +1,62 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/graphics_editor/Settings.gd" type="Script" id=1]
[node name="Settings" type="WindowDialog"]
margin_top = 20.0
margin_right = 300.0
margin_bottom = 120.0
window_title = "Settings"
script = ExtResource( 1 )
[node name="Ok" type="Button" parent="."]
margin_left = 210.0
margin_top = 70.0
margin_right = 290.0
margin_bottom = 90.0
text = "Ok"
[node name="CanvasOutlineToggle" type="Control" parent="."]
margin_left = 10.0
margin_top = 10.0
margin_right = 290.0
margin_bottom = 30.0
__meta__ = {
"_edit_group_": true
}
[node name="Label" type="Label" parent="CanvasOutlineToggle"]
margin_right = 130.0
margin_bottom = 20.0
text = "Canvas Outline:"
valign = 1
[node name="CheckButton" type="CheckButton" parent="CanvasOutlineToggle"]
margin_left = 210.0
margin_top = -10.0
margin_right = 286.0
margin_bottom = 30.0
pressed = true
[node name="CanvasOutlineColor" type="Control" parent="."]
margin_left = 10.0
margin_top = 40.0
margin_right = 290.0
margin_bottom = 60.0
__meta__ = {
"_edit_group_": true
}
[node name="Label" type="Label" parent="CanvasOutlineColor"]
margin_right = 130.0
margin_bottom = 20.0
text = "Canvas Outline Color:"
valign = 1
[node name="ColorPickerButton" type="ColorPickerButton" parent="CanvasOutlineColor"]
margin_left = 170.0
margin_right = 280.0
margin_bottom = 20.0
[connection signal="pressed" from="Ok" to="." method="_on_Ok_pressed"]
[connection signal="toggled" from="CanvasOutlineToggle/CheckButton" to="." method="_on_CheckButton_toggled"]
[connection signal="color_changed" from="CanvasOutlineColor/ColorPickerButton" to="." method="_on_ColorPickerButton_color_changed"]

View File

@ -1,21 +0,0 @@
#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

@ -1,38 +0,0 @@
tool
extends Node
var util = preload("res://addons/graphics_editor/Util.gd")
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 = util.get_files_from_path(tool_manager_folder.plus_file("Tools"))
for i in tool_scripts:
var file_name = util.get_file_name(i)
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

@ -1,8 +0,0 @@
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

@ -1,8 +0,0 @@
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

@ -1,11 +0,0 @@
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

@ -1,21 +1,6 @@
tool
extends Node
class time_debug:
var start_time = 0.0
var end_time = 0.0
func start():
start_time = OS.get_ticks_msec()
return start_time
func end():
end_time = OS.get_ticks_msec()
return end_time
func get_time_passed():
return end_time - start_time
static func color_from_array(color_array):
var r = color_array[0]
var g = color_array[1]
@ -30,40 +15,28 @@ 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
static func get_line_string(file, number):
return file.get_as_text().split("\n")[number - 1].strip_edges()
static func get_file_name(path):
var file_name_raw = path.get_file()
var file_extension = path.get_extension()
var file_name = file_name_raw.substr(0, file_name_raw.length()-(file_extension.length()+1))
return file_name
static func get_files_from_path(path):
var file_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():
file_array.append(path.plus_file(file_name))
file_name = dir.get_next()
return file_array
static func printv(variable):
var stack = get_stack()[get_stack().size() - 1]
var line = stack.line

View File

@ -1,9 +1,8 @@
extends ViewportContainer
func _ready():
print(name)
pass
func _notification(what):
if what == Control.NOTIFICATION_RESIZED:
get_node("Viewport").size = rect_size
get_node("Viewport/Node2D/Camera2D").position = Vector2(rect_size.x / 2, rect_size.y / 2)
pass

View File

@ -6,6 +6,11 @@ export var size = 16
export var zoom = 0
export var offset = Vector2(0, 0)
func _enter_tree():
set_process(true)
func _draw():
if size == 0:
size = 1
@ -13,19 +18,22 @@ 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 = floor(rect_size.x / temp_size) + 0.01
var ceil_y = floor(rect_size.y / temp_size) + 0.01
var ceil_x = ceil(rect_size.x / temp_size)
var ceil_y = ceil(rect_size.y / temp_size)
for i in ceil_y:
var start_x = Vector2(0, (i * temp_size) + wrap_offset.y)
var end_x = Vector2(rect_size.x, (i * temp_size) + wrap_offset.y)
# var end_x = Vector2(int(rect_size.x) + size - int(rect_size.x) % size, (i * temp_size) + wrap_offset.y)
draw_line(start_x, end_x, color, 1)
for i in ceil_x:
var start_y = Vector2((i * temp_size) + wrap_offset.x, 0)
var end_y = Vector2((i * temp_size) + (wrap_offset.x + 0.01), rect_size.y)
var end_y = Vector2((i * temp_size) + (wrap_offset.x), rect_size.y)
# var end_y = Vector2((i * temp_size) + (wrap_offset.x), int(rect_size.y) + size - int(rect_size.y) % size)
draw_line(start_y, end_y, color, 1)
func _process(delta):
update()

View File

@ -0,0 +1,17 @@
extends Reference
var action_data = {}
var painter
func _init():
pass
func do_action(data: Array):
pass
func undo_action(data: Array):
pass

View File

@ -0,0 +1,25 @@
extends "res://addons/graphics_editor/actions/Action.gd"
func do_action(data: Array):
action_data["do"] = {
"cell_position": data[0],
"last_cell_position": data[1],
"color": data[2],
}
action_data["undo"] = {
"cell_position": data[0],
"last_cell_position": data[1],
"color": get("painter").get_pixel_cell_color_v(action_data.do.cell_position),
}
get("painter").set_pixels_from_line(action_data.do.cell_position, action_data.do.last_cell_position, action_data.do.color)
func undo_action(data: Array):
get("painter").set_pixels_from_line(action_data.undo.cell_position, action_data.undo.last_cell_position, action_data.undo.color)

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 B

View File

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

Some files were not shown because too many files have changed in this diff Show More