Basic library editing + shortcuts

Added simple functions to add nodes to the user library and save it.
Added keyboard shortcuts for main menu.
This commit is contained in:
Rodolphe Suescun 2018-08-07 23:21:12 +02:00
parent 0e1f891910
commit 37eb661496
8 changed files with 258 additions and 17 deletions

1
.gitignore vendored
View File

@ -20,3 +20,4 @@ examples/input_image.png.import
*.import
*.import
*.import
/addons/procedural_material/nodes/godot_logo.png.import

View File

@ -24,7 +24,7 @@ func get_drag_data(position):
func _ready():
var root = create_item()
add_library("res://addons/procedural_material/library/base.json")
add_library("res://addons/procedural_material/library/user.json")
add_library("user://library/user.json")
func add_library(filename):
var root = get_root()
@ -35,12 +35,23 @@ func add_library(filename):
file.close()
for m in lib.lib:
m.library = filename
add_item(m, m.tree_item, root)
add_item(m, m.tree_item)
func add_item(item, item_name, item_parent):
func add_item(item, item_name, item_parent = null):
if item_parent == null:
item.tree_item = item_name
item_parent = get_root()
var slash_position = item_name.find("/")
if slash_position == -1:
var new_item = create_item(item_parent)
var new_item = null
var c = item_parent.get_children()
while c != null:
if c.get_text(0) == item_name:
new_item = c
break
c = c.get_next()
if new_item == null:
new_item = create_item(item_parent)
new_item.set_text(0, item_name)
new_item.set_metadata(0, item)
return new_item
@ -58,3 +69,23 @@ func add_item(item, item_name, item_parent):
new_parent = create_item(item_parent)
new_parent.set_text(0, prefix)
return add_item(item, suffix, new_parent)
func serialize_library(array, library_name, item = null):
if item == null:
item = get_root()
item = item.get_children()
while item != null:
var m = item.get_metadata(0)
if m != null && m.has("library") and m.library == library_name:
array.append(m)
serialize_library(array, library_name, item)
item = item.get_next()
func save_library(library_name, item = null):
var array = []
serialize_library(array, library_name)
print("Saving library "+library_name)
var file = File.new()
if file.open(library_name, File.WRITE) == OK:
file.store_string(to_json({lib=array}))
file.close()

View File

@ -4,17 +4,19 @@ var current_tab = -1
const MENU = [
{ menu="File", command="new_material", description="New material" },
{ menu="File", command="load_material", description="Load material" },
{ menu="File", command="load_material", shortcut="Control+O", description="Load material" },
{ menu="File" },
{ menu="File", command="save_material", description="Save material" },
{ menu="File", command="save_material_as", description="Save material as..." },
{ menu="File", command="save_material", shortcut="Control+S", description="Save material" },
{ menu="File", command="save_material_as", shortcut="Control+Shift+S", description="Save material as..." },
{ menu="File", command="save_all_materials", description="Save all materials..." },
{ menu="File" },
{ menu="File", command="export_material", description="Export material" },
{ menu="File", command="export_material", shortcut="Control+E", description="Export material" },
{ menu="File" },
{ menu="File", command="close_material", description="Close material" },
{ menu="File", command="exit", description="Exit" },
{ menu="File", command="quit", shortcut="Control+Q", description="Quit" },
{ menu="Tools", command="save_icons", description="Save icons for selected nodes" },
{ menu="Tools", command="add_to_user_library", description="Add selected node to user library" },
{ menu="Tools", command="save_user_library", description="Save user library" },
{ menu="Help", command="about", description="About" }
]
@ -33,7 +35,18 @@ func create_menu(menu, menu_name):
menu.add_child(submenu)
menu.add_submenu_item(MENU[i].description, submenu.get_name())
elif MENU[i].has("description"):
menu.add_item(MENU[i].description, i)
var shortcut = 0
if MENU[i].has("shortcut"):
for s in MENU[i].shortcut.split("+"):
if s == "Alt":
shortcut |= KEY_MASK_ALT
elif s == "Control":
shortcut |= KEY_MASK_CTRL
elif s == "Shift":
shortcut |= KEY_MASK_SHIFT
else:
shortcut |= OS.find_scancode_from_string(s)
menu.add_item(MENU[i].description, i, shortcut)
else:
menu.add_separator()
return menu
@ -73,12 +86,40 @@ func close_material():
func save_icons():
var graphedit = $VBoxContainer/HBoxContainer/Projects.get_current_tab_control()
if graphedit != null and graphedit is GraphEdit:
for n in graphedit.get_children():
if n is GraphNode and n.selected:
graphedit.export_texture(n, "res://addons/procedural_material/library/icons/"+n.name+".png", 64)
func exit():
queue_free()
func add_to_user_library():
var graphedit = $VBoxContainer/HBoxContainer/Projects.get_current_tab_control()
if graphedit != null and graphedit is GraphEdit:
for n in graphedit.get_children():
if n is GraphNode and n.selected:
var dialog = preload("res://addons/procedural_material/widgets/line_dialog.tscn").instance()
add_child(dialog)
dialog.connect("ok", self, "do_add_to_user_library", [n])
dialog.popup_centered()
break
func do_add_to_user_library(name, node):
var data = node.serialize()
var dir = Directory.new()
dir.make_dir("user://library")
dir.make_dir("user://library/user")
data.erase("node_position")
data.library = "user://library/user.json"
data.icon = name.right(name.rfind("/")+1).to_lower()
$VBoxContainer/HBoxContainer/VBoxContainer/Library.add_item(data, name)
var graphedit = $VBoxContainer/HBoxContainer/Projects.get_current_tab_control()
graphedit.export_texture(node, "user://library/user/"+data.icon+".png", 64)
func save_user_library():
print("Saving user library")
$VBoxContainer/HBoxContainer/VBoxContainer/Library.save_library("user://library/user.json")
func quit():
get_tree().quit()
func _on_PopupMenu_id_pressed(id):
var node_type = null

View File

@ -4,7 +4,7 @@
[ext_resource path="res://addons/procedural_material/library.gd" type="Script" id=2]
[ext_resource path="res://addons/procedural_material/preview.tscn" type="PackedScene" id=3]
[node name="MainWindow" type="Panel"]
[node name="MainWindow" type="Panel" index="0"]
anchor_left = 0.0
anchor_top = 0.0
@ -244,4 +244,6 @@ _sections_unfolded = [ "Size Flags" ]
[connection signal="tab_changed" from="VBoxContainer/HBoxContainer/Projects" to="." method="_on_Projects_tab_changed"]
[connection signal="tab_selected" from="VBoxContainer/HBoxContainer/Projects" to="." method="_on_Projects_tab_changed"]

View File

@ -0,0 +1,10 @@
extends WindowDialog
signal ok
func _ready():
pass
func _on_OK_pressed():
emit_signal("ok", $VBoxContainer/LineEdit.text)
queue_free()

View File

@ -0,0 +1,154 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/procedural_material/widgets/line_dialog.gd" type="Script" id=1]
[node name="LineDialog" type="WindowDialog"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 332.0
margin_bottom = 72.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
popup_exclusive = false
window_title = "New library element"
resizable = false
script = ExtResource( 1 )
[node name="VBoxContainer" type="VBoxContainer" parent="." index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 1
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
alignment = 0
[node name="Label" type="Label" parent="VBoxContainer" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 332.0
margin_bottom = 14.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "Select a name for the new library element"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="LineEdit" type="LineEdit" parent="VBoxContainer" index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_top = 18.0
margin_right = 332.0
margin_bottom = 42.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 1
size_flags_horizontal = 1
size_flags_vertical = 1
focus_mode = 2
context_menu_enabled = true
placeholder_alpha = 0.6
caret_blink = false
caret_blink_speed = 0.65
caret_position = 0
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer" index="2"]
anchor_left = 0.5
anchor_top = 0.0
anchor_right = 0.5
anchor_bottom = 0.0
margin_left = -62.0
margin_top = 49.0
margin_right = 62.0
margin_bottom = 69.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 1
mouse_default_cursor_shape = 0
size_flags_horizontal = 0
size_flags_vertical = 0
alignment = 0
_sections_unfolded = [ "Size Flags" ]
[node name="OK" type="Button" parent="VBoxContainer/HBoxContainer" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 60.0
margin_bottom = 20.0
rect_min_size = Vector2( 60, 0 )
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "OK"
flat = false
align = 1
_sections_unfolded = [ "Rect" ]
[node name="Cancel" type="Button" parent="VBoxContainer/HBoxContainer" index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 64.0
margin_right = 124.0
margin_bottom = 20.0
rect_min_size = Vector2( 60, 0 )
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "Cancel"
flat = false
align = 1
_sections_unfolded = [ "Rect" ]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/OK" to="." method="_on_OK_pressed"]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Cancel" to="." method="queue_free"]

View File

@ -0,0 +1 @@
{"connections":[{"from":"voronoi_0","from_port":0,"to":"colorize_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"normal_map_0","to_port":0},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"voronoi_0","from_port":0,"to":"colorize_1","to_port":0},{"from":"colorize_1","from_port":0,"to":"Material","to_port":0},{"from":"colorize_2","from_port":0,"to":"Material","to_port":1},{"from":"voronoi_0","from_port":0,"to":"colorize_2","to_port":0},{"from":"voronoi_0","from_port":0,"to":"colorize_3","to_port":0},{"from":"colorize_3","from_port":0,"to":"Material","to_port":2}],"nodes":[{"name":"Material","node_position":{"x":674,"y":164},"type":"material"},{"intensity":0.4,"name":"voronoi_0","node_position":{"x":72,"y":212},"scale_x":16,"scale_y":16,"type":"voronoi"},{"gradient":[{"b":0.010715,"g":0.411458,"pos":0,"r":0.22361},{"b":0,"g":1,"pos":1,"r":0.9375}],"name":"colorize_1","node_position":{"x":384,"y":137},"type":"colorize"},{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":0,"g":0,"pos":1,"r":0}],"name":"colorize_2","node_position":{"x":384,"y":197},"type":"colorize"},{"gradient":[{"b":0.505208,"g":0.505208,"pos":0,"r":0.505208},{"b":0.78125,"g":0.78125,"pos":1,"r":0.78125}],"name":"colorize_3","node_position":{"x":384,"y":258},"type":"colorize"},{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":0.5,"g":0.5,"pos":0.363636,"r":0.5},{"b":1,"g":1,"pos":0.618182,"r":1}],"name":"colorize_0","node_position":{"x":298,"y":317},"type":"colorize"},{"amount":0.5,"name":"normal_map_0","node_position":{"x":478,"y":319},"type":"normal_map"}]}

1
examples/floor2.ptex Normal file
View File

@ -0,0 +1 @@
{"connections":[{"from":"perlin_0","from_port":0,"to":"colorize_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"blend_0","to_port":1},{"from":"bricks_0","from_port":0,"to":"blend_0","to_port":0},{"from":"blend_0","from_port":0,"to":"Material","to_port":0},{"from":"colorize_2","from_port":0,"to":"Material","to_port":1},{"from":"bricks_0","from_port":0,"to":"normal_map_0","to_port":0},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"colorize_1","from_port":0,"to":"Material","to_port":2},{"from":"bricks_0","from_port":0,"to":"colorize_2","to_port":0},{"from":"blend_0","from_port":0,"to":"colorize_1","to_port":0}],"nodes":[{"amount":1,"blend_type":2,"name":"blend_0","node_position":{"x":450,"y":198},"type":"blend"},{"name":"Material","node_position":{"x":773,"y":290},"type":"material"},{"iterations":7,"name":"perlin_0","node_position":{"x":7,"y":263},"persistence":0.85,"scale_x":8,"scale_y":8,"type":"perlin"},{"bevel":0.01,"columns":4,"mortar":0.01,"name":"bricks_0","node_position":{"x":242,"y":382},"row_offset":0,"rows":4,"type":"bricks"},{"amount":0.2,"name":"normal_map_0","node_position":{"x":516,"y":466},"type":"normal_map"},{"gradient":[{"b":1,"g":1,"pos":0,"r":1},{"b":0.484375,"g":0.484375,"pos":1,"r":0.484375}],"name":"colorize_1","node_position":{"x":510,"y":386},"type":"colorize"},{"gradient":[{"b":0.302083,"g":0.302083,"pos":0,"r":0.302083},{"b":0.338542,"g":0.338542,"pos":1,"r":0.338542}],"name":"colorize_2","node_position":{"x":508,"y":315},"type":"colorize"},{"gradient":[{"b":0.588542,"g":0.742839,"pos":0,"r":1},{"b":1,"g":1,"pos":0.672727,"r":1}],"name":"colorize_0","node_position":{"x":232,"y":286},"type":"colorize"}]}