From 6b9b9545267a0383c6ea7176528eb900c635a342 Mon Sep 17 00:00:00 2001 From: RodZill4 Date: Mon, 30 Jul 2018 08:45:19 +0200 Subject: [PATCH] Fixed load/save dialogs and refactoring now load/save dialog use the non-editor classes (thus usable when running the project). Refactored graphedit and node code (mainly load/save and adding and removing nodes). --- addons/procedural_material/graph_edit.gd | 50 ++++++++++++++- addons/procedural_material/node_base.gd | 18 +++--- addons/procedural_material/nodes/blend.tscn | 6 +- addons/procedural_material/nodes/bricks.tscn | 4 +- .../procedural_material/nodes/colorize.tscn | 4 +- addons/procedural_material/nodes/image.gd | 5 +- addons/procedural_material/nodes/image.tscn | 4 +- .../procedural_material/nodes/material.tscn | 2 +- .../procedural_material/nodes/normal_map.tscn | 4 +- addons/procedural_material/nodes/perlin.tscn | 4 +- addons/procedural_material/nodes/sine.tscn | 4 +- .../procedural_material/nodes/transform.tscn | 2 - addons/procedural_material/nodes/voronoi.tscn | 4 +- addons/procedural_material/pm_editor.gd | 64 +++++-------------- addons/procedural_material/pm_editor.tscn | 58 ++++++++--------- examples/wood_with_blood.ptex | 2 +- 16 files changed, 115 insertions(+), 120 deletions(-) diff --git a/addons/procedural_material/graph_edit.gd b/addons/procedural_material/graph_edit.gd index 0f13114..edfc70b 100644 --- a/addons/procedural_material/graph_edit.gd +++ b/addons/procedural_material/graph_edit.gd @@ -11,10 +11,57 @@ func get_source(node, port): if c.to == node && c.to_port == port: return { node=c.from, slot=c.from_port } +func add_node(node, position = null): + add_child(node) + if position != null: + node.offset = position + node.connect("close_request", self, "remove_node", [ node ]) + +func add_node_globalpos(node, global_position): + add_node(node, (scroll_offset + global_position - rect_global_position) / zoom) + func remove_node(node): + var node_name = node.name for c in get_connection_list(): - if c.from == node or c.to == node: + if c.from == node_name or c.to == node_name: disconnect_node(c.from, c.from_port, c.to, c.to_port) + node.queue_free() + send_changed_signal() + +func load_file(filename): + var file = File.new() + if file.open(filename, File.READ) != OK: + return + var data = parse_json(file.get_as_text()) + file.close() + clear_connections() + for c in get_children(): + if c is GraphNode: + remove_child(c) + c.free() + for n in data.nodes: + if !n.has("type"): + continue + var node_type = load("res://addons/procedural_material/nodes/"+n.type+".tscn") + if node_type != null: + var node = node_type.instance() + node.name = n.name + add_node(node) + node.deserialize(n) + for c in data.connections: + connect_node(c.from, c.from_port, c.to, c.to_port) + do_send_changed_signal() + +func save_file(filename): + var data = { nodes = [] } + for c in get_children(): + if c is GraphNode: + data.nodes.append(c.serialize()) + data.connections = get_connection_list() + var file = File.new() + if file.open(filename, File.WRITE) == OK: + file.store_string(to_json(data)) + file.close() func send_changed_signal(): $Timer.start() @@ -62,7 +109,6 @@ func setup_material(shader_material, textures, shader_code): shader_material.set_shader_param(k+"_tex", textures[k]) shader_material.shader.code = shader_code - func export_texture(node, filename, size = 256): if node != null: $SaveViewport.size = Vector2(size, size) diff --git a/addons/procedural_material/node_base.gd b/addons/procedural_material/node_base.gd index f02fb02..d257d45 100644 --- a/addons/procedural_material/node_base.gd +++ b/addons/procedural_material/node_base.gd @@ -81,10 +81,16 @@ func get_source_rgb(source): func get_shader_code(uv): var rv = _get_shader_code(uv) - if !rv.has("f") && rv.has("rgb"): - rv.f = "(dot("+rv.rgb+", vec3(1.0))/3.0)" - if !rv.has("rgb") && rv.has("f"): - rv.rgb = "vec3("+rv.f+")" + if !rv.has("f"): + if rv.has("rgb"): + rv.f = "(dot("+rv.rgb+", vec3(1.0))/3.0)" + else: + rv.f = "0.0" + if !rv.has("rgb"): + if rv.has("f"): + rv.rgb = "vec3("+rv.f+")" + else: + rv.f = "vec3(0.0)" return rv func get_textures(): @@ -97,10 +103,6 @@ func get_textures(): list[k] = source_list[k] return list -func queue_free(): - get_parent().remove_node(self.name) - .queue_free() - func serialize_element(e): if typeof(e) == TYPE_COLOR: return { type= "Color", r=e.r, g=e.g, b=e.b, a=e.a } diff --git a/addons/procedural_material/nodes/blend.tscn b/addons/procedural_material/nodes/blend.tscn index 7222435..f5b4001 100644 --- a/addons/procedural_material/nodes/blend.tscn +++ b/addons/procedural_material/nodes/blend.tscn @@ -5,7 +5,7 @@ [sub_resource type="Theme" id=1] -[node name="Blend" type="GraphNode" index="0"] +[node name="Blend" type="GraphNode"] anchor_left = 0.0 anchor_top = 0.0 @@ -80,7 +80,7 @@ group = null text = "Normal" flat = false align = 0 -items = [ "Normal", null, false, -1, null ] +items = [ "Normal", null, false, 0, null, "Dissolve", null, false, 1, null, "Multiply", null, false, 2, null, "Screen", null, false, 3, null, "Overlay", null, false, 4, null, "Hard Light", null, false, 5, null, "Soft Light", null, false, 6, null ] selected = 0 [node name="Label1" type="Label" parent="." index="1"] @@ -189,6 +189,4 @@ editable = true prefix = "" suffix = "" -[connection signal="close_request" from="." to="." method="queue_free"] - diff --git a/addons/procedural_material/nodes/bricks.tscn b/addons/procedural_material/nodes/bricks.tscn index d364d2b..06b9087 100644 --- a/addons/procedural_material/nodes/bricks.tscn +++ b/addons/procedural_material/nodes/bricks.tscn @@ -5,7 +5,7 @@ [sub_resource type="Theme" id=1] -[node name="Bricks" type="GraphNode" index="0"] +[node name="Bricks" type="GraphNode"] anchor_left = 0.0 anchor_top = 0.0 @@ -294,6 +294,4 @@ prefix = "" suffix = "" _sections_unfolded = [ "Caret", "Placeholder" ] -[connection signal="close_request" from="." to="." method="queue_free"] - diff --git a/addons/procedural_material/nodes/colorize.tscn b/addons/procedural_material/nodes/colorize.tscn index 8e01ab3..5146b5e 100644 --- a/addons/procedural_material/nodes/colorize.tscn +++ b/addons/procedural_material/nodes/colorize.tscn @@ -6,7 +6,7 @@ [sub_resource type="Theme" id=1] -[node name="Colorize" type="GraphNode" index="0"] +[node name="Colorize" type="GraphNode"] anchor_left = 0.0 anchor_top = 0.0 @@ -46,8 +46,6 @@ margin_top = 24.0 margin_right = 136.0 margin_bottom = 54.0 -[connection signal="close_request" from="." to="." method="queue_free"] - [connection signal="updated" from="Control" to="." method="update_shaders"] diff --git a/addons/procedural_material/nodes/image.gd b/addons/procedural_material/nodes/image.gd index 340a2d5..8176898 100644 --- a/addons/procedural_material/nodes/image.gd +++ b/addons/procedural_material/nodes/image.gd @@ -1,7 +1,7 @@ tool extends "res://addons/procedural_material/node_base.gd" -var file_path +var file_path = null func _ready(): set_slot(0, false, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1)) @@ -9,7 +9,8 @@ func _ready(): func set_texture(path): file_path = path var texture = ImageTexture.new() - texture.load(path) + if path != null: + texture.load(path) $TextureButton.texture_normal = texture get_parent().get_parent().generate_shader() diff --git a/addons/procedural_material/nodes/image.tscn b/addons/procedural_material/nodes/image.tscn index a5bfbe3..e8e118d 100644 --- a/addons/procedural_material/nodes/image.tscn +++ b/addons/procedural_material/nodes/image.tscn @@ -6,7 +6,7 @@ [sub_resource type="Theme" id=1] -[node name="Image" type="GraphNode" index="0"] +[node name="Image" type="GraphNode"] anchor_left = 0.0 anchor_top = 0.0 @@ -67,8 +67,6 @@ expand = true stretch_mode = 5 _sections_unfolded = [ "Rect", "Textures" ] -[connection signal="close_request" from="." to="." method="queue_free"] - [connection signal="pressed" from="TextureButton" to="." method="_on_TextureButton_pressed"] diff --git a/addons/procedural_material/nodes/material.tscn b/addons/procedural_material/nodes/material.tscn index a03f290..ecd1c2e 100644 --- a/addons/procedural_material/nodes/material.tscn +++ b/addons/procedural_material/nodes/material.tscn @@ -5,7 +5,7 @@ [sub_resource type="Theme" id=1] -[node name="Material" type="GraphNode" index="0"] +[node name="Material" type="GraphNode"] anchor_left = 0.0 anchor_top = 0.0 diff --git a/addons/procedural_material/nodes/normal_map.tscn b/addons/procedural_material/nodes/normal_map.tscn index 8729e61..5fe27bd 100644 --- a/addons/procedural_material/nodes/normal_map.tscn +++ b/addons/procedural_material/nodes/normal_map.tscn @@ -5,7 +5,7 @@ [sub_resource type="Theme" id=1] -[node name="NormalMap" type="GraphNode" index="0"] +[node name="NormalMap" type="GraphNode"] anchor_left = 0.0 anchor_top = 0.0 @@ -64,6 +64,4 @@ caret_blink_speed = 0.65 caret_position = 0 _sections_unfolded = [ "Caret", "Placeholder" ] -[connection signal="close_request" from="." to="." method="queue_free"] - diff --git a/addons/procedural_material/nodes/perlin.tscn b/addons/procedural_material/nodes/perlin.tscn index 4f981b6..f84b686 100644 --- a/addons/procedural_material/nodes/perlin.tscn +++ b/addons/procedural_material/nodes/perlin.tscn @@ -5,7 +5,7 @@ [sub_resource type="Theme" id=1] -[node name="Perlin" type="GraphNode" index="0"] +[node name="Perlin" type="GraphNode"] anchor_left = 0.0 anchor_top = 0.0 @@ -247,8 +247,6 @@ prefix = "" suffix = "" _sections_unfolded = [ "Caret", "Placeholder" ] -[connection signal="close_request" from="." to="." method="queue_free"] - [connection signal="offset_changed" from="." to="." method="_on_offset_changed"] diff --git a/addons/procedural_material/nodes/sine.tscn b/addons/procedural_material/nodes/sine.tscn index f6bb2f8..2a8cfae 100644 --- a/addons/procedural_material/nodes/sine.tscn +++ b/addons/procedural_material/nodes/sine.tscn @@ -5,7 +5,7 @@ [sub_resource type="Theme" id=1] -[node name="Sine" type="GraphNode" index="0"] +[node name="Sine" type="GraphNode"] anchor_left = 0.0 anchor_top = 0.0 @@ -95,6 +95,4 @@ caret_blink_speed = 0.65 caret_position = 0 _sections_unfolded = [ "Caret", "Placeholder" ] -[connection signal="close_request" from="." to="." method="queue_free"] - diff --git a/addons/procedural_material/nodes/transform.tscn b/addons/procedural_material/nodes/transform.tscn index 8de38ef..bbc6398 100644 --- a/addons/procedural_material/nodes/transform.tscn +++ b/addons/procedural_material/nodes/transform.tscn @@ -151,6 +151,4 @@ prefix = "" suffix = "" _sections_unfolded = [ "Caret", "Placeholder" ] -[connection signal="close_request" from="." to="." method="queue_free"] - diff --git a/addons/procedural_material/nodes/voronoi.tscn b/addons/procedural_material/nodes/voronoi.tscn index 0c82231..d1ce147 100644 --- a/addons/procedural_material/nodes/voronoi.tscn +++ b/addons/procedural_material/nodes/voronoi.tscn @@ -5,7 +5,7 @@ [sub_resource type="Theme" id=1] -[node name="Voronoi" type="GraphNode" index="0"] +[node name="Voronoi" type="GraphNode"] anchor_left = 0.0 anchor_top = 0.0 @@ -249,8 +249,6 @@ prefix = "" suffix = "" _sections_unfolded = [ "Caret", "Placeholder", "Size Flags" ] -[connection signal="close_request" from="." to="." method="queue_free"] - [connection signal="offset_changed" from="." to="." method="_on_offset_changed"] diff --git a/addons/procedural_material/pm_editor.gd b/addons/procedural_material/pm_editor.gd index 039d334..2a1fa42 100644 --- a/addons/procedural_material/pm_editor.gd +++ b/addons/procedural_material/pm_editor.gd @@ -72,7 +72,7 @@ func _on_PopupMenu_id_pressed(id): node.set_name(name) break i += 1 - $GraphEdit.add_child(node) + $GraphEdit.add_node(node, popup_position) node.offset = ($GraphEdit.scroll_offset + popup_position - $GraphEdit.rect_global_position) / $GraphEdit.zoom func _on_GraphEdit_connection_request(from, from_slot, to, to_slot): @@ -83,64 +83,32 @@ func _on_GraphEdit_connection_request(from, from_slot, to, to_slot): generate_shader(); func load_texture(): - var dialog = EditorFileDialog.new() + var dialog = FileDialog.new() add_child(dialog) - dialog.access = EditorFileDialog.ACCESS_FILESYSTEM - dialog.mode = EditorFileDialog.MODE_OPEN_FILE - dialog.add_filter("*.ptex;Procedural texture file") - dialog.connect("file_selected", self, "load_file") + dialog.rect_min_size = Vector2(500, 500) + dialog.access = FileDialog.ACCESS_FILESYSTEM + dialog.mode = FileDialog.MODE_OPEN_FILE + dialog.add_filter("*.ptex;Procedural textures file") + dialog.connect("file_selected", $GraphEdit, "load_file") dialog.popup_centered() -func load_file(filename): - var file = File.new() - if file.open(filename, File.READ) != OK: - return - var data = parse_json(file.get_as_text()) - file.close() - $GraphEdit.clear_connections() - for c in $GraphEdit.get_children(): - if c is GraphNode: - $GraphEdit.remove_child(c) - c.free() - for n in data.nodes: - if !n.has("type"): - continue - var node_type = load("res://addons/procedural_material/nodes/"+n.type+".tscn") - if node_type != null: - var node = node_type.instance() - node.name = n.name - $GraphEdit.add_child(node) - node.deserialize(n) - for c in data.connections: - $GraphEdit.connect_node(c.from, c.from_port, c.to, c.to_port) - generate_shader() - func save_texture(): - var dialog = EditorFileDialog.new() + var dialog = FileDialog.new() add_child(dialog) - dialog.access = EditorFileDialog.ACCESS_FILESYSTEM - dialog.mode = EditorFileDialog.MODE_SAVE_FILE - dialog.add_filter("*.ptex;Procedural texture file") - dialog.connect("file_selected", self, "save_file") + dialog.rect_min_size = Vector2(500, 500) + dialog.access = FileDialog.ACCESS_FILESYSTEM + dialog.mode = FileDialog.MODE_SAVE_FILE + dialog.add_filter("*.ptex;Procedural textures file") + dialog.connect("file_selected", $GraphEdit, "save_file") dialog.popup_centered() -func save_file(filename): - var data = { nodes = [] } - for c in $GraphEdit.get_children(): - if c is GraphNode: - data.nodes.append(c.serialize()) - data.connections = $GraphEdit.get_connection_list() - var file = File.new() - if file.open(filename, File.WRITE) == OK: - file.store_string(to_json(data)) - file.close() - func export_texture(size = 256): $GraphEdit.export_texture(selected_node, "res://generated_image.png", size) func generate_shader(): - $GraphEdit/Material.update_materials($Preview/Preview.get_materials()) - if selected_node != null: + if $GraphEdit/Material != null: + $GraphEdit/Material.update_materials($Preview/Preview.get_materials()) + if selected_node != null && selected_node is GraphNode: $GraphEdit.setup_material(texture_preview_material, selected_node.get_textures(), $GraphEdit.generate_shader(selected_node)) func _on_GraphEdit_node_selected(node): diff --git a/addons/procedural_material/pm_editor.tscn b/addons/procedural_material/pm_editor.tscn index 5430801..71cc11d 100644 --- a/addons/procedural_material/pm_editor.tscn +++ b/addons/procedural_material/pm_editor.tscn @@ -6,7 +6,7 @@ [ext_resource path="res://addons/procedural_material/preview.gd" type="Script" id=4] [ext_resource path="res://addons/procedural_material/panoramas/park.hdr" type="Texture" id=5] -[sub_resource type="Shader" id=10] +[sub_resource type="Shader" id=1] code = "shader_type canvas_item; @@ -192,10 +192,10 @@ COLOR = vec4(colorize_2_0_rgb, 1.0); } " -[sub_resource type="ShaderMaterial" id=11] +[sub_resource type="ShaderMaterial" id=2] render_priority = 0 -shader = SubResource( 10 ) +shader = SubResource( 1 ) [sub_resource type="Animation" id=3] @@ -215,9 +215,8 @@ tracks/0/keys = { "values": [ Vector3( 0, 0, 0 ), Vector3( 0, 360, 0 ) ] } -[sub_resource type="ArrayMesh" id=1] +[sub_resource type="ArrayMesh" id=4] -resource_name = "Cube" blend_shape_mode = 1 custom_aabb = AABB( 0, 0, 0, 0, 0, 0 ) surfaces/0 = { @@ -234,7 +233,7 @@ surfaces/0 = { } _sections_unfolded = [ "surface_1" ] -[sub_resource type="SpatialMaterial" id=12] +[sub_resource type="SpatialMaterial" id=13] render_priority = 0 flags_transparent = false @@ -288,9 +287,8 @@ proximity_fade_enable = false distance_fade_enable = false _sections_unfolded = [ "Depth" ] -[sub_resource type="ArrayMesh" id=2] +[sub_resource type="ArrayMesh" id=6] -resource_name = "Cylinder" blend_shape_mode = 1 custom_aabb = AABB( 0, 0, 0, 0, 0, 0 ) surfaces/0 = { @@ -306,15 +304,15 @@ surfaces/0 = { } _sections_unfolded = [ "surface_1" ] -[sub_resource type="PanoramaSky" id=4] +[sub_resource type="PanoramaSky" id=7] radiance_size = 2 panorama = ExtResource( 5 ) -[sub_resource type="Environment" id=5] +[sub_resource type="Environment" id=8] background_mode = 2 -background_sky = SubResource( 4 ) +background_sky = SubResource( 7 ) background_sky_custom_fov = 0.0 background_color = Color( 0, 0, 0, 1 ) background_energy = 1.0 @@ -391,7 +389,7 @@ adjustment_contrast = 1.0 adjustment_saturation = 1.0 _sections_unfolded = [ "Background" ] -[sub_resource type="Shader" id=13] +[sub_resource type="Shader" id=14] code = "shader_type canvas_item; @@ -401,14 +399,13 @@ void fragment() { " _sections_unfolded = [ "Resource" ] -[sub_resource type="ShaderMaterial" id=14] +[sub_resource type="ShaderMaterial" id=15] render_priority = 0 -shader = SubResource( 13 ) +shader = SubResource( 14 ) -[sub_resource type="Animation" id=8] +[sub_resource type="Animation" id=11] -resource_name = "maximize" length = 0.2 loop = false step = 0.1 @@ -449,9 +446,8 @@ tracks/2/keys = { "values": [ 0 ] } -[sub_resource type="Animation" id=9] +[sub_resource type="Animation" id=12] -resource_name = "minimize" length = 0.2 loop = false step = 0.1 @@ -568,11 +564,11 @@ shadow_atlas_quad_0 = 2 shadow_atlas_quad_1 = 2 shadow_atlas_quad_2 = 3 shadow_atlas_quad_3 = 4 -_sections_unfolded = [ "GUI", "Render Target" ] +_sections_unfolded = [ "GUI", "Render Target", "Rendering" ] [node name="ColorRect" type="ColorRect" parent="GraphEdit/SaveViewport" index="0"] -material = SubResource( 11 ) +material = SubResource( 2 ) anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 @@ -591,7 +587,7 @@ _sections_unfolded = [ "Material", "Rect" ] [node name="Timer" type="Timer" parent="GraphEdit/SaveViewport" index="1"] process_mode = 1 -wait_time = 0.1 +wait_time = 0.5 one_shot = true autostart = false @@ -692,7 +688,7 @@ _sections_unfolded = [ "GUI", "Render Target" ] [node name="Objects" type="Spatial" parent="Preview/Preview/MaterialPreview" index="0"] -transform = Transform( -0.324656, 0, -0.94583, 0, 1, 0, 0.94583, 0, -0.324656, 0, 0, 0 ) +transform = Transform( -0.978985, 0, -0.20392, 0, 1, 0, 0.20392, 0, -0.978985, 0, 0, 0 ) _sections_unfolded = [ "Transform" ] [node name="Cube" type="MeshInstance" parent="Preview/Preview/MaterialPreview/Objects" index="0"] @@ -706,9 +702,9 @@ lod_min_distance = 0.0 lod_min_hysteresis = 0.0 lod_max_distance = 0.0 lod_max_hysteresis = 0.0 -mesh = SubResource( 1 ) +mesh = SubResource( 4 ) skeleton = NodePath("..") -material/0 = SubResource( 12 ) +material/0 = SubResource( 13 ) _sections_unfolded = [ "Geometry", "Transform", "material" ] [node name="Cylinder" type="MeshInstance" parent="Preview/Preview/MaterialPreview/Objects" index="1"] @@ -723,9 +719,9 @@ lod_min_distance = 0.0 lod_min_hysteresis = 0.0 lod_max_distance = 0.0 lod_max_hysteresis = 0.0 -mesh = SubResource( 2 ) +mesh = SubResource( 6 ) skeleton = NodePath("..") -material/0 = SubResource( 12 ) +material/0 = SubResource( 13 ) _sections_unfolded = [ "Geometry", "Transform", "material" ] [node name="OmniLight" type="OmniLight" parent="Preview/Preview/MaterialPreview" index="1"] @@ -756,7 +752,7 @@ _sections_unfolded = [ "Shadow" ] transform = Transform( 1, 0, 0, 0, 0.766044, 0.642787, 0, -0.642787, 0.766044, 0, 1.83022, 2.2549 ) keep_aspect = 1 cull_mask = 1048575 -environment = SubResource( 5 ) +environment = SubResource( 8 ) h_offset = 0.0 v_offset = 0.0 doppler_tracking = 0 @@ -770,7 +766,7 @@ _sections_unfolded = [ "Transform" ] [node name="WorldEnvironment" type="WorldEnvironment" parent="Preview/Preview/MaterialPreview" index="3"] -environment = SubResource( 5 ) +environment = SubResource( 8 ) [node name="Model" type="OptionButton" parent="Preview/Preview" index="2"] @@ -830,7 +826,7 @@ selected = 3 [node name="SelectedPreview" type="ColorRect" parent="Preview/Preview" index="4"] -material = SubResource( 14 ) +material = SubResource( 15 ) anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 @@ -856,8 +852,8 @@ autoplay = "" playback_process_mode = 1 playback_default_blend_time = 0.0 playback_speed = 1.0 -anims/maximize = SubResource( 8 ) -anims/minimize = SubResource( 9 ) +anims/maximize = SubResource( 11 ) +anims/minimize = SubResource( 12 ) blend_times = [ ] [connection signal="connection_request" from="GraphEdit" to="." method="_on_GraphEdit_connection_request"] diff --git a/examples/wood_with_blood.ptex b/examples/wood_with_blood.ptex index e2c04ce..361bfe2 100644 --- a/examples/wood_with_blood.ptex +++ b/examples/wood_with_blood.ptex @@ -1 +1 @@ -{"connections":[{"from":"perlin_0","from_port":0,"to":"colorize_0","to_port":0},{"from":"bricks_0","from_port":0,"to":"blend_0","to_port":0},{"from":"perlin_0","from_port":0,"to":"blend_0","to_port":1},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"blend_0","from_port":0,"to":"normal_map_0","to_port":0},{"from":"blend_0","from_port":0,"to":"colorize_1","to_port":0},{"from":"perlin_1","from_port":0,"to":"colorize_2","to_port":0},{"from":"colorize_2","from_port":0,"to":"blend_1","to_port":0},{"from":"colorize_0","from_port":0,"to":"blend_1","to_port":1},{"from":"perlin_2","from_port":0,"to":"colorize_3","to_port":0},{"from":"colorize_3","from_port":0,"to":"blend_1","to_port":2},{"from":"blend_1","from_port":0,"to":"Material","to_port":0},{"from":"colorize_1","from_port":0,"to":"blend_2","to_port":1},{"from":"colorize_3","from_port":0,"to":"blend_2","to_port":0},{"from":"blend_2","from_port":0,"to":"Material","to_port":2}],"nodes":[{"gradient":[{"b":0.004367,"g":0.004367,"pos":0,"r":0.059896},{"b":0.012831,"g":0.012831,"pos":0.172727,"r":0.111979},{"b":0.006687,"g":0.006687,"pos":0.463636,"r":0.075521},{"b":0.007871,"g":0.007871,"pos":0.754545,"r":0.144176},{"b":0.002062,"g":0.002062,"pos":1,"r":0.049479}],"name":"colorize_2","node_position":{"x":487.633789,"y":-144.5},"type":"colorize"},{"gradient":[{"b":0.025567,"g":0.207086,"pos":0,"r":0.377604},{"b":0.013346,"g":0.061518,"pos":0.163636,"r":0.106771},{"b":0.017965,"g":0.174595,"pos":0.345455,"r":0.321733},{"b":0.015933,"g":0.124841,"pos":0.527273,"r":0.22715},{"b":0.017148,"g":0.148096,"pos":0.681818,"r":0.271107},{"b":0.015842,"g":0.105696,"pos":0.854545,"r":0.190104},{"b":0.011393,"g":0.14651,"pos":1,"r":0.273438}],"name":"colorize_0","node_position":{"x":468,"y":62.5},"type":"colorize"},{"gradient":[{"b":0,"g":0,"pos":0.454545,"r":0},{"b":1,"g":1,"pos":0.563636,"r":1}],"name":"colorize_3","node_position":{"x":494.633789,"y":-32},"type":"colorize"},{"amount":0.35,"blend_type":0,"name":"blend_2","node_position":{"x":687.633789,"y":201.5},"type":"blend"},{"gradient":[{"b":0.690104,"g":0.690104,"pos":0,"r":0.690104},{"b":0.492188,"g":0.492188,"pos":1,"r":0.492188}],"name":"colorize_1","node_position":{"x":495.633789,"y":220.5},"type":"colorize"},{"amount":0.5,"name":"normal_map_0","node_position":{"x":724.633789,"y":345.5},"type":"normal_map"},{"iterations":3,"name":"perlin_0","node_position":{"x":29,"y":214.5},"persistence":0.5,"scale_x":20,"scale_y":3,"type":"perlin"},{"bevel":0,"columns":5,"mortar":0.05,"name":"bricks_0","node_position":{"x":-1,"y":30.5},"row_offset":0.5,"rows":1,"type":"bricks"},{"iterations":6,"name":"perlin_2","node_position":{"x":220.633789,"y":19},"persistence":0.65,"scale_x":4,"scale_y":4,"type":"perlin"},{"iterations":7,"name":"perlin_1","node_position":{"x":110.633789,"y":-137.5},"persistence":0.55,"scale_x":4,"scale_y":4,"type":"perlin"},{"name":"Material","node_position":{"x":938,"y":96},"type":"material"},{"amount":0.2,"blend_type":0,"name":"blend_0","node_position":{"x":280,"y":302.5},"type":"blend"},{"amount":0.5,"blend_type":0,"name":"blend_1","node_position":{"x":694.633789,"y":-2},"type":"blend"}]} \ No newline at end of file +{"connections":[{"from":"bricks_0","from_port":0,"to":"blend_0","to_port":0},{"from":"perlin_0","from_port":0,"to":"blend_0","to_port":1},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"blend_0","from_port":0,"to":"normal_map_0","to_port":0},{"from":"blend_0","from_port":0,"to":"colorize_1","to_port":0},{"from":"perlin_1","from_port":0,"to":"colorize_2","to_port":0},{"from":"colorize_2","from_port":0,"to":"blend_1","to_port":0},{"from":"colorize_0","from_port":0,"to":"blend_1","to_port":1},{"from":"perlin_2","from_port":0,"to":"colorize_3","to_port":0},{"from":"colorize_3","from_port":0,"to":"blend_1","to_port":2},{"from":"blend_1","from_port":0,"to":"Material","to_port":0},{"from":"colorize_1","from_port":0,"to":"blend_2","to_port":1},{"from":"colorize_3","from_port":0,"to":"blend_2","to_port":0},{"from":"blend_2","from_port":0,"to":"Material","to_port":2},{"from":"blend_0","from_port":0,"to":"colorize_0","to_port":0}],"nodes":[{"gradient":[{"b":0.004367,"g":0.004367,"pos":0,"r":0.059896},{"b":0.012831,"g":0.012831,"pos":0.163636,"r":0.111979},{"b":0.006687,"g":0.006687,"pos":0.454545,"r":0.075521},{"b":0.007871,"g":0.007871,"pos":0.745455,"r":0.144176},{"b":0.002062,"g":0.002062,"pos":1,"r":0.049479}],"name":"colorize_2","node_position":{"x":487.633789,"y":-144.5},"type":"colorize"},{"gradient":[{"b":0.690104,"g":0.690104,"pos":0,"r":0.690104},{"b":0.492188,"g":0.492188,"pos":1,"r":0.492188}],"name":"colorize_1","node_position":{"x":495.633789,"y":220.5},"type":"colorize"},{"amount":0.5,"name":"normal_map_0","node_position":{"x":724.633789,"y":345.5},"type":"normal_map"},{"name":"Material","node_position":{"x":938,"y":96},"type":"material"},{"iterations":6,"name":"perlin_2","node_position":{"x":222.633789,"y":19},"persistence":0.65,"scale_x":4,"scale_y":4,"type":"perlin"},{"amount":0.5,"blend_type":0,"name":"blend_1","node_position":{"x":707.633789,"y":-68},"type":"blend"},{"gradient":[{"b":0,"g":0,"pos":0.445455,"r":0},{"b":1,"g":1,"pos":0.554545,"r":1}],"name":"colorize_3","node_position":{"x":487.633789,"y":65},"type":"colorize"},{"iterations":3,"name":"perlin_0","node_position":{"x":12,"y":225.5},"persistence":0.5,"scale_x":20,"scale_y":3,"type":"perlin"},{"bevel":0,"columns":5,"mortar":0.05,"name":"bricks_0","node_position":{"x":-1,"y":30.5},"row_offset":0.5,"rows":1,"type":"bricks"},{"gradient":[{"b":0.00826,"g":0.042941,"pos":0,"r":0.075521},{"b":0.025567,"g":0.207086,"pos":0.118182,"r":0.377604},{"b":0.015259,"g":0.067816,"pos":0.263636,"r":0.117188},{"b":0.017965,"g":0.174595,"pos":0.381818,"r":0.321733},{"b":0.015933,"g":0.124841,"pos":0.527273,"r":0.22715},{"b":0.017148,"g":0.148096,"pos":0.672727,"r":0.271107},{"b":0.015842,"g":0.105696,"pos":0.845455,"r":0.190104},{"b":0.011393,"g":0.14651,"pos":1,"r":0.273438}],"name":"colorize_0","node_position":{"x":472,"y":-41.5},"type":"colorize"},{"amount":1,"blend_type":2,"name":"blend_0","node_position":{"x":271,"y":306.5},"type":"blend"},{"iterations":7,"name":"perlin_1","node_position":{"x":110.633789,"y":-143.5},"persistence":0.55,"scale_x":4,"scale_y":4,"type":"perlin"},{"amount":0.35,"blend_type":0,"name":"blend_2","node_position":{"x":690.633789,"y":201.5},"type":"blend"}]} \ No newline at end of file