Updated remote and group creation

This commit is contained in:
RodZill4 2019-10-24 09:00:31 +02:00
parent 4246673c85
commit 26f083cd3d
14 changed files with 216 additions and 108 deletions

View File

@ -37,6 +37,9 @@ var parameters = {}
func _ready() -> void: func _ready() -> void:
init_parameters() init_parameters()
func _post_load() -> void:
pass
func can_be_deleted() -> bool: func can_be_deleted() -> bool:
return true return true
@ -68,6 +71,13 @@ func get_type_name() -> String:
func get_parameter_defs() -> Array: func get_parameter_defs() -> Array:
return [] return []
func get_parameter_def(param_name : String) -> Dictionary:
var parameter_defs = get_parameter_defs()
for p in parameter_defs:
if p.name == param_name:
return p
return {}
func set_parameter(n : String, v): func set_parameter(n : String, v):
parameters[n] = v parameters[n] = v
source_changed(0) source_changed(0)

View File

@ -7,6 +7,13 @@ var connections = []
var editable = false var editable = false
func fix_remotes() -> void:
for c in get_children():
if c is MMGenRemote:
c.fix()
func _post_load() -> void:
fix_remotes()
func get_type() -> String: func get_type() -> String:
return "graph" return "graph"
@ -87,6 +94,9 @@ func remove_generator(generator : MMGenBase) -> void:
if c.from != generator.name and c.to != generator.name: if c.from != generator.name and c.to != generator.name:
new_connections.append(c) new_connections.append(c)
connections = new_connections connections = new_connections
remove_child(generator)
fix_remotes()
add_child(generator)
generator.queue_free() generator.queue_free()
func replace_generator(old : MMGenBase, new : MMGenBase) -> void: func replace_generator(old : MMGenBase, new : MMGenBase) -> void:
@ -152,13 +162,15 @@ func _serialize(data: Dictionary) -> Dictionary:
func edit(node) -> void: func edit(node) -> void:
node.get_parent().call_deferred("update_view", self) node.get_parent().call_deferred("update_view", self)
func create_subgraph(gens) -> void: func create_subgraph(gens : Array) -> void:
# Remove material, gen_inputs and gen_outputs nodes # Remove material, gen_inputs and gen_outputs nodes
var generators = [] var generators = []
var center = Vector2(0, 0) var center = Vector2(0, 0)
var left_bound = 65535 var left_bound = 65535
var right_bound = -65536 var right_bound = -65536
var upper_bound = 65536
var count = 0 var count = 0
# Filter group nodes and calculate boundin box
for g in gens: for g in gens:
if g.name != "Material" and g.name != "gen_inputs" and g.name != "gen_outputs": if g.name != "Material" and g.name != "gen_inputs" and g.name != "gen_outputs":
generators.push_back(g) generators.push_back(g)
@ -167,22 +179,33 @@ func create_subgraph(gens) -> void:
count += 1 count += 1
if left_bound > p.x: left_bound = p.x if left_bound > p.x: left_bound = p.x
if right_bound < p.x: right_bound = p.x if right_bound < p.x: right_bound = p.x
if upper_bound > p.y: upper_bound = p.y
if count == 0: if count == 0:
return return
center /= count center /= count
# Create a new graph and add it to the current one
var new_graph = get_script().new() var new_graph = get_script().new()
new_graph.name = "graph" new_graph.name = "graph"
add_generator(new_graph) add_generator(new_graph)
new_graph.position = center new_graph.position = center
# Add grouped generators and keep their names
var names : Array = [] var names : Array = []
for g in generators: for g in generators:
names.push_back(g.name) names.push_back(g.name)
remove_child(g) remove_child(g)
new_graph.add_generator(g) new_graph.add_generator(g)
# Create inputs and outputs generators
var gen_inputs = MMGenIOs.new()
gen_inputs.name = "gen_inputs"
gen_inputs.position = Vector2(left_bound-300, center.y)
new_graph.add_generator(gen_inputs)
var gen_outputs = MMGenIOs.new()
gen_outputs.name = "gen_outputs"
gen_outputs.position = Vector2(right_bound+300, center.y)
new_graph.add_generator(gen_outputs)
# Process connections
var new_graph_connections = [] var new_graph_connections = []
var my_new_connections = [] var my_new_connections = []
var gen_inputs = null
var gen_outputs = null
var inputs = [] var inputs = []
var outputs = [] var outputs = []
for c in connections: for c in connections:
@ -194,11 +217,6 @@ func create_subgraph(gens) -> void:
if port_index == -1: if port_index == -1:
port_index = outputs.size() port_index = outputs.size()
outputs.push_back(src_name) outputs.push_back(src_name)
if gen_outputs == null:
gen_outputs = MMGenIOs.new()
gen_outputs.name = "gen_outputs"
gen_outputs.position = Vector2(right_bound+300, center.y)
new_graph.add_generator(gen_outputs)
gen_outputs.ports.push_back( { name="port"+str(port_index), type="rgba" } ) gen_outputs.ports.push_back( { name="port"+str(port_index), type="rgba" } )
print(gen_outputs.ports) print(gen_outputs.ports)
my_new_connections.push_back( { from=new_graph.name, from_port=port_index, to=c.to, to_port=c.to_port } ) my_new_connections.push_back( { from=new_graph.name, from_port=port_index, to=c.to, to_port=c.to_port } )
@ -208,11 +226,6 @@ func create_subgraph(gens) -> void:
if port_index == -1: if port_index == -1:
port_index = inputs.size() port_index = inputs.size()
inputs.push_back(src_name) inputs.push_back(src_name)
if gen_inputs == null:
gen_inputs = MMGenIOs.new()
gen_inputs.name = "gen_inputs"
gen_inputs.position = Vector2(left_bound-300, center.y)
new_graph.add_generator(gen_inputs)
gen_inputs.ports.push_back( { name="port"+str(port_index), type="rgba" } ) gen_inputs.ports.push_back( { name="port"+str(port_index), type="rgba" } )
my_new_connections.push_back( { from=c.from, from_port=c.from_port, to=new_graph.name, to_port=port_index } ) my_new_connections.push_back( { from=c.from, from_port=c.from_port, to=new_graph.name, to_port=port_index } )
new_graph_connections.push_back( { from="gen_inputs", from_port=port_index, to=c.to, to_port=c.to_port } ) new_graph_connections.push_back( { from="gen_inputs", from_port=port_index, to=c.to, to_port=c.to_port } )
@ -220,7 +233,18 @@ func create_subgraph(gens) -> void:
my_new_connections.push_back(c) my_new_connections.push_back(c)
connections = my_new_connections connections = my_new_connections
new_graph.connections = new_graph_connections new_graph.connections = new_graph_connections
var found_remote = false
var remote_script = load("res://addons/material_maker/engine/gen_remote.gd")
for g in generators: for g in generators:
if g.get_script() == load("res://addons/material_maker/engine/gen_remote.gd"): if g.get_script() == remote_script:
g.name = "gen_parameters" g.name = "gen_parameters"
found_remote = true
new_graph.parameters = g.parameters.duplicate(true)
break break
if !found_remote:
var gen_parameters = remote_script.new()
gen_parameters.name = "gen_parameters"
gen_parameters.position = Vector2(center.x - 200, upper_bound-300)
new_graph.add_child(gen_parameters)
fix_remotes()
new_graph.fix_remotes()

View File

@ -8,6 +8,9 @@ IOs just forward their inputs to their outputs and are used to specify graph int
var ports : Array = [] var ports : Array = []
func can_be_deleted() -> bool:
return name != "gen_inputs" and name != "gen_outputs"
func get_type() -> String: func get_type() -> String:
return "ios" return "ios"

View File

@ -6,16 +6,67 @@ class_name MMGenRemote
Remote can be used to control parameters from several generators in the same graph Remote can be used to control parameters from several generators in the same graph
""" """
var widgets = null var widgets = []
func set_widgets(w) -> void: func can_be_deleted() -> bool:
return name != "gen_parameters"
func set_widgets(w : Array) -> void:
widgets = w widgets = w
fix()
func get_widget(n : String) -> Dictionary:
for w in widgets:
if w.name == n:
return w
return {}
func get_next_widget_name():
var i = 0
while true:
var param_name = "param"+str(i)
var used = false
for w in widgets:
if w.has("name") and w.name == param_name:
used = true
break
if !used:
return param_name
i += 1
func fix() -> void:
# Make sure all widgets have a name
var i = 0 var i = 0
for w in widgets: for w in widgets:
var param_name = "param"+str(i) if !w.has("name"):
if !parameters.has(param_name): w.name = get_next_widget_name()
parameters[param_name] = 0 print("Named "+w.name)
i += 1 var parent = get_parent()
if parent == null:
return
var updated_widgets : Array = []
var removed_widgets = false
for w in widgets:
var updated_linked_widgets : Array = []
for l in w.linked_widgets:
var linked_widget : MMGenBase = parent.get_node(l.node)
if linked_widget != null and linked_widget.get_parameter_def(l.widget).size() > 0:
updated_linked_widgets.push_back(l)
if updated_linked_widgets.size() == 0:
removed_widgets = true
continue
w.linked_widgets = updated_linked_widgets
updated_widgets.push_back(w)
if !parameters.has(w.name):
match w.type:
"config_control":
parameters[w.name] = 0
"linked_control":
# Should get current value of a linked widget
parameters[w.name] = 0
if removed_widgets:
widgets = updated_widgets
emit_signal("parameter_changed", "__update_all__", null)
func get_type() -> String: func get_type() -> String:
return "remote" return "remote"
@ -29,7 +80,7 @@ func get_parameter_defs() -> Array:
for w in widgets: for w in widgets:
match w.type: match w.type:
"config_control": "config_control":
var p = { name="param"+str(i), label=w.label, type="enum", values=[] } var p : Dictionary = { name=w.name, label=w.label, type="enum", values=[] }
var configurations = w.configurations.keys() var configurations = w.configurations.keys()
configurations.sort() configurations.sort()
for c in configurations: for c in configurations:
@ -38,7 +89,7 @@ func get_parameter_defs() -> Array:
i += 1 i += 1
"linked_control": "linked_control":
var linked = w.linked_widgets[0] var linked = w.linked_widgets[0]
var p = {} var p : Dictionary
if linked != null && is_inside_tree(): if linked != null && is_inside_tree():
var gen = get_parent().get_node(linked.node) var gen = get_parent().get_node(linked.node)
if gen != null: if gen != null:
@ -47,26 +98,19 @@ func get_parameter_defs() -> Array:
if pd.name == linked.widget: if pd.name == linked.widget:
p = pd.duplicate(true) p = pd.duplicate(true)
break break
p.name = "param"+str(i) p.name = w.name
p.label = w.label p.label = w.label
rv.append(p) rv.append(p)
i += 1 i += 1
_: _:
print(w.type) print("Unsupported widget of type "+str(w.type))
return rv return rv
func set_parameter(p : String, v) -> void: func set_parameter(p : String, v) -> void:
var parent = get_parent() var parent = get_parent()
if parent == null: if parent == null:
return return
var param_index_str : String = p.trim_prefix("param") var widget = get_widget(p)
if !param_index_str.is_valid_integer():
return
var param_index : int = param_index_str.to_int()
if param_index >= widgets.size():
return
print("Setting "+p+" to "+str(v))
var widget = widgets[param_index]
match widget.type: match widget.type:
"linked_control": "linked_control":
for w in widget.linked_widgets: for w in widget.linked_widgets:
@ -92,52 +136,70 @@ func _serialize(data: Dictionary) -> Dictionary:
data.widgets = widgets data.widgets = widgets
return data return data
func create_linked_control(label) -> int: func create_linked_control(label : String) -> String:
var index = widgets.size() var n = get_next_widget_name()
widgets.push_back({ label=label, type="linked_control", linked_widgets=[] }) widgets.push_back({ name=n, label=label, type="linked_control", linked_widgets=[] })
return index return n
func create_config_control(label) -> int: func create_config_control(label : String) -> String:
var index = widgets.size() var n = get_next_widget_name()
widgets.push_back({ label=label, type="config_control", linked_widgets=[], configurations={} }) widgets.push_back({ name=n, label=label, type="config_control", linked_widgets=[], configurations={} })
return index return n
func set_label(index, new_label) -> void: func set_label(widget_name : String, new_label : String) -> void:
widgets[index].label = new_label get_widget(widget_name).label = new_label
func can_link_parameter(index, generator, param) -> bool: func can_link_parameter(widget_name : String, generator : MMGenBase, param : String) -> bool:
var widget : Dictionary = get_widget(widget_name)
if !widget.linked_widgets.empty():
# Check if the param is already linked
for lw in widget.linked_widgets:
if lw.node == generator.name and lw.widget == param:
return false
# Check the parameter type
var linked : Dictionary = widget.linked_widgets[0]
var linked_generator : MMGenBase = get_parent().get_node(linked.node)
var linked_parameter : Dictionary = linked_generator.get_parameter_def(linked.widget)
var parameter : Dictionary = generator.get_parameter_def(param)
if parameter.type != linked_parameter.type:
return false
match parameter.type:
"enum":
if to_json(linked_parameter.values) != to_json(parameter.values):
return false
return true return true
func link_parameter(index, generator, param) -> void: func link_parameter(widget_name : String, generator : MMGenBase, param : String) -> void:
if !can_link_parameter(index, generator, param): if !can_link_parameter(widget_name, generator, param):
return return
var widget = widgets[index] var widget : Dictionary = get_widget(widget_name)
widget.linked_widgets.push_back({ node=generator.name, widget=param }) widget.linked_widgets.push_back({ node=generator.name, widget=param })
if widget.linked_widgets.size() == 1: if widget.linked_widgets.size() == 1:
match widget.type: match widget.type:
"linked_control": "linked_control":
parameters["param"+str(index)] = generator.parameters[param] parameters[widget_name] = generator.parameters[param]
"config_control": "config_control":
parameters["param"+str(index)] = 0 parameters[widget_name] = 0
emit_signal("parameter_changed", "", null) emit_signal("parameter_changed", "__update_all__", null)
func remove_parameter(index) -> void: func remove_parameter(widget_name : String) -> void:
for i in range(index, widgets.size()-2): for i in range(widgets.size()):
parameters["param"+str(i)] = parameters["param"+str(i+1)] if widgets[i].name == widget_name:
widgets.remove(index) widgets.remove(i)
emit_signal("parameter_changed", "", null) break
emit_signal("parameter_changed", "__update_all__", null)
func add_configuration(index, config_name) -> void: func add_configuration(widget_name : String, config_name : String) -> void:
var widget = widgets[index] var widget = get_widget(widget_name)
if widget.type == "config_control": if widget.type == "config_control":
widget.configurations[config_name] = [] widget.configurations[config_name] = []
var configurations = widget.configurations.keys() var configurations = widget.configurations.keys()
configurations.sort() configurations.sort()
parameters["param"+str(index)] =configurations.find(config_name) parameters[widget.name] = configurations.find(config_name)
update_configuration(index, config_name) update_configuration(widget_name, config_name)
func update_configuration(index, config_name) -> void: func update_configuration(widget_name : String, config_name : String) -> void:
var widget = widgets[index] var widget = get_widget(widget_name)
if widget.type == "config_control": if widget.type == "config_control":
var c = [] var c = []
var parent = get_parent() var parent = get_parent()
@ -147,10 +209,10 @@ func update_configuration(index, config_name) -> void:
var value = MMType.serialize_value(g.parameters[w.widget]) var value = MMType.serialize_value(g.parameters[w.widget])
c.push_back({ node=w.node, widget=w.widget, value=value }) c.push_back({ node=w.node, widget=w.widget, value=value })
widget.configurations[config_name] = c widget.configurations[config_name] = c
emit_signal("parameter_changed", "", null) emit_signal("parameter_changed", "__update_all__", null)
func remove_configuration(index, config_name) -> void: func remove_configuration(widget_name : String, config_name : String) -> void:
var widget = widgets[index] var widget = get_widget(widget_name)
if widget.type == "config_control": if widget.type == "config_control":
widget.configurations.erase(config_name) widget.configurations.erase(config_name)
emit_signal("parameter_changed", "", null) emit_signal("parameter_changed", "__update_all__", null)

View File

@ -120,6 +120,7 @@ static func create_gen(data) -> MMGenBase:
for p in generator.get_parameter_defs(): for p in generator.get_parameter_defs():
if data.has(p.name): if data.has(p.name):
generator.set_parameter(p.name, MMType.deserialize_value(data[p.name])) generator.set_parameter(p.name, MMType.deserialize_value(data[p.name]))
generator._post_load()
return generator return generator
static func get_generator_list() -> Array: static func get_generator_list() -> Array:

View File

@ -143,7 +143,7 @@ func update_graph(generators, connections) -> Array:
func new_material() -> void: func new_material() -> void:
clear_material() clear_material()
var loader = MMGenLoader.new() var loader = MMGenLoader.new()
top_generator = loader.create_gen({nodes=[{name="Material", type="material"}], connections=[]}) top_generator = loader.create_gen({nodes=[{name="Material", type="material","parameters":{"size":11}}], connections=[]})
if top_generator != null: if top_generator != null:
add_child(top_generator) add_child(top_generator)
update_view(top_generator) update_view(top_generator)

View File

@ -59,8 +59,8 @@ func get_preview_texture(data : Dictionary) -> ImageTexture:
if data.has("icon") and data.has("library"): if data.has("icon") and data.has("library"):
var image_path = data.library.left(data.library.rfind("."))+"/"+data.icon+".png" var image_path = data.library.left(data.library.rfind("."))+"/"+data.icon+".png"
var t : ImageTexture var t : ImageTexture
if image_path.left(6) == "res://": if false && image_path.left(6) == "res://":
return load(image_path) as ImageTexture t = load(image_path) as ImageTexture
else: else:
t = ImageTexture.new() t = ImageTexture.new()
var image : Image = Image.new() var image : Image = Image.new()
@ -110,19 +110,22 @@ func add_item(item, item_name, item_icon = null, item_parent = null, force_expan
new_parent.set_text(0, prefix) new_parent.set_text(0, prefix)
return add_item(item, suffix, item_icon, new_parent, force_expand) return add_item(item, suffix, item_icon, new_parent, force_expand)
func serialize_library(array, library_name = null, item = null) -> void: func serialize_library(array : Array, library_name : String = "", item : TreeItem = null) -> void:
if item == null: if item == null:
item = tree.get_root() item = tree.get_root()
item = item.get_children() item = item.get_children()
while item != null: while item != null:
var m = item.get_metadata(0) if item.get_metadata(0) != null:
if m != null and (library_name == null or (m.has("library") and m.library == library_name)): var m : Dictionary = item.get_metadata(0)
array.append(m) if library_name == "" or (m.has("library") and m.library == library_name):
var copy : Dictionary = m.duplicate()
copy.erase("library")
array.append(copy)
serialize_library(array, library_name, item) serialize_library(array, library_name, item)
item = item.get_next() item = item.get_next()
func save_library(library_name, item = null) -> void: func save_library(library_name : String, item : TreeItem = null) -> void:
var array = [] var array : Array = []
serialize_library(array, library_name) serialize_library(array, library_name)
var file = File.new() var file = File.new()
if file.open(library_name, File.WRITE) == OK: if file.open(library_name, File.WRITE) == OK:

View File

@ -23,17 +23,20 @@ const MENU = [
{ menu="File" }, { menu="File" },
{ menu="File", command="close_material", description="Close material" }, { menu="File", command="close_material", description="Close material" },
{ menu="File", command="quit", shortcut="Control+Q", description="Quit" }, { menu="File", command="quit", shortcut="Control+Q", description="Quit" },
{ menu="Edit", command="edit_cut", shortcut="Control+X", description="Cut" }, { menu="Edit", command="edit_cut", shortcut="Control+X", description="Cut" },
{ menu="Edit", command="edit_copy", shortcut="Control+C", description="Copy" }, { menu="Edit", command="edit_copy", shortcut="Control+C", description="Copy" },
{ menu="Edit", command="edit_paste", shortcut="Control+V", description="Paste" }, { menu="Edit", command="edit_paste", shortcut="Control+V", description="Paste" },
{ menu="View", command="view_center", shortcut="C", description="Center view" }, { menu="View", command="view_center", shortcut="C", description="Center view" },
{ menu="View", command="view_reset_zoom", shortcut="Control+0", description="Reset zoom" }, { menu="View", command="view_reset_zoom", shortcut="Control+0", description="Reset zoom" },
{ menu="Tools", submenu="create", description="Create" }, { menu="Tools", submenu="create", description="Create" },
{ menu="Tools", command="create_subgraph", shortcut="Control+G", description="Create group" }, { menu="Tools", command="create_subgraph", shortcut="Control+G", description="Create group" },
{ menu="Tools", command="make_selected_nodes_editable", shortcut="Control+E", description="Make selected nodes editable" }, { menu="Tools", command="make_selected_nodes_editable", shortcut="Control+E", description="Make selected nodes editable" },
{ menu="Tools" }, { menu="Tools" },
{ menu="Tools", command="add_to_user_library", description="Add selected node to user library" }, { 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" }, { menu="Help", command="show_doc", description="User manual" },
{ menu="Help", command="bug_report", description="Report a bug" }, { menu="Help", command="bug_report", description="Report a bug" },
{ menu="Help" }, { menu="Help" },
@ -346,9 +349,6 @@ func do_add_to_user_library(name, nodes) -> void:
result.save_to_file("user://library/user/"+data.icon+".png") result.save_to_file("user://library/user/"+data.icon+".png")
result.release() result.release()
library.add_item(data, name, library.get_preview_texture(data)) library.add_item(data, name, library.get_preview_texture(data))
func save_user_library() -> void:
print("Saving user library")
library.save_library("user://library/user.json") library.save_library("user://library/user.json")
func show_doc() -> void: func show_doc() -> void:

View File

@ -0,0 +1 @@
{"name":"circle_map","node_position":{"x":0,"y":0},"parameters":{},"shader_model":{"code":"","global":"","inputs":[{"default":"vec4($uv, 0.0, 1.0)","label":"","name":"in","type":"rgba"}],"instance":"","name":"CircleMap","outputs":[{"rgba":"$in(vec2(fract(atan($uv.y-0.5, $uv.x-0.5)*0.15915494309), min(0.99999, 2.0*length($uv-vec2(0.5)))))","type":"rgba"}],"parameters":[]},"type":"shader"}

View File

@ -198,7 +198,6 @@ func update_node() -> void:
var control : Control = Control.new() var control : Control = Control.new()
control.rect_min_size.y = 16 control.rect_min_size.y = 16
hsizer.add_child(control) hsizer.add_child(control)
add_child(hsizer) add_child(hsizer)
var input_names_width : int = 0 var input_names_width : int = 0
for c in get_children(): for c in get_children():

View File

@ -1 +1 @@
{"name":"pattern","node_position":{"x":0,"y":0},"parameters":{"mix":0,"x_scale":4,"x_wave":0,"y_scale":4,"y_wave":0},"shader_model":{"global":"float wave_constant(float x) {\n\treturn 1.0;\n}\n\nfloat wave_sine(float x) {\n\treturn 0.5-0.5*cos(3.14159265359*2.0*x);\n}\n\nfloat wave_triangle(float x) {\n\tx = fract(x);\n\treturn min(2.0*x, 2.0-2.0*x);\n}\n\nfloat wave_sawtooth(float x) {\n\treturn fract(x);\n}\n\nfloat wave_square(float x) {\n\treturn (fract(x) < 0.5) ? 0.0 : 1.0;\n}\n\nfloat mix_mul(float x, float y) {\n\treturn x*y;\n}\n\nfloat mix_add(float x, float y) {\n\treturn min(x+y, 1.0);\n}\n\nfloat mix_max(float x, float y) {\n\treturn max(x, y);\n}\n\nfloat mix_min(float x, float y) {\n\treturn min(x, y);\n}\n\nfloat mix_xor(float x, float y) {\n\treturn min(x+y, 2.0-x-y);\n}\n\nfloat mix_pow(float x, float y) {\n\treturn pow(x, y);\n}","inputs":[],"instance":"float $(name)_fct(vec2 uv) {\n\treturn mix_$(mix)(wave_$(x_wave)($(x_scale)*uv.x), wave_$(y_wave)($(y_scale)*uv.y));\n}","name":"Pattern","outputs":[{"f":"$(name)_fct($(uv))","type":"f"}],"parameters":[{"default":0,"label":"Combiner","name":"mix","type":"enum","values":[{"name":"Multiply","value":"mul"},{"name":"Add","value":"add"},{"name":"Max","value":"max"},{"name":"Min","value":"min"},{"name":"Xor","value":"xor"},{"name":"Pow","value":"pow"}]},{"default":0,"label":"X","name":"x_wave","type":"enum","values":[{"name":"Sine","value":"sine"},{"name":"Triangle","value":"triangle"},{"name":"Square","value":"square"},{"name":"Sawtooth","value":"sawtooth"},{"name":"Constant","value":"constant"}]},{"default":4,"label":"2:","max":32,"min":0,"name":"x_scale","step":1,"type":"float","widget":"spinbox"},{"default":0,"label":"Y","name":"y_wave","type":"enum","values":[{"name":"Sine","value":"sine"},{"name":"Triangle","value":"triangle"},{"name":"Square","value":"square"},{"name":"Sawtooth","value":"sawtooth"},{"name":"Constant","value":"constant"}]},{"default":4,"label":"3:","max":32,"min":0,"name":"y_scale","step":1,"type":"float","widget":"spinbox"}]}} {"name":"pattern","node_position":{"x":0,"y":0},"parameters":{"mix":0,"x_scale":4,"x_wave":0,"y_scale":4,"y_wave":0},"shader_model":{"code":"","global":"float wave_constant(float x) {\n\treturn 1.0;\n}\n\nfloat wave_sine(float x) {\n\treturn 0.5-0.5*cos(3.14159265359*2.0*x);\n}\n\nfloat wave_triangle(float x) {\n\tx = fract(x);\n\treturn min(2.0*x, 2.0-2.0*x);\n}\n\nfloat wave_sawtooth(float x) {\n\treturn fract(x);\n}\n\nfloat wave_square(float x) {\n\treturn (fract(x) < 0.5) ? 0.0 : 1.0;\n}\n\nfloat wave_bounce(float x) {\n\tx = 2.0*(fract(x)-0.5);\n\treturn sqrt(1.0-x*x);\n}\n\nfloat mix_mul(float x, float y) {\n\treturn x*y;\n}\n\nfloat mix_add(float x, float y) {\n\treturn min(x+y, 1.0);\n}\n\nfloat mix_max(float x, float y) {\n\treturn max(x, y);\n}\n\nfloat mix_min(float x, float y) {\n\treturn min(x, y);\n}\n\nfloat mix_xor(float x, float y) {\n\treturn min(x+y, 2.0-x-y);\n}\n\nfloat mix_pow(float x, float y) {\n\treturn pow(x, y);\n}","inputs":[],"instance":"float $(name)_fct(vec2 uv) {\n\treturn mix_$(mix)(wave_$(x_wave)($(x_scale)*uv.x), wave_$(y_wave)($(y_scale)*uv.y));\n}","name":"Pattern","outputs":[{"f":"$(name)_fct($(uv))","type":"f"}],"parameters":[{"default":0,"label":"Combiner","name":"mix","type":"enum","values":[{"name":"Multiply","value":"mul"},{"name":"Add","value":"add"},{"name":"Max","value":"max"},{"name":"Min","value":"min"},{"name":"Xor","value":"xor"},{"name":"Pow","value":"pow"}]},{"default":5,"label":"X","name":"x_wave","type":"enum","values":[{"name":"Sine","value":"sine"},{"name":"Triangle","value":"triangle"},{"name":"Square","value":"square"},{"name":"Sawtooth","value":"sawtooth"},{"name":"Constant","value":"constant"},{"name":"Bounce","value":"bounce"}]},{"default":4,"label":"2:","max":32,"min":0,"name":"x_scale","step":1,"type":"float","widget":"spinbox"},{"default":5,"label":"Y","name":"y_wave","type":"enum","values":[{"name":"Sine","value":"sine"},{"name":"Triangle","value":"triangle"},{"name":"Square","value":"square"},{"name":"Sawtooth","value":"sawtooth"},{"name":"Constant","value":"constant"},{"name":"Bounce","value":"bounce"}]},{"default":4,"label":"3:","max":32,"min":0,"name":"y_scale","step":1,"type":"float","widget":"spinbox"}]},"type":"shader"}

View File

@ -10,7 +10,7 @@ func add_control(text, control) -> void:
var index = grid.get_child_count() / 4 var index = grid.get_child_count() / 4
var label = preload("res://addons/material_maker/widgets/linked_widgets/editable_label.tscn").instance() var label = preload("res://addons/material_maker/widgets/linked_widgets/editable_label.tscn").instance()
label.set_text(text) label.set_text(text)
label.connect("label_changed", self, "on_label_changed", [ index ]) label.connect("label_changed", self, "on_label_changed", [ control.name ])
grid.add_child(label) grid.add_child(label)
grid.add_child(control) grid.add_child(control)
control.connect("mouse_entered", self, "on_enter_widget", [ control ]) control.connect("mouse_entered", self, "on_enter_widget", [ control ])
@ -18,13 +18,16 @@ func add_control(text, control) -> void:
var button = Button.new() var button = Button.new()
button.icon = preload("res://addons/material_maker/icons/link.tres") button.icon = preload("res://addons/material_maker/icons/link.tres")
grid.add_child(button) grid.add_child(button)
button.connect("pressed", self, "_on_Link_pressed", [ index ]) button.connect("pressed", self, "_on_Link_pressed", [ control.name ])
button = Button.new() button = Button.new()
button.icon = preload("res://addons/material_maker/icons/remove.tres") button.icon = preload("res://addons/material_maker/icons/remove.tres")
grid.add_child(button) grid.add_child(button)
button.connect("pressed", generator, "remove_parameter", [ index ]) button.connect("pressed", generator, "remove_parameter", [ control.name ])
func update_node() -> void: func update_node() -> void:
# Show or hide the close button
show_close = generator.can_be_deleted()
# Delete the contents and wait until it's done
var i : int = 0 var i : int = 0
for c in grid.get_children(): for c in grid.get_children():
c.queue_free() c.queue_free()
@ -36,11 +39,11 @@ func update_node() -> void:
if control != null: if control != null:
control.name = p.name control.name = p.name
controls[control.name] = control controls[control.name] = control
add_control(generator.widgets[i].label, control) add_control(generator.get_widget(p.name).label, control)
if generator.widgets[i].type == "config_control": if generator.widgets[i].type == "config_control":
var current = null var current = null
if control.get_item_count() > 0: if control.get_item_count() > 0:
control.selected = generator.parameters["param"+str(i)] control.selected = generator.parameters[p.name]
current = control.get_item_text(control.selected) current = control.get_item_text(control.selected)
control.add_separator() control.add_separator()
control.add_item("<add configuration>") control.add_item("<add configuration>")
@ -52,12 +55,11 @@ func update_node() -> void:
rect_size = Vector2(0, 0) rect_size = Vector2(0, 0)
initialize_properties() initialize_properties()
func _on_value_changed(new_value, variable) -> void: func _on_value_changed(new_value, variable : String) -> void:
var param_index = variable.trim_prefix("param").to_int() var widget = generator.get_widget(variable)
var widget = generator.widgets[param_index]
if widget.type == "config_control": if widget.type == "config_control":
var configuration_count = widget.configurations.size() var configuration_count = widget.configurations.size()
var control = grid.get_child(param_index*4+1) var control = controls[variable]
if new_value < configuration_count: if new_value < configuration_count:
._on_value_changed(new_value, variable) ._on_value_changed(new_value, variable)
var current = control.get_item_text(new_value) var current = control.get_item_text(new_value)
@ -71,39 +73,43 @@ func _on_value_changed(new_value, variable) -> void:
var dialog = preload("res://addons/material_maker/widgets/line_dialog.tscn").instance() var dialog = preload("res://addons/material_maker/widgets/line_dialog.tscn").instance()
add_child(dialog) add_child(dialog)
dialog.set_texts("Configuration", "Enter a name for the new configuration") dialog.set_texts("Configuration", "Enter a name for the new configuration")
dialog.connect("ok", self, "do_add_configuration", [ param_index ]) dialog.connect("ok", self, "do_add_configuration", [ variable ])
dialog.popup_centered() dialog.popup_centered()
3: 3:
generator.update_configuration(param_index, current) generator.update_configuration(variable, current)
4: 4:
generator.parameters[variable] = 0 generator.parameters[variable] = 0
generator.remove_configuration(param_index, current) generator.remove_configuration(variable, current)
_: _:
print(command) print(command)
else: else:
._on_value_changed(new_value, variable) ._on_value_changed(new_value, variable)
func do_add_configuration(config_name, param_index) -> void: func do_add_configuration(config_name : String, param_name : String) -> void:
generator.add_configuration(param_index, config_name) generator.add_configuration(param_name, config_name)
func on_label_changed(new_name, index) -> void: func on_label_changed(new_label, param_name) -> void:
generator.set_label(index, new_name) generator.set_label(param_name, new_label)
func _on_AddLink_pressed() -> void: func _on_AddLink_pressed() -> void:
var control = generator.create_linked_control("Unnamed")
var widget = Control.new() var widget = Control.new()
widget.name = control
add_control("Unnamed", widget) add_control("Unnamed", widget)
var link = MMNodeLink.new(get_parent()) var link = MMNodeLink.new(get_parent())
link.pick(widget, generator, generator.create_linked_control("Unnamed"), true) link.pick(widget, generator, control, true)
func _on_AddConfig_pressed() -> void: func _on_AddConfig_pressed() -> void:
var control = generator.create_config_control("Unnamed")
var widget = Control.new() var widget = Control.new()
widget.name = control
add_control("Unnamed", widget) add_control("Unnamed", widget)
var link = MMNodeLink.new(get_parent()) var link = MMNodeLink.new(get_parent())
link.pick(widget, generator, generator.create_config_control("Unnamed"), true) link.pick(widget, generator, control, true)
func _on_Link_pressed(index) -> void: func _on_Link_pressed(param_name) -> void:
var link = MMNodeLink.new(get_parent()) var link = MMNodeLink.new(get_parent())
link.pick(grid.get_child(index*4+1), generator, index) link.pick(controls[param_name], generator, param_name)
func _on_Remote_resize_request(new_minsize) -> void: func _on_Remote_resize_request(new_minsize) -> void:
rect_size = new_minsize rect_size = new_minsize
@ -118,8 +124,7 @@ func on_parameter_changed(p, v) -> void:
.on_parameter_changed(p, v) .on_parameter_changed(p, v)
func on_enter_widget(widget) -> void: func on_enter_widget(widget) -> void:
var param_index = widget.name.trim_prefix("param").to_int() var w = generator.get_widget(widget.name)
var w = generator.widgets[param_index]
var new_links = [] var new_links = []
for l in w.linked_widgets: for l in w.linked_widgets:
var graph_node = get_parent().get_node("node_"+l.node) var graph_node = get_parent().get_node("node_"+l.node)

View File

@ -7,8 +7,8 @@ var source = null
var target = null var target = null
var generator = null var generator = null
var param_index = 0 var param_name : String = ""
var creating = false var creating : bool = false
func _init(parent) -> void: func _init(parent) -> void:
size_flags_horizontal = SIZE_EXPAND_FILL size_flags_horizontal = SIZE_EXPAND_FILL
@ -17,11 +17,11 @@ func _init(parent) -> void:
rect_clip_content = true rect_clip_content = true
parent.add_child(self) parent.add_child(self)
func pick(s, g, i, c = false) -> void: func pick(s, g, n : String, c : bool = false) -> void:
source = s source = s
end = get_global_transform().xform_inv(source.get_global_transform().xform(0.5*source.rect_size)) end = get_global_transform().xform_inv(source.get_global_transform().xform(0.5*source.rect_size))
generator = g generator = g
param_index = i param_name = n
creating = c creating = c
set_process_input(true) set_process_input(true)
@ -69,16 +69,16 @@ func _input(event: InputEvent) -> void:
elif event is InputEventMouseMotion: elif event is InputEventMouseMotion:
var control = find_control(event.global_position) var control = find_control(event.global_position)
end = get_global_transform().xform_inv(event.global_position) end = get_global_transform().xform_inv(event.global_position)
target = control.widget if control != null and generator.can_link_parameter(param_index, control.node.generator, control.widget.name) else null target = control.widget if control != null and generator.can_link_parameter(param_name, control.node.generator, control.widget.name) else null
update() update()
elif event is InputEventMouseButton: elif event is InputEventMouseButton:
if event.pressed: if event.pressed:
if event.button_index == BUTTON_LEFT: if event.button_index == BUTTON_LEFT:
var control = find_control(event.global_position) var control = find_control(event.global_position)
if control != null: if control != null:
generator.link_parameter(param_index, control.node.generator, control.widget.name) generator.link_parameter(param_name, control.node.generator, control.widget.name)
elif creating: elif creating:
generator.remove_parameter(param_index) generator.remove_parameter(param_name)
set_process_input(false) set_process_input(false)
queue_free() queue_free()
get_tree().set_input_as_handled() get_tree().set_input_as_handled()