mirror of
https://github.com/Relintai/material-maker.git
synced 2024-11-13 06:27:18 +01:00
Added support for inputs in generic node and rewrote AdjustHSV as generic.
This commit is contained in:
parent
7f4cc79a47
commit
f06ffaf9f7
1
addons/material_maker/nodes/adjust_hsv.mmn
Normal file
1
addons/material_maker/nodes/adjust_hsv.mmn
Normal 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"}]}
|
@ -77,7 +77,7 @@ func update_node(data):
|
||||
control.selected = 0 if !p.has("default") else p.default-p.first
|
||||
elif p.type == "enum":
|
||||
control = OptionButton.new()
|
||||
for i in p.values.size():
|
||||
for i in range(p.values.size()):
|
||||
var value = p.values[i]
|
||||
control.add_item(value.name)
|
||||
control.selected = 0 if !p.has("default") else p.default
|
||||
@ -105,8 +105,25 @@ func update_node(data):
|
||||
initialize_properties(control_list)
|
||||
else:
|
||||
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:
|
||||
for i in model_data.outputs.size():
|
||||
for i in range(model_data.outputs.size()):
|
||||
var output = model_data.outputs[i]
|
||||
var enable_right = false
|
||||
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)
|
||||
elif output.has("f"):
|
||||
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:
|
||||
model_data.outputs = []
|
||||
if custom_node_buttons != null:
|
||||
move_child(custom_node_buttons, get_child_count()-1)
|
||||
|
||||
func subst(string, uv = ""):
|
||||
string = string.replace("$(name)", name)
|
||||
string = string.replace("$(seed)", str(get_seed()))
|
||||
string = string.replace("$(uv)", uv)
|
||||
func replace_input(string, input, type, src, context = null):
|
||||
var required_defs = ""
|
||||
var required_code = ""
|
||||
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:
|
||||
for p in model_data.parameters:
|
||||
if !p.has("name") or !p.has("type"):
|
||||
@ -144,32 +199,41 @@ func subst(string, uv = ""):
|
||||
elif p.type == "color":
|
||||
value_string = "vec4(%.9f, %.9f, %.9f, %.9f)" % [ value.r, value.g, value.b, value.a ]
|
||||
if value_string != null:
|
||||
string = string.replace("$(%s)" % p.name, value_string)
|
||||
return string
|
||||
string = replace_variable(string, p.name, value_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):
|
||||
var output_info = [ { field="rgba", type="vec4" }, { field="rgb", type="vec3" }, { field="f", type="float" } ]
|
||||
var rv = { defs="", code="" }
|
||||
var variant_string = uv+","+str(slot)
|
||||
if model_data != null and model_data.has("outputs") and model_data.outputs.size() > slot:
|
||||
var output = model_data.outputs[slot]
|
||||
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)
|
||||
if variant_index == -1:
|
||||
variant_index = generated_variants.size()
|
||||
generated_variants.append(variant_string)
|
||||
if output.has("rgba"):
|
||||
rv.code += "vec4 %s_%d_%d_rgba = %s;\n" % [ name, slot, variant_index, subst(output.rgba, uv) ]
|
||||
if output.has("rgb"):
|
||||
rv.code += "vec3 %s_%d_%d_rgb = %s;\n" % [ name, slot, variant_index, subst(output.rgb, uv) ]
|
||||
if output.has("f"):
|
||||
rv.code += "float %s_%d_%d_f = %s;\n" % [ name, slot, variant_index, subst(output.f, uv) ]
|
||||
if output.has("rgba"):
|
||||
rv.rgba = "%s_%d_%d_rgba" % [ name, slot, variant_index ]
|
||||
if output.has("rgb"):
|
||||
rv.rgb = "%s_%d_%d_rgb" % [ name, slot, variant_index ]
|
||||
if output.has("f"):
|
||||
rv.f = "%s_%d_%d_f" % [ name, slot, variant_index ]
|
||||
for t in output_info:
|
||||
if output.has(t.field):
|
||||
var subst_output = subst(output[t.field], uv, rv)
|
||||
rv.defs += subst_output.defs
|
||||
rv.code += subst_output.code
|
||||
rv.code += "%s %s_%d_%d_%s = %s;\n" % [ t.type, name, slot, variant_index, t.field, subst_output.string ]
|
||||
for t in output_info:
|
||||
if output.has(t.field):
|
||||
rv[t.field] = "%s_%d_%d_%s" % [ name, slot, variant_index, t.field ]
|
||||
return rv
|
||||
|
||||
func get_globals():
|
||||
|
@ -4,5 +4,26 @@ extends HBoxContainer
|
||||
func _ready():
|
||||
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():
|
||||
queue_free()
|
||||
|
@ -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/icons/minus.png" type="Texture" id=2]
|
||||
|
||||
[node name="Parameter" type="HBoxContainer"]
|
||||
[node name="Parameter" type="HBoxContainer" index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
@ -123,7 +123,7 @@ group = null
|
||||
text = "GreyScale"
|
||||
flat = false
|
||||
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
|
||||
_sections_unfolded = [ "Focus", "Hint", "Rect" ]
|
||||
|
||||
|
@ -21,9 +21,12 @@ func set_model_data(data):
|
||||
if data.has("parameters"):
|
||||
for p in data.parameters:
|
||||
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"):
|
||||
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"):
|
||||
$Sizer/Tabs/Global.text = data.global
|
||||
if data.has("instance"):
|
||||
@ -39,8 +42,12 @@ func get_model_data():
|
||||
for p in $Sizer/Tabs/General/Parameters/Sizer.get_children():
|
||||
if p.has_method("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 = []
|
||||
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"):
|
||||
data.outputs.append(o.get_model_data())
|
||||
return data
|
||||
@ -52,7 +59,7 @@ func _on_AddInput_pressed():
|
||||
add_item($Sizer/Tabs/General/Inputs/Sizer, InputEditor)
|
||||
|
||||
func _on_AddOutput_pressed():
|
||||
add_item($Sizer/Tabs/General/Outputs/Sizer, OutputEditor)
|
||||
add_item($Sizer/Tabs/Outputs/Outputs/Sizer, OutputEditor)
|
||||
|
||||
func _on_OK_pressed():
|
||||
emit_signal("node_changed", get_model_data())
|
||||
|
@ -222,14 +222,13 @@ _sections_unfolded = [ "Size Flags" ]
|
||||
|
||||
[node name="LabelInputs" type="Label" parent="Sizer/Tabs/General" index="3"]
|
||||
|
||||
visible = false
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_top = 176.0
|
||||
margin_right = 718.0
|
||||
margin_bottom = 190.0
|
||||
margin_top = 185.0
|
||||
margin_right = 825.0
|
||||
margin_bottom = 199.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 2
|
||||
@ -244,14 +243,13 @@ _sections_unfolded = [ "Size Flags" ]
|
||||
|
||||
[node name="Inputs" type="ScrollContainer" parent="Sizer/Tabs/General" index="4"]
|
||||
|
||||
visible = false
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_top = 139.0
|
||||
margin_right = 718.0
|
||||
margin_bottom = 228.0
|
||||
margin_top = 203.0
|
||||
margin_right = 825.0
|
||||
margin_bottom = 338.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = true
|
||||
mouse_filter = 0
|
||||
@ -271,7 +269,7 @@ anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_right = 718.0
|
||||
margin_right = 825.0
|
||||
margin_bottom = 22.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
@ -306,15 +304,33 @@ flat = true
|
||||
align = 1
|
||||
_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_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_top = 185.0
|
||||
margin_right = 825.0
|
||||
margin_bottom = 199.0
|
||||
margin_bottom = 14.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 2
|
||||
@ -327,13 +343,13 @@ lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
_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_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_top = 203.0
|
||||
margin_top = 18.0
|
||||
margin_right = 825.0
|
||||
margin_bottom = 338.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
@ -349,7 +365,7 @@ scroll_vertical = 0
|
||||
scroll_deadzone = 0
|
||||
_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_top = 0.0
|
||||
@ -366,7 +382,7 @@ size_flags_vertical = 1
|
||||
alignment = 0
|
||||
_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_top = 0.0
|
||||
@ -390,7 +406,7 @@ flat = true
|
||||
align = 1
|
||||
_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
|
||||
anchor_left = 0.0
|
||||
@ -425,7 +441,7 @@ caret_blink = false
|
||||
caret_blink_speed = 0.65
|
||||
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
|
||||
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/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"]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user