material-maker/addons/material_maker/engine/gen_remote.gd

233 lines
6.9 KiB
GDScript

tool
extends MMGenBase
class_name MMGenRemote
"""
Remote can be used to control parameters from several generators in the same graph
"""
var widgets = []
func can_be_deleted() -> bool:
return name != "gen_parameters"
func set_widgets(w : Array) -> void:
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() -> String:
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
return ""
func fix() -> void:
# Make sure all widgets have a name
var i = 0
for w in widgets:
if !w.has("name"):
w.name = get_next_widget_name()
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:
return "remote"
func get_type_name() -> String:
return "Parameters" if name == "gen_parameters" else "Remote"
func get_parameter_defs() -> Array:
var rv = []
var i = 0
for w in widgets:
match w.type:
"config_control":
var p : Dictionary = { name=w.name, label=w.label, type="enum" }
var configurations = w.configurations.keys()
configurations.sort()
if configurations == [ "False", "True" ]:
p.type = "boolean"
else:
p.values=[]
for c in configurations:
p.values.push_back({ name=c, value=c })
rv.append(p)
i += 1
"linked_control":
var linked = w.linked_widgets[0]
var p : Dictionary
if linked != null && is_inside_tree():
var gen = get_parent().get_node(linked.node)
if gen != null:
var gen_params = gen.get_parameter_defs()
for pd in gen_params:
if pd.name == linked.widget:
p = pd.duplicate(true)
break
p.name = w.name
p.label = w.label
rv.append(p)
i += 1
_:
print("Unsupported widget of type "+str(w.type))
return rv
func set_parameter(p : String, v) -> void:
var parent = get_parent()
if parent == null:
return
var widget = get_widget(p)
if !widget.empty():
match widget.type:
"linked_control":
for w in widget.linked_widgets:
var node = parent.get_node(w.node)
if node != null:
node.set_parameter(w.widget, v)
"config_control":
if v is bool:
v = 1 if v else 0
if v < widget.configurations.size():
var configurations = widget.configurations.keys()
configurations.sort()
for w in widget.configurations[configurations[v]]:
var node = parent.get_node(w.node)
if node != null:
node.set_parameter(w.widget, MMType.deserialize_value(w.value))
else:
# incorrect configuration index
print("error: incorrect config control parameter value")
return
.set_parameter(p, v)
if name == "gen_parameters":
get_parent().parameters[p] = v
func create_linked_control(label : String) -> String:
var n = get_next_widget_name()
widgets.push_back({ name=n, label=label, type="linked_control", linked_widgets=[] })
return n
func create_config_control(label : String) -> String:
var n = get_next_widget_name()
widgets.push_back({ name=n, label=label, type="config_control", linked_widgets=[], configurations={} })
return n
func set_label(widget_name : String, new_label : String) -> void:
get_widget(widget_name).label = new_label
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
if widget.type == "linked_control":
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
func link_parameter(widget_name : String, generator : MMGenBase, param : String) -> void:
if !can_link_parameter(widget_name, generator, param):
return
var widget : Dictionary = get_widget(widget_name)
widget.linked_widgets.push_back({ node=generator.name, widget=param })
if widget.linked_widgets.size() == 1:
match widget.type:
"linked_control":
parameters[widget_name] = generator.parameters[param]
"config_control":
parameters[widget_name] = 0
emit_signal("parameter_changed", "__update_all__", null)
func remove_parameter(widget_name : String) -> void:
for i in range(widgets.size()):
if widgets[i].name == widget_name:
widgets.remove(i)
break
emit_signal("parameter_changed", "__update_all__", null)
func add_configuration(widget_name : String, config_name : String) -> void:
var widget = get_widget(widget_name)
if widget.type == "config_control":
widget.configurations[config_name] = []
var configurations = widget.configurations.keys()
configurations.sort()
parameters[widget.name] = configurations.find(config_name)
update_configuration(widget_name, config_name)
func update_configuration(widget_name : String, config_name : String) -> void:
var widget = get_widget(widget_name)
if widget.type == "config_control":
var c = []
var parent = get_parent()
for w in widget.linked_widgets:
var g = parent.get_node(w.node)
if g != null:
var value = MMType.serialize_value(g.parameters[w.widget])
c.push_back({ node=w.node, widget=w.widget, value=value })
widget.configurations[config_name] = c
emit_signal("parameter_changed", "__update_all__", null)
func remove_configuration(widget_name : String, config_name : String) -> void:
var widget = get_widget(widget_name)
if widget.type == "config_control":
widget.configurations.erase(config_name)
emit_signal("parameter_changed", "__update_all__", null)
func _serialize(data: Dictionary) -> Dictionary:
data.type = "remote"
data.widgets = widgets
return data
func _deserialize(data : Dictionary) -> void:
set_widgets(data.widgets.duplicate(true))