Added a generic node type

Updated all nodes so parameters are located in a "parameters" variable.
Started writing a generic node model whose behavior is defined in a json file. Should be able to replace all generators so far.
Wrote json files for bricks and noise nodes.
Started preparing a custom node.
This commit is contained in:
RodZill4 2018-10-02 07:46:20 +02:00
parent ab9ae4ce5d
commit ee0bc96f30
38 changed files with 886 additions and 179 deletions

View File

@ -116,9 +116,15 @@ func create_nodes(data, position = null):
if data == null:
return
if data.has("type"):
var node = null
if File.new().file_exists("res://addons/material_maker/nodes/"+data.type+".json"):
node = preload("res://addons/material_maker/nodes/node_generic.gd").new()
node.model = data.type
else:
var node_type = load("res://addons/material_maker/nodes/"+data.type+"/"+data.type+".tscn")
if node_type != null:
var node = node_type.instance()
node = node_type.instance()
if node != null:
if data.has("name") && !has_node(data.name):
node.name = data.name
else:

View File

@ -3,11 +3,10 @@
[ext_resource path="res://addons/material_maker/graph_edit.gd" type="Script" id=1]
[ext_resource path="res://addons/material_maker/nodes/material/material.tscn" type="PackedScene" id=2]
[sub_resource type="Theme" id=1]
[node name="GraphEdit" type="GraphEdit"]
[node name="GraphEdit" type="GraphEdit" index="0"]
self_modulate = Color( 1, 1, 1, 0 )
anchor_left = 0.0
@ -22,7 +21,7 @@ mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
right_disconnects = true
scroll_offset = Vector2( -525, -250 )
scroll_offset = Vector2( -458.75, -292.25 )
snap_distance = 20
use_snap = false
zoom = 1.0
@ -31,11 +30,12 @@ _sections_unfolded = [ "Material", "Mouse", "Visibility" ]
[node name="Material" parent="." index="0" instance=ExtResource( 2 )]
margin_left = 525.0
margin_top = 250.0
margin_right = 755.0
margin_bottom = 470.0
margin_left = 658.75
margin_top = 292.25
margin_right = 888.75
margin_bottom = 512.25
theme = SubResource( 1 )
offset = Vector2( 200, 0 )
_sections_unfolded = [ "Anchor", "Margin", "Mouse", "Theme", "slot", "slot/0", "slot/1", "slot/2", "slot/3", "slot/4", "slot/5" ]
[node name="Timer" type="Timer" parent="." index="1"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

View File

@ -7,6 +7,7 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
@ -17,7 +18,29 @@
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="icons.svg">
<defs
id="defs2" />
id="defs2">
<linearGradient
inkscape:collect="always"
id="linearGradient836">
<stop
style="stop-color:#7c5000;stop-opacity:1"
offset="0"
id="stop832" />
<stop
style="stop-color:#ffcb68;stop-opacity:1"
offset="1"
id="stop834" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient836"
id="linearGradient840"
gradientUnits="userSpaceOnUse"
x1="25.135416"
y1="58.875"
x2="25.135416"
y2="48.291668" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
@ -26,8 +49,8 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="127.97633"
inkscape:cy="1033.5955"
inkscape:cx="161.54776"
inkscape:cy="928.95264"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
@ -48,7 +71,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@ -117,5 +140,70 @@
d="m 23.783078,44.110649 -4.508983,4.648736 -3.980261,-5.27284 a 12.770835,12.770835 0 0 0 -2.631282,1.045173 l 0.825522,6.441784 -6.571368,-0.17469 a 12.770835,12.770835 0 0 0 -0.7896172,2.557631 12.770835,12.770835 0 0 0 -0.027504,0.173796 l 5.5120272,3.347264 -4.1861363,4.972095 a 12.770835,12.770835 0 0 0 1.6563998,2.37002 l 5.9760855,-2.194035 1.267643,6.324612 a 12.770835,12.770835 0 0 0 2.907828,0.192046 l 1.997862,-6.001057 5.727797,2.948399 a 12.770835,12.770835 0 0 0 1.98019,-2.135962 l -3.455675,-5.317616 5.926699,-2.662342 a 12.770835,12.770835 0 0 0 -0.414249,-2.850168 l -6.383635,-0.620945 1.631047,-6.361785 a 12.770835,12.770835 0 0 0 -2.46039,-1.430116 z m -4.472442,8.529047 a 3.1927084,3.1927084 0 0 1 2.523332,3.744269 3.1927084,3.1927084 0 0 1 -3.744267,2.523336 3.1927084,3.1927084 0 0 1 -2.523335,-3.744269 3.1927084,3.1927084 0 0 1 3.74427,-2.523336 z"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.80446196;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
</g>
<g
id="g855"
transform="matrix(0.48976049,-0.48711566,0.48711566,0.48976049,-26.645494,39.257287)"
inkscape:export-filename="edit.png"
inkscape:export-xdpi="14.942099"
inkscape:export-ydpi="14.942099">
<rect
ry="0"
y="48.291664"
x="7.9375"
height="10.583336"
width="35.71875"
id="rect830"
style="opacity:1;fill:url(#linearGradient840);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
<path
inkscape:connector-curvature="0"
id="path842"
d="M 7.9374999,48.291667 -3.96875,53.583334 7.9374999,58.875001 Z"
style="fill:#ffe0a7;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:#242424;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.08819444px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M -9.9999999e-8,51.819444 -3.96875,53.583333 -9.9999999e-8,55.347222 Z"
id="path844"
inkscape:connector-curvature="0" />
<rect
ry="0"
y="48.291664"
x="38.364582"
height="10.583333"
width="2.6458333"
id="rect846"
style="opacity:1;fill:#adadad;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
<rect
style="opacity:1;fill:#ff66bc;fill-opacity:1;stroke:none;stroke-width:1.11803377;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
id="rect848"
width="6.6145821"
height="10.583336"
x="39.6875"
y="48.291664"
ry="2.8421709e-014" />
</g>
<g
id="g879"
inkscape:export-filename="save.png"
inkscape:export-xdpi="14"
inkscape:export-ydpi="14">
<path
id="rect859"
transform="scale(0.26458333)"
d="M 130 152.51953 L 130 262.51953 L 240 262.51953 L 240 163.23047 L 229.28906 152.51953 L 130 152.51953 z "
style="opacity:1;fill:#14008d;fill-opacity:1;stroke:none;stroke-width:3.77952766;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
<path
id="rect861"
transform="scale(0.26458333)"
d="M 155 152.51953 L 155 192.51953 L 215 192.51953 L 215 152.51953 L 155 152.51953 z M 195 162.51953 L 205 162.51953 L 205 182.51953 L 195 182.51953 L 195 162.51953 z "
style="opacity:1;fill:#afafaf;fill-opacity:1;stroke:none;stroke-width:4.04048538;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
<rect
ry="2.6458347"
y="53.583332"
x="37.041668"
height="14.552081"
width="23.812498"
id="rect874"
style="opacity:1;fill:#afafaf;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

View File

@ -241,7 +241,6 @@ size_flags_horizontal = 3
size_flags_vertical = 3
size_flags_stretch_ratio = 3.0
script = ExtResource( 4 )
_sections_unfolded = [ "custom_styles" ]
[node name="Tabs" type="Tabs" parent="VBoxContainer/HBoxContainer/Projects" index="1"]

View File

@ -18,6 +18,7 @@ class OutPort:
var generated = false
var generated_variants = []
var parameters = {}
var property_widgets = []
const Types = preload("res://addons/material_maker/types/types.gd")
@ -31,25 +32,25 @@ func initialize_properties(object_list):
if o == null:
print("error in node "+name)
elif o is LineEdit:
set(o.name, float(o.text))
parameters[o.name] = float(o.text)
o.connect("text_changed", self, "_on_text_changed", [ o.name ])
elif o is SpinBox:
set(o.name, o.value)
parameters[o.name] = o.value
o.connect("value_changed", self, "_on_value_changed", [ o.name ])
elif o is HSlider:
set(o.name, o.value)
parameters[o.name] = o.value
o.connect("value_changed", self, "_on_value_changed", [ o.name ])
elif o is OptionButton:
set(o.name, o.selected)
parameters[o.name] = o.selected
o.connect("item_selected", self, "_on_value_changed", [ o.name ])
elif o is CheckBox:
set(o.name, o.pressed)
parameters[o.name] = o.pressed
o.connect("toggled", self, "_on_value_changed", [ o.name ])
elif o is ColorPickerButton:
set(o.name, o.color)
parameters[o.name] = o.color
o.connect("color_changed", self, "_on_color_changed", [ o.name ])
elif o is Control and o.filename == "res://addons/material_maker/widgets/gradient_editor.tscn":
set(o.name, o.value)
parameters[o.name] = o.value
o.connect("updated", self, "_on_gradient_changed", [ o.name ])
else:
print("unsupported widget "+str(o))
@ -59,20 +60,21 @@ func get_seed():
func update_property_widgets():
for o in property_widgets:
if parameters.has(o.name) and parameters[o.name] != null:
if o is LineEdit:
o.text = str(get(o.name))
o.text = str(parameters[o.name])
elif o is SpinBox:
o.value = get(o.name)
o.value = parameters[o.name]
elif o is HSlider:
o.value = get(o.name)
o.value = parameters[o.name]
elif o is OptionButton:
o.selected = get(o.name)
o.selected = parameters[o.name]
elif o is CheckBox:
o.pressed = get(o.name)
o.pressed = parameters[o.name]
elif o is ColorPickerButton:
o.color = get(o.name)
o.color = parameters[o.name]
elif o is Control and o.filename == "res://addons/material_maker/widgets/gradient_editor.tscn":
o.value = get(o.name)
o.value = parameters[o.name]
else:
print("Failed to update "+o.name)
@ -80,19 +82,19 @@ func update_shaders():
get_parent().send_changed_signal()
func _on_text_changed(new_text, variable):
set(variable, float(new_text))
parameters[variable] = float(new_text)
update_shaders()
func _on_value_changed(new_value, variable):
set(variable, new_value)
parameters[variable] = new_value
update_shaders()
func _on_color_changed(new_color, variable):
set(variable, new_color)
parameters[variable] = new_color
update_shaders()
func _on_gradient_changed(new_gradient, variable):
set(variable, new_gradient)
parameters[variable] = new_gradient
update_shaders()
func get_source(index = 0):
@ -187,8 +189,8 @@ func serialize():
type = type.left(type.find_last("."))
var data = { name=name, type=type, node_position={x=offset.x, y=offset.y} }
for w in property_widgets:
var v = w.name
data[v] = Types.serialize_value(get(v)) # serialize_element(get(v))
var variable = w.name
data[variable] = Types.serialize_value(parameters[variable]) # serialize_element(get(v))
return data
func deserialize(data):
@ -198,7 +200,7 @@ func deserialize(data):
var variable = w.name
if data.has(variable):
var value = Types.deserialize_value(data[variable]) #deserialize_element(data[variable])
set(variable, value)
parameters[variable] = value
update_property_widgets()
# Render targets again for multipass filters

View File

@ -1,10 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var hue
var saturation
var value
func _ready():
initialize_properties([ $HBoxContainer1/hue, $HBoxContainer2/saturation, $HBoxContainer3/value ])
@ -17,7 +13,7 @@ func _get_shader_code(uv, output = 0):
src_code = src.get_shader_code(uv)
if generated_variants.empty():
rv.defs = src_code.defs;
rv.defs += "vec3 %s_rgb(vec3 c) { vec3 hsv = rgb2hsv(c); return hsv2rgb(vec3(fract(hsv.x+%.9f), clamp(hsv.y*%.9f, 0.0, 1.0), clamp(hsv.z*%.9f, 0.0, 1.0))); }\n" % [ name, hue, saturation, value ]
rv.defs += "vec3 %s_rgb(vec3 c) { vec3 hsv = rgb2hsv(c); return hsv2rgb(vec3(fract(hsv.x+%.9f), clamp(hsv.y*%.9f, 0.0, 1.0), clamp(hsv.z*%.9f, 0.0, 1.0))); }\n" % [ name, parameters.hue, parameters.saturation, parameters.value ]
var variant_index = generated_variants.find(uv)
if variant_index == -1:
variant_index = generated_variants.size()

View File

@ -2,7 +2,6 @@
[ext_resource path="res://addons/material_maker/nodes/adjust_hsv/adjust_hsv.gd" type="Script" id=1]
[sub_resource type="Theme" id=1]

View File

@ -1,9 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var blend_type = 0
var amount = 0.0
const BLEND_TYPES = [
{ name="Normal", shortname="normal" },
{ name="Dissolve", shortname="dissolve" },
@ -35,7 +32,7 @@ func _get_shader_code(uv):
var src0_code = src0.get_shader_code(uv)
var src1_code = src1.get_shader_code(uv)
var src2_code = { defs="", code="" }
var amount_str = "%.9f" % amount
var amount_str = "%.9f" % parameters.amount
if src2 != null:
src2_code = src2.get_shader_code(uv)
amount_str = src2_code.f
@ -46,7 +43,7 @@ func _get_shader_code(uv):
variant_index = generated_variants.size()
generated_variants.append(uv)
rv.code = src0_code.code+src1_code.code+src2_code.code
rv.code += "vec3 %s_%d_rgb = blend_%s(%s, %s, %s, %s);\n" % [ name, variant_index, BLEND_TYPES[blend_type].shortname, uv, src0_code.rgb, src1_code.rgb, amount_str ]
rv.code += "vec3 %s_%d_rgb = blend_%s(%s, %s, %s, %s);\n" % [ name, variant_index, BLEND_TYPES[parameters.blend_type].shortname, uv, src0_code.rgb, src1_code.rgb, amount_str ]
rv.rgb = "%s_%d_rgb" % [ name, variant_index ]
return rv

View File

@ -1,10 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var size = 5
var direction = 0
var sigma = 1.0
var input_shader = ""
var saved_texture
@ -21,17 +17,17 @@ func _ready():
$HBoxContainer1/size.clear()
for i in range(7):
$HBoxContainer1/size.add_item(str(int(pow(2, 5+i))), i)
$HBoxContainer1/size.selected = size
$HBoxContainer1/size.selected = 5
# init direction widget
$HBoxContainer2/direction.clear()
for d in DIRECTIONS:
$HBoxContainer2/direction.add_item(d.name)
$HBoxContainer2/direction.selected = direction
$HBoxContainer2/direction.selected = 0
initialize_properties([ $HBoxContainer1/size, $HBoxContainer2/direction, $HBoxContainer3/sigma ])
saved_texture = ImageTexture.new()
func get_gaussian_blur_shader(horizontal):
var convolution = { x=0, y=0, kernel=[], epsilon=1.0/pow(2, 5+size) }
var convolution = { x=0, y=0, kernel=[], epsilon=1.0/pow(2, 5+parameters.size) }
var kernel_size = 50
if horizontal:
convolution.x = kernel_size
@ -40,7 +36,7 @@ func get_gaussian_blur_shader(horizontal):
convolution.kernel.resize(2*kernel_size+1)
var sum = 0
for x in range(-kernel_size, kernel_size+1):
var coef = exp(-0.5*(pow((x)/sigma, 2.0))) / (2.0*PI*sigma*sigma)
var coef = exp(-0.5*(pow((x)/parameters.sigma, 2.0))) / (2.0*PI*parameters.sigma*parameters.sigma)
convolution.kernel[x+kernel_size] = coef
sum += coef
for x in range(-kernel_size, kernel_size+1):
@ -48,20 +44,19 @@ func get_gaussian_blur_shader(horizontal):
return get_convolution_shader(convolution)
func _rerender():
if DIRECTIONS[direction].mask & DIRECTION_H != 0:
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), saved_texture, self, "pass_1", [])
if DIRECTIONS[parameters.direction].mask & DIRECTION_H != 0:
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+parameters.size)), saved_texture, self, "pass_1", [])
else:
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), saved_texture, self, "pass_2", [])
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+parameters.size)), saved_texture, self, "pass_2", [])
func pass_1():
if DIRECTIONS[direction].mask & DIRECTION_V != 0:
get_parent().renderer.precalculate_shader(get_gaussian_blur_shader(true), { input=saved_texture }, int(pow(2, 5+size)), saved_texture, self, "pass_2", [])
if DIRECTIONS[parameters.direction].mask & DIRECTION_V != 0:
get_parent().renderer.precalculate_shader(get_gaussian_blur_shader(true), { input=saved_texture }, int(pow(2, 5+parameters.size)), saved_texture, self, "pass_2", [])
else:
get_parent().renderer.precalculate_shader(get_gaussian_blur_shader(true), { input=saved_texture }, int(pow(2, 5+size)), saved_texture, self, "rerender_targets", [])
get_parent().renderer.precalculate_shader(get_gaussian_blur_shader(true), { input=saved_texture }, int(pow(2, 5+parameters.size)), saved_texture, self, "rerender_targets", [])
func pass_2():
get_parent().renderer.precalculate_shader(get_gaussian_blur_shader(false), { input=saved_texture }, int(pow(2, 5+size)), saved_texture, self, "rerender_targets", [])
get_parent().renderer.precalculate_shader(get_gaussian_blur_shader(false), { input=saved_texture }, int(pow(2, 5+parameters.size)), saved_texture, self, "rerender_targets", [])
func get_textures():
var list = {}

View File

@ -0,0 +1,122 @@
{
"name":"Bricks",
"parameters":[
{ "name":"pattern", "label":"", "type":"enum", "values":[
{ "name":"Running bond", "value":"rb" },
{ "name":"Running bond (2)", "value":"rb2" },
{ "name":"HerringBone", "value":"hb" },
{ "name":"Basket weave", "value":"bw" },
{ "name":"Spanish bond", "value":"sb" }
] },
{ "name":"repeat", "label":"Repeat:", "type":"float", "min":1, "max":8, "step":1, "default":1, "widget":"spinbox" },
{ "name":"rows", "label":"Rows:", "type":"float", "min":1, "max":64, "step":1, "default":6, "widget":"spinbox" },
{ "name":"columns", "label":"Columns:", "type":"float", "min":1, "max":64, "step":1, "default":3, "widget":"spinbox" },
{ "name":"row_offset", "label":"Offset:", "type":"float", "min":0, "max":1, "default":0.5 },
{ "name":"mortar", "label":"Mortar:", "type":"float", "min":0, "max":0.5, "default":0.1 },
{ "name":"bevel", "label":"Bevel:", "type":"float", "min":0, "max":0.5, "default":0.1 }
],
"include":[ "noise" ],
"global":"
vec3 brick(vec2 uv, vec2 bmin, vec2 bmax, float mortar, float bevel) {
float color = 0.5;
vec2 c1 = (uv-bmin-vec2(mortar))/bevel;
vec2 c2 = (bmax-uv-vec2(mortar))/bevel;
vec2 c = min(c1, c2);
color = clamp(min(c.x, c.y), 0.0, 1.0);
return vec3(color, mod(bmin, vec2(1.0, 1.0)));
}
vec3 bricks_rb(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {
count *= repeat;
mortar /= max(count.x, count.y);
bevel /= max(count.x, count.y);
float x_offset = offset*step(0.5, fract(uv.y*count.y*0.5));
vec2 bmin = floor(vec2(uv.x*count.x-x_offset, uv.y*count.y));
bmin.x += x_offset;
bmin /= count;
return brick(uv, bmin, bmin+vec2(1.0)/count, mortar, bevel);
}
vec3 bricks_rb2(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {
count *= repeat;
mortar /= max(2.0*count.x, count.y);
bevel /= max(2.0*count.x, count.y);
float x_offset = offset*step(0.5, fract(uv.y*count.y*0.5));
count.x = count.x*(1.0+step(0.5, fract(uv.y*count.y*0.5)));
vec2 bmin = floor(vec2(uv.x*count.x-x_offset, uv.y*count.y));
bmin.x += x_offset;
bmin /= count;
return brick(uv, bmin, bmin+vec2(1.0)/count, mortar, bevel);
}
vec3 bricks_hb(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {
float pc = count.x+count.y;
float c = pc*repeat;
mortar /= c;
bevel /= c;
vec2 corner = floor(uv*c);
float cdiff = mod(corner.x-corner.y, pc);
if (cdiff < count.x) {
return brick(uv, (corner-vec2(cdiff, 0.0))/c, (corner-vec2(cdiff, 0.0)+vec2(count.x, 1.0))/c, mortar, bevel);
} else {
return brick(uv, (corner-vec2(0.0, pc-cdiff-1.0))/c, (corner-vec2(0.0, pc-cdiff-1.0)+vec2(1.0, count.y))/c, mortar, bevel);
}
}
vec3 bricks_bw(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {
vec2 c = 2.0*count*repeat;
float mc = max(c.x, c.y);
mortar /= mc;
bevel /= mc;
vec2 corner1 = floor(uv*c);
vec2 corner2 = count*floor(repeat*2.0*uv);
float cdiff = mod(dot(floor(repeat*2.0*uv), vec2(1.0)), 2.0);
vec2 corner;
vec2 size;
if (cdiff == 0.0) {
corner = vec2(corner1.x, corner2.y);
size = vec2(1.0, count.y);
} else {
corner = vec2(corner2.x, corner1.y);
size = vec2(count.x, 1.0);
}
return brick(uv, corner/c, (corner+size)/c, mortar, bevel);
}
vec3 bricks_sb(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {
vec2 c = (count+vec2(1.0))*repeat;
float mc = max(c.x, c.y);
mortar /= mc;
bevel /= mc;
vec2 corner1 = floor(uv*c);
vec2 corner2 = (count+vec2(1.0))*floor(repeat*uv);
vec2 rcorner = corner1 - corner2;
vec2 corner;
vec2 size;
if (rcorner.x == 0.0 && rcorner.y < count.y) {
corner = corner2;
size = vec2(1.0, count.y);
} else if (rcorner.y == 0.0) {
corner = corner2+vec2(1.0, 0.0);
size = vec2(count.x, 1.0);
} else if (rcorner.x == count.x) {
corner = corner2+vec2(count.x, 1.0);
size = vec2(1.0, count.y);
} else if (rcorner.y == count.y) {
corner = corner2+vec2(0.0, count.y);
size = vec2(count.x, 1.0);
} else {
corner = corner2+vec2(1.0);
size = vec2(count.x-1.0, count.y-1.0);
}
return brick(uv, corner/c, (corner+size)/c, mortar, bevel);
}",
"instance":"
vec3 $(name)_xyz(vec2 uv) {
return bricks_$(pattern)(uv, vec2($(columns), $(rows)), $(repeat), $(row_offset), $(mortar), max(0.001, $(bevel)));
}",
"outputs":[
{ "f":"$(name)_xyz($(uv)).x" },
{ "rgb":"rand3($(name)_xyz($(uv)).yz+vec2($(seed)))" }
]
}

View File

@ -1,14 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var pattern = 0
var repeat
var rows
var columns
var row_offset
var mortar
var bevel
const BRICK_PATTERNS = [
{ name="Running bond", suffix="rb", has_offset=true, has_repeat=false },
{ name="Running bond (2)", suffix="rb2", has_offset=true, has_repeat=false },
@ -26,7 +18,7 @@ func _ready():
func _get_shader_code(uv, slot = 0):
var rv = { defs="", code="" }
if generated_variants.empty():
rv.defs = "vec3 %s_xyz(vec2 uv) { return bricks_%s(uv, vec2(%d, %d), %.9f, %.9f, %.9f, %.9f); }\n" % [ name, BRICK_PATTERNS[pattern].suffix, columns, rows, repeat, row_offset, mortar, max(0.001, bevel) ]
rv.defs = "vec3 %s_xyz(vec2 uv) { return bricks_%s(uv, vec2(%d, %d), %.9f, %.9f, %.9f, %.9f); }\n" % [ name, BRICK_PATTERNS[parameters.pattern].suffix, parameters.columns, parameters.rows, parameters.repeat, parameters.row_offset, parameters.mortar, max(0.001, parameters.bevel) ]
var variant_index = generated_variants.find(uv)
if variant_index == -1:
variant_index = generated_variants.size()

View File

@ -1,8 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var gradient
func _ready():
initialize_properties([ $gradient ])
@ -13,7 +11,7 @@ func _get_shader_code(uv):
return rv
var src_code = src.get_shader_code(uv)
if generated_variants.empty():
rv.defs = src_code.defs+gradient.get_shader("%s_gradient" % name);
rv.defs = src_code.defs+parameters.gradient.get_shader("%s_gradient" % name);
var variant_index = generated_variants.find(uv)
if variant_index == -1:
variant_index = generated_variants.size()
@ -23,5 +21,5 @@ func _get_shader_code(uv):
return rv
func _on_Control_updated(v):
gradient = v
parameters.gradient = v
update_shaders()

View File

@ -0,0 +1,8 @@
tool
extends "res://addons/material_maker/nodes/node_generic.gd"
func _on_Edit_pressed():
pass # replace with function body
func _on_Save_pressed():
pass # replace with function body

View File

@ -0,0 +1,107 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/material_maker/nodes/custom/custom.gd" type="Script" id=1]
[ext_resource path="res://addons/material_maker/icons/edit.png" type="Texture" id=2]
[ext_resource path="res://addons/material_maker/icons/save.png" type="Texture" id=3]
[node name="Custom" type="GraphNode" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 385.0
margin_top = 287.0
margin_right = 479.0
margin_bottom = 338.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
title = "Custom"
offset = Vector2( 0, 0 )
show_close = true
resizable = false
selected = false
comment = false
overlay = 0
slot/0/left_enabled = false
slot/0/left_type = 0
slot/0/left_color = Color( 1, 1, 1, 1 )
slot/0/right_enabled = false
slot/0/right_type = 0
slot/0/right_color = Color( 1, 1, 1, 1 )
script = ExtResource( 1 )
[node name="CustomNodeButtons" type="HBoxContainer" parent="." index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 16.0
margin_top = 24.0
margin_right = 78.0
margin_bottom = 46.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="Edit" type="Button" parent="CustomNodeButtons" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 27.0
margin_bottom = 22.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
icon = ExtResource( 2 )
flat = true
align = 1
[node name="Save" type="Button" parent="CustomNodeButtons" index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 31.0
margin_right = 59.0
margin_bottom = 22.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
icon = ExtResource( 3 )
flat = true
align = 1
[connection signal="pressed" from="CustomNodeButtons/Edit" to="." method="_on_Edit_pressed"]
[connection signal="pressed" from="CustomNodeButtons/Save" to="." method="_on_Save_pressed"]

View File

@ -1,9 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var size = 5
var direction = 0
var input_shader = ""
var input_texture
var final_texture
@ -28,20 +25,20 @@ func _ready():
$HBoxContainer1/size.clear()
for i in range(7):
$HBoxContainer1/size.add_item(str(int(pow(2, 5+i))), i)
$HBoxContainer1/size.selected = size
$HBoxContainer1/size.selected = 5
input_texture = ImageTexture.new()
final_texture = ImageTexture.new()
initialize_properties([ $HBoxContainer1/size, $HBoxContainer2/direction ])
func _rerender():
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), input_texture, self, "pass_1", [])
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+parameters.size)), input_texture, self, "pass_1", [])
func pass_1():
var convolution = CONVOLUTION
convolution.epsilon=1.0/pow(2, 5+size)
convolution.epsilon=1.0/pow(2, 5+parameters.size)
for i in range(8):
convolution.kernel[INDICES[i]] = COEFS[(i+8-int(direction))%8]
get_parent().renderer.precalculate_shader(get_convolution_shader(convolution), {input=input_texture}, int(pow(2, 5+size)), final_texture, self, "rerender_targets", [])
convolution.kernel[INDICES[i]] = COEFS[(i+8-int(parameters.direction))%8]
get_parent().renderer.precalculate_shader(get_convolution_shader(convolution), {input=input_texture}, int(pow(2, 5+parameters.size)), final_texture, self, "rerender_targets", [])
func get_textures():
var list = {}

View File

@ -1,7 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var resolution = 1
var suffix = "suffix"
func _ready():
@ -18,7 +17,7 @@ func export_textures(prefix, size = null):
var suffix = $Suffix.text
if suffix != "":
if size == null:
size = int(pow(2, 8+resolution))
size = int(pow(2, 8+parameters.resolution))
get_parent().renderer.export_texture(get_source(), "%s_%s.png" % [ prefix, suffix ], size)
func serialize():

View File

@ -1,15 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var resolution = 1
var albedo_color
var metallic
var roughness
var emission_energy
var normal_scale
var ao_light_affect
var depth_scale
var texture_list
var current_material_list = []
@ -42,7 +33,7 @@ func _ready():
initialize_properties([ $resolution, $Albedo/albedo_color, $Metallic/metallic, $Roughness/roughness, $Emission/emission_energy, $NormalMap/normal_scale, $AmbientOcclusion/ao_light_affect, $DepthMap/depth_scale ])
func _rerender():
var size = int(pow(2, 8+resolution))
var size = int(pow(2, 8+parameters.resolution))
var has_textures = false
for t in texture_list:
var shader = generated_textures[t.texture].shader
@ -116,10 +107,10 @@ func get_generated_texture(slot, file_prefix = null):
func update_spatial_material(m, file_prefix = null):
var texture
m.albedo_color = albedo_color
m.albedo_color = parameters.albedo_color
m.albedo_texture = get_generated_texture("albedo", file_prefix)
m.metallic = metallic
m.roughness = roughness
m.metallic = parameters.metallic
m.roughness = parameters.roughness
if Engine.editor_hint:
texture = get_generated_texture("mrao", file_prefix)
m.metallic_texture = texture
@ -132,7 +123,7 @@ func update_spatial_material(m, file_prefix = null):
texture = get_generated_texture("emission", file_prefix)
if texture != null:
m.emission_enabled = true
m.emission_energy = emission_energy
m.emission_energy = parameters.emission_energy
m.emission_texture = texture
else:
m.emission_enabled = false
@ -145,7 +136,7 @@ func update_spatial_material(m, file_prefix = null):
if Engine.editor_hint:
if (generated_textures.mrao.mask & (1 << 2)) != 0:
m.ao_enabled = true
m.ao_light_affect = ao_light_affect
m.ao_light_affect = parameters.ao_light_affect
m.ao_texture = m.metallic_texture
m.ao_texture_channel = SpatialMaterial.TEXTURE_CHANNEL_BLUE
else:
@ -154,14 +145,14 @@ func update_spatial_material(m, file_prefix = null):
texture = get_generated_texture("ambient_occlusion", file_prefix)
if texture != null:
m.ao_enabled = true
m.ao_light_affect = ao_light_affect
m.ao_light_affect = parameters.ao_light_affect
m.ao_texture = texture
else:
m.ao_enabled = false
texture = get_generated_texture("depth_map", file_prefix)
if texture != null:
m.depth_enabled = true
m.depth_scale = depth_scale
m.depth_scale = parameters.depth_scale
m.depth_texture = texture
else:
m.depth_enabled = false
@ -173,7 +164,7 @@ func do_update_materials(material_list):
func export_textures(prefix, size = null):
if size == null:
size = int(pow(2, 8+resolution))
size = int(pow(2, 8+parameters.resolution))
for t in texture_list:
var texture = generated_textures[t.texture].texture
if texture != null:

View File

@ -0,0 +1,149 @@
tool
extends "res://addons/material_maker/node_base.gd"
export(String) var model = null setget set_model
var model_data = null
var uses_seed = false
func _ready():
show_close = true
connect("offset_changed", self, "_on_offset_changed")
func set_model(m):
if m != null and typeof(m) == TYPE_STRING:
var file = File.new()
var file_name = m
if !file.file_exists(file_name):
file_name = "res://addons/material_maker/nodes/%s.json" % [ m ]
if file.file_exists(file_name):
if file.open(file_name, File.READ) != OK:
return
var data = file.get_as_text()
var status = validate_json(data)
file.close()
if status != "":
print("Incorrect node description (%s)" % status)
return
data = parse_json(data)
model = m
update_node(data)
func update_node(data):
if typeof(data) != TYPE_DICTIONARY:
return
if !data.has("name"):
return
title = data.name
model_data = data
uses_seed = false
if model_data.has("instance") and model_data.instance.find("$(seed)"):
uses_seed = true
if model_data.has("parameters") and typeof(model_data.parameters) == TYPE_ARRAY:
var control_list = []
for p in model_data.parameters:
if !p.has("name") or !p.has("type"):
continue
var control = null
if p.type == "float":
if p.has("widget") and p.widget == "spinbox":
control = SpinBox.new()
else:
control = HSlider.new()
control.min_value = p.min
control.max_value = p.max
control.step = 0 if !p.has("step") else p.step
control.rect_min_size.x = 80
parameters[p.name] = 0.5*(p.min+p.max)
elif p.type == "size":
control = OptionButton.new()
for i in range(p.first, p.last):
var s = pow(2, i)
control.add_item("%dx%d" % [ s, s ])
control.selected = 0 if !p.has("default") else p.default
elif p.type == "enum":
control = OptionButton.new()
for i in p.values.size():
var value = p.values[i]
control.add_item(value.name)
control.selected = 0 if !p.has("default") else p.default
if control != null:
var label = p.name
control.name = label
control_list.append(control)
var sizer = HBoxContainer.new()
sizer.size_flags_horizontal = SIZE_EXPAND | SIZE_FILL
if p.has("label"):
label = p.label
if label != "":
var label_widget = Label.new()
label_widget.text = label
label_widget.size_flags_horizontal = SIZE_EXPAND | SIZE_FILL
sizer.add_child(label_widget)
control.size_flags_horizontal = SIZE_EXPAND | SIZE_FILL
sizer.add_child(control)
add_child(sizer)
initialize_properties(control_list)
else:
model_data.parameters = []
if model_data.has("outputs") and typeof(model_data.outputs) == TYPE_ARRAY:
for i in model_data.outputs.size():
var output = model_data.outputs[i]
var enable_right = false
var color_right = Color(0.5, 0.5, 0.5)
if typeof(output) == TYPE_DICTIONARY:
if output.has("rgb"):
enable_right = true
color_right = Color(0.5, 0.5, 1.0)
elif output.has("f"):
enable_right = true
set_slot(i, false, 0, color_right, enable_right, 0, color_right)
else:
model_data.outputs = []
func subst(string, uv = ""):
string = string.replace("$(name)", name)
string = string.replace("$(seed)", str(get_seed()))
string = string.replace("$(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"):
continue
var value = parameters[p.name]
var value_string = null
if p.type == "float":
value_string = "%.9f" % value
elif p.type == "size":
value_string = "%.9f" % pow(2, value+p.first)
elif p.type == "enum":
value_string = p.values[value].value
if value_string != null:
string = string.replace("$(%s)" % p.name, value_string)
return string
func _get_shader_code(uv, slot = 0):
var rv = { defs="", code="", f="0.0" }
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)
var variant_index = generated_variants.find(uv)
if variant_index == -1:
variant_index = generated_variants.size()
generated_variants.append(uv)
if output.has("rgb"):
rv.code += "vec3 %s_%d_rgb = %s;\n" % [ name, variant_index, subst(output.rgb, uv) ]
if output.has("f"):
rv.code += "float %s_%d_f = %s;\n" % [ name, variant_index, subst(output.f, uv) ]
if output.has("rgb"):
rv.rgb = "%s_%d_rgb" % [ name, variant_index ]
if output.has("f"):
rv.f = "%s_%d_f" % [ name, variant_index ]
return rv
func _on_offset_changed():
update_shaders()
func serialize():
var return_value = .serialize()
return_value.type = model
return return_value

View File

@ -0,0 +1,27 @@
{
"name":"Noise",
"parameters":[
{ "name":"size", "label":"Grid Size:", "type":"size", "first":2, "last":12, "default":8 },
{ "name":"density", "label":"Density:", "type":"float", "min":0.0, "max":1.0 }
],
"global":"
float rand(vec2 x) {
return fract(cos(dot(x, vec2(13.9898, 8.141))) * 43758.5453);
}
vec2 rand2(vec2 x) {
return fract(cos(vec2(dot(x, vec2(13.9898, 8.141)),
dot(x, vec2(3.4562, 17.398)))) * 43758.5453);
}
vec3 rand3(vec2 x) {
return fract(cos(vec3(dot(x, vec2(13.9898, 8.141)),
dot(x, vec2(3.4562, 17.398)),
dot(x, vec2(13.254, 5.867)))) * 43758.5453);
}",
"instance":"
float $(name)_f(vec2 uv) {
return dots(uv, 1.0/$(size), $(density), $(seed));
}",
"outputs":[
{ "f":"$(name)_f($(uv))" }
]
}

View File

@ -1,20 +1,17 @@
tool
extends "res://addons/material_maker/node_base.gd"
var size = 4
var density = 0.5
func _ready():
$HBoxContainer1/size.clear()
for i in range(7):
$HBoxContainer1/size.add_item(str(int(pow(2, 5+i))), i)
$HBoxContainer1/size.selected = size
$HBoxContainer1/size.selected = 4
initialize_properties([ $HBoxContainer1/size, $HBoxContainer2/density ])
func _get_shader_code(uv):
var rv = { defs="", code="" }
if generated_variants.empty():
rv.defs = "float %s_f(vec2 uv) { return dots(uv, %.9f, %.9f, %d); }\n" % [ name, 1.0/pow(2.0, 5.0+size), density, get_seed() ]
rv.defs = "float %s_f(vec2 uv) { return dots(uv, %.9f, %.9f, %d); }\n" % [ name, 1.0/pow(2.0, 5.0+parameters.size), parameters.density, get_seed() ]
var variant_index = generated_variants.find(uv)
if variant_index == -1:
variant_index = generated_variants.size()

View File

@ -2,11 +2,10 @@
[ext_resource path="res://addons/material_maker/nodes/noise/noise.gd" type="Script" id=1]
[sub_resource type="Theme" id=1]
[node name="Dots" type="GraphNode" index="0"]
[node name="Dots" type="GraphNode"]
anchor_left = 0.0
anchor_top = 0.0

View File

@ -1,9 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var size = 5
var amount = 0.0
var input_shader = ""
var input_texture
var final_texture
@ -29,19 +26,20 @@ func _ready():
$HBoxContainer1/size.clear()
for i in range(7):
$HBoxContainer1/size.add_item(str(int(pow(2, 5+i))), i)
$HBoxContainer1/size.selected = size
parameters.size = 2
$HBoxContainer1/size.selected = parameters.size
input_texture = ImageTexture.new()
final_texture = ImageTexture.new()
initialize_properties([ $HBoxContainer1/size, $HBoxContainer2/amount ])
func _rerender():
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), input_texture, self, "pass_1", [])
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+parameters.size)), input_texture, self, "pass_1", [])
func pass_1():
var convolution = CONVOLUTION
convolution.epsilon=1.0/pow(2, 5+size)
convolution.scale_before_normalize = pow(2, size-1)*amount
get_parent().renderer.precalculate_shader(get_convolution_shader(convolution), { input=input_texture}, int(pow(2, 5+size)), final_texture, self, "rerender_targets", [])
convolution.epsilon=1.0/pow(2, 5+parameters.size)
convolution.scale_before_normalize = pow(2, parameters.size-1)*parameters.amount
get_parent().renderer.precalculate_shader(get_convolution_shader(convolution), { input=input_texture}, int(pow(2, 5+parameters.size)), final_texture, self, "rerender_targets", [])
func get_textures():
var list = {}

View File

@ -1,12 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var mix = 0;
var x_wave = 0
var x_scale = 4.0
var y_wave = 0
var y_scale = 4.0
const WAVE_FCT = [ "wave_sin", "wave_triangle", "wave_square", "fract", "wave_constant" ]
const MIX_FCT = [ "mix_multiply", "mix_add", "mix_max", "mix_min", "mix_xor", "mix_pow" ]
@ -16,7 +10,7 @@ func _ready():
func _get_shader_code(uv):
var rv = { defs="", code="" }
if generated_variants.empty():
rv.defs = "float %s_f(vec2 uv) { uv *= vec2(%.9f, %.9f); return %s(%s(uv.x), %s(uv.y)); }\n" % [ name, x_scale, y_scale, MIX_FCT[mix], WAVE_FCT[x_wave], WAVE_FCT[y_wave] ]
rv.defs = "float %s_f(vec2 uv) { uv *= vec2(%.9f, %.9f); return %s(%s(uv.x), %s(uv.y)); }\n" % [ name, parameters.x_scale, parameters.y_scale, MIX_FCT[parameters.mix], WAVE_FCT[parameters.x_wave], WAVE_FCT[parameters.y_wave] ]
var variant_index = generated_variants.find(uv)
if variant_index == -1:
variant_index = generated_variants.size()

View File

@ -1,11 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var scale_x
var scale_y
var iterations
var persistence
func _ready():
set_slot(0, false, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1))
initialize_properties([ $GridContainer/scale_x, $GridContainer/scale_y, $GridContainer/iterations, $GridContainer/persistence ])
@ -13,7 +8,7 @@ func _ready():
func _get_shader_code(uv):
var rv = { defs="", code="" }
if generated_variants.empty():
rv.defs = "float %s_f(vec2 uv) { return perlin(uv, vec2(%f, %f), %d, %.9f, %d); }\n" % [ name, scale_x, scale_y, iterations, persistence, get_seed() ]
rv.defs = "float %s_f(vec2 uv) { return perlin(uv, vec2(%f, %f), %d, %.9f, %d); }\n" % [ name, parameters.scale_x, parameters.scale_y, parameters.iterations, parameters.persistence, get_seed() ]
var variant_index = generated_variants.find(uv)
if variant_index == -1:
variant_index = generated_variants.size()

View File

@ -1,11 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var shape
var sides
var radius
var edge
const SHAPES = [ "circle", "polygon", "star", "curved_star", "rays" ]
func _ready():
@ -13,5 +8,5 @@ func _ready():
func _get_shader_code(uv):
var rv = { defs="", code="" }
rv.f = "%s(%s, %d, %f, %f)" % [ SHAPES[shape], uv, sides, radius, edge ]
rv.f = "%s(%s, %d, %f, %f)" % [ SHAPES[parameters.shape], uv, parameters.sides, parameters.radius, parameters.edge ]
return rv

View File

@ -1,8 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var source = 0
func _ready():
initialize_properties([ $source ])
@ -12,7 +10,7 @@ func reset():
func _get_shader_code(uv, index = 0):
var rv = { defs="", code="" }
var src = get_source(2*source+index)
var src = get_source(2*parameters.source+index)
var src_code = { defs="", code="", rgb="0.0" }
if src != null:
src_code = src.get_shader_code(uv)

View File

@ -1,13 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var translate_x = 0.0
var translate_y = 0.0
var rotate = 0.0
var scale_x = 1.0
var scale_y = 1.0
var repeat = true
func _ready():
set_slot(0, true, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1))
initialize_properties([ $HBoxContainer1/translate_x, $HBoxContainer2/translate_y, $HBoxContainer3/rotate, $HBoxContainer4/scale_x, $HBoxContainer5/scale_y, $repeat ])
@ -30,7 +23,7 @@ func _get_shader_code(uv):
rv.defs += tsrc_code.defs
rv.code += tsrc_code.code
inputs[i] = "*(2.0*(%s)-1.0)" % tsrc_code.f
rv.code += "vec2 %s_%d_uv = %s(%s, vec2(%.9f%s, %.9f%s), %.9f%s, vec2(%.9f%s, %.9f%s));\n" % [ name, variant_index, "transform_repeat" if repeat else "transform_norepeat", uv, translate_x, inputs[0], translate_y, inputs[1], PI*rotate/180.0, inputs[2], scale_x, inputs[3], scale_y, inputs[4] ]
rv.code += "vec2 %s_%d_uv = %s(%s, vec2(%.9f%s, %.9f%s), %.9f%s, vec2(%.9f%s, %.9f%s));\n" % [ name, variant_index, "transform_repeat" if parameters.repeat else "transform_norepeat", uv, parameters.translate_x, inputs[0], parameters.translate_y, inputs[1], PI*parameters.rotate/180.0, inputs[2], parameters.scale_x, inputs[3], parameters.scale_y, inputs[4] ]
var src_code = src.get_shader_code("%s_%d_uv" % [ name, variant_index ])
if rv.code != "":
if generated_variants.size() == 1:
@ -41,6 +34,6 @@ func _get_shader_code(uv):
func deserialize(data):
if data.has("scale"):
scale_x = data.scale
scale_y = data.scale
parameters.scale_x = data.scale
parameters.scale_y = data.scale
.deserialize(data)

View File

@ -1,12 +1,10 @@
tool
extends "res://addons/material_maker/node_base.gd"
var color = Color(0.0, 0.0, 0.0)
func _ready():
initialize_properties([ $color ])
func _get_shader_code(uv):
var rv = { defs="", code="" }
rv.rgb = "vec3(%.9f, %.9f, %.9f)" % [ color.r, color.g, color.b ]
rv.rgb = "vec3(%.9f, %.9f, %.9f)" % [ parameters.color.r, parameters.color.g, parameters.color.b ]
return rv

View File

@ -1,10 +1,6 @@
tool
extends "res://addons/material_maker/node_base.gd"
var scale_x
var scale_y
var intensity
func _ready():
set_slot(0, false, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1))
initialize_properties([ $HBoxContainer1/scale_x, $HBoxContainer2/scale_y, $HBoxContainer3/intensity ])
@ -12,7 +8,7 @@ func _ready():
func _get_shader_code(uv, slot = 0):
var rv = { defs="", code="" }
if generated_variants.empty():
rv.defs = "vec4 %s_xyzw(vec2 uv) { return voronoi(uv, vec2(%f, %f), %.9f, %d); }\n" % [ name, scale_x, scale_y, intensity, get_seed() ]
rv.defs = "vec4 %s_xyzw(vec2 uv) { return voronoi(uv, vec2(%f, %f), %.9f, %d); }\n" % [ name, parameters.scale_x, parameters.scale_y, parameters.intensity, get_seed() ]
var variant_index = generated_variants.find(uv)
if variant_index == -1:
variant_index = generated_variants.size()

View File

@ -1,11 +1,7 @@
tool
extends "res://addons/material_maker/node_base.gd"
var amount = 0.0
func _ready():
set_slot(0, true, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1))
set_slot(1, true, 0, Color(0.5, 0.5, 1), false, 0, Color(0.5, 0.5, 1))
initialize_properties([ $amount ])
func _get_shader_code(uv):
@ -25,7 +21,7 @@ func _get_shader_code(uv):
var src1_code3 = src1.get_shader_code("fract(%s-vec2(0.0, %.9f))" % [ uv, epsilon ])
rv.defs = src1_code0.defs
rv.code = src1_code0.code+src1_code1.code+src1_code2.code+src1_code3.code
rv.code += "vec2 %s_%d_uv = %s+%.9f*vec2((%s)-(%s), (%s)-(%s));\n" % [ name, variant_index, uv, amount, src1_code0.f, src1_code1.f, src1_code2.f, src1_code3.f ]
rv.code += "vec2 %s_%d_uv = %s+%.9f*vec2((%s)-(%s), (%s)-(%s));\n" % [ name, variant_index, uv, parameters.amount, src1_code0.f, src1_code1.f, src1_code2.f, src1_code3.f ]
var src0_code = src0.get_shader_code("%s_%d_uv" % [ name, variant_index ])
rv.defs += src0_code.defs
rv.code += src0_code.code

View File

@ -2,7 +2,6 @@
[ext_resource path="res://addons/material_maker/nodes/warp/warp.gd" type="Script" id=1]
[sub_resource type="Theme" id=1]

View File

@ -52,7 +52,7 @@ func apply_configuration(c):
for w in configurations[c]:
var value = duplicate_value(w.value)
w.widget.set(WIDGETS[get_widget_type(w.widget)].value_attr, value)
w.node.set(w.widget.name, value)
w.node.parameters[w.widget.name] = value
var graph_node = get_parent()
while !(graph_node is GraphNode):
graph_node = graph_node.get_parent()
@ -61,7 +61,7 @@ func apply_configuration(c):
func do_update_configuration(name):
var configuration = []
for w in linked_widgets:
configuration.append({ node=w.node, widget=w.widget, value=duplicate_value(w.node.get(w.widget.name)) })
configuration.append({ node=w.node, widget=w.widget, value=duplicate_value(w.node.parameters[w.widget.name]) })
configurations[name] = configuration
current = name
update_options()

View File

@ -68,24 +68,25 @@ func update_shaders():
func _on_value_changed(v):
for l in linked_widgets:
l.widget.value = v
l.node.set(l.widget.name, v)
l.node.parameters[l.widget.name] = v
update_shaders()
func _on_color_changed(c):
for l in linked_widgets:
l.widget.color = c
l.node.set(l.widget.name, c)
l.node.parameters[l.widget.name] = c
update_shaders()
func _on_item_selected(i):
for l in linked_widgets:
l.widget.selected = i
l.node.set(l.widget.name, i)
l.node.parameters[l.widget.name] = i
update_shaders()
func _on_gradient_updated(g):
for l in linked_widgets:
l.widget.value = g
l.node.parameters[l.widget.name] = g
update_shaders()
func serialize():

View File

@ -0,0 +1,187 @@
[gd_scene format=2]
[node name="WindowDialog" type="WindowDialog" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 666.0
margin_bottom = 592.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
popup_exclusive = false
window_title = "Custom node"
resizable = true
[node name="TabContainer" type="TabContainer" parent="." index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_right = -89.0
margin_bottom = -41.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
tab_align = 1
tabs_visible = true
[node name="General" type="VBoxContainer" parent="TabContainer" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_top = 26.0
margin_bottom = 26.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 1
mouse_default_cursor_shape = 0
size_flags_horizontal = 3
size_flags_vertical = 3
alignment = 0
_sections_unfolded = [ "Anchor", "Grow Direction", "Margin", "Size Flags" ]
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/General" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 577.0
margin_bottom = 24.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 1
mouse_default_cursor_shape = 0
size_flags_horizontal = 3
size_flags_vertical = 1
alignment = 0
_sections_unfolded = [ "Size Flags" ]
[node name="Label" type="Label" parent="TabContainer/General/HBoxContainer" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_top = 5.0
margin_right = 42.0
margin_bottom = 19.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "Name:"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="LineEdit" type="LineEdit" parent="TabContainer/General/HBoxContainer" index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 46.0
margin_right = 577.0
margin_bottom = 24.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 1
size_flags_horizontal = 3
size_flags_vertical = 1
focus_mode = 2
context_menu_enabled = true
placeholder_alpha = 0.6
caret_blink = false
caret_blink_speed = 0.65
caret_position = 0
_sections_unfolded = [ "Size Flags" ]
[node name="Global functions" type="TextEdit" parent="TabContainer" index="1"]
visible = false
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_top = 72.0
margin_right = -8.0
margin_bottom = 36.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 3
size_flags_vertical = 3
text = ""
readonly = false
highlight_current_line = false
syntax_highlighting = false
show_line_numbers = false
highlight_all_occurrences = false
override_selected_font_color = false
context_menu_enabled = true
smooth_scrolling = false
v_scroll_speed = 80.0
hiding_enabled = 0
wrap_lines = false
caret_block_mode = false
caret_blink = false
caret_blink_speed = 0.65
caret_moving_by_right_click = true
_sections_unfolded = [ "Size Flags" ]
[node name="Instance functions" type="TextEdit" parent="TabContainer" index="2"]
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
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 3
size_flags_vertical = 3
text = ""
readonly = false
highlight_current_line = false
syntax_highlighting = false
show_line_numbers = false
highlight_all_occurrences = false
override_selected_font_color = false
context_menu_enabled = true
smooth_scrolling = false
v_scroll_speed = 80.0
hiding_enabled = 0
wrap_lines = false
caret_block_mode = false
caret_blink = false
caret_blink_speed = 0.65
caret_moving_by_right_click = true
_sections_unfolded = [ "Size Flags" ]

View File

@ -0,0 +1,16 @@
extends WindowDialog
var model_data
func _init(data):
model_data = data
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
pass
#func _process(delta):
# # Called every frame. Delta is time since last frame.
# # Update game logic here.
# pass

View File

@ -0,0 +1,73 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/material_maker/widgets/node_editor/node_editor.gd" type="Script" id=1]
[node name="NodeEditor" type="WindowDialog" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 469.0
margin_bottom = 373.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
popup_exclusive = false
window_title = "Node Editor"
resizable = false
script = ExtResource( 1 )
[node name="Tabs" type="TabContainer" parent="." index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
tab_align = 0
tabs_visible = true
[node name="Global" type="TextEdit" parent="Tabs" index="0"]
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
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
text = ""
readonly = false
highlight_current_line = false
syntax_highlighting = false
show_line_numbers = false
highlight_all_occurrences = false
override_selected_font_color = false
context_menu_enabled = true
smooth_scrolling = false
v_scroll_speed = 80.0
hiding_enabled = 0
wrap_lines = false
caret_block_mode = false
caret_blink = false
caret_blink_speed = 0.65
caret_moving_by_right_click = true