Added support for inputs in generic node and rewrote AdjustHSV as generic.

This commit is contained in:
RodZill4 2018-11-11 19:18:26 +01:00
parent 7f4cc79a47
commit f06ffaf9f7
6 changed files with 155 additions and 46 deletions

View File

@ -0,0 +1 @@
{"global":"vec3 rgb_to_hsv(vec3 c) {\n\tvec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n\tvec4 p = c.g < c.b ? vec4(c.bg, K.wz) : vec4(c.gb, K.xy);\n\tvec4 q = c.r < p.x ? vec4(p.xyw, c.r) : vec4(c.r, p.yzx);\n\n\tfloat d = q.x - min(q.w, q.y);\n\tfloat e = 1.0e-10;\n\treturn vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n}\n\nvec3 hsv_to_rgb(vec3 c) {\n\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n\treturn c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n","inputs":[{"default":"vec3(1.0)","label":"","name":"in","type":"rgb"}],"instance":"vec3 $(name)_f(vec3 c) {\n\tvec3 hsv = rgb_to_hsv(c);\n\treturn hsv_to_rgb(vec3(fract(hsv.x+$(hue)), clamp(hsv.y*$(saturation), 0.0, 1.0), clamp(hsv.z*$(value), 0.0, 1.0)));\n}","name":"AdjustHSV","outputs":[{"rgb":"$(name)_f($in($(uv)))"}],"parameters":[{"default":0,"label":"Hue","max":0.5,"min":-0.5,"name":"hue","step":0,"type":"float"},{"default":1,"label":"Saturation","max":2,"min":0,"name":"saturation","step":0,"type":"float"},{"default":1,"label":"Value","max":2,"min":0,"name":"value","step":0,"type":"float"}]}

View File

@ -77,7 +77,7 @@ func update_node(data):
control.selected = 0 if !p.has("default") else p.default-p.first control.selected = 0 if !p.has("default") else p.default-p.first
elif p.type == "enum": elif p.type == "enum":
control = OptionButton.new() control = OptionButton.new()
for i in p.values.size(): for i in range(p.values.size()):
var value = p.values[i] var value = p.values[i]
control.add_item(value.name) control.add_item(value.name)
control.selected = 0 if !p.has("default") else p.default control.selected = 0 if !p.has("default") else p.default
@ -105,8 +105,25 @@ func update_node(data):
initialize_properties(control_list) initialize_properties(control_list)
else: else:
model_data.parameters = [] model_data.parameters = []
if model_data.has("inputs") and typeof(model_data.inputs) == TYPE_ARRAY:
for i in range(model_data.inputs.size()):
var input = model_data.inputs[i]
var enable_left = false
var color_left = Color(0.5, 0.5, 0.5)
if typeof(input) == TYPE_DICTIONARY:
if input.type == "rgb":
enable_left = true
color_left = Color(0.5, 0.5, 1.0)
elif input.type == "rgba":
enable_left = true
color_left = Color(0.0, 0.5, 0.0, 0.5)
else:
enable_left = true
set_slot(i, enable_left, 0, color_left, false, 0, Color())
else:
model_data.inputs = []
if model_data.has("outputs") and typeof(model_data.outputs) == TYPE_ARRAY: if model_data.has("outputs") and typeof(model_data.outputs) == TYPE_ARRAY:
for i in model_data.outputs.size(): for i in range(model_data.outputs.size()):
var output = model_data.outputs[i] var output = model_data.outputs[i]
var enable_right = false var enable_right = false
var color_right = Color(0.5, 0.5, 0.5) var color_right = Color(0.5, 0.5, 0.5)
@ -119,16 +136,54 @@ func update_node(data):
color_right = Color(0.0, 0.5, 0.0, 0.5) color_right = Color(0.0, 0.5, 0.0, 0.5)
elif output.has("f"): elif output.has("f"):
enable_right = true enable_right = true
set_slot(i, false, 0, color_right, enable_right, 0, color_right) set_slot(i, is_slot_enabled_left(i), get_slot_type_left(i), get_slot_color_left(i), enable_right, 0, color_right)
else: else:
model_data.outputs = [] model_data.outputs = []
if custom_node_buttons != null: if custom_node_buttons != null:
move_child(custom_node_buttons, get_child_count()-1) move_child(custom_node_buttons, get_child_count()-1)
func subst(string, uv = ""): func replace_input(string, input, type, src, context = null):
string = string.replace("$(name)", name) var required_defs = ""
string = string.replace("$(seed)", str(get_seed())) var required_code = ""
string = string.replace("$(uv)", uv) var keyword = "$%s(" % input
while true:
var position = string.find(keyword)
if position == -1:
break
var parenthesis_level = 0
var parameter_begin = position+keyword.length()
var parameter_end = -1
for i in range(parameter_begin, string.length()):
if string[i] == '(':
parenthesis_level += 1
elif string[i] == ')':
if parenthesis_level == 0:
parameter_end = i
break
else:
parenthesis_level -= 1
if parameter_end != -1:
var uv = string.substr(parameter_begin, parameter_end-parameter_begin)
var src_code = src.get_shader_code(uv)
required_defs += src_code.defs
required_code += src_code.code
string = string.replace(string.substr(position, parameter_end-position+1), src_code[type])
else:
print("syntax error")
break
return { string=string, defs=required_defs, code=required_code }
func replace_variable(string, variable, value):
string = string.replace("$(%s)" % variable, value)
return string
func subst(string, uv = "", context = null):
var required_defs = ""
var required_code = ""
string = replace_variable(string, "name", name)
string = replace_variable(string, "seed", str(get_seed()))
if uv != "":
string = replace_variable(string, "uv", uv)
if model_data.has("parameters") and typeof(model_data.parameters) == TYPE_ARRAY: if model_data.has("parameters") and typeof(model_data.parameters) == TYPE_ARRAY:
for p in model_data.parameters: for p in model_data.parameters:
if !p.has("name") or !p.has("type"): if !p.has("name") or !p.has("type"):
@ -144,32 +199,41 @@ func subst(string, uv = ""):
elif p.type == "color": elif p.type == "color":
value_string = "vec4(%.9f, %.9f, %.9f, %.9f)" % [ value.r, value.g, value.b, value.a ] value_string = "vec4(%.9f, %.9f, %.9f, %.9f)" % [ value.r, value.g, value.b, value.a ]
if value_string != null: if value_string != null:
string = string.replace("$(%s)" % p.name, value_string) string = replace_variable(string, p.name, value_string)
return string if model_data.has("inputs") and typeof(model_data.inputs) == TYPE_ARRAY:
for i in range(model_data.inputs.size()):
var input = model_data.inputs[i]
var source = get_source(i)
if source == null:
string = replace_variable(string, input.name, input.default)
else:
var result = replace_input(string, input.name, input.type, source, context)
string = result.string
required_defs += result.defs
required_code += result.code
return { string=string, defs=required_defs, code=required_code }
func _get_shader_code(uv, slot = 0): func _get_shader_code(uv, slot = 0):
var output_info = [ { field="rgba", type="vec4" }, { field="rgb", type="vec3" }, { field="f", type="float" } ]
var rv = { defs="", code="" } var rv = { defs="", code="" }
var variant_string = uv+","+str(slot) var variant_string = uv+","+str(slot)
if model_data != null and model_data.has("outputs") and model_data.outputs.size() > slot: if model_data != null and model_data.has("outputs") and model_data.outputs.size() > slot:
var output = model_data.outputs[slot] var output = model_data.outputs[slot]
if model_data.has("instance") && generated_variants.empty(): if model_data.has("instance") && generated_variants.empty():
rv.defs = subst(model_data.instance) rv.defs = subst(model_data.instance).string
var variant_index = generated_variants.find(variant_string) var variant_index = generated_variants.find(variant_string)
if variant_index == -1: if variant_index == -1:
variant_index = generated_variants.size() variant_index = generated_variants.size()
generated_variants.append(variant_string) generated_variants.append(variant_string)
if output.has("rgba"): for t in output_info:
rv.code += "vec4 %s_%d_%d_rgba = %s;\n" % [ name, slot, variant_index, subst(output.rgba, uv) ] if output.has(t.field):
if output.has("rgb"): var subst_output = subst(output[t.field], uv, rv)
rv.code += "vec3 %s_%d_%d_rgb = %s;\n" % [ name, slot, variant_index, subst(output.rgb, uv) ] rv.defs += subst_output.defs
if output.has("f"): rv.code += subst_output.code
rv.code += "float %s_%d_%d_f = %s;\n" % [ name, slot, variant_index, subst(output.f, uv) ] rv.code += "%s %s_%d_%d_%s = %s;\n" % [ t.type, name, slot, variant_index, t.field, subst_output.string ]
if output.has("rgba"): for t in output_info:
rv.rgba = "%s_%d_%d_rgba" % [ name, slot, variant_index ] if output.has(t.field):
if output.has("rgb"): rv[t.field] = "%s_%d_%d_%s" % [ name, slot, variant_index, t.field ]
rv.rgb = "%s_%d_%d_rgb" % [ name, slot, variant_index ]
if output.has("f"):
rv.f = "%s_%d_%d_f" % [ name, slot, variant_index ]
return rv return rv
func get_globals(): func get_globals():

View File

@ -4,5 +4,26 @@ extends HBoxContainer
func _ready(): func _ready():
pass pass
func set_model_data(data):
$Name.text = data.name
$Label.text = data.label
if data.type == "rgb":
$Type.selected = 1
elif data.type == "rgba":
$Type.selected = 2
else:
$Type.selected = 0
$Default.text = data.default
func get_model_data():
var data = { name=$Name.text, label=$Label.text, default=$Default.text }
if $Type.selected == 1:
data.type = "rgb"
elif $Type.selected == 2:
data.type = "rgba"
else:
data.type = "f"
return data
func _on_Delete_pressed(): func _on_Delete_pressed():
queue_free() queue_free()

View File

@ -3,7 +3,7 @@
[ext_resource path="res://addons/material_maker/widgets/node_editor/input.gd" type="Script" id=1] [ext_resource path="res://addons/material_maker/widgets/node_editor/input.gd" type="Script" id=1]
[ext_resource path="res://addons/material_maker/icons/minus.png" type="Texture" id=2] [ext_resource path="res://addons/material_maker/icons/minus.png" type="Texture" id=2]
[node name="Parameter" type="HBoxContainer"] [node name="Parameter" type="HBoxContainer" index="0"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
@ -123,7 +123,7 @@ group = null
text = "GreyScale" text = "GreyScale"
flat = false flat = false
align = 0 align = 0
items = [ "GreyScale", null, false, 0, null, "Color", null, false, 1, null ] items = [ "GreyScale", null, false, 0, null, "Color", null, false, 1, null, "RGBA", null, false, -1, null ]
selected = 0 selected = 0
_sections_unfolded = [ "Focus", "Hint", "Rect" ] _sections_unfolded = [ "Focus", "Hint", "Rect" ]

View File

@ -21,9 +21,12 @@ func set_model_data(data):
if data.has("parameters"): if data.has("parameters"):
for p in data.parameters: for p in data.parameters:
add_item($Sizer/Tabs/General/Parameters/Sizer, ParameterEditor).set_model_data(p) add_item($Sizer/Tabs/General/Parameters/Sizer, ParameterEditor).set_model_data(p)
if data.has("inputs"):
for i in data.inputs:
add_item($Sizer/Tabs/General/Inputs/Sizer, InputEditor).set_model_data(i)
if data.has("outputs"): if data.has("outputs"):
for o in data.outputs: for o in data.outputs:
add_item($Sizer/Tabs/General/Outputs/Sizer, OutputEditor).set_model_data(o) add_item($Sizer/Tabs/Outputs/Outputs/Sizer, OutputEditor).set_model_data(o)
if data.has("global"): if data.has("global"):
$Sizer/Tabs/Global.text = data.global $Sizer/Tabs/Global.text = data.global
if data.has("instance"): if data.has("instance"):
@ -39,8 +42,12 @@ func get_model_data():
for p in $Sizer/Tabs/General/Parameters/Sizer.get_children(): for p in $Sizer/Tabs/General/Parameters/Sizer.get_children():
if p.has_method("get_model_data"): if p.has_method("get_model_data"):
data.parameters.append(p.get_model_data()) data.parameters.append(p.get_model_data())
data.inputs = []
for i in $Sizer/Tabs/General/Inputs/Sizer.get_children():
if i.has_method("get_model_data"):
data.inputs.append(i.get_model_data())
data.outputs = [] data.outputs = []
for o in $Sizer/Tabs/General/Outputs/Sizer.get_children(): for o in $Sizer/Tabs/Outputs/Outputs/Sizer.get_children():
if o.has_method("get_model_data"): if o.has_method("get_model_data"):
data.outputs.append(o.get_model_data()) data.outputs.append(o.get_model_data())
return data return data
@ -52,7 +59,7 @@ func _on_AddInput_pressed():
add_item($Sizer/Tabs/General/Inputs/Sizer, InputEditor) add_item($Sizer/Tabs/General/Inputs/Sizer, InputEditor)
func _on_AddOutput_pressed(): func _on_AddOutput_pressed():
add_item($Sizer/Tabs/General/Outputs/Sizer, OutputEditor) add_item($Sizer/Tabs/Outputs/Outputs/Sizer, OutputEditor)
func _on_OK_pressed(): func _on_OK_pressed():
emit_signal("node_changed", get_model_data()) emit_signal("node_changed", get_model_data())

View File

@ -222,14 +222,13 @@ _sections_unfolded = [ "Size Flags" ]
[node name="LabelInputs" type="Label" parent="Sizer/Tabs/General" index="3"] [node name="LabelInputs" type="Label" parent="Sizer/Tabs/General" index="3"]
visible = false
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_top = 176.0 margin_top = 185.0
margin_right = 718.0 margin_right = 825.0
margin_bottom = 190.0 margin_bottom = 199.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false rect_clip_content = false
mouse_filter = 2 mouse_filter = 2
@ -244,14 +243,13 @@ _sections_unfolded = [ "Size Flags" ]
[node name="Inputs" type="ScrollContainer" parent="Sizer/Tabs/General" index="4"] [node name="Inputs" type="ScrollContainer" parent="Sizer/Tabs/General" index="4"]
visible = false
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_top = 139.0 margin_top = 203.0
margin_right = 718.0 margin_right = 825.0
margin_bottom = 228.0 margin_bottom = 338.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = true rect_clip_content = true
mouse_filter = 0 mouse_filter = 0
@ -271,7 +269,7 @@ anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_right = 718.0 margin_right = 825.0
margin_bottom = 22.0 margin_bottom = 22.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false rect_clip_content = false
@ -306,15 +304,33 @@ flat = true
align = 1 align = 1
_sections_unfolded = [ "Size Flags" ] _sections_unfolded = [ "Size Flags" ]
[node name="LabelOutputs" type="Label" parent="Sizer/Tabs/General" index="5"] [node name="Outputs" type="VBoxContainer" parent="Sizer/Tabs" index="1"]
visible = false
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 32.0
margin_right = -4.0
margin_bottom = -4.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="LabelOutputs" type="Label" parent="Sizer/Tabs/Outputs" index="0"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_top = 185.0
margin_right = 825.0 margin_right = 825.0
margin_bottom = 199.0 margin_bottom = 14.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false rect_clip_content = false
mouse_filter = 2 mouse_filter = 2
@ -327,13 +343,13 @@ lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
_sections_unfolded = [ "Size Flags" ] _sections_unfolded = [ "Size Flags" ]
[node name="Outputs" type="ScrollContainer" parent="Sizer/Tabs/General" index="6"] [node name="Outputs" type="ScrollContainer" parent="Sizer/Tabs/Outputs" index="1"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
anchor_right = 0.0 anchor_right = 0.0
anchor_bottom = 0.0 anchor_bottom = 0.0
margin_top = 203.0 margin_top = 18.0
margin_right = 825.0 margin_right = 825.0
margin_bottom = 338.0 margin_bottom = 338.0
rect_pivot_offset = Vector2( 0, 0 ) rect_pivot_offset = Vector2( 0, 0 )
@ -349,7 +365,7 @@ scroll_vertical = 0
scroll_deadzone = 0 scroll_deadzone = 0
_sections_unfolded = [ "Size Flags" ] _sections_unfolded = [ "Size Flags" ]
[node name="Sizer" type="VBoxContainer" parent="Sizer/Tabs/General/Outputs" index="0"] [node name="Sizer" type="VBoxContainer" parent="Sizer/Tabs/Outputs/Outputs" index="0"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
@ -366,7 +382,7 @@ size_flags_vertical = 1
alignment = 0 alignment = 0
_sections_unfolded = [ "Size Flags" ] _sections_unfolded = [ "Size Flags" ]
[node name="AddOutput" type="Button" parent="Sizer/Tabs/General/Outputs/Sizer" index="0"] [node name="AddOutput" type="Button" parent="Sizer/Tabs/Outputs/Outputs/Sizer" index="0"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
@ -390,7 +406,7 @@ flat = true
align = 1 align = 1
_sections_unfolded = [ "Size Flags" ] _sections_unfolded = [ "Size Flags" ]
[node name="Global" type="TextEdit" parent="Sizer/Tabs" index="1"] [node name="Global" type="TextEdit" parent="Sizer/Tabs" index="2"]
visible = false visible = false
anchor_left = 0.0 anchor_left = 0.0
@ -425,7 +441,7 @@ caret_blink = false
caret_blink_speed = 0.65 caret_blink_speed = 0.65
caret_moving_by_right_click = true caret_moving_by_right_click = true
[node name="Instance" type="TextEdit" parent="Sizer/Tabs" index="2"] [node name="Instance" type="TextEdit" parent="Sizer/Tabs" index="3"]
visible = false visible = false
anchor_left = 0.0 anchor_left = 0.0
@ -532,7 +548,7 @@ align = 1
[connection signal="pressed" from="Sizer/Tabs/General/Inputs/Sizer/AddInput" to="." method="_on_AddInput_pressed"] [connection signal="pressed" from="Sizer/Tabs/General/Inputs/Sizer/AddInput" to="." method="_on_AddInput_pressed"]
[connection signal="pressed" from="Sizer/Tabs/General/Outputs/Sizer/AddOutput" to="." method="_on_AddOutput_pressed"] [connection signal="pressed" from="Sizer/Tabs/Outputs/Outputs/Sizer/AddOutput" to="." method="_on_AddOutput_pressed"]
[connection signal="pressed" from="Sizer/HBoxContainer/OK" to="." method="_on_OK_pressed"] [connection signal="pressed" from="Sizer/HBoxContainer/OK" to="." method="_on_OK_pressed"]