From ee0bc96f3054935e30ebb4c17efbb9fad24200ce Mon Sep 17 00:00:00 2001 From: RodZill4 Date: Tue, 2 Oct 2018 07:46:20 +0200 Subject: [PATCH] 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. --- addons/material_maker/graph_edit.gd | 12 +- addons/material_maker/graph_edit.tscn | 14 +- addons/material_maker/icons/edit.png | Bin 0 -> 482 bytes addons/material_maker/icons/icons.svg | 96 ++++++++- addons/material_maker/icons/save.png | Bin 0 -> 375 bytes addons/material_maker/main_window.tscn | 1 - addons/material_maker/node_base.gd | 62 +++--- .../nodes/adjust_hsv/adjust_hsv.gd | 6 +- .../nodes/adjust_hsv/adjust_hsv.tscn | 1 - addons/material_maker/nodes/blend/blend.gd | 7 +- addons/material_maker/nodes/blur/blur.gd | 27 ++- addons/material_maker/nodes/bricks.json | 122 ++++++++++++ addons/material_maker/nodes/bricks/bricks.gd | 10 +- .../material_maker/nodes/colorize/colorize.gd | 6 +- addons/material_maker/nodes/custom/custom.gd | 8 + .../material_maker/nodes/custom/custom.tscn | 107 ++++++++++ addons/material_maker/nodes/emboss/emboss.gd | 13 +- addons/material_maker/nodes/export/export.gd | 3 +- .../material_maker/nodes/material/material.gd | 27 +-- addons/material_maker/nodes/node_generic.gd | 149 ++++++++++++++ addons/material_maker/nodes/noise.json | 27 +++ addons/material_maker/nodes/noise/noise.gd | 7 +- addons/material_maker/nodes/noise/noise.tscn | 3 +- .../nodes/normal_map/normal_map.gd | 14 +- .../material_maker/nodes/pattern/pattern.gd | 8 +- addons/material_maker/nodes/perlin/perlin.gd | 7 +- addons/material_maker/nodes/shape/shape.gd | 7 +- addons/material_maker/nodes/switch/switch.gd | 4 +- .../nodes/transform/transform.gd | 13 +- .../material_maker/nodes/uniform/uniform.gd | 4 +- .../material_maker/nodes/voronoi/voronoi.gd | 6 +- addons/material_maker/nodes/warp/warp.gd | 6 +- addons/material_maker/nodes/warp/warp.tscn | 1 - .../widgets/linked_widgets/config_control.gd | 4 +- .../widgets/linked_widgets/linked_control.gd | 7 +- .../material_maker/widgets/node_editor.tscn | 187 ++++++++++++++++++ .../widgets/node_editor/node_editor.gd | 16 ++ .../widgets/node_editor/node_editor.tscn | 73 +++++++ 38 files changed, 886 insertions(+), 179 deletions(-) create mode 100644 addons/material_maker/icons/edit.png create mode 100644 addons/material_maker/icons/save.png create mode 100644 addons/material_maker/nodes/bricks.json create mode 100644 addons/material_maker/nodes/custom/custom.gd create mode 100644 addons/material_maker/nodes/custom/custom.tscn create mode 100644 addons/material_maker/nodes/node_generic.gd create mode 100644 addons/material_maker/nodes/noise.json create mode 100644 addons/material_maker/widgets/node_editor.tscn create mode 100644 addons/material_maker/widgets/node_editor/node_editor.gd create mode 100644 addons/material_maker/widgets/node_editor/node_editor.tscn diff --git a/addons/material_maker/graph_edit.gd b/addons/material_maker/graph_edit.gd index 22b2501..eab0249 100644 --- a/addons/material_maker/graph_edit.gd +++ b/addons/material_maker/graph_edit.gd @@ -116,9 +116,15 @@ func create_nodes(data, position = null): if data == null: return if data.has("type"): - var node_type = load("res://addons/material_maker/nodes/"+data.type+"/"+data.type+".tscn") - if node_type != null: - var node = node_type.instance() + 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: + node = node_type.instance() + if node != null: if data.has("name") && !has_node(data.name): node.name = data.name else: diff --git a/addons/material_maker/graph_edit.tscn b/addons/material_maker/graph_edit.tscn index 1f756ee..3d9f9ed 100644 --- a/addons/material_maker/graph_edit.tscn +++ b/addons/material_maker/graph_edit.tscn @@ -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"] diff --git a/addons/material_maker/icons/edit.png b/addons/material_maker/icons/edit.png new file mode 100644 index 0000000000000000000000000000000000000000..4e76bbcff1b42b558741d8a41805735decfed4b3 GIT binary patch literal 482 zcmeAS@N?(olHy`uVBq!ia0vp^{24nJ zFsXwu<36Df4xpf9iEBhjaDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$QVa}?@t!V@ zAsQ2>p11X2Dr8{&@O{7aDn;ET?>9{FSg~+gTZWfZmR7sRLd8=KE4O83YbbF@&5DWA znmVnGWje>ArHUn5Ow$i6J^1_A{N=R;Gyg?zn&5HXe7}6Zdw}zesuD@dZtmDSOgGDF zg*FH9w4J{#XO(u4z_d77Kyph1!Cw^cKaGJjq*jaT}Y z?ffmK3qrFUYv;Ac1)S4L68l~qqAM+=8ag3`>*r6tm44b^_7vTekBR*I{j+&b$0V%| zqgIW;4kO)FS;w|ZALV4=*y=DdZQ8d*7P?>m>4dk4?-yV=Ww+Vo!0L>f9VtxHbV1Au zJ`s~vXmT*fFl<=9*f7+bFT2rRqAB(4HS>@2Dt`)`bz*oB@oI-;!)$?jhE^}Dt4+Hy zjRhEfEOdO{cln~-xxym~GUd7NWpB*6x1%exnL*)5p4?p-9}J$ZelF{r5}E*-|Gj$v literal 0 HcmV?d00001 diff --git a/addons/material_maker/icons/icons.svg b/addons/material_maker/icons/icons.svg index 4a56982..54563e2 100644 --- a/addons/material_maker/icons/icons.svg +++ b/addons/material_maker/icons/icons.svg @@ -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"> + id="defs2"> + + + + + + image/svg+xml - + @@ -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" /> + + + + + + + + + + + + diff --git a/addons/material_maker/icons/save.png b/addons/material_maker/icons/save.png new file mode 100644 index 0000000000000000000000000000000000000000..c2e227ea26b985cc500b22855d05dc42541d9bd8 GIT binary patch literal 375 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ zFsXwu<36Df4xpf9iEBhjaDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$Qb0vtJY5_^ zEP9hg5?}m1&%ip3Zx4^>&qX{x4(#b%FWD#mf7j|@Z zHaf<1O?`N>c|K3P-GA4K$u51YMGV}`K)|mr?Ci0}pm_mDpj}eM|7ZM%U$N#(?yLLB zZg}9}JAVJ4vl~jkva_kN0Rf+%+od~afi64A+Ud}>xNwI=!TV?aZU0r4 zwEh1tDe*4m|G@(X8m3HGl5$gmrDaB^(SyUg_w$^W`=68m1Ply^(w&u~`4n1!{%7!X L^>bP0l+XkKUG9=5 literal 0 HcmV?d00001 diff --git a/addons/material_maker/main_window.tscn b/addons/material_maker/main_window.tscn index 5ae8cf6..c488d39 100644 --- a/addons/material_maker/main_window.tscn +++ b/addons/material_maker/main_window.tscn @@ -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"] diff --git a/addons/material_maker/node_base.gd b/addons/material_maker/node_base.gd index 77b5683..c208980 100644 --- a/addons/material_maker/node_base.gd +++ b/addons/material_maker/node_base.gd @@ -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,40 +60,41 @@ func get_seed(): func update_property_widgets(): for o in property_widgets: - if o is LineEdit: - o.text = str(get(o.name)) - elif o is SpinBox: - o.value = get(o.name) - elif o is HSlider: - o.value = get(o.name) - elif o is OptionButton: - o.selected = get(o.name) - elif o is CheckBox: - o.pressed = get(o.name) - elif o is ColorPickerButton: - o.color = get(o.name) - elif o is Control and o.filename == "res://addons/material_maker/widgets/gradient_editor.tscn": - o.value = get(o.name) - else: - print("Failed to update "+o.name) + if parameters.has(o.name) and parameters[o.name] != null: + if o is LineEdit: + o.text = str(parameters[o.name]) + elif o is SpinBox: + o.value = parameters[o.name] + elif o is HSlider: + o.value = parameters[o.name] + elif o is OptionButton: + o.selected = parameters[o.name] + elif o is CheckBox: + o.pressed = parameters[o.name] + elif o is ColorPickerButton: + o.color = parameters[o.name] + elif o is Control and o.filename == "res://addons/material_maker/widgets/gradient_editor.tscn": + o.value = parameters[o.name] + else: + print("Failed to update "+o.name) 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 diff --git a/addons/material_maker/nodes/adjust_hsv/adjust_hsv.gd b/addons/material_maker/nodes/adjust_hsv/adjust_hsv.gd index 40af204..714c314 100644 --- a/addons/material_maker/nodes/adjust_hsv/adjust_hsv.gd +++ b/addons/material_maker/nodes/adjust_hsv/adjust_hsv.gd @@ -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() diff --git a/addons/material_maker/nodes/adjust_hsv/adjust_hsv.tscn b/addons/material_maker/nodes/adjust_hsv/adjust_hsv.tscn index ba4aa02..42905b5 100644 --- a/addons/material_maker/nodes/adjust_hsv/adjust_hsv.tscn +++ b/addons/material_maker/nodes/adjust_hsv/adjust_hsv.tscn @@ -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] diff --git a/addons/material_maker/nodes/blend/blend.gd b/addons/material_maker/nodes/blend/blend.gd index abd45d3..32695c7 100644 --- a/addons/material_maker/nodes/blend/blend.gd +++ b/addons/material_maker/nodes/blend/blend.gd @@ -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 diff --git a/addons/material_maker/nodes/blur/blur.gd b/addons/material_maker/nodes/blur/blur.gd index 11bb9e7..9651693 100644 --- a/addons/material_maker/nodes/blur/blur.gd +++ b/addons/material_maker/nodes/blur/blur.gd @@ -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 = {} diff --git a/addons/material_maker/nodes/bricks.json b/addons/material_maker/nodes/bricks.json new file mode 100644 index 0000000..7893471 --- /dev/null +++ b/addons/material_maker/nodes/bricks.json @@ -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)))" } + ] +} \ No newline at end of file diff --git a/addons/material_maker/nodes/bricks/bricks.gd b/addons/material_maker/nodes/bricks/bricks.gd index d207f3c..b8a7b06 100644 --- a/addons/material_maker/nodes/bricks/bricks.gd +++ b/addons/material_maker/nodes/bricks/bricks.gd @@ -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() diff --git a/addons/material_maker/nodes/colorize/colorize.gd b/addons/material_maker/nodes/colorize/colorize.gd index 749aa25..ab660f9 100644 --- a/addons/material_maker/nodes/colorize/colorize.gd +++ b/addons/material_maker/nodes/colorize/colorize.gd @@ -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() diff --git a/addons/material_maker/nodes/custom/custom.gd b/addons/material_maker/nodes/custom/custom.gd new file mode 100644 index 0000000..760164c --- /dev/null +++ b/addons/material_maker/nodes/custom/custom.gd @@ -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 diff --git a/addons/material_maker/nodes/custom/custom.tscn b/addons/material_maker/nodes/custom/custom.tscn new file mode 100644 index 0000000..0b08856 --- /dev/null +++ b/addons/material_maker/nodes/custom/custom.tscn @@ -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"] + + diff --git a/addons/material_maker/nodes/emboss/emboss.gd b/addons/material_maker/nodes/emboss/emboss.gd index ee7809f..935195a 100644 --- a/addons/material_maker/nodes/emboss/emboss.gd +++ b/addons/material_maker/nodes/emboss/emboss.gd @@ -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 = {} diff --git a/addons/material_maker/nodes/export/export.gd b/addons/material_maker/nodes/export/export.gd index 5e81674..3094a8c 100644 --- a/addons/material_maker/nodes/export/export.gd +++ b/addons/material_maker/nodes/export/export.gd @@ -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(): diff --git a/addons/material_maker/nodes/material/material.gd b/addons/material_maker/nodes/material/material.gd index 4f56092..90eb786 100644 --- a/addons/material_maker/nodes/material/material.gd +++ b/addons/material_maker/nodes/material/material.gd @@ -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: diff --git a/addons/material_maker/nodes/node_generic.gd b/addons/material_maker/nodes/node_generic.gd new file mode 100644 index 0000000..4dba772 --- /dev/null +++ b/addons/material_maker/nodes/node_generic.gd @@ -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 diff --git a/addons/material_maker/nodes/noise.json b/addons/material_maker/nodes/noise.json new file mode 100644 index 0000000..cc216ba --- /dev/null +++ b/addons/material_maker/nodes/noise.json @@ -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))" } + ] +} \ No newline at end of file diff --git a/addons/material_maker/nodes/noise/noise.gd b/addons/material_maker/nodes/noise/noise.gd index 7d8e379..cf0ea9f 100644 --- a/addons/material_maker/nodes/noise/noise.gd +++ b/addons/material_maker/nodes/noise/noise.gd @@ -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() diff --git a/addons/material_maker/nodes/noise/noise.tscn b/addons/material_maker/nodes/noise/noise.tscn index 40972e4..a7827de 100644 --- a/addons/material_maker/nodes/noise/noise.tscn +++ b/addons/material_maker/nodes/noise/noise.tscn @@ -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 diff --git a/addons/material_maker/nodes/normal_map/normal_map.gd b/addons/material_maker/nodes/normal_map/normal_map.gd index cf49e16..ebaeadf 100644 --- a/addons/material_maker/nodes/normal_map/normal_map.gd +++ b/addons/material_maker/nodes/normal_map/normal_map.gd @@ -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 = {} diff --git a/addons/material_maker/nodes/pattern/pattern.gd b/addons/material_maker/nodes/pattern/pattern.gd index f2cadeb..74f2b90 100644 --- a/addons/material_maker/nodes/pattern/pattern.gd +++ b/addons/material_maker/nodes/pattern/pattern.gd @@ -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() diff --git a/addons/material_maker/nodes/perlin/perlin.gd b/addons/material_maker/nodes/perlin/perlin.gd index 0e12fd9..a18bd4c 100644 --- a/addons/material_maker/nodes/perlin/perlin.gd +++ b/addons/material_maker/nodes/perlin/perlin.gd @@ -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() diff --git a/addons/material_maker/nodes/shape/shape.gd b/addons/material_maker/nodes/shape/shape.gd index 6c3d01b..f0cc284 100644 --- a/addons/material_maker/nodes/shape/shape.gd +++ b/addons/material_maker/nodes/shape/shape.gd @@ -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 diff --git a/addons/material_maker/nodes/switch/switch.gd b/addons/material_maker/nodes/switch/switch.gd index d6a493f..9ed8401 100644 --- a/addons/material_maker/nodes/switch/switch.gd +++ b/addons/material_maker/nodes/switch/switch.gd @@ -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) diff --git a/addons/material_maker/nodes/transform/transform.gd b/addons/material_maker/nodes/transform/transform.gd index 77e73c8..402341d 100644 --- a/addons/material_maker/nodes/transform/transform.gd +++ b/addons/material_maker/nodes/transform/transform.gd @@ -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) diff --git a/addons/material_maker/nodes/uniform/uniform.gd b/addons/material_maker/nodes/uniform/uniform.gd index dfcc368..203a2d6 100644 --- a/addons/material_maker/nodes/uniform/uniform.gd +++ b/addons/material_maker/nodes/uniform/uniform.gd @@ -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 diff --git a/addons/material_maker/nodes/voronoi/voronoi.gd b/addons/material_maker/nodes/voronoi/voronoi.gd index 1b98481..44afdb4 100644 --- a/addons/material_maker/nodes/voronoi/voronoi.gd +++ b/addons/material_maker/nodes/voronoi/voronoi.gd @@ -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() diff --git a/addons/material_maker/nodes/warp/warp.gd b/addons/material_maker/nodes/warp/warp.gd index 2a8191b..c7c0dc9 100644 --- a/addons/material_maker/nodes/warp/warp.gd +++ b/addons/material_maker/nodes/warp/warp.gd @@ -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 diff --git a/addons/material_maker/nodes/warp/warp.tscn b/addons/material_maker/nodes/warp/warp.tscn index 5af5895..00decbf 100644 --- a/addons/material_maker/nodes/warp/warp.tscn +++ b/addons/material_maker/nodes/warp/warp.tscn @@ -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] diff --git a/addons/material_maker/widgets/linked_widgets/config_control.gd b/addons/material_maker/widgets/linked_widgets/config_control.gd index 36179a2..96fbde1 100644 --- a/addons/material_maker/widgets/linked_widgets/config_control.gd +++ b/addons/material_maker/widgets/linked_widgets/config_control.gd @@ -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() diff --git a/addons/material_maker/widgets/linked_widgets/linked_control.gd b/addons/material_maker/widgets/linked_widgets/linked_control.gd index d60fa56..1d42a6d 100644 --- a/addons/material_maker/widgets/linked_widgets/linked_control.gd +++ b/addons/material_maker/widgets/linked_widgets/linked_control.gd @@ -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(): diff --git a/addons/material_maker/widgets/node_editor.tscn b/addons/material_maker/widgets/node_editor.tscn new file mode 100644 index 0000000..c54ec64 --- /dev/null +++ b/addons/material_maker/widgets/node_editor.tscn @@ -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" ] + + diff --git a/addons/material_maker/widgets/node_editor/node_editor.gd b/addons/material_maker/widgets/node_editor/node_editor.gd new file mode 100644 index 0000000..7655466 --- /dev/null +++ b/addons/material_maker/widgets/node_editor/node_editor.gd @@ -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 diff --git a/addons/material_maker/widgets/node_editor/node_editor.tscn b/addons/material_maker/widgets/node_editor/node_editor.tscn new file mode 100644 index 0000000..ffc7dcd --- /dev/null +++ b/addons/material_maker/widgets/node_editor/node_editor.tscn @@ -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 + +