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).
This commit is contained in:
RodZill4 2018-07-30 08:45:19 +02:00
parent 279b0e0103
commit 6b9b954526
16 changed files with 115 additions and 120 deletions

View File

@ -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)

View File

@ -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"):
if !rv.has("f"):
if rv.has("rgb"):
rv.f = "(dot("+rv.rgb+", vec3(1.0))/3.0)"
if !rv.has("rgb") && rv.has("f"):
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 }

View File

@ -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"]

View File

@ -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"]

View File

@ -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"]

View File

@ -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,6 +9,7 @@ func _ready():
func set_texture(path):
file_path = path
var texture = ImageTexture.new()
if path != null:
texture.load(path)
$TextureButton.texture_normal = texture
get_parent().get_parent().generate_shader()

View File

@ -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"]

View File

@ -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

View File

@ -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"]

View File

@ -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"]

View File

@ -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"]

View File

@ -151,6 +151,4 @@ prefix = ""
suffix = ""
_sections_unfolded = [ "Caret", "Placeholder" ]
[connection signal="close_request" from="." to="." method="queue_free"]

View File

@ -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"]

View File

@ -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():
if $GraphEdit/Material != null:
$GraphEdit/Material.update_materials($Preview/Preview.get_materials())
if selected_node != null:
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):

View File

@ -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"]

View File

@ -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"}]}
{"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"}]}