diff --git a/addons/material_maker/engine/gen_base.gd b/addons/material_maker/engine/gen_base.gd index 74798f8..e665262 100644 --- a/addons/material_maker/engine/gen_base.gd +++ b/addons/material_maker/engine/gen_base.gd @@ -228,12 +228,15 @@ func _serialize(data: Dictionary) -> Dictionary: print("cannot save "+name) return data +func _serialize_data(data: Dictionary) -> Dictionary: + return data + func serialize() -> Dictionary: var rv = { name=name, type=get_type(), parameters={}, node_position={ x=position.x, y=position.y } } for p in get_parameter_defs(): if parameters.has(p.name): rv.parameters[p.name] = MMType.serialize_value(parameters[p.name]) - else: + elif p.has("default"): rv.parameters[p.name] = p.default if seed_locked: rv.seed_value = seed_value @@ -241,6 +244,7 @@ func serialize() -> Dictionary: rv.type = model else: rv = _serialize(rv) + rv = _serialize_data(rv) return rv func _deserialize(_data : Dictionary) -> void: diff --git a/addons/material_maker/engine/gen_export.gd b/addons/material_maker/engine/gen_export.gd index a9fc6cb..e42ac39 100644 --- a/addons/material_maker/engine/gen_export.gd +++ b/addons/material_maker/engine/gen_export.gd @@ -34,19 +34,13 @@ func get_parameter_defs() -> Array: func get_input_defs() -> Array: return [ { name="in", type="rgba" } ] -func render_textures() -> void: +func export_material(prefix : String, _profile : String, size : int = 0) -> void: + if size == 0: + size = get_image_size() var source = get_source(0) if source != null: - var result = source.generator.render(source.output_index, get_image_size()) + var result = source.generator.render(source.output_index, size) while result is GDScriptFunctionState: result = yield(result, "completed") - texture = ImageTexture.new() - result.copy_to_texture(texture) + result.save_to_file("%s_%s.png" % [ prefix, parameters.suffix]) result.release() - else: - texture = null - -func export_textures(prefix, __ = null) -> void: - if texture != null: - var image = texture.get_data() - image.save_png("%s_%s.png" % [ prefix, parameters.suffix]) diff --git a/addons/material_maker/engine/gen_material.gd b/addons/material_maker/engine/gen_material.gd index c1fb41b..1af89e1 100644 --- a/addons/material_maker/engine/gen_material.gd +++ b/addons/material_maker/engine/gen_material.gd @@ -1,19 +1,30 @@ tool -extends MMGenBase +extends MMGenShader class_name MMGenMaterial +var export_paths = {} + var material : SpatialMaterial var generated_textures = {} const TEXTURE_LIST = [ - { port=0, texture="albedo" }, - { port=3, texture="emission" }, - { port=4, texture="normal" }, - { ports=[5, 2, 1], default_values=["1.0", "1.0", "1.0"], texture="orm" }, - { port=6, texture="depth" }, - { port=7, texture="subsurf_scatter" } + { port=0, texture="albedo", sources=[0] }, + { port=1, texture="orm", sources=[1, 2, 5] }, + { port=2, texture="emission", sources=[3] }, + { port=3, texture="normal", sources=[4] }, + { port=4, texture="depth", sources=[6] }, + { port=5, texture="sss", sources=[7] } ] +const INPUT_ALBEDO : int = 0 +const INPUT_METALLIC : int = 1 +const INPUT_ROUGHNESS : int = 2 +const INPUT_EMISSION : int = 3 +const INPUT_NORMAL : int = 4 +const INPUT_OCCLUSION : int = 5 +const INPUT_DEPTH : int = 6 +const INPUT_SSS : int = 7 + # The minimum allowed texture size as a power-of-two exponent const TEXTURE_SIZE_MIN = 4 # 16x16 @@ -23,6 +34,7 @@ const TEXTURE_SIZE_MAX = 12 # 4096x4096 # The default texture size as a power-of-two exponent const TEXTURE_SIZE_DEFAULT = 10 # 1024x1024 + func _ready() -> void: for t in TEXTURE_LIST: generated_textures[t.texture] = null @@ -37,30 +49,8 @@ func get_type() -> String: func get_type_name() -> String: return "Material" -func get_parameter_defs() -> Array: - return [ - { name="albedo_color", label="Albedo", type="color", default={ r=1.0, g=1.0, b=1.0, a=1.0} }, - { name="metallic", label="Metallic", type="float", min=0.0, max=1.0, step=0.05, default=1.0 }, - { name="roughness", label="Roughness", type="float", min=0.0, max=1.0, step=0.05, default=1.0 }, - { name="emission_energy", label="Emission", type="float", min=0.0, max=8.0, step=0.05, default=1.0 }, - { name="normal_scale", label="Normal", type="float", min=0.0, max=8.0, step=0.05, default=1.0 }, - { name="ao_light_affect", label="Ambient occlusion", type="float", min=0.0, max=1.0, step=0.05, default=1.0 }, - { name="depth_scale", label="Depth", type="float", min=0.0, max=1.0, step=0.05, default=1.0 }, - { name="subsurf_scatter_strength", label="Subsurf. Scatter.", type="float", min=0.0, max=1.0, step=0.05, default=0.0 }, - { name="size", label="Size", type="size", first=TEXTURE_SIZE_MIN, last=TEXTURE_SIZE_MAX, default=TEXTURE_SIZE_DEFAULT } - ] - -func get_input_defs() -> Array: - return [ - { name="albedo_texture", label="", type="rgb" }, - { name="metallic_texture", label="", type="f" }, - { name="roughness_texture", label="", type="f" }, - { name="emission_texture", label="", type="rgb" }, - { name="normal_texture", label="", type="rgb" }, - { name="ao_texture", label="", type="f" }, - { name="depth_texture", label="", type="f" }, - { name="subsurf_scatter_texture", label="", type="f" } - ] +func get_output_defs() -> Array: + return [] func get_image_size() -> int: var rv : int @@ -83,9 +73,7 @@ func set_parameter(p, v) -> void: func source_changed(input_index : int) -> void: for t in TEXTURE_LIST: - if t.has("port") and t.port == input_index: - generated_textures[t.texture] = null - elif t.has("ports") and t.ports.has(input_index): + if t.has("sources") and t.sources.find(input_index) != -1: generated_textures[t.texture] = null update_preview() @@ -96,37 +84,10 @@ func render_textures() -> void: if t.has("port"): if generated_textures[t.texture] != null: continue - var source = get_source(t.port) - if source == null: - generated_textures[t.texture] = null - continue - result = source.generator.render(source.output_index, get_image_size()) - elif t.has("ports"): - var context : MMGenContext = MMGenContext.new() - var code = [] - var shader_textures = {} - var sources = 0 - for i in range(t.ports.size()): - var source = get_source(t.ports[i]) - if source != null: - var status = source.generator.get_shader_code("UV", source.output_index, context) - while status is GDScriptFunctionState: - status = yield(status, "completed") - code.push_back(status) - for t in status.textures.keys(): - shader_textures[t] = status.textures[t] - sources += 1 - else: - code.push_back({ defs="", code="", f=t.default_values[i] }) - if sources == 0: - generated_textures[t.texture] = null - continue - var shader : String = mm_renderer.generate_combined_shader(code[0], code[1], code[2]) - result = mm_renderer.render_shader(shader, shader_textures, get_image_size()) + result = render(t.port, get_image_size()) else: generated_textures[t.texture] = null continue - while result is GDScriptFunctionState: result = yield(result, "completed") texture = ImageTexture.new() @@ -143,8 +104,9 @@ func render_textures() -> void: generated_textures[t.texture] = texture func update_materials(material_list) -> void: + render_textures() for m in material_list: - update_spatial_material(m) + update_material(m) func get_generated_texture(slot, file_prefix = null) -> ImageTexture: if file_prefix != null: @@ -157,62 +119,63 @@ func get_generated_texture(slot, file_prefix = null) -> ImageTexture: else: return generated_textures[slot] -func update_spatial_material(m, file_prefix = null) -> void: +func update_material(m, file_prefix = null) -> void: var texture - if m is SpatialMaterial: # Make the material double-sided for better visiblity in the preview m.params_cull_mode = SpatialMaterial.CULL_DISABLED # Albedo m.albedo_color = parameters.albedo_color m.albedo_texture = get_generated_texture("albedo", file_prefix) - m.metallic = parameters.metallic - m.roughness = parameters.roughness - # Metallic - texture = get_generated_texture("orm", file_prefix) - m.metallic_texture = texture - m.metallic_texture_channel = SpatialMaterial.TEXTURE_CHANNEL_BLUE - # Roughness - m.roughness_texture = texture - m.roughness_texture_channel = SpatialMaterial.TEXTURE_CHANNEL_GREEN - # Emission - texture = get_generated_texture("emission", file_prefix) - if texture != null: - m.emission_enabled = true - m.emission_energy = parameters.emission_energy - m.emission_texture = texture - else: - m.emission_enabled = false - # Normal map - texture = get_generated_texture("normal", file_prefix) - if texture != null: - m.normal_enabled = true - m.normal_texture = texture - else: - m.normal_enabled = false # Ambient occlusion - if get_source(5) != null: + if get_source(INPUT_OCCLUSION) != null: m.ao_enabled = true - m.ao_light_affect = parameters.ao_light_affect - m.ao_texture = m.metallic_texture + m.ao_light_affect = parameters.ao + m.ao_texture = get_generated_texture("orm", file_prefix) m.ao_texture_channel = SpatialMaterial.TEXTURE_CHANNEL_RED else: m.ao_enabled = false + # Roughness + m.roughness = parameters.roughness + if get_source(INPUT_ROUGHNESS) != null: + m.roughness_texture = get_generated_texture("orm", file_prefix) + m.roughness_texture_channel = SpatialMaterial.TEXTURE_CHANNEL_GREEN + else: + m.roughness_texture = null + # Metallic + m.metallic = parameters.metallic + if get_source(INPUT_METALLIC) != null: + m.metallic_texture = get_generated_texture("orm", file_prefix) + m.metallic_texture_channel = SpatialMaterial.TEXTURE_CHANNEL_BLUE + else: + m.metallic_texture = null + # Emission + if get_source(INPUT_EMISSION) != null: + m.emission_enabled = true + m.emission_energy = parameters.emission_energy + m.emission_texture = get_generated_texture("emission", file_prefix) + else: + m.emission_enabled = false + # Normal map + if get_source(INPUT_NORMAL) != null: + m.normal_enabled = true + m.normal_texture = get_generated_texture("normal", file_prefix) + m.normal_scale = parameters.normal + else: + m.normal_enabled = false # Depth - texture = get_generated_texture("depth", file_prefix) - if texture != null and parameters.depth_scale > 0: + if get_source(INPUT_DEPTH) != null and parameters.depth_scale > 0: m.depth_enabled = true m.depth_deep_parallax = true m.depth_scale = parameters.depth_scale * 0.2 - m.depth_texture = texture + m.depth_texture = get_generated_texture("depth", file_prefix) else: m.depth_enabled = false # Subsurface scattering - texture = get_generated_texture("subsurf_scatter", file_prefix) - if texture != null: + if get_source(INPUT_SSS) != null: m.subsurf_scatter_enabled = true - m.subsurf_scatter_strength = parameters.subsurf_scatter_strength - m.subsurf_scatter_texture = texture + m.subsurf_scatter_strength = parameters.sss + m.subsurf_scatter_texture = get_generated_texture("sss", file_prefix) else: m.subsurf_scatter_enabled = false else: @@ -231,25 +194,149 @@ func update_spatial_material(m, file_prefix = null) -> void: m.set_shader_param("depth_scale", parameters.depth_scale * 0.2) m.set_shader_param("texture_depth", get_generated_texture("depth", file_prefix)) -func export_textures(prefix, editor_interface = null) -> SpatialMaterial: - for t in TEXTURE_LIST: - var texture = generated_textures[t.texture] - if texture != null: - var image = texture.get_data() - image.save_png("%s_%s.png" % [ prefix, t.texture ]) - if Engine.editor_hint and editor_interface != null: - var resource_filesystem = editor_interface.get_resource_filesystem() - resource_filesystem.scan() - yield(resource_filesystem, "resources_reimported") - print("resources_reimported") - var new_material = SpatialMaterial.new() - update_spatial_material(new_material, prefix) - var file_name : String = "%s.tres" % [ prefix ] - ResourceSaver.save(file_name, new_material) - resource_filesystem.update_file(file_name) - return new_material +# Export - return null +func get_export_profiles() -> Array: + return shader_model.exports.keys() -func _serialize(data: Dictionary) -> Dictionary: +func get_export_extension(profile : String) -> String: + return shader_model.exports[profile].export_extension + +func get_export_path(profile : String) -> String: + if export_paths.has(profile): + return export_paths[profile] + return "" + +func subst_string(s : String, export_context : Dictionary) -> String: + var modified : bool = true + while modified: + modified = false + for k in export_context.keys(): + var new_s = s.replace(k, export_context[k]) + if new_s != s: + s = new_s + modified = true + while (true): + var search_string = "$(expr:" + var position = s.find(search_string) + if position == -1: + break + var parenthesis_level = 0 + var expr_begin = position+search_string.length() + for i in range(expr_begin, s.length()): + if s[i] == '(': + parenthesis_level += 1 + elif s[i] == ')': + if parenthesis_level == 0: + var expression = s.substr(expr_begin, i-expr_begin) + var expr = Expression.new() + var error = expr.parse(expression, []) + if error == OK: + s = s.replace(s.substr(position, i+1-position), str(expr.execute())) + else: + s = s.replace(s.substr(position, i+1-position), "EXPRESSION ERROR ("+expression+")") + break + parenthesis_level -= 1 + return s + +func create_file_from_template(template : String, file_name : String, export_context : Dictionary) -> bool: + var in_file = File.new() + var out_file = File.new() + if in_file.open(mm_loader.STD_GENDEF_PATH+"/"+template, File.READ) != OK: + if in_file.open(OS.get_executable_path().get_base_dir()+"/generators/"+template, File.READ) != OK: + print("Cannot find template file "+template) + return false + Directory.new().remove(file_name) + if out_file.open(file_name, File.WRITE) != OK: + print("Cannot write file '"+file_name+"' ("+str(out_file.get_error())+")") + return false + var skip_state : Array = [ false ] + while ! in_file.eof_reached(): + var l = in_file.get_line() + if l.left(4) == "$if ": + var condition = subst_string(l.right(4), export_context) + var expr = Expression.new() + var error = expr.parse(condition, []) + if error != OK: + print("Error in expression "+condition+": "+expr.get_error_text()) + continue + skip_state.push_back(!expr.execute()) + elif l.left(3) == "$fi": + skip_state.pop_back() + elif l.left(5) == "$else": + skip_state.push_back(!skip_state.pop_back()) + elif ! skip_state.back(): + out_file.store_line(subst_string(l, export_context)) + return true + +func export_material(prefix : String, profile : String, size : int = 0) -> void: + if size == 0: + size = get_image_size() + export_paths[profile] = prefix + var export_context : Dictionary = { + "$(path_prefix)":prefix, + "$(file_prefix)":prefix.get_file() + } + for i in range(shader_model.inputs.size()): + var input = shader_model.inputs[i] + export_context["$(connected:"+input.name+")"] = "true" if get_source(i) != null else "false" + for p in shader_model.parameters: + var value = p.default + if parameters.has(p.name): + value = parameters[p.name] + match p.type: + "float", "size": + export_context["$(param:"+p.name+")"] = str(value) + "color": + export_context["$(param:"+p.name+".r)"] = str(value.r) + export_context["$(param:"+p.name+".g)"] = str(value.g) + export_context["$(param:"+p.name+".b)"] = str(value.b) + export_context["$(param:"+p.name+".a)"] = str(value.a) + _: + print(p.type+" not supported in material") + if shader_model.exports[profile].has("uids"): + for i in range(shader_model.exports[profile].uids): + var uid : String + var r = [] + for k in range(16): + r.append(randi() & 255) + r[6] = (r[6] & 0x0f) | 0x40 + r[8] = (r[8] & 0x3f) | 0x80 + for k in range(16): + uid += '%02x' % r[k] + export_context["$(uid:"+str(i)+")"] = uid + for f in shader_model.exports[profile].files: + if f.has("conditions"): + var condition = subst_string(f.conditions, export_context) + var expr = Expression.new() + var error = expr.parse(condition, []) + if error != OK: + print("Error in expression: "+expr.get_error_text()) + continue + if !expr.execute(): + continue + match f.type: + "texture": + var file_name = subst_string(f.file_name, export_context) + var result = render(f.output, size) + while result is GDScriptFunctionState: + result = yield(result, "completed") + result.save_to_file(file_name) + result.release() + "template": + var file_export_context = export_context.duplicate() + if f.has("file_params"): + for p in f.file_params.keys(): + file_export_context["$(file_param:"+p+")"] = f.file_params[p] + var file_name = subst_string(f.file_name, export_context) + create_file_from_template(f.template, file_name, file_export_context) + +func _serialize_data(data: Dictionary) -> Dictionary: + data = ._serialize_data(data) + data.export_paths = export_paths return data + +func _deserialize(data : Dictionary) -> void: + ._deserialize(data) + if data.has("export_paths"): + export_paths = data.export_paths.duplicate() diff --git a/addons/material_maker/engine/gen_shader.gd b/addons/material_maker/engine/gen_shader.gd index 3410f79..35c866b 100644 --- a/addons/material_maker/engine/gen_shader.gd +++ b/addons/material_maker/engine/gen_shader.gd @@ -157,6 +157,10 @@ func replace_variable(string : String, variable : String, value : String) -> Str break new_string += string.left(pos) string = string.right(pos) + if string.length() > keyword_size and is_word_letter(string[keyword_size]): + new_string += string.left(keyword_size) + string = string.right(keyword_size) + continue if string.empty() or !is_word_letter(string[0]): new_string += value else: diff --git a/addons/material_maker/engine/io_types.gd b/addons/material_maker/engine/io_types.gd index 5bf862f..c16e324 100644 --- a/addons/material_maker/engine/io_types.gd +++ b/addons/material_maker/engine/io_types.gd @@ -6,17 +6,17 @@ var types : Dictionary = {} func _ready(): var file = File.new() - if file.open("res://addons/material_maker/nodes/io_types.mmt", File.READ) != OK: - print("Cannot read types") - return false - var type_list = parse_json(file.get_as_text()) - file.close() - for t in type_list: - if t.has("label"): - type_names.push_back(t.name) - var c = t.color - t.color = Color(c.r, c.g, c.b, c.a) - if file.open("res://addons/material_maker/nodes/preview_"+t.name+".shader", File.READ) == OK: - t.preview = file.get_as_text() + for p in mm_loader.get_nodes_paths(): + if file.open(p+"/io_types.mmt", File.READ) == OK: + var type_list = parse_json(file.get_as_text()) file.close() - types[t.name] = t + for t in type_list: + if t.has("label"): + type_names.push_back(t.name) + var c = t.color + t.color = Color(c.r, c.g, c.b, c.a) + if file.open(p+"/preview_"+t.name+".shader", File.READ) == OK: + t.preview = file.get_as_text() + file.close() + types[t.name] = t + break diff --git a/addons/material_maker/engine/loader.gd b/addons/material_maker/engine/loader.gd index 0aa9eeb..20a4482 100644 --- a/addons/material_maker/engine/loader.gd +++ b/addons/material_maker/engine/loader.gd @@ -8,9 +8,12 @@ var predefined_generators = {} func _ready()-> void: update_predefined_generators() +func get_nodes_paths() -> Array: + return [ STD_GENDEF_PATH, OS.get_executable_path().get_base_dir()+"/nodes" ] + func update_predefined_generators()-> void: predefined_generators = {} - for path in [ STD_GENDEF_PATH, OS.get_executable_path().get_base_dir()+"/generators" ]: + for path in get_nodes_paths(): var dir = Directory.new() if dir.open(path) == OK: dir.list_dir_begin() @@ -24,7 +27,7 @@ func update_predefined_generators()-> void: file_name = dir.get_next() func generator_name_from_path(path : String) -> String: - for p in [ STD_GENDEF_PATH, OS.get_executable_path().get_base_dir()+"/generators" ]: + for p in get_nodes_paths(): print(p) print(path.get_base_dir()) return path.get_basename().get_file() @@ -56,6 +59,8 @@ func add_to_gen_graph(gen_graph, generators, connections) -> Dictionary: func create_gen(data) -> MMGenBase: var guess = [ + { keyword="export", type=MMGenMaterial }, + { keyword="connections", type=MMGenGraph }, { keyword="connections", type=MMGenGraph }, { keyword="nodes", type=MMGenGraph }, { keyword="shader_model", type=MMGenShader }, @@ -65,7 +70,7 @@ func create_gen(data) -> MMGenBase: { keyword="widgets", type=MMGenRemote } ] var types = { - material = MMGenMaterial, + material_export = MMGenMaterial, buffer = MMGenBuffer, image = MMGenImage, ios = MMGenIOs, @@ -99,7 +104,7 @@ func create_gen(data) -> MMGenBase: func get_generator_list() -> Array: var rv = [] var dir : Directory = Directory.new() - for p in [ STD_GENDEF_PATH, OS.get_executable_path().get_base_dir()+"/generators" ]: + for p in get_nodes_paths(): dir.open(p) dir.list_dir_begin(true) while true: diff --git a/addons/material_maker/import_plugin/ptex_import.gd b/addons/material_maker/import_plugin/ptex_import.gd index b74fd0a..b39f6d4 100644 --- a/addons/material_maker/import_plugin/ptex_import.gd +++ b/addons/material_maker/import_plugin/ptex_import.gd @@ -46,20 +46,26 @@ func get_visible_name() -> String: return "Material Maker Importer" func import(source_file: String, save_path: String, options: Dictionary, platform_variants: Array, gen_files: Array) -> int: - var filename = save_path + "." + get_save_extension() var material = null if options.render: - material = plugin.generate_material(source_file) - while material is GDScriptFunctionState: - material = yield(material, "completed") + var gen = mm_loader.load_gen(source_file) + if gen != null: + plugin.add_child(gen) + for c in gen.get_children(): + if c.has_method("get_export_profiles"): + var result = c.export_material(source_file.get_basename(), "Godot") + while result is GDScriptFunctionState: + result = yield(result, "completed") + break + gen.queue_free() else: + var filename = save_path + "." + get_save_extension() material = SpatialMaterial.new() material.set_script(preload("res://addons/material_maker/import_plugin/ptex_spatial_material.gd")) var file : File = File.new() if file.open(source_file, File.READ) == OK: material.set_ptex_no_render(to_json(parse_json(file.get_as_text()))) file.close() - if material != null: material.uv1_scale = options.scale * Vector3(1.0, 1.0, 1.0) ResourceSaver.save(filename, material) return OK diff --git a/addons/material_maker/import_plugin/ptex_spatial_material.gd b/addons/material_maker/import_plugin/ptex_spatial_material.gd index b9310a5..4808d56 100644 --- a/addons/material_maker/import_plugin/ptex_spatial_material.gd +++ b/addons/material_maker/import_plugin/ptex_spatial_material.gd @@ -23,6 +23,6 @@ func update_texture() -> void: var status = mm_material.render_textures() while status is GDScriptFunctionState: status = yield(status, "completed") - mm_material.update_spatial_material(self) + mm_material.update_material(self) mm_graph.queue_free() diff --git a/addons/material_maker/nodes/godot.tres.tmpl b/addons/material_maker/nodes/godot.tres.tmpl new file mode 100644 index 0000000..fd6d6bd --- /dev/null +++ b/addons/material_maker/nodes/godot.tres.tmpl @@ -0,0 +1,52 @@ +[gd_resource type="SpatialMaterial" load_steps=5 format=2] + +$if $(connected:albedo_tex) +[ext_resource path="$(file_prefix)_albedo.png" type="Texture" id=1] +$fi +$if $(connected:ao_tex) or $(connected:roughness_tex) or $(connected:metallic_tex) +[ext_resource path="$(file_prefix)_orm.png" type="Texture" id=2] +$fi +$if $(connected:normal_tex) +[ext_resource path="$(file_prefix)_normal.png" type="Texture" id=3] +$fi +$if $(connected:depth_tex) +[ext_resource path="$(file_prefix)_depth.png" type="Texture" id=4] +$fi + +[resource] +albedo_color = Color($(param:albedo_color.r), $(param:albedo_color.g), $(param:albedo_color.b), $(param:albedo_color.a)) +$if $(connected:albedo_tex) +albedo_texture = ExtResource( 1 ) +$fi +metallic = $(param:metallic) +$if $(connected:metallic_tex) +metallic_texture = ExtResource( 2 ) +metallic_texture_channel = 2 +$fi +roughness = $(param:roughness) +$if $(connected:ao_tex) or $(connected:roughness_tex) or $(connected:metallic_tex) +roughness_texture = ExtResource( 2 ) +roughness_texture_channel = 1 +$fi +$if $(connected:normal_tex) +normal_enabled = true +normal_scale = $(param:normal) +normal_texture = ExtResource( 3 ) +$fi +$if $(connected:ao_tex) +ao_enabled = true +ao_light_affect = $(param:ao) +ao_texture = ExtResource( 2 ) +ao_on_uv2 = false +ao_texture_channel = 0 +$fi +$if $(connected:depth_tex) +depth_enabled = true +depth_scale = $(expr:0.2*$(param:depth_scale)) +depth_deep_parallax = true +depth_min_layers = 8 +depth_max_layers = 32 +depth_flip_tangent = false +depth_flip_binormal = false +depth_texture = ExtResource( 4 ) +$fi diff --git a/addons/material_maker/nodes/material.mmg b/addons/material_maker/nodes/material.mmg new file mode 100644 index 0000000..a64f898 --- /dev/null +++ b/addons/material_maker/nodes/material.mmg @@ -0,0 +1,427 @@ +{ + "name": "material", + "node_position": { + "x": 0, + "y": 0 + }, + "parameters": { + "albedo_color": { + "a": 1, + "b": 1, + "g": 1, + "r": 1, + "type": "Color" + }, + "ao": 1, + "depth_scale": 0.5, + "emission": 1, + "metallic": 1, + "normal": 1, + "roughness": 1, + "size": 11, + "sss": 0 + }, + "export": { + }, + "shader_model": { + "code": "", + "global": "", + "inputs": [ + { + "default": "vec3(1.0)", + "label": "", + "name": "albedo_tex", + "type": "rgb" + }, + { + "default": "1.0", + "label": "", + "name": "metallic_tex", + "type": "f" + }, + { + "default": "1.0", + "label": "", + "name": "roughness_tex", + "type": "f" + }, + { + "default": "vec3(0.0)", + "label": "", + "name": "emission_tex", + "type": "rgb" + }, + { + "default": "vec3(0.5)", + "label": "", + "name": "normal_tex", + "type": "rgb" + }, + { + "default": "1.0", + "label": "", + "name": "ao_tex", + "type": "f" + }, + { + "default": "0.0", + "label": "", + "name": "depth_tex", + "type": "f" + }, + { + "default": "0.0", + "label": "", + "name": "sss_tex", + "type": "f" + } + ], + "instance": "", + "name": "Material", + "outputs": [ + { + "desc":"0: albedo", + "rgb": "$albedo_tex($uv)", + "type": "rgb" + }, + { + "desc":"1: ambient occlusion, roughness, metallic", + "rgb": "vec3($ao_tex($uv), $roughness_tex($uv), $metallic_tex($uv))", + "type": "rgb" + }, + { + "desc":"2: emission", + "rgb": "$emission_tex($uv)", + "type": "rgb" + }, + { + "desc":"3: normal map for Godot", + "rgb": "$normal_tex($uv)*vec3(-1.0, 1.0, 1.0)+vec3(1.0, 0.0, 0.0)", + "type": "rgb" + }, + { + "desc":"4: normal map for Godot", + "f": "$depth_tex($uv)", + "type": "f" + }, + { + "desc":"5: sub surface scattering", + "f": "$sss_tex($uv)", + "type": "f" + }, + { + "desc":"6: unity metallic/smoothness", + "rgba": "vec4(vec3($metallic_tex($uv)), 1.0-$roughness_tex($uv))", + "type": "rgba" + }, + { + "desc":"7: unity normal", + "rgb": "$normal_tex($uv)*vec3(-1.0, 1.0, -1.0)+vec3(1.0, 0.0, 1.0)", + "type": "rgb" + }, + { + "desc":"8: unity height", + "f": "1.0-$depth_tex($uv)", + "type": "f" + }, + { + "desc":"9: unity occlusion", + "f": "$ao_tex($uv)", + "type": "f" + }, + { + "desc":"10: unreal normal", + "rgb": "$normal_tex($uv)*vec3(-1.0)+vec3(1.0)", + "type": "rgb" + } + ], + "exports": { + "Godot": { + "export_extension":"tres", + "files": [ + { + "type":"texture", + "file_name":"$(path_prefix)_albedo.png", + "output":0, + "conditions":"$(connected:albedo_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_orm.png", + "output":1, + "conditions":"$(connected:ao_tex) or $(connected:roughness_tex) or $(connected:metallic_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_emission.png", + "output":2, + "conditions":"$(connected:emission_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_normal.png", + "output":3, + "conditions":"$(connected:normal_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_depth.png", + "output":4, + "conditions":"$(connected:depth_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_sss.png", + "output":5, + "conditions":"$(connected:sss_tex)" + }, + { + "type":"template", + "file_name":"$(path_prefix).tres", + "template":"godot.tres.tmpl" + } + ] + }, + "Unity": { + "export_extension":"mat", + "uids":6, + "files": [ + { + "type":"texture", + "file_name":"$(path_prefix)_albedo.png", + "output":0, + "conditions":"$(connected:albedo_tex)" + }, + { + "type":"template", + "file_name":"$(path_prefix)_albedo.png.meta", + "template":"unity.png.meta.tmpl", + "file_params": { + "uid":"$(uid:0)", + "srgb":"1", + "normal":"0" + }, + "conditions":"$(connected:albedo_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_metal_smoothness.png", + "output":6, + "conditions":"$(connected:roughness_tex) or $(connected:metallic_tex)" + }, + { + "type":"template", + "file_name":"$(path_prefix)_metal_smoothness.png.meta", + "template":"unity.png.meta.tmpl", + "file_params": { + "uid":"$(uid:1)", + "srgb":"1", + "normal":"0" + }, + "conditions":"$(connected:roughness_tex) or $(connected:metallic_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_normal.png", + "output":7, + "conditions":"$(connected:normal_tex)" + }, + { + "type":"template", + "file_name":"$(path_prefix)_normal.png.meta", + "template":"unity.png.meta.tmpl", + "file_params": { + "uid":"$(uid:2)", + "srgb":"0", + "normal":"1" + }, + "conditions":"$(connected:normal_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_height.png", + "output":8, + "conditions":"$(connected:depth_tex)" + }, + { + "type":"template", + "file_name":"$(path_prefix)_height.png.meta", + "template":"unity.png.meta.tmpl", + "file_params": { + "uid":"$(uid:3)", + "srgb":"1", + "normal":"0" + }, + "conditions":"$(connected:depth_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_occlusion.png", + "output":9, + "conditions":"$(connected:ao_tex)" + }, + { + "type":"template", + "file_name":"$(path_prefix)_occlusion.png.meta", + "template":"unity.png.meta.tmpl", + "file_params": { + "uid":"$(uid:4)", + "srgb":"1", + "normal":"0" + }, + "conditions":"$(connected:ao_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_emission.png", + "output":2, + "conditions":"$(connected:emission_tex)" + }, + { + "type":"template", + "file_name":"$(path_prefix)_emission.png.meta", + "template":"unity.png.meta.tmpl", + "file_params": { + "uid":"$(uid:5)", + "srgb":"1", + "normal":"0" + }, + "conditions":"$(connected:emission_tex)" + }, + { + "type":"template", + "file_name":"$(path_prefix).mat", + "template":"unity.mat.tmpl" + } + ] + }, + "Unreal": { + "export_extension":"tres", + "files": [ + { + "type":"texture", + "file_name":"$(path_prefix)_albedo.png", + "output":0, + "conditions":"$(connected:albedo_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_orm.png", + "output":1, + "conditions":"$(connected:ao_tex) or $(connected:roughness_tex) or $(connected:metallic_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_emission.png", + "output":2, + "conditions":"$(connected:emission_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_normal.png", + "output":10, + "conditions":"$(connected:normal_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_height.png", + "output":8, + "conditions":"$(connected:depth_tex)" + } + ] + }, + }, + "parameters": [ + { + "default": { + "a": 1, + "b": 1, + "g": 1, + "r": 1 + }, + "label": "Albedo", + "name": "albedo_color", + "type": "color" + }, + { + "control": "None", + "default": 1, + "label": "Metallic", + "max": 1, + "min": 0, + "name": "metallic", + "step": 0.01, + "type": "float" + }, + { + "control": "None", + "default": 1, + "label": "Roughness", + "max": 1, + "min": 0, + "name": "roughness", + "step": 0.01, + "type": "float" + }, + { + "control": "None", + "default": 1, + "label": "Emission", + "max": 1, + "min": 0, + "name": "emission_energy", + "step": 0.01, + "type": "float" + }, + { + "control": "None", + "default": 1, + "label": "Normal", + "max": 10, + "min": 0, + "name": "normal", + "step": 0.01, + "type": "float" + }, + { + "control": "None", + "default": 1, + "label": "Ambient occlusion", + "max": 1, + "min": 0, + "name": "ao", + "step": 0.01, + "type": "float" + }, + { + "control": "None", + "default": 0.5, + "label": "Depth", + "max": 1, + "min": 0, + "name": "depth_scale", + "step": 0.01, + "type": "float" + }, + { + "control": "None", + "default": 0, + "label": "Subsurf. scatter.", + "max": 1, + "min": 0, + "name": "sss", + "step": 0.01, + "type": "float" + }, + { + "default": 11, + "first": 6, + "label": "Size", + "last": 12, + "name": "size", + "type": "size" + } + ] + }, + "type": "material_export" +} \ No newline at end of file diff --git a/addons/material_maker/nodes/unity.mat.tmpl b/addons/material_maker/nodes/unity.mat.tmpl new file mode 100644 index 0000000..0b45a4d --- /dev/null +++ b/addons/material_maker/nodes/unity.mat.tmpl @@ -0,0 +1,97 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: test + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords:$(expr:" _METALLICGLOSSMAP" if $(connected:roughness_tex) or $(connected:metallic_tex) else "")$(expr:" _NORMALMAP" if $(connected:normal_tex) else "")$(expr:" _PARALLAXMAP" if $(connected:depth_tex) else "") + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: +$if $(connected:normal_tex) + m_Texture: {fileID: 2800000, guid: $(uid:2), type: 3} +$else + m_Texture: {fileID: 0} +$fi + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: +$if $(connected:albedo_tex) + m_Texture: {fileID: 2800000, guid: $(uid:0), type: 3} +$else + m_Texture: {fileID: 0} +$fi + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: +$if $(connected:roughness_tex) or $(connected:metallic_tex) + m_Texture: {fileID: 2800000, guid: $(uid:1), type: 3} +$else + m_Texture: {fileID: 0} +$fi + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: +$if $(connected:ao_tex) + m_Texture: {fileID: 2800000, guid: $(uid:4), type: 3} +$else + m_Texture: {fileID: 0} +$fi + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: +$if $(connected:depth_tex) + m_Texture: {fileID: 2800000, guid: $(uid:3), type: 3} +$else + m_Texture: {fileID: 0} +$fi + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/addons/material_maker/nodes/unity.png.meta.tmpl b/addons/material_maker/nodes/unity.png.meta.tmpl new file mode 100644 index 0000000..7321aa3 --- /dev/null +++ b/addons/material_maker/nodes/unity.png.meta.tmpl @@ -0,0 +1,91 @@ +fileFormatVersion: 2 +guid: $(file_param:uid) +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 10 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: $(file_param:srgb) + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: $(file_param:normal) + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/addons/material_maker/plugin.cfg b/addons/material_maker/plugin.cfg index 27726c0..debdbba 100644 --- a/addons/material_maker/plugin.cfg +++ b/addons/material_maker/plugin.cfg @@ -1,7 +1,7 @@ [plugin] -name="MaterialMaker" -description="Procedural Material creation tool" +name="Material Maker" +description="Import plugin for Material Maker" author="RodZilla" -version="0.6" +version="0.9" script="plugin.gd" diff --git a/addons/material_maker/plugin.gd b/addons/material_maker/plugin.gd index b6b6011..12dbbee 100644 --- a/addons/material_maker/plugin.gd +++ b/addons/material_maker/plugin.gd @@ -11,16 +11,3 @@ func _exit_tree() -> void: if importer != null: remove_import_plugin(importer) importer = null - -func generate_material(ptex_filename: String) -> Material: - var generator = mm_loader.load_gen(ptex_filename) - add_child(generator) - if generator.has_node("Material"): - var gen_material = generator.get_node("Material") - if gen_material != null: - var return_value = gen_material.render_textures() - while return_value is GDScriptFunctionState: - return_value = yield(return_value, "completed") - var prefix = ptex_filename.left(ptex_filename.rfind(".")) - return gen_material.export_textures(prefix, get_editor_interface()) - return null diff --git a/export_presets.cfg b/export_presets.cfg index 5a32dec..a4cccdb 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -5,10 +5,10 @@ platform="Windows Desktop" runnable=false custom_features="" export_filter="resources" -export_files=PoolStringArray( "res://addons/material_maker/common.shader", "res://addons/material_maker/engine/gen_base.gd", "res://addons/material_maker/engine/gen_buffer.gd", "res://addons/material_maker/engine/gen_comment.gd", "res://addons/material_maker/engine/gen_context.gd", "res://addons/material_maker/engine/gen_convolution.gd", "res://addons/material_maker/engine/gen_debug.gd", "res://addons/material_maker/engine/gen_export.gd", "res://addons/material_maker/engine/gen_graph.gd", "res://addons/material_maker/engine/gen_image.gd", "res://addons/material_maker/engine/gen_ios.gd", "res://addons/material_maker/engine/gen_material.gd", "res://addons/material_maker/engine/gen_remote.gd", "res://addons/material_maker/engine/gen_shader.gd", "res://addons/material_maker/engine/gen_switch.gd", "res://addons/material_maker/engine/gen_texture.gd", "res://addons/material_maker/engine/loader.gd", "res://addons/material_maker/engine/renderer.gd", "res://addons/material_maker/engine/renderer.tscn", "res://addons/material_maker/types/gradient.gd", "res://addons/material_maker/types/types.gd", "res://default_env.tres", "res://icon.png", "res://material_maker/environment.gd", "res://material_maker/fonts/hack.ttf", "res://material_maker/graph_edit.gd", "res://material_maker/graph_edit.tscn", "res://material_maker/icons/icon.png", "res://material_maker/icons/icons.svg", "res://material_maker/icons/link.tres", "res://material_maker/icons/randomness_locked.tres", "res://material_maker/icons/randomness_unlocked.tres", "res://material_maker/icons/remove.tres", "res://material_maker/library.gd", "res://material_maker/library.tscn", "res://material_maker/library_tree.gd", "res://material_maker/main_window.gd", "res://material_maker/main_window.tscn", "res://material_maker/node_factory.gd", "res://material_maker/nodes/base.gd", "res://material_maker/nodes/comment.gd", "res://material_maker/nodes/comment.tscn", "res://material_maker/nodes/debug.gd", "res://material_maker/nodes/debug.tscn", "res://material_maker/nodes/debug/debug_popup.gd", "res://material_maker/nodes/debug/debug_popup.tscn", "res://material_maker/nodes/edit_buttons.gd", "res://material_maker/nodes/edit_buttons.tscn", "res://material_maker/nodes/generic.gd", "res://material_maker/nodes/generic.tscn", "res://material_maker/nodes/image.gd", "res://material_maker/nodes/image.tscn", "res://material_maker/nodes/image/godot_logo.png", "res://material_maker/nodes/ios.gd", "res://material_maker/nodes/ios.tscn", "res://material_maker/nodes/ios/add.tscn", "res://material_maker/nodes/ios/port.gd", "res://material_maker/nodes/ios/port.tscn", "res://material_maker/nodes/remote.gd", "res://material_maker/nodes/remote.tscn", "res://material_maker/nodes/switch.gd", "res://material_maker/nodes/switch.tscn", "res://material_maker/preview/control_point.gd", "res://material_maker/preview/control_point.tscn", "res://material_maker/preview/panoramas/epping_forest_01.hdr", "res://material_maker/preview/panoramas/moonless_golf.hdr", "res://material_maker/preview/panoramas/studio_sky.tres", "res://material_maker/preview/preview_2d.gd", "res://material_maker/preview/preview_2d.tscn", "res://material_maker/preview/preview_3d.gd", "res://material_maker/preview/preview_3d.tscn", "res://material_maker/preview/preview_3d_scene.tscn", "res://material_maker/preview/preview_3d_ui.gd", "res://material_maker/preview/preview_3d_ui.tscn", "res://material_maker/preview/preview_light.gd", "res://material_maker/preview/preview_light.tscn", "res://material_maker/preview/preview_objects.tscn", "res://material_maker/widgets/about/about.gd", "res://material_maker/widgets/about/about.tscn", "res://material_maker/widgets/about/facebook.png", "res://material_maker/widgets/about/github.png", "res://material_maker/widgets/about/itchio.png", "res://material_maker/widgets/about/twitter.png", "res://material_maker/widgets/about/youtube.png", "res://material_maker/widgets/add_node_popup.gd", "res://material_maker/widgets/add_node_popup.tscn", "res://material_maker/widgets/float_edit.gd", "res://material_maker/widgets/float_edit.tscn", "res://material_maker/widgets/gradient_editor.gd", "res://material_maker/widgets/gradient_editor.tscn", "res://material_maker/widgets/gradient_popup.gd", "res://material_maker/widgets/gradient_popup.tscn", "res://material_maker/widgets/graph_tree/graph_tree.gd", "res://material_maker/widgets/graph_tree/graph_tree.tscn", "res://material_maker/widgets/hslider.gd", "res://material_maker/widgets/hslider.tscn", "res://material_maker/widgets/icon.png", "res://material_maker/widgets/line_dialog.gd", "res://material_maker/widgets/line_dialog.tscn", "res://material_maker/widgets/linked_widgets/editable_label.gd", "res://material_maker/widgets/linked_widgets/editable_label.tscn", "res://material_maker/widgets/linked_widgets/link.gd", "res://material_maker/widgets/node_editor.tscn", "res://material_maker/widgets/node_editor/enum_editor.gd", "res://material_maker/widgets/node_editor/enum_editor.tscn", "res://material_maker/widgets/node_editor/input.gd", "res://material_maker/widgets/node_editor/input.tscn", "res://material_maker/widgets/node_editor/node_editor.gd", "res://material_maker/widgets/node_editor/node_editor.tscn", "res://material_maker/widgets/node_editor/node_editor_item_list.gd", "res://material_maker/widgets/node_editor/output.gd", "res://material_maker/widgets/node_editor/output.tscn", "res://material_maker/widgets/node_editor/parameter.gd", "res://material_maker/widgets/node_editor/parameter.tscn", "res://material_maker/widgets/node_editor/parameter_boolean.gd", "res://material_maker/widgets/node_editor/parameter_boolean.tscn", "res://material_maker/widgets/node_editor/parameter_color.gd", "res://material_maker/widgets/node_editor/parameter_color.tscn", "res://material_maker/widgets/node_editor/parameter_enum.gd", "res://material_maker/widgets/node_editor/parameter_enum.tscn", "res://material_maker/widgets/node_editor/parameter_float.gd", "res://material_maker/widgets/node_editor/parameter_float.tscn", "res://material_maker/widgets/node_editor/parameter_gradient.gd", "res://material_maker/widgets/node_editor/parameter_gradient.tscn", "res://material_maker/widgets/node_editor/parameter_size.gd", "res://material_maker/widgets/node_editor/parameter_size.tscn", "res://material_maker/widgets/preview_button.tscn", "res://material_maker/widgets/size_option_button.gd", "res://material_maker/widgets/tabs.gd", "res://material_maker/widgets/text_dialog.gd", "res://material_maker/widgets/text_dialog.tscn", "res://material_maker/window_dialog.tscn", "res://rodz_labs_logo.png" ) +export_files=PoolStringArray( "res://addons/material_maker/common.shader", "res://addons/material_maker/engine/gen_base.gd", "res://addons/material_maker/engine/gen_buffer.gd", "res://addons/material_maker/engine/gen_comment.gd", "res://addons/material_maker/engine/gen_context.gd", "res://addons/material_maker/engine/gen_convolution.gd", "res://addons/material_maker/engine/gen_debug.gd", "res://addons/material_maker/engine/gen_export.gd", "res://addons/material_maker/engine/gen_graph.gd", "res://addons/material_maker/engine/gen_image.gd", "res://addons/material_maker/engine/gen_ios.gd", "res://addons/material_maker/engine/gen_material.gd", "res://addons/material_maker/engine/gen_remote.gd", "res://addons/material_maker/engine/gen_shader.gd", "res://addons/material_maker/engine/gen_switch.gd", "res://addons/material_maker/engine/gen_texture.gd", "res://addons/material_maker/engine/io_types.gd", "res://addons/material_maker/engine/loader.gd", "res://addons/material_maker/engine/renderer.gd", "res://addons/material_maker/engine/renderer.tscn", "res://addons/material_maker/types/gradient.gd", "res://addons/material_maker/types/types.gd", "res://default_env.tres", "res://icon.png", "res://material_maker/environment.gd", "res://material_maker/fonts/hack.ttf", "res://material_maker/graph_edit.gd", "res://material_maker/graph_edit.tscn", "res://material_maker/icons/edit.tres", "res://material_maker/icons/icon.png", "res://material_maker/icons/icons.svg", "res://material_maker/icons/link.tres", "res://material_maker/icons/randomness_locked.tres", "res://material_maker/icons/randomness_unlocked.tres", "res://material_maker/icons/remove.tres", "res://material_maker/library.gd", "res://material_maker/library.tscn", "res://material_maker/library_tree.gd", "res://material_maker/main_window.gd", "res://material_maker/main_window.tscn", "res://material_maker/node_factory.gd", "res://material_maker/nodes/base.gd", "res://material_maker/nodes/comment.gd", "res://material_maker/nodes/comment.tscn", "res://material_maker/nodes/debug.gd", "res://material_maker/nodes/debug.tscn", "res://material_maker/nodes/debug/debug_popup.gd", "res://material_maker/nodes/debug/debug_popup.tscn", "res://material_maker/nodes/edit_buttons.gd", "res://material_maker/nodes/edit_buttons.tscn", "res://material_maker/nodes/generic.gd", "res://material_maker/nodes/generic.tscn", "res://material_maker/nodes/image.gd", "res://material_maker/nodes/image.tscn", "res://material_maker/nodes/image/godot_logo.png", "res://material_maker/nodes/ios.gd", "res://material_maker/nodes/ios.tscn", "res://material_maker/nodes/ios/add.tscn", "res://material_maker/nodes/ios/port.gd", "res://material_maker/nodes/ios/port.tscn", "res://material_maker/nodes/remote.gd", "res://material_maker/nodes/remote.tscn", "res://material_maker/nodes/switch.gd", "res://material_maker/nodes/switch.tscn", "res://material_maker/preview/control_point.gd", "res://material_maker/preview/control_point.tscn", "res://material_maker/preview/panoramas/epping_forest_01.hdr", "res://material_maker/preview/panoramas/moonless_golf.hdr", "res://material_maker/preview/panoramas/studio_sky.tres", "res://material_maker/preview/preview_2d.gd", "res://material_maker/preview/preview_2d.tscn", "res://material_maker/preview/preview_3d.gd", "res://material_maker/preview/preview_3d.tscn", "res://material_maker/preview/preview_3d_scene.tscn", "res://material_maker/preview/preview_3d_ui.gd", "res://material_maker/preview/preview_3d_ui.tscn", "res://material_maker/preview/preview_light.gd", "res://material_maker/preview/preview_light.tscn", "res://material_maker/preview/preview_objects.tscn", "res://material_maker/theme/dark.tres", "res://material_maker/theme/default.tres", "res://material_maker/theme/light.tres", "res://material_maker/widgets/about/about.gd", "res://material_maker/widgets/about/about.tscn", "res://material_maker/widgets/about/facebook.png", "res://material_maker/widgets/about/github.png", "res://material_maker/widgets/about/itchio.png", "res://material_maker/widgets/about/twitter.png", "res://material_maker/widgets/about/youtube.png", "res://material_maker/widgets/add_node_popup.gd", "res://material_maker/widgets/add_node_popup.tscn", "res://material_maker/widgets/float_edit.gd", "res://material_maker/widgets/float_edit.tscn", "res://material_maker/widgets/gradient_editor.gd", "res://material_maker/widgets/gradient_editor.tscn", "res://material_maker/widgets/gradient_popup.gd", "res://material_maker/widgets/gradient_popup.tscn", "res://material_maker/widgets/graph_tree/graph_tree.gd", "res://material_maker/widgets/graph_tree/graph_tree.tscn", "res://material_maker/widgets/hslider.gd", "res://material_maker/widgets/hslider.tscn", "res://material_maker/widgets/icon.png", "res://material_maker/widgets/line_dialog.gd", "res://material_maker/widgets/line_dialog.tscn", "res://material_maker/widgets/linked_widgets/editable_label.gd", "res://material_maker/widgets/linked_widgets/editable_label.tscn", "res://material_maker/widgets/linked_widgets/link.gd", "res://material_maker/widgets/node_editor.tscn", "res://material_maker/widgets/node_editor/enum_editor.gd", "res://material_maker/widgets/node_editor/enum_editor.tscn", "res://material_maker/widgets/node_editor/input.gd", "res://material_maker/widgets/node_editor/input.tscn", "res://material_maker/widgets/node_editor/node_editor.gd", "res://material_maker/widgets/node_editor/node_editor.tscn", "res://material_maker/widgets/node_editor/node_editor_item_list.gd", "res://material_maker/widgets/node_editor/output.gd", "res://material_maker/widgets/node_editor/output.tscn", "res://material_maker/widgets/node_editor/parameter.gd", "res://material_maker/widgets/node_editor/parameter.tscn", "res://material_maker/widgets/node_editor/parameter_boolean.gd", "res://material_maker/widgets/node_editor/parameter_boolean.tscn", "res://material_maker/widgets/node_editor/parameter_color.gd", "res://material_maker/widgets/node_editor/parameter_color.tscn", "res://material_maker/widgets/node_editor/parameter_enum.gd", "res://material_maker/widgets/node_editor/parameter_enum.tscn", "res://material_maker/widgets/node_editor/parameter_float.gd", "res://material_maker/widgets/node_editor/parameter_float.tscn", "res://material_maker/widgets/node_editor/parameter_gradient.gd", "res://material_maker/widgets/node_editor/parameter_gradient.tscn", "res://material_maker/widgets/node_editor/parameter_size.gd", "res://material_maker/widgets/node_editor/parameter_size.tscn", "res://material_maker/widgets/preview_button.tscn", "res://material_maker/widgets/size_option_button.gd", "res://material_maker/widgets/tabs.gd", "res://material_maker/widgets/text_dialog.gd", "res://material_maker/widgets/text_dialog.tscn", "res://material_maker/window_dialog.tscn", "res://rodz_labs_logo.png", "res://start.gd", "res://start.tscn" ) include_filter="" exclude_filter="*.ptex,*.mmn,*.mmg" -export_path="../../Releases/material_maker_0.8_windows/material_maker.exe" +export_path="../../Releases/material_maker_0.9_windows/material_maker.exe" patch_list=PoolStringArray( ) script_export_mode=1 script_encryption_key="" @@ -34,8 +34,8 @@ codesign/digest_algorithm=1 codesign/description="" codesign/custom_options=PoolStringArray( ) application/icon="res://icon.ico" -application/file_version="0.8" -application/product_version="0.8" +application/file_version="0.9" +application/product_version="0.9" application/company_name="Rodz Labs" application/product_name="Material Maker" application/file_description="" @@ -49,10 +49,10 @@ platform="Linux/X11" runnable=true custom_features="" export_filter="resources" -export_files=PoolStringArray( "res://addons/material_maker/common.shader", "res://addons/material_maker/engine/gen_base.gd", "res://addons/material_maker/engine/gen_buffer.gd", "res://addons/material_maker/engine/gen_comment.gd", "res://addons/material_maker/engine/gen_context.gd", "res://addons/material_maker/engine/gen_convolution.gd", "res://addons/material_maker/engine/gen_debug.gd", "res://addons/material_maker/engine/gen_export.gd", "res://addons/material_maker/engine/gen_graph.gd", "res://addons/material_maker/engine/gen_image.gd", "res://addons/material_maker/engine/gen_ios.gd", "res://addons/material_maker/engine/gen_material.gd", "res://addons/material_maker/engine/gen_remote.gd", "res://addons/material_maker/engine/gen_shader.gd", "res://addons/material_maker/engine/gen_switch.gd", "res://addons/material_maker/engine/gen_texture.gd", "res://addons/material_maker/engine/loader.gd", "res://addons/material_maker/engine/renderer.gd", "res://addons/material_maker/engine/renderer.tscn", "res://addons/material_maker/types/gradient.gd", "res://addons/material_maker/types/types.gd", "res://default_env.tres", "res://icon.png", "res://material_maker/environment.gd", "res://material_maker/fonts/hack.ttf", "res://material_maker/graph_edit.gd", "res://material_maker/graph_edit.tscn", "res://material_maker/icons/icon.png", "res://material_maker/icons/icons.svg", "res://material_maker/icons/link.tres", "res://material_maker/icons/randomness_locked.tres", "res://material_maker/icons/randomness_unlocked.tres", "res://material_maker/icons/remove.tres", "res://material_maker/library.gd", "res://material_maker/library.tscn", "res://material_maker/library_tree.gd", "res://material_maker/main_window.gd", "res://material_maker/main_window.tscn", "res://material_maker/node_factory.gd", "res://material_maker/nodes/base.gd", "res://material_maker/nodes/comment.gd", "res://material_maker/nodes/comment.tscn", "res://material_maker/nodes/debug.gd", "res://material_maker/nodes/debug.tscn", "res://material_maker/nodes/debug/debug_popup.gd", "res://material_maker/nodes/debug/debug_popup.tscn", "res://material_maker/nodes/edit_buttons.gd", "res://material_maker/nodes/edit_buttons.tscn", "res://material_maker/nodes/generic.gd", "res://material_maker/nodes/generic.tscn", "res://material_maker/nodes/image.gd", "res://material_maker/nodes/image.tscn", "res://material_maker/nodes/image/godot_logo.png", "res://material_maker/nodes/ios.gd", "res://material_maker/nodes/ios.tscn", "res://material_maker/nodes/ios/add.tscn", "res://material_maker/nodes/ios/port.gd", "res://material_maker/nodes/ios/port.tscn", "res://material_maker/nodes/remote.gd", "res://material_maker/nodes/remote.tscn", "res://material_maker/nodes/switch.gd", "res://material_maker/nodes/switch.tscn", "res://material_maker/preview/control_point.gd", "res://material_maker/preview/control_point.tscn", "res://material_maker/preview/panoramas/epping_forest_01.hdr", "res://material_maker/preview/panoramas/moonless_golf.hdr", "res://material_maker/preview/panoramas/studio_sky.tres", "res://material_maker/preview/preview_2d.gd", "res://material_maker/preview/preview_2d.tscn", "res://material_maker/preview/preview_3d.gd", "res://material_maker/preview/preview_3d.tscn", "res://material_maker/preview/preview_3d_scene.tscn", "res://material_maker/preview/preview_3d_ui.gd", "res://material_maker/preview/preview_3d_ui.tscn", "res://material_maker/preview/preview_light.gd", "res://material_maker/preview/preview_light.tscn", "res://material_maker/preview/preview_objects.tscn", "res://material_maker/widgets/about/about.gd", "res://material_maker/widgets/about/about.tscn", "res://material_maker/widgets/about/facebook.png", "res://material_maker/widgets/about/github.png", "res://material_maker/widgets/about/itchio.png", "res://material_maker/widgets/about/twitter.png", "res://material_maker/widgets/about/youtube.png", "res://material_maker/widgets/float_edit.gd", "res://material_maker/widgets/float_edit.tscn", "res://material_maker/widgets/gradient_editor.gd", "res://material_maker/widgets/gradient_editor.tscn", "res://material_maker/widgets/gradient_popup.gd", "res://material_maker/widgets/gradient_popup.tscn", "res://material_maker/widgets/graph_tree/graph_tree.gd", "res://material_maker/widgets/graph_tree/graph_tree.tscn", "res://material_maker/widgets/hslider.gd", "res://material_maker/widgets/hslider.tscn", "res://material_maker/widgets/icon.png", "res://material_maker/widgets/line_dialog.gd", "res://material_maker/widgets/line_dialog.tscn", "res://material_maker/widgets/linked_widgets/editable_label.gd", "res://material_maker/widgets/linked_widgets/editable_label.tscn", "res://material_maker/widgets/linked_widgets/link.gd", "res://material_maker/widgets/node_editor.tscn", "res://material_maker/widgets/node_editor/enum_editor.gd", "res://material_maker/widgets/node_editor/enum_editor.tscn", "res://material_maker/widgets/node_editor/input.gd", "res://material_maker/widgets/node_editor/input.tscn", "res://material_maker/widgets/node_editor/node_editor.gd", "res://material_maker/widgets/node_editor/node_editor.tscn", "res://material_maker/widgets/node_editor/node_editor_item_list.gd", "res://material_maker/widgets/node_editor/output.gd", "res://material_maker/widgets/node_editor/output.tscn", "res://material_maker/widgets/node_editor/parameter.gd", "res://material_maker/widgets/node_editor/parameter.tscn", "res://material_maker/widgets/node_editor/parameter_boolean.gd", "res://material_maker/widgets/node_editor/parameter_boolean.tscn", "res://material_maker/widgets/node_editor/parameter_color.gd", "res://material_maker/widgets/node_editor/parameter_color.tscn", "res://material_maker/widgets/node_editor/parameter_enum.gd", "res://material_maker/widgets/node_editor/parameter_enum.tscn", "res://material_maker/widgets/node_editor/parameter_float.gd", "res://material_maker/widgets/node_editor/parameter_float.tscn", "res://material_maker/widgets/node_editor/parameter_gradient.gd", "res://material_maker/widgets/node_editor/parameter_gradient.tscn", "res://material_maker/widgets/node_editor/parameter_size.gd", "res://material_maker/widgets/node_editor/parameter_size.tscn", "res://material_maker/widgets/preview_button.tscn", "res://material_maker/widgets/size_option_button.gd", "res://material_maker/widgets/tabs.gd", "res://material_maker/widgets/text_dialog.gd", "res://material_maker/widgets/text_dialog.tscn", "res://material_maker/window_dialog.tscn", "res://rodz_labs_logo.png" ) +export_files=PoolStringArray( "res://addons/material_maker/common.shader", "res://addons/material_maker/engine/gen_base.gd", "res://addons/material_maker/engine/gen_buffer.gd", "res://addons/material_maker/engine/gen_comment.gd", "res://addons/material_maker/engine/gen_context.gd", "res://addons/material_maker/engine/gen_convolution.gd", "res://addons/material_maker/engine/gen_debug.gd", "res://addons/material_maker/engine/gen_export.gd", "res://addons/material_maker/engine/gen_graph.gd", "res://addons/material_maker/engine/gen_image.gd", "res://addons/material_maker/engine/gen_ios.gd", "res://addons/material_maker/engine/gen_material.gd", "res://addons/material_maker/engine/gen_remote.gd", "res://addons/material_maker/engine/gen_shader.gd", "res://addons/material_maker/engine/gen_switch.gd", "res://addons/material_maker/engine/gen_texture.gd", "res://addons/material_maker/engine/io_types.gd", "res://addons/material_maker/engine/loader.gd", "res://addons/material_maker/engine/renderer.gd", "res://addons/material_maker/engine/renderer.tscn", "res://addons/material_maker/types/gradient.gd", "res://addons/material_maker/types/types.gd", "res://default_env.tres", "res://icon.png", "res://material_maker/environment.gd", "res://material_maker/fonts/hack.ttf", "res://material_maker/graph_edit.gd", "res://material_maker/graph_edit.tscn", "res://material_maker/icons/edit.tres", "res://material_maker/icons/icon.png", "res://material_maker/icons/icons.svg", "res://material_maker/icons/link.tres", "res://material_maker/icons/randomness_locked.tres", "res://material_maker/icons/randomness_unlocked.tres", "res://material_maker/icons/remove.tres", "res://material_maker/library.gd", "res://material_maker/library.tscn", "res://material_maker/library_tree.gd", "res://material_maker/main_window.gd", "res://material_maker/main_window.tscn", "res://material_maker/node_factory.gd", "res://material_maker/nodes/base.gd", "res://material_maker/nodes/comment.gd", "res://material_maker/nodes/comment.tscn", "res://material_maker/nodes/debug.gd", "res://material_maker/nodes/debug.tscn", "res://material_maker/nodes/debug/debug_popup.gd", "res://material_maker/nodes/debug/debug_popup.tscn", "res://material_maker/nodes/edit_buttons.gd", "res://material_maker/nodes/edit_buttons.tscn", "res://material_maker/nodes/generic.gd", "res://material_maker/nodes/generic.tscn", "res://material_maker/nodes/image.gd", "res://material_maker/nodes/image.tscn", "res://material_maker/nodes/image/godot_logo.png", "res://material_maker/nodes/ios.gd", "res://material_maker/nodes/ios.tscn", "res://material_maker/nodes/ios/add.tscn", "res://material_maker/nodes/ios/port.gd", "res://material_maker/nodes/ios/port.tscn", "res://material_maker/nodes/remote.gd", "res://material_maker/nodes/remote.tscn", "res://material_maker/nodes/switch.gd", "res://material_maker/nodes/switch.tscn", "res://material_maker/preview/control_point.gd", "res://material_maker/preview/control_point.tscn", "res://material_maker/preview/panoramas/epping_forest_01.hdr", "res://material_maker/preview/panoramas/moonless_golf.hdr", "res://material_maker/preview/panoramas/studio_sky.tres", "res://material_maker/preview/preview_2d.gd", "res://material_maker/preview/preview_2d.tscn", "res://material_maker/preview/preview_3d.gd", "res://material_maker/preview/preview_3d.tscn", "res://material_maker/preview/preview_3d_scene.tscn", "res://material_maker/preview/preview_3d_ui.gd", "res://material_maker/preview/preview_3d_ui.tscn", "res://material_maker/preview/preview_light.gd", "res://material_maker/preview/preview_light.tscn", "res://material_maker/preview/preview_objects.tscn", "res://material_maker/theme/dark.tres", "res://material_maker/theme/default.tres", "res://material_maker/theme/light.tres", "res://material_maker/widgets/about/about.gd", "res://material_maker/widgets/about/about.tscn", "res://material_maker/widgets/about/facebook.png", "res://material_maker/widgets/about/github.png", "res://material_maker/widgets/about/itchio.png", "res://material_maker/widgets/about/twitter.png", "res://material_maker/widgets/about/youtube.png", "res://material_maker/widgets/add_node_popup.gd", "res://material_maker/widgets/add_node_popup.tscn", "res://material_maker/widgets/float_edit.gd", "res://material_maker/widgets/float_edit.tscn", "res://material_maker/widgets/gradient_editor.gd", "res://material_maker/widgets/gradient_editor.tscn", "res://material_maker/widgets/gradient_popup.gd", "res://material_maker/widgets/gradient_popup.tscn", "res://material_maker/widgets/graph_tree/graph_tree.gd", "res://material_maker/widgets/graph_tree/graph_tree.tscn", "res://material_maker/widgets/hslider.gd", "res://material_maker/widgets/hslider.tscn", "res://material_maker/widgets/icon.png", "res://material_maker/widgets/line_dialog.gd", "res://material_maker/widgets/line_dialog.tscn", "res://material_maker/widgets/linked_widgets/editable_label.gd", "res://material_maker/widgets/linked_widgets/editable_label.tscn", "res://material_maker/widgets/linked_widgets/link.gd", "res://material_maker/widgets/node_editor.tscn", "res://material_maker/widgets/node_editor/enum_editor.gd", "res://material_maker/widgets/node_editor/enum_editor.tscn", "res://material_maker/widgets/node_editor/input.gd", "res://material_maker/widgets/node_editor/input.tscn", "res://material_maker/widgets/node_editor/node_editor.gd", "res://material_maker/widgets/node_editor/node_editor.tscn", "res://material_maker/widgets/node_editor/node_editor_item_list.gd", "res://material_maker/widgets/node_editor/output.gd", "res://material_maker/widgets/node_editor/output.tscn", "res://material_maker/widgets/node_editor/parameter.gd", "res://material_maker/widgets/node_editor/parameter.tscn", "res://material_maker/widgets/node_editor/parameter_boolean.gd", "res://material_maker/widgets/node_editor/parameter_boolean.tscn", "res://material_maker/widgets/node_editor/parameter_color.gd", "res://material_maker/widgets/node_editor/parameter_color.tscn", "res://material_maker/widgets/node_editor/parameter_enum.gd", "res://material_maker/widgets/node_editor/parameter_enum.tscn", "res://material_maker/widgets/node_editor/parameter_float.gd", "res://material_maker/widgets/node_editor/parameter_float.tscn", "res://material_maker/widgets/node_editor/parameter_gradient.gd", "res://material_maker/widgets/node_editor/parameter_gradient.tscn", "res://material_maker/widgets/node_editor/parameter_size.gd", "res://material_maker/widgets/node_editor/parameter_size.tscn", "res://material_maker/widgets/preview_button.tscn", "res://material_maker/widgets/size_option_button.gd", "res://material_maker/widgets/tabs.gd", "res://material_maker/widgets/text_dialog.gd", "res://material_maker/widgets/text_dialog.tscn", "res://material_maker/window_dialog.tscn", "res://rodz_labs_logo.png", "res://start.gd", "res://start.tscn" ) include_filter="" exclude_filter="*.ptex,*.mmn,*.mmg" -export_path="../../Releases/material_maker_0.8_linux/material_maker.x86_64" +export_path="../../Releases/material_maker_0.9_linux/material_maker.x86_64" patch_list=PoolStringArray( ) script_export_mode=1 script_encryption_key="" @@ -93,8 +93,8 @@ application/info="Made with Godot Engine" application/icon="" application/identifier="" application/signature="" -application/short_version="0.8" -application/version="0.8" +application/short_version="0.9" +application/version="0.9" application/copyright="" display/high_res=false privacy/camera_usage_description="" @@ -134,8 +134,8 @@ platform="Windows Desktop" runnable=true custom_features="" export_filter="resources" -export_files=PoolStringArray( "res://addons/material_maker/common.shader", "res://addons/material_maker/engine/gen_base.gd", "res://addons/material_maker/engine/gen_buffer.gd", "res://addons/material_maker/engine/gen_comment.gd", "res://addons/material_maker/engine/gen_context.gd", "res://addons/material_maker/engine/gen_convolution.gd", "res://addons/material_maker/engine/gen_debug.gd", "res://addons/material_maker/engine/gen_export.gd", "res://addons/material_maker/engine/gen_graph.gd", "res://addons/material_maker/engine/gen_image.gd", "res://addons/material_maker/engine/gen_ios.gd", "res://addons/material_maker/engine/gen_material.gd", "res://addons/material_maker/engine/gen_remote.gd", "res://addons/material_maker/engine/gen_shader.gd", "res://addons/material_maker/engine/gen_switch.gd", "res://addons/material_maker/engine/gen_texture.gd", "res://addons/material_maker/engine/loader.gd", "res://addons/material_maker/engine/renderer.gd", "res://addons/material_maker/engine/renderer.tscn", "res://addons/material_maker/import_plugin/ptex_spatial_material.gd", "res://addons/material_maker/import_plugin/tesselated.shader", "res://addons/material_maker/types/gradient.gd", "res://addons/material_maker/types/types.gd", "res://default_env.tres", "res://demo/demo.tscn", "res://icon.png", "res://rodz_labs_logo.png", "res://start.gd", "res://start.tscn" ) -include_filter="*.mmg,*.json" +export_files=PoolStringArray( "res://addons/material_maker/common.shader", "res://addons/material_maker/engine/gen_base.gd", "res://addons/material_maker/engine/gen_buffer.gd", "res://addons/material_maker/engine/gen_comment.gd", "res://addons/material_maker/engine/gen_context.gd", "res://addons/material_maker/engine/gen_convolution.gd", "res://addons/material_maker/engine/gen_debug.gd", "res://addons/material_maker/engine/gen_export.gd", "res://addons/material_maker/engine/gen_graph.gd", "res://addons/material_maker/engine/gen_image.gd", "res://addons/material_maker/engine/gen_ios.gd", "res://addons/material_maker/engine/gen_material.gd", "res://addons/material_maker/engine/gen_remote.gd", "res://addons/material_maker/engine/gen_shader.gd", "res://addons/material_maker/engine/gen_switch.gd", "res://addons/material_maker/engine/gen_texture.gd", "res://addons/material_maker/engine/io_types.gd", "res://addons/material_maker/engine/loader.gd", "res://addons/material_maker/engine/renderer.gd", "res://addons/material_maker/engine/renderer.tscn", "res://addons/material_maker/import_plugin/ptex_spatial_material.gd", "res://addons/material_maker/import_plugin/tesselated.shader", "res://addons/material_maker/types/gradient.gd", "res://addons/material_maker/types/types.gd", "res://default_env.tres", "res://demo/demo.tscn", "res://icon.png", "res://rodz_labs_logo.png", "res://start.gd", "res://start.tscn" ) +include_filter="*.mmg,*.json,*.mmt" exclude_filter="" export_path="../../Releases/material_maker_demo.exe" patch_list=PoolStringArray( ) @@ -163,8 +163,8 @@ codesign/digest_algorithm=1 codesign/description="" codesign/custom_options=PoolStringArray( ) application/icon="res://icon.ico" -application/file_version="0.8" -application/product_version="0.8" +application/file_version="0.9" +application/product_version="0.9" application/company_name="Rodz Labs" application/product_name="Material Maker" application/file_description="" diff --git a/material_maker/doc/command_line.rst b/material_maker/doc/command_line.rst new file mode 100644 index 0000000..d393e37 --- /dev/null +++ b/material_maker/doc/command_line.rst @@ -0,0 +1,18 @@ +Command line arguments +====================== + +When launched with no command line argument, Material Maker will start with an empty project. + +When launched with the path of a .ptex file as command line argument, Material Maker will +start with this project file. Material Maker can thus be associated to files with .ptex +extension so double-clicking on them will directly open them. + +Material Maker can also be used to export several .ptex file with the following command line: + + material_maker --export -t -o + +Where: + +* **engine** is the target engine (Godot, Unity or Unreal) +* **output_path** is the path where files will be generated +* **input_files** is the list of input files (wildcards are accepted) \ No newline at end of file diff --git a/material_maker/doc/conf.py b/material_maker/doc/conf.py index cfbe359..a8390b7 100644 --- a/material_maker/doc/conf.py +++ b/material_maker/doc/conf.py @@ -24,7 +24,7 @@ copyright = '2018-2020, Rodz Labs' author = 'Rodz Labs' # The short X.Y version -version = '0.8' +version = '0.9' # The full version, including alpha/beta/rc tags release = '' diff --git a/material_maker/doc/export.rst b/material_maker/doc/export.rst new file mode 100644 index 0000000..4f6c5fc --- /dev/null +++ b/material_maker/doc/export.rst @@ -0,0 +1,59 @@ +.. _export-section: + +Exporting Materials +=================== + +When exporting a material, using either the Export submenu or the command line arguments, +Material Maker generates PNG image files for all elements of the material as well as +specific files for the target game engine. + +In all cases, the generated PNG files (and especially the normal map) is generated in the +correct format. + +Godot game engine +----------------- + +When exporting for the Godot game engine, Material Maker will generate a .tres file that +describes a fully configured SpatialMaterial. + +Note that exporting for Godot is not necessary if you use the Material maker addon, that +provides an import plugin. This import plugin can either generate a precomputed material, +or a material that will be rendered at runtime. + +Unity game engine +----------------- + +When exporting for the Unity game engine, Material Maker will generate a .mat file that +describes a fully configured material. It is thus possible to export materials directly +into one of your project assets directory, and Unity will automatically detect the newly +exported materials. + +Unreal game engine +------------------ + +When exporting for the Unreal game engine, Material Maker will only generate PNG image +files, and it is necessary to create the material in Unreal. + +To create a minimal material: + +* import all PNG files into unreal +* create a new material using the **Add new -> Material** menu +* open the new material to edit it +* drag and drop all textures into the material graph to create a Texture Sample node + for each texture +* connect the RGB output of the albedo *Texture Sample* node to the *Base Color* input + of the material node +* connect the R output of the ORM *Texture Sample* node to the *Ambient Occlusion* input + of the material node +* connect the G output of the ORM *Texture Sample* node to the *Roughness* input + of the material node +* connect the B output of the ORM *Texture Sample* node to the *Metallic* input + of the material node +* connect the RGB output of the normal *Texture Sample* node to the *Normal* input + of the material node + +More complex materials with support for emission textures, depth maps, texture +coordinate scaling... + +.. image:: images/unreal_export.png + :align: center diff --git a/material_maker/doc/images/unreal_export.png b/material_maker/doc/images/unreal_export.png new file mode 100644 index 0000000..6d2e399 Binary files /dev/null and b/material_maker/doc/images/unreal_export.png differ diff --git a/material_maker/doc/index.rst b/material_maker/doc/index.rst index eb3421d..7268459 100644 --- a/material_maker/doc/index.rst +++ b/material_maker/doc/index.rst @@ -8,3 +8,5 @@ Material Maker User Manual user_interface nodes base_library + export + command_line diff --git a/material_maker/doc/node_filter_normal_map.rst b/material_maker/doc/node_filter_normal_map.rst index c5072f9..c722de8 100644 --- a/material_maker/doc/node_filter_normal_map.rst +++ b/material_maker/doc/node_filter_normal_map.rst @@ -21,17 +21,29 @@ Parameters The **Normal map** node has the following parameters: -* the *format* of the normal map (default, OpenGL or DirectX) +* the *format* of the normal map (default, OpenGL or DirectX). The format should + always be set to "default" when connected to the Normal input of a Material node. + The correct normal map format for the target game engine will be generated when + the material is exported. * the *size* of the normal map * the *strength* of the normal map effect +* the *buffer* parameter decides if the input must be stored in a buffer before + generating the normal map. Using a buffer is faster but can create artifacts + in the normal map, and disabling this option will generate more accurate normal + maps. It is recommended to enable the buffer while editing a material and + disable it before exporting. + Notes +++++ This node outputs an image that has a fixed size. +When using 3D Signed distance functions, it is recommended to use the normal map +generated by the + Example images ++++++++++++++ diff --git a/material_maker/doc/user_interface.rst b/material_maker/doc/user_interface.rst index bd91b38..f4dfeac 100644 --- a/material_maker/doc/user_interface.rst +++ b/material_maker/doc/user_interface.rst @@ -224,10 +224,10 @@ The main menu bar is organized in 5 menus: File menu ^^^^^^^^^ -* *New material* creates a new material and opens a tab in the right pane to edit it +* *New material* creates a new material and opens a tab in the center pane to edit it * *Load material* opens a file dialog to select a procedural material (.ptex) file. If - a material file is selected, it will be open in a new tab in the right pane. If the current + a material file is selected, it will be open in a new tab in the center pane. If the current tab contains an empty material (about material that only consists of a Material node), the material will be loaded into this tab. @@ -239,12 +239,10 @@ File menu * *Save all materials* saves all currently open materials. Materials that were already saved are ignored. -* *Export material* generates PNG image files for all elements of the material. File names are - defined using the path of the **.ptex** material file and their role (albedo, emission...) - in the material. - The Ambient occlusion, roughness and metallic textures are saved into a single file whose - suffix is **orm**. - If the material contains **export** nodes, their textures will be exported as well. +* the *Export* submenu can be used to export the current Material for Godot, Unity + or Unreal. It will prompt for a file name and generate PNG files for all components + of the material. Exporting to one of those engines is described in the + :ref:`export-section` section. * *Close material* closes the current material. diff --git a/material_maker/examples/wood.ptex b/material_maker/examples/wood.ptex index 988563b..04dece2 100644 --- a/material_maker/examples/wood.ptex +++ b/material_maker/examples/wood.ptex @@ -72,24 +72,12 @@ "to": "blend_0", "to_port": 1 }, - { - "from": "colorize_0", - "from_port": 0, - "to": "combine_0", - "to_port": 1 - }, { "from": "blend_0", "from_port": 0, "to": "colorize_2", "to_port": 0 }, - { - "from": "blend_0", - "from_port": 0, - "to": "combine_0", - "to_port": 0 - }, { "from": "colorize_2", "from_port": 0, @@ -121,8 +109,8 @@ { "name": "perlin_1", "node_position": { - "x": -424, - "y": 343.5 + "x": -635, + "y": 341.5 }, "parameters": { "iterations": 3, @@ -135,8 +123,8 @@ { "name": "perlin_0", "node_position": { - "x": -424, - "y": 212.5 + "x": -635, + "y": 210.5 }, "parameters": { "iterations": 3, @@ -149,21 +137,20 @@ { "name": "warp_0", "node_position": { - "x": -180, - "y": 317.5 + "x": -311, + "y": 280.5 }, "parameters": { "amount": 0.1, - "eps": 0.05, - "epsilon": 0 + "eps": 0.05 }, "type": "warp" }, { "name": "colorize_1", "node_position": { - "x": -194, - "y": 466.5 + "x": -340, + "y": 402.5 }, "parameters": { "gradient": { @@ -192,21 +179,20 @@ { "name": "warp_1", "node_position": { - "x": -31, - "y": 349.5 + "x": -89, + "y": 325.5 }, "parameters": { "amount": 0.1, - "eps": 0.045, - "epsilon": 0 + "eps": 0.045 }, "type": "warp" }, { "name": "voronoi_0", "node_position": { - "x": -437, - "y": 484.5 + "x": -648, + "y": 482.5 }, "parameters": { "intensity": 1, @@ -221,8 +207,8 @@ { "name": "blend_0", "node_position": { - "x": 83, - "y": 245.5 + "x": 101, + "y": 250.5 }, "parameters": { "amount": 1, @@ -230,29 +216,11 @@ }, "type": "blend" }, - { - "name": "combine_0", - "node_position": { - "x": 515.35144, - "y": -15.818176 - }, - "parameters": { - "color": { - "a": 1, - "b": 1, - "g": 1, - "r": 1, - "type": "Color" - }, - "name": 0 - }, - "type": "combine" - }, { "name": "Material", "node_position": { - "x": 544, - "y": 79 + "x": 687, + "y": 172 }, "parameters": { "albedo_color": { @@ -267,7 +235,6 @@ "emission_energy": 1, "metallic": 1, "normal_scale": 1, - "resolution": 1, "roughness": 1, "size": 11, "subsurf_scatter_strength": 0 @@ -277,25 +244,46 @@ { "name": "colorize_2", "node_position": { - "x": 305.35144, - "y": 76.181824 + "x": 407.35144, + "y": 127.181824 }, "parameters": { "gradient": { - "interpolation": 1, + "interpolation": 2, "points": [ { "a": 1, "b": 0.071126, "g": 0.34877, - "pos": 0, + "pos": 0.120364, "r": 0.59375 }, { "a": 1, "b": 0.013021, "g": 0.144043, - "pos": 1, + "pos": 0.263636, + "r": 0.3125 + }, + { + "a": 1, + "b": 0.071126, + "g": 0.34877, + "pos": 0.402182, + "r": 0.59375 + }, + { + "a": 1, + "b": 0.071126, + "g": 0.34877, + "pos": 0.663636, + "r": 0.59375 + }, + { + "a": 1, + "b": 0.013021, + "g": 0.144043, + "pos": 0.893091, "r": 0.3125 } ], @@ -307,25 +295,22 @@ { "name": "normal_map_0", "node_position": { - "x": 319, - "y": 265.5 + "x": 431, + "y": 423.5 }, "parameters": { - "amount": 0.1, "param0": 11, "param1": 0.99, "param2": 0, - "param3": 0, - "param4": 1, - "size": 5 + "param4": 1 }, "type": "normal_map" }, { "name": "colorize_0", "node_position": { - "x": 313, - "y": 176.5 + "x": 423, + "y": 306.5 }, "parameters": { "gradient": { diff --git a/material_maker/graph_edit.gd b/material_maker/graph_edit.gd index 49d39e2..91f04bd 100644 --- a/material_maker/graph_edit.gd +++ b/material_maker/graph_edit.gd @@ -213,16 +213,25 @@ func create_nodes(data, position : Vector2 = Vector2(0, 0)) -> Array: func create_gen_from_type(gen_name) -> void: create_nodes({ type=gen_name, parameters={} }, scroll_offset+0.5*rect_size) -func load_file(filename) -> void: - clear_material() - top_generator = mm_loader.load_gen(filename) - if top_generator != null: +func load_file(filename) -> bool: + var new_generator = mm_loader.load_gen(filename) + if new_generator != null: + clear_material() + top_generator = new_generator add_child(top_generator) move_child(top_generator, 0) update_view(top_generator) center_view() set_save_path(filename) set_need_save(false) + return true + else: + var dialog : AcceptDialog = AcceptDialog.new() + add_child(dialog) + dialog.window_title = "Load failed!" + dialog.dialog_text = "Failed to load "+filename + dialog.popup_centered() + return false func save_file(filename) -> void: var data = top_generator.serialize() @@ -233,14 +242,16 @@ func save_file(filename) -> void: set_save_path(filename) set_need_save(false) -func export_textures() -> void: - if save_path != null: - var prefix = save_path.left(save_path.rfind(".")) - for g in top_generator.get_children(): - if g.has_method("render_textures"): - g.render_textures() - if g.has_method("export_textures"): - g.export_textures(prefix, editor_interface) +func get_material_node() -> MMGenMaterial: + for g in top_generator.get_children(): + if g.has_method("get_export_profiles"): + return g + return null + +func export_material(export_prefix, profile) -> void: + for g in top_generator.get_children(): + if g.has_method("export_material"): + g.export_material(export_prefix, profile) # Cut / copy / paste / duplicate diff --git a/material_maker/main_window.gd b/material_maker/main_window.gd index 26203a3..7700f3e 100644 --- a/material_maker/main_window.gd +++ b/material_maker/main_window.gd @@ -37,7 +37,8 @@ const MENU = [ { menu="File", command="save_material_as", shortcut="Control+Shift+S", description="Save material as..." }, { menu="File", command="save_all_materials", description="Save all materials..." }, { menu="File" }, - { menu="File", command="export_material", shortcut="Control+E", description="Export material" }, + { menu="File", submenu="export_material", description="Export material" }, + #{ menu="File", command="export_material", shortcut="Control+E", description="Export material" }, { menu="File" }, { menu="File", command="close_material", description="Close material" }, { menu="File", command="quit", shortcut="Control+Q", description="Quit" }, @@ -61,7 +62,7 @@ const MENU = [ { menu="Tools", command="add_to_user_library", description="Add selected node to user library" }, { menu="Tools", command="export_library", description="Export the nodes library" }, - { menu="Tools", command="generate_screenshots", description="Generate screenshots for the library nodes" }, + #{ menu="Tools", command="generate_screenshots", description="Generate screenshots for the library nodes" }, @@ -150,6 +151,8 @@ func _ready() -> void: create_menu(menu, m.name) m.connect("about_to_show", self, "menu_about_to_show", [ m.name, menu ]) new_material() + + do_load_materials(OS.get_cmdline_args()) func _input(event: InputEvent) -> void: if event.is_action_pressed("toggle_fullscreen"): @@ -199,7 +202,6 @@ func create_menu(menu, menu_name) -> PopupMenu: func create_menu_load_recent(menu) -> void: menu.clear() - if recent_files.empty(): menu.add_item("No items found", 0) menu.set_item_disabled(0, true) @@ -210,7 +212,8 @@ func create_menu_load_recent(menu) -> void: menu.connect("id_pressed", self, "_on_LoadRecent_id_pressed") func _on_LoadRecent_id_pressed(id) -> void: - do_load_material(recent_files[id]) + if !do_load_material(recent_files[id]): + recent_files.remove(id) func load_recents() -> void: var f = File.new() @@ -233,6 +236,42 @@ func add_recent(path) -> void: f.store_string(to_json(recent_files)) f.close() + +func create_menu_export_material(menu) -> void: + menu.clear() + var graph_edit : MMGraphEdit = get_current_graph_edit() + if graph_edit != null: + var material_node = graph_edit.get_material_node() + for p in material_node.get_export_profiles(): + menu.add_item(p) + if !menu.is_connected("id_pressed", self, "_on_ExportMaterial_id_pressed"): + menu.connect("id_pressed", self, "_on_ExportMaterial_id_pressed") + +func export_material(file_path : String, profile : String) -> void: + var graph_edit : MMGraphEdit = get_current_graph_edit() + if graph_edit == null: + return + var export_prefix = file_path.trim_suffix("."+file_path.get_extension()) + graph_edit.export_material(export_prefix, profile) + +func _on_ExportMaterial_id_pressed(id) -> void: + var graph_edit : MMGraphEdit = get_current_graph_edit() + if graph_edit == null: + return + var material_node = graph_edit.get_material_node() + if material_node == null: + return + var profile = material_node.get_export_profiles()[id] + var dialog : FileDialog = FileDialog.new() + dialog.rect_min_size = Vector2(500, 500) + dialog.access = FileDialog.ACCESS_FILESYSTEM + dialog.mode = FileDialog.MODE_SAVE_FILE + dialog.add_filter("*."+material_node.get_export_extension(profile)+";"+profile+" Material") + add_child(dialog) + dialog.connect("file_selected", self, "export_material", [ profile ]) + dialog.popup_centered() + + func create_menu_set_theme(menu) -> void: menu.clear() for t in THEMES: @@ -359,15 +398,6 @@ func save_material_as() -> void: func close_material() -> void: projects.close_tab() -func export_material() -> void: - var graph_edit : MMGraphEdit = get_current_graph_edit() - if graph_edit != null : - graph_edit.export_textures() - -func export_material_is_disabled() -> bool: - var graph_edit : MMGraphEdit = get_current_graph_edit() - return graph_edit == null or graph_edit.save_path == null - func quit() -> void: dim_window() get_tree().quit() diff --git a/project.godot b/project.godot index 2bd16b2..c23b2b3 100644 --- a/project.godot +++ b/project.godot @@ -64,7 +64,7 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://addons/material_maker/engine/gen_image.gd" }, { -"base": "MMGenBase", +"base": "MMGenShader", "class": "MMGenMaterial", "language": "GDScript", "path": "res://addons/material_maker/engine/gen_material.gd" @@ -171,7 +171,7 @@ _global_script_class_icons={ [application] config/name="Material Maker" -config/description="An open source, extensible procedural material generation tool" +config/description="An open source, extensible procedural material authoring tool" run/main_scene="res://start.tscn" config/use_custom_user_dir=true config/custom_user_dir_name="material_maker" @@ -179,7 +179,8 @@ boot_splash/image="res://rodz_labs_logo.png" boot_splash/fullsize=false boot_splash/bg_color=Color( 0.0901961, 0.0941176, 0.141176, 1 ) config/icon="res://icon.png" -config/release="0.8" +config/windows_native_icon="res://icon.ico" +config/release="0.9" [autoload] diff --git a/rodz_labs_logo.png.import b/rodz_labs_logo.png.import index c20ba04..5b5554d 100644 --- a/rodz_labs_logo.png.import +++ b/rodz_labs_logo.png.import @@ -21,7 +21,7 @@ compress/lossy_quality=0.7 compress/hdr_mode=0 compress/bptc_ldr=0 compress/normal_map=0 -flags/repeat=true +flags/repeat=0 flags/filter=true flags/mipmaps=true flags/anisotropic=false diff --git a/start.gd b/start.gd index 94e3f05..edd58d5 100644 --- a/start.gd +++ b/start.gd @@ -1,25 +1,88 @@ extends Control -var loader +var loader = null onready var progress_bar = $VBoxContainer/ProgressBar func _ready(): + set_process(false) var path : String if Directory.new().file_exists("res://material_maker/main_window.tscn"): - path = "res://material_maker/main_window.tscn" + if OS.get_cmdline_args().size() > 0 && OS.get_cmdline_args()[0] == "--export": + var output = [] + var dir : Directory = Directory.new() + match OS.get_name(): + "Windows": + var bat_file_path : String = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS)+"\\mm_cd.bat" + var bat_file : File = File.new() + bat_file.open(bat_file_path, File.WRITE) + bat_file.store_line("cd") + bat_file.close() + OS.execute(bat_file_path, [], true, output) + dir.remove(bat_file_path) + dir.change_dir(output[0].split("\n")[2]) + var target : String = "Godot" + var output_dir : String = dir.get_current_dir() + var size : int = 0 + var files : Array = [] + var i = 1 + while i < OS.get_cmdline_args().size(): + match OS.get_cmdline_args()[i]: + "-t", "--target": + i += 1 + target = OS.get_cmdline_args()[i] + "-o", "--output-dir": + i += 1 + output_dir = OS.get_cmdline_args()[i] + "--size": + i += 1 + size = int(OS.get_cmdline_args()[i]) + if size < 0: + show_error("ERROR: incorrect size "+OS.get_cmdline_args()[i]) + return + _: + files.push_back(OS.get_cmdline_args()[i]) + i += 1 + if !dir.dir_exists(output_dir): + show_error("ERROR: Output directory '%s' does not exist" % output_dir) + return + var expanded_files = [] + for f in files: + var basedir : String = f.get_base_dir() + if basedir == "": + basedir = "." + var basename : String = f.get_file() + if basename.find("*") != -1: + basename = basename.replace("*", ".*") + if dir.open(basedir) == OK: + var regex : RegEx = RegEx.new() + regex.compile("^"+basename+"$") + dir.list_dir_begin() + var file_name = dir.get_next() + while file_name != "": + if regex.search(file_name) && file_name.get_extension() == "ptex": + expanded_files.push_back(basedir+"/"+file_name) + file_name = dir.get_next() + else: + expanded_files.push_back(f) + export_files(expanded_files, output_dir, target, size) + return + else: + path = "res://material_maker/main_window.tscn" else: path = "res://demo/demo.tscn" loader = ResourceLoader.load_interactive(path) if loader == null: # check for errors print("error") queue_free() + set_process(true) -func _process(_delta): +func _process(_delta) -> void: var err = loader.poll() if err == ERR_FILE_EOF: var resource = loader.get_resource() - get_node("/root").add_child(resource.instance()) + var scene = resource.instance() + get_node("/root").add_child(scene) queue_free() elif err == OK: var progress = float(loader.get_stage()) / loader.get_stage_count() @@ -27,3 +90,30 @@ func _process(_delta): else: # error during loading print("error") queue_free() + +func export_files(files, output_dir, target, size) -> void: + $VBoxContainer/ProgressBar.min_value = 0 + $VBoxContainer/ProgressBar.max_value = files.size() + $VBoxContainer/ProgressBar.value = 0 + for f in files: + var gen = mm_loader.load_gen(f) + if gen != null: + add_child(gen) + for c in gen.get_children(): + if c.has_method("get_export_profiles"): + if c.get_export_profiles().find(target) == -1: + show_error("ERROR: Unsupported target %s"+target) + return + $VBoxContainer/Label.text = "Exporting "+f.get_file() + var prefix : String = output_dir+"/"+f.get_file().get_basename() + var result = c.export_material(prefix, target, size) + while result is GDScriptFunctionState: + result = yield(result, "completed") + break + gen.queue_free() + $VBoxContainer/ProgressBar.value += 1 + get_tree().quit() + +func show_error(message : String): + $ErrorPanel.show() + $ErrorPanel/Label.text = message diff --git a/start.tscn b/start.tscn index d3f15a3..5cae50f 100644 --- a/start.tscn +++ b/start.tscn @@ -1,8 +1,16 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=4 format=2] [ext_resource path="res://start.gd" type="Script" id=1] [ext_resource path="res://rodz_labs_logo.png" type="Texture" id=2] +[sub_resource type="StyleBoxFlat" id=1] +bg_color = Color( 0.0235294, 0.0313726, 0.12549, 0.929412 ) +border_width_left = 3 +border_width_top = 3 +border_width_right = 3 +border_width_bottom = 3 +border_color = Color( 1, 0, 0, 1 ) + [node name="Start" type="Panel"] anchor_right = 1.0 anchor_bottom = 1.0 @@ -40,3 +48,26 @@ align = 1 margin_top = 492.0 margin_right = 256.0 margin_bottom = 506.0 + +[node name="ErrorPanel" type="Panel" parent="."] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -268.5 +margin_top = -76.0 +margin_right = 268.5 +margin_bottom = 76.0 +rect_pivot_offset = Vector2( 267.976, 75.7381 ) +custom_styles/panel = SubResource( 1 ) + +[node name="Label" type="Label" parent="ErrorPanel"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 10.0 +margin_top = 10.0 +margin_right = -10.0 +margin_bottom = -10.0 +align = 1 +valign = 1