Updated code editors and added a menu to create all elementary generators

This commit is contained in:
RodZill4 2019-10-07 20:41:57 +02:00
parent a7f371e142
commit ad2de4a52e
11 changed files with 150 additions and 60 deletions

View File

@ -2,6 +2,8 @@ tool
extends Object
class_name MMGenLoader
const STD_GENDEF_PATH = "res://addons/material_maker/nodes"
static func load_gen(filename: String) -> MMGenBase:
var file = File.new()
if file.open(filename, File.READ) == OK:
@ -28,6 +30,20 @@ static func add_to_gen_graph(gen_graph, generators, connections):
return rv
static func create_gen(data) -> MMGenBase:
var guess = [
{ keyword="connections", type=MMGenGraph },
{ keyword="nodes", type=MMGenGraph },
{ keyword="shader_model", type=MMGenShader },
{ keyword="model_data", type=MMGenShader },
{ keyword="convolution_params", type=MMGenConvolution },
{ keyword="widgets", type=MMGenRemote }
]
var types = {
material = MMGenMaterial,
buffer = MMGenBuffer,
image = MMGenImage,
switch = MMGenSwitch
}
var generator = null
if data.has("connections") and data.has("nodes"):
generator = MMGenGraph.new()
@ -60,21 +76,20 @@ static func create_gen(data) -> MMGenBase:
generator = MMGenSwitch.new()
else:
var file = File.new()
var gen_path = OS.get_executable_path().get_base_dir()+"/generators"
if file.open(gen_path+"/"+data.type+".mmg", File.READ) == OK:
generator = create_gen(parse_json(file.get_as_text()))
generator.model = data.type
file.close()
elif file.open("res://addons/material_maker/nodes/"+data.type+".mmg", File.READ) == OK:
generator = create_gen(parse_json(file.get_as_text()))
generator.model = data.type
file.close()
elif file.open("res://addons/material_maker/nodes/"+data.type+".mmn", File.READ) == OK:
generator = MMGenShader.new()
generator.model = data.type
generator.set_shader_model(parse_json(file.get_as_text()))
file.close()
else:
var gen_paths = [ STD_GENDEF_PATH, OS.get_executable_path().get_base_dir()+"/generators" ]
for p in gen_paths:
if file.open(p+"/"+data.type+".mmg", File.READ) == OK:
generator = create_gen(parse_json(file.get_as_text()))
generator.model = data.type
file.close()
break
elif file.open(p+"/"+data.type+".mmn", File.READ) == OK:
generator = MMGenShader.new()
generator.model = data.type
generator.set_shader_model(parse_json(file.get_as_text()))
file.close()
break
if generator == null:
print("Cannot find description for "+data.type)
if generator != null:
generator.name = data.type
@ -90,3 +105,20 @@ static func create_gen(data) -> MMGenBase:
for p in data.parameters.keys():
generator.parameters[p] = MMType.deserialize_value(data.parameters[p])
return generator
static func get_generator_list() -> Array:
var rv = []
var dir : Directory = Directory.new()
for p in [ STD_GENDEF_PATH, OS.get_executable_path().get_base_dir()+"/generators" ]:
dir.open(p)
dir.list_dir_begin(true)
while true:
var f = dir.get_next()
if f == "":
break
if f.right(f.length()-4) == ".mmg":
var n = f.left(f.length()-4)
if rv.find(n) == -1:
rv.push_back(n)
rv.sort()
return rv

View File

@ -95,11 +95,17 @@ func render_shader(shader, textures, render_size):
return self
func copy_to_texture(t : ImageTexture):
get_texture().get_data().lock()
var image : Image = get_texture().get_data()
image.lock()
t.create_from_image(get_texture().get_data())
get_texture().get_data().unlock()
image.unlock()
func save_to_file(fn : String):
var image : Image = get_texture().get_data()
image.lock()
image.save_png(fn)
image.unlock()
func release():
rendering = false
emit_signal("done")

Binary file not shown.

View File

@ -1,5 +1,6 @@
tool
extends GraphEdit
class_name MMGraphEdit
var editor_interface = null
var node_factory = null
@ -167,6 +168,9 @@ func create_nodes(data, position : Vector2 = Vector2(0, 0)):
return update_graph(new_stuff.generators, new_stuff.connections)
return []
func create_gen_from_type(gen_name):
create_nodes({ type=gen_name }, scroll_offset+0.5*rect_size)
func load_file(filename):
clear_material()
top_generator = MMGenLoader.load_gen(filename)

View File

@ -2,13 +2,13 @@ tool
extends Panel
var recent_files = []
var recent_files_submenu = null
var editor_interface = null
var current_tab = null
onready var renderer = $Renderer
onready var projects = $VBoxContainer/HBoxContainer/ProjectsPane/Projects
onready var library = $VBoxContainer/HBoxContainer/VBoxContainer/Library
const MENU = [
{ menu="File", command="new_material", description="New material" },
@ -26,8 +26,10 @@ const MENU = [
{ menu="Edit", command="edit_cut", shortcut="Control+X", description="Cut" },
{ menu="Edit", command="edit_copy", shortcut="Control+C", description="Copy" },
{ menu="Edit", command="edit_paste", shortcut="Control+V", description="Paste" },
{ menu="Tools", submenu="create", description="Create" },
{ menu="Tools", command="create_subgraph", shortcut="Control+G", description="Create group" },
{ menu="Tools", command="make_selected_nodes_editable", shortcut="Control+F", description="Make selected nodes editable" },
{ menu="Tools" },
{ 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="show_doc", description="User manual" },
@ -48,7 +50,7 @@ func _ready():
m.connect("about_to_show", self, "menu_about_to_show", [ m.name, menu ])
new_material()
func get_current_graph_edit():
func get_current_graph_edit() -> MMGraphEdit:
var graph_edit = projects.get_current_tab_control()
if graph_edit != null and graph_edit is GraphEdit:
return graph_edit
@ -66,7 +68,7 @@ func create_menu(menu, menu_name):
var submenu = PopupMenu.new()
var submenu_function = "create_menu_"+MENU[i].submenu
if has_method(submenu_function):
call(submenu_function, submenu)
submenu.connect("about_to_show", self, submenu_function, [ submenu ]);
else:
create_menu(submenu, MENU[i].submenu)
menu.add_child(submenu)
@ -88,16 +90,15 @@ func create_menu(menu, menu_name):
menu.add_separator()
return menu
func update_recents_menu():
if recent_files_submenu != null:
recent_files_submenu.clear()
for i in recent_files.size():
recent_files_submenu.add_item(recent_files[i], i)
func create_menu_load_recent(menu):
menu.connect("id_pressed", self, "_on_LoadRecent_id_pressed")
recent_files_submenu = menu
update_recents_menu()
menu.clear()
for i in recent_files.size():
menu.add_item(recent_files[i], i)
if !menu.is_connected("id_pressed", self, "_on_LoadRecent_id_pressed"):
menu.connect("id_pressed", self, "_on_LoadRecent_id_pressed")
func _on_LoadRecent_id_pressed(id):
do_load_material(recent_files[id])
func load_recents():
var f = File.new()
@ -113,12 +114,25 @@ func add_recent(path):
else:
break
recent_files.push_front(path)
update_recents_menu()
var f = File.new()
f.open("user://recent_files.bin", File.WRITE)
f.store_string(to_json(recent_files))
f.close()
func create_menu_create(menu):
var gens = MMGenLoader.get_generator_list()
menu.clear()
for i in gens.size():
menu.add_item(gens[i], i)
if !menu.is_connected("id_pressed", self, "_on_Create_id_pressed"):
menu.connect("id_pressed", self, "_on_Create_id_pressed")
func _on_Create_id_pressed(id):
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null:
var gens = MMGenLoader.get_generator_list()
graph_edit.create_gen_from_type(gens[id])
func menu_about_to_show(name, menu):
for i in MENU.size():
if MENU[i].menu != name:
@ -160,7 +174,7 @@ func do_load_materials(filenames):
do_load_material(f)
func do_load_material(filename):
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
var node_count = 2 # So test below succeeds if graph_edit is null...
if graph_edit != null:
node_count = 0
@ -175,7 +189,7 @@ func do_load_material(filename):
add_recent(filename)
func save_material():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null:
if graph_edit.save_path != null:
graph_edit.save_file(graph_edit.save_path)
@ -183,7 +197,7 @@ func save_material():
save_material_as()
func save_material_as():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null:
var dialog = FileDialog.new()
add_child(dialog)
@ -198,12 +212,12 @@ func close_material():
projects.close_tab()
func export_material():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null :
graph_edit.export_textures()
func export_material_is_disabled():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit == null or graph_edit.save_path == null:
return true
return false
@ -216,16 +230,16 @@ func quit():
func edit_cut():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null:
graph_edit.cut()
func edit_cut_is_disabled():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
return graph_edit == null or !graph_edit.can_copy()
func edit_copy():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null:
graph_edit.copy()
@ -233,7 +247,7 @@ func edit_copy_is_disabled():
return edit_cut_is_disabled()
func edit_paste():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null:
graph_edit.paste()
@ -242,14 +256,14 @@ func edit_paste_is_disabled():
return data == null
func get_selected_nodes():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null:
return graph_edit.get_selected_nodes()
else:
return []
func create_subgraph():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null:
graph_edit.create_subgraph()
@ -270,10 +284,10 @@ func add_to_user_library():
dialog.popup_centered()
func do_add_to_user_library(name, nodes):
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
var data
if nodes.size() == 1:
data = nodes[0].serialize()
data = nodes[0].generator.serialize()
data.erase("node_position")
elif graph_edit != null:
data = graph_edit.serialize_selection()
@ -282,12 +296,16 @@ func do_add_to_user_library(name, nodes):
dir.make_dir("user://library/user")
data.library = "user://library/user.json"
data.icon = name.right(name.rfind("/")+1).to_lower()
$VBoxContainer/HBoxContainer/VBoxContainer/Library.add_item(data, name)
graph_edit.export_texture(nodes[0], "user://library/user/"+data.icon+".png", 64)
library.add_item(data, name)
var result = nodes[0].generator.render(0, renderer, 64)
while result is GDScriptFunctionState:
result = yield(result, "completed")
result.save_to_file("user://library/user/"+data.icon+".png")
result.release()
func save_user_library():
print("Saving user library")
$VBoxContainer/HBoxContainer/VBoxContainer/Library.save_library("user://library/user.json")
library.save_library("user://library/user.json")
func show_doc():
var doc_path = OS.get_executable_path()
@ -312,9 +330,6 @@ func _on_PopupMenu_id_pressed(id):
if has_method(command):
call(command)
func _on_LoadRecent_id_pressed(id):
do_load_material(recent_files[id])
# Preview
func update_preview():
@ -322,7 +337,7 @@ func update_preview():
update_preview_3d()
func update_preview_2d(node = null):
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null:
var preview = $VBoxContainer/HBoxContainer/VBoxContainer/Preview
if node == null:
@ -340,7 +355,7 @@ func update_preview_2d(node = null):
preview.set_2d(tex)
func update_preview_3d():
var graph_edit = get_current_graph_edit()
var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null and graph_edit.top_generator != null and graph_edit.top_generator.has_node("Material"):
var gen_material = graph_edit.top_generator.get_node("Material")
var status = gen_material.render_textures(renderer)

View File

@ -42,14 +42,14 @@ margin_left = 79.0
margin_right = 125.0
margin_bottom = 20.0
text = "Tools"
items = [ "Create group", null, 0, false, false, 15, 268435527, null, "", false, "Make selected nodes editable", null, 0, false, false, 16, 268435526, null, "", false, "Add selected node to user library", null, 0, false, false, 17, 0, null, "", false, "Save user library", null, 0, false, false, 18, 0, null, "", false ]
items = [ "Create", null, 0, false, false, -1, 0, null, "PopupMenu", false, "Create group", null, 0, false, false, 16, 268435527, null, "", false, "Make selected nodes editable", null, 0, false, false, 17, 268435526, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Add selected node to user library", null, 0, false, false, 19, 0, null, "", false, "Save user library", null, 0, false, false, 20, 0, null, "", false ]
[node name="Help" type="MenuButton" parent="VBoxContainer/Menu"]
margin_left = 129.0
margin_right = 171.0
margin_bottom = 20.0
text = "Help"
items = [ "User manual", null, 0, false, false, 19, 0, null, "", false, "Report a bug", null, 0, false, false, 20, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "About", null, 0, false, false, 22, 0, null, "", false ]
items = [ "User manual", null, 0, false, false, 21, 0, null, "", false, "Report a bug", null, 0, false, false, 22, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "About", null, 0, false, false, 24, 0, null, "", false ]
[node name="HBoxContainer" type="HSplitContainer" parent="VBoxContainer"]
margin_top = 24.0

View File

@ -142,7 +142,8 @@ func create_parameter_control(p : Dictionary):
func update_node():
# Clean node
var custom_node_buttons = null
remove_child(preview)
if preview != null:
remove_child(preview)
if preview_timer != null:
preview_timer.stop()
remove_child(preview_timer)
@ -319,10 +320,13 @@ func do_load_generator(file_name : String):
else:
new_generator = MMGenLoader.load_gen(file_name)
if new_generator != null:
var gen_name = MMGenLoader.generator_from_path(file_name)
if gen_name != "":
new_generator.type = gen_name
var parent_generator = generator.get_parent()
parent_generator.replace_generator(generator, new_generator)
generator = new_generator
update_node()
call_deferred("update_node")
func save_generator():
var dialog = FileDialog.new()

View File

@ -1 +1 @@
{"name":"weave","node_position":{"x":0,"y":0},"parameters":{"columns":4,"rows":4},"shader_model":{"global":"float weave(vec2 uv) {\n\tvec2 v = sin(3.1415892*vec2(uv.x+floor(uv.y), 1.0+uv.y+floor(uv.x)));\n\treturn max(v.x, v.y)*0.5+0.5;\n}","inputs":[],"instance":"","name":"Weave","outputs":[{"f":"weave(vec2($columns, $rows)*$uv)","type":"f"}],"parameters":[{"default":0,"label":"","max":32,"min":2,"name":"rows","step":1,"type":"float","widget":"spinbox"},{"default":0,"label":"","max":32,"min":2,"name":"columns","step":1,"type":"float","widget":"spinbox"}]},"type":"shader"}
{"name":"weave","node_position":{"x":0,"y":0},"parameters":{"columns":8,"rows":8,"width":0.85},"shader_model":{"global":"float weave(vec2 uv, vec2 count, float width) {\n uv *= count;\n\tfloat c = (sin(3.1415926*(uv.x+floor(uv.y)))*0.5+0.5)*step(abs(fract(uv.y)-0.5), width*0.5);\n\tc = max(c, (sin(3.1415926*(1.0+uv.y+floor(uv.x)))*0.5+0.5)*step(abs(fract(uv.x)-0.5), width*0.5));\n\treturn c;\n}","inputs":[],"instance":"","name":"Weave","outputs":[{"f":"weave($uv, vec2($columns, $rows), $width)","type":"f"}],"parameters":[{"default":4,"label":"","max":32,"min":2,"name":"columns","step":1,"type":"float","widget":"spinbox"},{"default":4,"label":"","max":32,"min":2,"name":"rows","step":1,"type":"float","widget":"spinbox"},{"default":0.8,"label":"","max":1,"min":0,"name":"width","step":0.05,"type":"float"}]},"type":"shader"}

View File

@ -3,12 +3,18 @@ extends WindowDialog
var model_data = null
onready var global_editor : TextEdit = $Sizer/Tabs/Global
const ParameterEditor = preload("res://addons/material_maker/widgets/node_editor/parameter.tscn")
const InputEditor = preload("res://addons/material_maker/widgets/node_editor/input.tscn")
const OutputEditor = preload("res://addons/material_maker/widgets/node_editor/output.tscn")
signal node_changed
func _ready():
global_editor.add_color_region("//", "", Color(0, 0.5, 0), true)
func add_item(parent, scene):
var object = scene.instance()
parent.add_child(object)

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=4 format=2]
[gd_scene load_steps=6 format=2]
[ext_resource path="res://addons/material_maker/widgets/node_editor/node_editor.gd" type="Script" id=1]
[ext_resource path="res://addons/material_maker/icons/icons.svg" type="Texture" id=2]
@ -8,6 +8,13 @@ flags = 4
atlas = ExtResource( 2 )
region = Rect2( 48, 0, 16, 16 )
[sub_resource type="DynamicFontData" id=2]
font_path = "res://addons/material_maker/fonts/hack.ttf"
[sub_resource type="DynamicFont" id=3]
size = 12
font_data = SubResource( 2 )
[node name="NodeEditor" type="WindowDialog"]
margin_right = 833.0
margin_bottom = 398.0
@ -148,6 +155,10 @@ margin_top = 32.0
margin_right = -4.0
margin_bottom = -4.0
mouse_default_cursor_shape = 0
custom_fonts/font = SubResource( 3 )
custom_colors/brace_mismatch_color = Color( 1, 0, 0, 1 )
syntax_highlighting = true
show_line_numbers = true
[node name="Instance" type="TextEdit" parent="Sizer/Tabs"]
visible = false
@ -158,6 +169,8 @@ margin_top = 32.0
margin_right = -4.0
margin_bottom = -4.0
mouse_default_cursor_shape = 0
syntax_highlighting = true
show_line_numbers = true
[node name="HBoxContainer" type="HBoxContainer" parent="Sizer"]
margin_left = 307.0

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=4 format=2]
[gd_scene load_steps=6 format=2]
[ext_resource path="res://addons/material_maker/widgets/node_editor/output.gd" type="Script" id=1]
[ext_resource path="res://addons/material_maker/icons/icons.svg" type="Texture" id=2]
@ -8,6 +8,13 @@ flags = 4
atlas = ExtResource( 2 )
region = Rect2( 0, 16, 16, 16 )
[sub_resource type="DynamicFontData" id=2]
font_path = "res://addons/material_maker/fonts/hack.ttf"
[sub_resource type="DynamicFont" id=3]
size = 12
font_data = SubResource( 2 )
[node name="Output" type="HBoxContainer"]
margin_right = 201.0
margin_bottom = 24.0
@ -30,11 +37,14 @@ text = "GreyScale"
items = [ "GreyScale", null, false, 0, null, "Color", null, false, 1, null, "RGBA", null, false, -1, null ]
selected = 0
[node name="Value" type="LineEdit" parent="."]
[node name="Value" type="TextEdit" parent="."]
margin_left = 140.0
margin_right = 201.0
margin_bottom = 24.0
hint_tooltip = "Default value"
size_flags_horizontal = 3
custom_fonts/font = SubResource( 3 )
text = "0.0"
syntax_highlighting = true
context_menu_enabled = false
[connection signal="pressed" from="Delete" to="." method="_on_Delete_pressed"]