diff --git a/addons/material_maker/engine/gen_base.gd b/addons/material_maker/engine/gen_base.gd index 74798f8..17793a5 100644 --- a/addons/material_maker/engine/gen_base.gd +++ b/addons/material_maker/engine/gen_base.gd @@ -53,6 +53,9 @@ func toggle_editable() -> bool: func is_template() -> bool: return model != null +func get_template_name() -> bool: + return model + func is_editable() -> bool: return false @@ -228,12 +231,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 +247,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_graph.gd b/addons/material_maker/engine/gen_graph.gd index cd26cd0..e34675d 100644 --- a/addons/material_maker/engine/gen_graph.gd +++ b/addons/material_maker/engine/gen_graph.gd @@ -42,6 +42,10 @@ func get_type() -> String: func get_type_name() -> String: return label +func set_type_name(l) -> void: + if l !=label: + label = l + emit_hierarchy_changed() func toggle_editable() -> bool: editable = !editable diff --git a/addons/material_maker/engine/gen_material.gd b/addons/material_maker/engine/gen_material.gd index c1fb41b..58f9c6a 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()+"/nodes/"+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 507b6a6..c74d031 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, @@ -100,7 +105,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/fbm.mmg b/addons/material_maker/nodes/fbm.mmg index 6ce950a..c414cbe 100644 --- a/addons/material_maker/nodes/fbm.mmg +++ b/addons/material_maker/nodes/fbm.mmg @@ -79,7 +79,7 @@ { "control": "None", "default": 0.5, - "label": "Persistance", + "label": "Persistence", "max": 1, "min": 0, "name": "persistence", 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/perlin.mmg b/addons/material_maker/nodes/perlin.mmg index 92d0178..e2ab8d3 100644 --- a/addons/material_maker/nodes/perlin.mmg +++ b/addons/material_maker/nodes/perlin.mmg @@ -52,7 +52,7 @@ }, { "default": 0.5, - "label": "Persistance", + "label": "Persistence", "max": 1, "min": 0, "name": "persistence", diff --git a/addons/material_maker/nodes/perlin_color.mmg b/addons/material_maker/nodes/perlin_color.mmg index a6552ec..3c1b993 100644 --- a/addons/material_maker/nodes/perlin_color.mmg +++ b/addons/material_maker/nodes/perlin_color.mmg @@ -54,7 +54,7 @@ }, { "default": 0.5, - "label": "Persistance", + "label": "Persistence", "max": 1, "min": 0, "name": "persistence", diff --git a/addons/material_maker/nodes/tex3d_blend.mmg b/addons/material_maker/nodes/tex3d_blend.mmg index 1436b34..0a2c2a1 100644 --- a/addons/material_maker/nodes/tex3d_blend.mmg +++ b/addons/material_maker/nodes/tex3d_blend.mmg @@ -5,12 +5,12 @@ "y": 0 }, "parameters": { - "amount": 1, - "blend_type": 1 + "amount": 0, + "blend_type": 8 }, "shader_model": { "code": "", - "global": "vec3 blend3d_normal(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*c1 + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_multiply(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*c1*c2 + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_screen(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*(1.0-(1.0-c1)*(1.0-c2)) + (1.0-opacity)*c2;\n}\n\nfloat blend3d_overlay_f(float c1, float c2) {\n\treturn (c1 < 0.5) ? (2.0*c1*c2) : (1.0-2.0*(1.0-c1)*(1.0-c2));\n}\n\nvec3 blend3d_overlay(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*vec3(blend3d_overlay_f(c1.x, c2.x), blend3d_overlay_f(c1.y, c2.y), blend3d_overlay_f(c1.z, c2.z)) + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_hard_light(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*0.5*(c1*c2+blend3d_overlay(c1, c2, 1.0)) + (1.0-opacity)*c2;\n}\n\nfloat blend3d_soft_light_f(float c1, float c2) {\n\treturn (c2 < 0.5) ? (2.0*c1*c2+c1*c1*(1.0-2.0*c2)) : 2.0*c1*(1.0-c2)+sqrt(c1)*(2.0*c2-1.0);\n}\n\nvec3 blend3d_soft_light(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*vec3(blend3d_soft_light_f(c1.x, c2.x), blend3d_soft_light_f(c1.y, c2.y), blend3d_soft_light_f(c1.z, c2.z)) + (1.0-opacity)*c2;\n}\n\nfloat blend3d_burn_f(float c1, float c2) {\n\treturn (c1==0.0)?c1:max((1.0-((1.0-c2)/c1)),0.0);\n}\n\nvec3 blend3d_burn(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*vec3(blend3d_burn_f(c1.x, c2.x), blend3d_burn_f(c1.y, c2.y), blend3d_burn_f(c1.z, c2.z)) + (1.0-opacity)*c2;\n}\n\nfloat blend3d_dodge_f(float c1, float c2) {\n\treturn (c1==1.0)?c1:min(c2/(1.0-c1),1.0);\n}\n\nvec3 blend3d_dodge(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*vec3(blend3d_dodge_f(c1.x, c2.x), blend3d_dodge_f(c1.y, c2.y), blend3d_dodge_f(c1.z, c2.z)) + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_lighten(vec2 uv, vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*max(c1, c2) + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_darken(vec2 uv, vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*min(c1, c2) + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_difference(vec2 uv, vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*clamp(c2-c1, vec3(0.0), vec3(1.0)) + (1.0-opacity)*c2;\n}\n", + "global": "vec3 blend3d_normal(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*c1 + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_multiply(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*c1*c2 + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_screen(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*(1.0-(1.0-c1)*(1.0-c2)) + (1.0-opacity)*c2;\n}\n\nfloat blend3d_overlay_f(float c1, float c2) {\n\treturn (c1 < 0.5) ? (2.0*c1*c2) : (1.0-2.0*(1.0-c1)*(1.0-c2));\n}\n\nvec3 blend3d_overlay(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*vec3(blend3d_overlay_f(c1.x, c2.x), blend3d_overlay_f(c1.y, c2.y), blend3d_overlay_f(c1.z, c2.z)) + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_hard_light(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*0.5*(c1*c2+blend3d_overlay(c1, c2, 1.0)) + (1.0-opacity)*c2;\n}\n\nfloat blend3d_soft_light_f(float c1, float c2) {\n\treturn (c2 < 0.5) ? (2.0*c1*c2+c1*c1*(1.0-2.0*c2)) : 2.0*c1*(1.0-c2)+sqrt(c1)*(2.0*c2-1.0);\n}\n\nvec3 blend3d_soft_light(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*vec3(blend3d_soft_light_f(c1.x, c2.x), blend3d_soft_light_f(c1.y, c2.y), blend3d_soft_light_f(c1.z, c2.z)) + (1.0-opacity)*c2;\n}\n\nfloat blend3d_burn_f(float c1, float c2) {\n\treturn (c1==0.0)?c1:max((1.0-((1.0-c2)/c1)),0.0);\n}\n\nvec3 blend3d_burn(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*vec3(blend3d_burn_f(c1.x, c2.x), blend3d_burn_f(c1.y, c2.y), blend3d_burn_f(c1.z, c2.z)) + (1.0-opacity)*c2;\n}\n\nfloat blend3d_dodge_f(float c1, float c2) {\n\treturn (c1==1.0)?c1:min(c2/(1.0-c1),1.0);\n}\n\nvec3 blend3d_dodge(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*vec3(blend3d_dodge_f(c1.x, c2.x), blend3d_dodge_f(c1.y, c2.y), blend3d_dodge_f(c1.z, c2.z)) + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_lighten(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*max(c1, c2) + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_darken(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*min(c1, c2) + (1.0-opacity)*c2;\n}\n\nvec3 blend3d_difference(vec3 c1, vec3 c2, float opacity) {\n\treturn opacity*clamp(c2-c1, vec3(0.0), vec3(1.0)) + (1.0-opacity)*c2;\n}\n", "inputs": [ { "default": "vec3($uv.x, 1.0, 1.0)", diff --git a/addons/material_maker/nodes/tex3d_fbm.mmg b/addons/material_maker/nodes/tex3d_fbm.mmg index dc496d5..b11471d 100644 --- a/addons/material_maker/nodes/tex3d_fbm.mmg +++ b/addons/material_maker/nodes/tex3d_fbm.mmg @@ -90,7 +90,7 @@ { "control": "None", "default": 0.5, - "label": "Persistance", + "label": "Persistence", "max": 1, "min": 0, "name": "persistence", diff --git a/addons/material_maker/nodes/tones.mmg b/addons/material_maker/nodes/tones.mmg new file mode 100644 index 0000000..be161f0 --- /dev/null +++ b/addons/material_maker/nodes/tones.mmg @@ -0,0 +1,122 @@ +{ + "name": "levels", + "node_position": { + "x": 0, + "y": 0 + }, + "parameters": { + "in_max": { + "a": 1, + "b": 1, + "g": 1, + "r": 1, + "type": "Color" + }, + "in_mid": { + "a": 0.5, + "b": 0.5, + "g": 0.5, + "r": 0.5, + "type": "Color" + }, + "in_min": { + "a": 0, + "b": 0, + "g": 0, + "r": 0, + "type": "Color" + }, + "out_max": { + "a": 1, + "b": 1, + "g": 1, + "r": 1, + "type": "Color" + }, + "out_min": { + "a": 0, + "b": 0, + "g": 0, + "r": 0, + "type": "Color" + } + }, + "shader_model": { + "code": "", + "global": "vec4 adjust_levels(vec4 input, vec4 in_min, vec4 in_mid, vec4 in_max, vec4 out_min, vec4 out_max) {\n\tinput = clamp((input-in_min)/(in_max-in_min), 0.0, 1.0);\n\tin_mid = (in_mid-in_min)/(in_max-in_min);\n\tvec4 dark = step(in_mid, input);\n\tinput = 0.5*mix(input/(in_mid), 1.0+(input-in_mid)/(1.0-in_mid), dark);\n\treturn out_min+input*(out_max-out_min);\n}\n", + "inputs": [ + { + "default": "vec4(1.0)", + "label": "", + "name": "input", + "type": "rgba" + } + ], + "instance": "", + "name": "Levels", + "outputs": [ + { + "rgba": "adjust_levels($input($uv), $in_min, $in_mid, $in_max, $out_min, $out_max)", + "type": "rgba" + } + ], + "parameters": [ + { + "default": { + "a": 0, + "b": 0, + "g": 0, + "r": 0 + }, + "label": "", + "name": "in_min", + "type": "color" + }, + { + "default": { + "a": 0.498039, + "b": 0.498039, + "g": 0.498039, + "r": 0.498039 + }, + "label": "", + "name": "in_mid", + "type": "color" + }, + { + "default": { + "a": 1, + "b": 1, + "g": 1, + "r": 1 + }, + "label": "", + "name": "in_max", + "type": "color" + }, + { + "default": { + "a": 1, + "b": 0, + "g": 0, + "r": 0 + }, + "label": "", + "name": "out_min", + "type": "color" + }, + { + "default": { + "a": 1, + "b": 1, + "g": 1, + "r": 1 + }, + "label": "", + "name": "out_max", + "type": "color" + } + ] + }, + "type": "shader" +} \ 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..da65a0c 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/output_preview.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/main_window_layout.gd", "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_2d_panel.tscn", "res://material_maker/preview/preview_3d.gd", "res://material_maker/preview/preview_3d.tscn", "res://material_maker/preview/preview_3d_panel.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/graph_tree/hierarchy_pane.gd", "res://material_maker/widgets/graph_tree/hierarchy_pane.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/tab_container.gd", "res://material_maker/widgets/tab_container.tscn", "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/output_preview.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/main_window_layout.gd", "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_2d_panel.tscn", "res://material_maker/preview/preview_3d.gd", "res://material_maker/preview/preview_3d.tscn", "res://material_maker/preview/preview_3d_panel.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/graph_tree/hierarchy_pane.gd", "res://material_maker/widgets/graph_tree/hierarchy_pane.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/tab_container.gd", "res://material_maker/widgets/tab_container.tscn", "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/node_filter_tones.png b/material_maker/doc/images/node_filter_tones.png new file mode 100644 index 0000000..a2acbf2 Binary files /dev/null and b/material_maker/doc/images/node_filter_tones.png differ diff --git a/material_maker/doc/images/screenshot.png b/material_maker/doc/images/screenshot.png index 363af77..b78c9d6 100644 Binary files a/material_maker/doc/images/screenshot.png and b/material_maker/doc/images/screenshot.png differ 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/node_filter_tones.rst b/material_maker/doc/node_filter_tones.rst new file mode 100644 index 0000000..e4cbb26 --- /dev/null +++ b/material_maker/doc/node_filter_tones.rst @@ -0,0 +1,38 @@ +Tones node +~~~~~~~~~~ + +The **Tones** node provides an easy interface to adjust the tones of its input. It can be applied +homogeneously to the R, G and B channels, or separately on R, G, B and A. + +The nodes shows an histogram of all channels of its input, and 3 cursors to modify the input +adjustment at the top, and 2 cursors to modify the output adjustment. + +.. image:: images/node_filter_tones.png + :align: center + +Inputs +++++++ + +The **Tones** node requires an RGBA input texture. + +Outputs ++++++++ + +The **Tones** node provides a single RGBA texture. + +Parameters +++++++++++ + +At the top of the node, a control can be used to select the active channel (Luminance, Red, +Green, Blue and Alpha). + +The button can be used to adjust automatically the Tones to the node's input to obtain better +contrast. + +The 3 cursors at the top of the histogram can be used to select the input colors that will be +remapped to black (value = 0 for single channel), mid-grey (value = 0.5) and white (value = 1). +Values between those defined by cursors are interpolated linearly, and all values are clamped +between 0 and 1. + +The 2 bottom cursors define the output color for black (value = 0 for single channel) and +white (value = 1). \ No newline at end of file diff --git a/material_maker/doc/nodes_filter.rst b/material_maker/doc/nodes_filter.rst index 06d11e9..1d04094 100644 --- a/material_maker/doc/nodes_filter.rst +++ b/material_maker/doc/nodes_filter.rst @@ -9,6 +9,7 @@ The filter nodes accept one or several inputs and generate one or several images node_filter_invert node_filter_brightness_contrast node_filter_adjust_hsv + node_filter_tones node_filter_greyscale node_filter_colorize node_filter_combine 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..ba166a1 100644 --- a/material_maker/graph_edit.gd +++ b/material_maker/graph_edit.gd @@ -166,7 +166,7 @@ func clear_material() -> void: func update_graph(generators, connections) -> Array: var rv = [] for g in generators: - var node = node_factory.create_node(g.get_type()) + var node = node_factory.create_node(g.get_template_name() if g.is_template() else "", g.get_type()) if node != null: node.name = "node_"+g.name add_node(node) @@ -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 @@ -341,7 +352,7 @@ func on_ButtonUp_pressed() -> void: call_deferred("update_view", generator.get_parent()) func _on_Label_text_changed(new_text) -> void: - generator.label = new_text + generator.set_type_name(new_text) # Create subgraph @@ -382,7 +393,7 @@ func set_last_selected(node) -> void: func _on_GraphEdit_gui_input(event) -> void: if event.is_action_pressed("ui_library_popup") && get_rect().has_point(get_local_mouse_position()): node_popup.rect_global_position = get_global_mouse_position() - node_popup.show() + node_popup.show_popup() if event is InputEventMouseButton: call_deferred("check_last_selected") @@ -397,7 +408,7 @@ func request_popup(from, from_slot, release_position) -> void: else: # Request the popup node_popup.rect_global_position = get_global_mouse_position() - node_popup.show() + node_popup.show_popup(mm_io_types.types[node.generator.get_output_defs()[from_slot].type].slot_type) node_popup.set_quick_connect(from, from_slot) func check_last_selected() -> void: diff --git a/material_maker/icons/icons.svg b/material_maker/icons/icons.svg index ab74fb5..f4a511c 100644 --- a/material_maker/icons/icons.svg +++ b/material_maker/icons/icons.svg @@ -55,9 +55,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="40.459032" - inkscape:cx="12.31719" - inkscape:cy="41.781829" + inkscape:zoom="7.152214" + inkscape:cx="122.70346" + inkscape:cy="36.247815" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" @@ -605,5 +605,42 @@ sodipodi:end="0.0018129957" sodipodi:open="true" d="m 15.411452,304.10377 a 7.4148879,7.4346347 0 0 1 -7.4502054,7.39166 7.4148879,7.4346347 0 0 1 -7.37939334,-7.46273 7.4148879,7.4346347 0 0 1 7.43561054,-7.40642 7.4148879,7.4346347 0 0 1 7.3941002,7.44808" /> + + + + + diff --git a/material_maker/library/base.json b/material_maker/library/base.json index a2962cc..b792392 100644 --- a/material_maker/library/base.json +++ b/material_maker/library/base.json @@ -2289,6 +2289,50 @@ "tree_item": "Filter/AdjustHSV", "type": "adjust_hsv" }, + { + "collapsed": true, + "icon": "filter_tones", + "name": "tones", + "parameters": { + "in_max": { + "a": 1, + "b": 1, + "g": 1, + "r": 1, + "type": "Color" + }, + "in_mid": { + "a": 0.5, + "b": 0.5, + "g": 0.5, + "r": 0.5, + "type": "Color" + }, + "in_min": { + "a": 0, + "b": 0, + "g": 0, + "r": 0, + "type": "Color" + }, + "out_max": { + "a": 1, + "b": 1, + "g": 1, + "r": 1, + "type": "Color" + }, + "out_min": { + "a": 0, + "b": 0, + "g": 0, + "r": 0, + "type": "Color" + } + }, + "tree_item": "Filter/Tones", + "type": "tones" + }, { "collapsed": true, "icon": "filter_greyscale", diff --git a/material_maker/library/base/filter_tones.png b/material_maker/library/base/filter_tones.png new file mode 100644 index 0000000..b2809d0 Binary files /dev/null and b/material_maker/library/base/filter_tones.png differ diff --git a/material_maker/main_window.gd b/material_maker/main_window.gd index 26203a3..be7af06 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" }, @@ -131,6 +132,7 @@ func _ready() -> void: library = layout.get_pane("Library") preview_2d = layout.get_pane("Preview2D") preview_3d = layout.get_pane("Preview3D") + preview_3d.connect("need_update", self, "update_preview_3d") hierarchy = layout.get_pane("Hierarchy") hierarchy.connect("group_selected", self, "on_group_selected") @@ -150,6 +152,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 +203,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 +213,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 +237,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 +399,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() @@ -431,7 +462,7 @@ func make_selected_nodes_editable() -> void: var selected_nodes = get_selected_nodes() if !selected_nodes.empty(): for n in selected_nodes: - if n.generator.toggle_editable(): + if n.generator.toggle_editable() and n.has_method("update_node"): n.update_node() func add_to_user_library() -> void: diff --git a/material_maker/misc/linux/io.github.RodZill4.Material-Maker.appdata.xml b/material_maker/misc/linux/io.github.RodZill4.Material-Maker.appdata.xml index d7e6576..39854e7 100644 --- a/material_maker/misc/linux/io.github.RodZill4.Material-Maker.appdata.xml +++ b/material_maker/misc/linux/io.github.RodZill4.Material-Maker.appdata.xml @@ -17,13 +17,13 @@ https://github.com/RodZill4/godot-procedural-textures/issues - https://raw.githubusercontent.com/RodZill4/godot-procedural-textures/master/addons/material_maker/doc/images/screenshot.png + https://raw.githubusercontent.com/RodZill4/material-maker/master/material_maker/doc/images/screenshot.png Editing a procedurally generated texture - + hugo.locurcio@hugo.pro diff --git a/material_maker/node_factory.gd b/material_maker/node_factory.gd index 12a908e..7548ff4 100644 --- a/material_maker/node_factory.gd +++ b/material_maker/node_factory.gd @@ -2,13 +2,16 @@ extends Node var includes -func create_node(type) -> Node: +func create_node(model : String, type : String) -> Node: + var node_type = null var node = null - var file_name = "res://material_maker/nodes/"+type+".tscn" + var file_name = "res://material_maker/nodes/"+model+".tscn" + if ! ResourceLoader.exists(file_name): + file_name = "res://material_maker/nodes/"+type+".tscn" if ResourceLoader.exists(file_name): - var node_type = load(file_name) - if node_type != null: - node = node_type.instance() + node_type = load(file_name) + if node_type != null: + node = node_type.instance() if node == null: node = preload("res://material_maker/nodes/generic.tscn").instance() return node diff --git a/material_maker/nodes/ios.gd b/material_maker/nodes/ios.gd index 1a86116..2f06e9a 100644 --- a/material_maker/nodes/ios.gd +++ b/material_maker/nodes/ios.gd @@ -5,7 +5,7 @@ func set_generator(g) -> void: generator.connect("parameter_changed", self, "on_parameter_changed") update_node() -func on_parameter_changed(p, v) -> void: +func on_parameter_changed(p, _v) -> void: if p == "__update_all__": call_deferred("update_node") diff --git a/material_maker/nodes/remote.gd b/material_maker/nodes/remote.gd index 989911a..c5b9b23 100644 --- a/material_maker/nodes/remote.gd +++ b/material_maker/nodes/remote.gd @@ -6,7 +6,6 @@ var links = {} onready var grid = $Controls func add_control(text, control) -> void: - var index = grid.get_child_count() / 4 var label = preload("res://material_maker/widgets/linked_widgets/editable_label.tscn").instance() label.set_text(text) label.connect("label_changed", self, "on_label_changed", [ control.name ]) diff --git a/material_maker/nodes/tones.gd b/material_maker/nodes/tones.gd new file mode 100644 index 0000000..aff0e33 --- /dev/null +++ b/material_maker/nodes/tones.gd @@ -0,0 +1,170 @@ +extends MMGraphNodeBase + +class Cursor: + extends Control + + var color : Color + var top : bool = true + var position : float + + const WIDTH : int = 8 + const HEIGHT : int = 8 + + func _init(c, p, t = true): + color = c + position = p + top = t + + func _ready() -> void: + rect_position.y = -2 if top else get_parent().rect_size.y+2-HEIGHT + set_value(position) + rect_size = Vector2(WIDTH, HEIGHT) + + func _draw() -> void: + var polygon : PoolVector2Array + if top: + polygon = PoolVector2Array([Vector2(0, 0), Vector2(WIDTH/2, HEIGHT), Vector2(WIDTH, 0), Vector2(0, 0)]) + else: + polygon = PoolVector2Array([Vector2(0, HEIGHT), Vector2(WIDTH/2, 0), Vector2(WIDTH, HEIGHT), Vector2(0, HEIGHT)]) + var c = color + c.a = 1.0 + draw_colored_polygon(polygon, c) + var outline_color = 0.0 if position > 0.5 else 1.0 + draw_polyline(polygon, Color(outline_color, outline_color, outline_color), 1.0, true) + + func _gui_input(ev) -> void: + if ev is InputEventMouseMotion && (ev.button_mask & 1) != 0: + rect_position.x += ev.relative.x + rect_position.x = min(max(-0.5*WIDTH, rect_position.x), get_parent().rect_size.x-0.5*WIDTH) + update_value((rect_position.x+0.5*WIDTH)/get_parent().rect_size.x) + + func update_value(p : float) -> void: + if p != position: + set_value(p) + get_parent().get_parent().update_value(self, position) + update() + + func set_value(v : float): + position = v + rect_position.x = position * get_parent().rect_size.x - 0.5*WIDTH + +var cursor_in_min : Cursor +var cursor_in_mid : Cursor +var cursor_in_max : Cursor +var cursor_out_min : Cursor +var cursor_out_max : Cursor + +func _ready() -> void: + var slot_color = mm_io_types.types["rgba"].color + var slot_type = mm_io_types.types["rgba"].slot_type + set_slot(0, true, slot_type, slot_color, true, slot_type, slot_color) + cursor_in_min = Cursor.new(Color(0.0, 0.0, 0.0), 0.0) + $Histogram.add_child(cursor_in_min) + cursor_in_mid = Cursor.new(Color(0.5, 0.5, 0.5), 0.5) + $Histogram.add_child(cursor_in_mid) + cursor_in_max = Cursor.new(Color(1.0, 1.0, 1.0), 1.0) + $Histogram.add_child(cursor_in_max) + cursor_out_min = Cursor.new(Color(0.0, 0.0, 0.0), 0.0, false) + $Histogram.add_child(cursor_out_min) + cursor_out_max = Cursor.new(Color(1.0, 1.0, 1.0), 1.0, false) + $Histogram.add_child(cursor_out_max) + +func set_generator(g) -> void: + .set_generator(g) + generator.connect("parameter_changed", self, "on_parameter_changed") + _on_Mode_item_selected(0) + +func on_parameter_changed(p, v) -> void: + if p == "__input_changed__": + var source = generator.get_source(0) + var result = source.generator.render(source.output_index, 128, true) + while result is GDScriptFunctionState: + result = yield(result, "completed") + result.copy_to_texture($Histogram.get_image_texture()) + result.release() + +func get_parameter(n : String) -> float: + var value = generator.get_parameter(n) + match $Bar/Mode.selected: + 1: + return value.r + 2: + return value.g + 3: + return value.b + 4: + return value.a + return (value.r+value.g+value.b)/3.0 + +func _on_Mode_item_selected(_id): + cursor_in_min.set_value(get_parameter("in_min")) + cursor_in_mid.set_value(get_parameter("in_mid")) + cursor_in_max.set_value(get_parameter("in_max")) + cursor_out_min.set_value(get_parameter("out_min")) + cursor_out_max.set_value(get_parameter("out_max")) + +func set_parameter(n : String, v : float, d : float) -> void: + var value = generator.get_parameter(n) + match $Bar/Mode.selected: + 0: + value.r = v + value.g = v + value.b = v + value.a = d + 1: + value.r = v + 2: + value.g = v + 3: + value.b = v + 4: + value.a = v + generator.set_parameter(n, value) + +func update_value(control : Cursor, value : float) -> void: + match control: + cursor_in_min: + set_parameter("in_min", value, 0) + cursor_in_mid: + set_parameter("in_mid", value, 0.5) + cursor_in_max: + set_parameter("in_max", value, 1) + cursor_out_min: + set_parameter("out_min", value, 0) + cursor_out_max: + set_parameter("out_max", value, 1) + get_parent().send_changed_signal() + +func _on_Auto_pressed(): + var histogram = $Histogram.get_histogram_texture().get_data() + histogram.lock() + var in_min : int = -1 + var in_mid : int = -1 + var in_mid_value : float = 0 + var in_max : int = -1 + var histogram_size = histogram.get_size().x + for i in range(histogram_size): + var color : Color = histogram.get_pixel(i, 0) + var value : float + match $Bar/Mode.selected: + 0: + value = (color.r+color.g+color.b)/3.0 + 1: + value = color.r + 2: + value = color.g + 3: + value = color.b + 4: + value = color.a + if value > 0.0: + if in_min == -1: + in_min = i + in_max = i + if in_mid_value < value: + in_mid = i + in_mid_value = value + histogram.unlock() + cursor_in_min.update_value(in_min/(histogram_size-1)) + cursor_in_mid.update_value(in_mid/(histogram_size-1)) + cursor_in_max.update_value(in_max/(histogram_size-1)) diff --git a/material_maker/nodes/tones.tscn b/material_maker/nodes/tones.tscn new file mode 100644 index 0000000..bd5f634 --- /dev/null +++ b/material_maker/nodes/tones.tscn @@ -0,0 +1,103 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://material_maker/nodes/tones.gd" type="Script" id=1] +[ext_resource path="res://material_maker/widgets/histogram/histogram.tscn" type="PackedScene" id=2] +[ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=3] + +[sub_resource type="AtlasTexture" id=1] +flags = 4 +atlas = ExtResource( 3 ) +region = Rect2( 16, 80, 16, 16 ) + +[node name="Tones" type="GraphNode"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 2.75074 +margin_top = 1.78928 +margin_right = -1053.25 +margin_bottom = -529.211 +title = "Tones" +show_close = true +slot/0/left_enabled = true +slot/0/left_type = 0 +slot/0/left_color = Color( 0, 0.396078, 1, 1 ) +slot/0/right_enabled = true +slot/0/right_type = 0 +slot/0/right_color = Color( 0, 0.415686, 1, 1 ) +slot/1/left_enabled = false +slot/1/left_type = 0 +slot/1/left_color = Color( 1, 1, 1, 1 ) +slot/1/right_enabled = false +slot/1/right_type = 0 +slot/1/right_color = Color( 1, 1, 1, 1 ) +slot/2/left_enabled = false +slot/2/left_type = 0 +slot/2/left_color = Color( 1, 1, 1, 1 ) +slot/2/right_enabled = false +slot/2/right_type = 0 +slot/2/right_color = Color( 1, 1, 1, 1 ) +slot/3/left_enabled = false +slot/3/left_type = 0 +slot/3/left_color = Color( 1, 1, 1, 1 ) +slot/3/right_enabled = false +slot/3/right_type = 0 +slot/3/right_color = Color( 1, 1, 1, 1 ) +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Bar" type="HBoxContainer" parent="."] +margin_left = 16.0 +margin_top = 24.0 +margin_right = 208.0 +margin_bottom = 44.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Mode" type="OptionButton" parent="Bar"] +margin_right = 172.0 +margin_bottom = 20.0 +size_flags_horizontal = 3 +text = "Luminance" +items = [ "Luminance", null, false, 0, null, "Red", null, false, 1, null, "Green", null, false, 2, null, "Blue", null, false, 3, null, "Alpha", null, false, 4, null ] +selected = 0 + +[node name="Auto" type="TextureButton" parent="Bar"] +margin_left = 176.0 +margin_top = 2.0 +margin_right = 192.0 +margin_bottom = 18.0 +hint_tooltip = "Set levels automatically" +size_flags_vertical = 4 +texture_normal = SubResource( 1 ) + +[node name="Spacer1" type="Control" parent="."] +margin_left = 16.0 +margin_top = 45.0 +margin_right = 208.0 +margin_bottom = 49.0 +rect_min_size = Vector2( 0, 4 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Histogram" parent="." instance=ExtResource( 2 )] +margin_left = 16.0 +margin_top = 50.0 +margin_right = 208.0 +margin_bottom = 178.0 +rect_min_size = Vector2( 192, 128 ) + +[node name="Spacer2" type="Control" parent="."] +margin_left = 16.0 +margin_top = 179.0 +margin_right = 208.0 +margin_bottom = 183.0 +rect_min_size = Vector2( 0, 4 ) +__meta__ = { +"_edit_use_anchors_": false +} +[connection signal="item_selected" from="Bar/Mode" to="." method="_on_Mode_item_selected"] +[connection signal="pressed" from="Bar/Auto" to="." method="_on_Auto_pressed"] diff --git a/material_maker/preview/preview_3d.gd b/material_maker/preview/preview_3d.gd index 2fefb78..f765f60 100644 --- a/material_maker/preview/preview_3d.gd +++ b/material_maker/preview/preview_3d.gd @@ -54,7 +54,9 @@ func _on_Rotate_toggled(button_pressed) -> void: $MaterialPreview/Preview3d/ObjectRotate.stop(false) func get_materials() -> Array: - return [ current_object.get_surface_material(0) ] + if current_object != null: + return [ current_object.get_surface_material(0) ] + return [] func on_gui_input(event) -> void: if event is InputEventMouseButton: diff --git a/material_maker/preview/preview_3d_ui.tscn b/material_maker/preview/preview_3d_ui.tscn index 430914c..a303811 100644 --- a/material_maker/preview/preview_3d_ui.tscn +++ b/material_maker/preview/preview_3d_ui.tscn @@ -3,8 +3,6 @@ [ext_resource path="res://material_maker/preview/preview_3d_ui.gd" type="Script" id=1] [ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=2] - - [sub_resource type="AtlasTexture" id=1] flags = 4 atlas = ExtResource( 2 ) @@ -15,6 +13,9 @@ anchor_right = 1.0 margin_bottom = 20.0 size_flags_horizontal = 3 script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} [node name="Model" type="OptionButton" parent="."] margin_right = 100.0 @@ -26,7 +27,7 @@ selected = 0 [node name="Environment" type="OptionButton" parent="."] margin_left = 104.0 -margin_right = 231.0 +margin_right = 219.0 margin_bottom = 22.0 rect_min_size = Vector2( 100, 0 ) text = "Epping Forest" @@ -34,8 +35,8 @@ items = [ "Epping Forest", null, false, 0, null, "Moonless Golf", null, false, 1 selected = 0 [node name="Rotate" type="Button" parent="."] -margin_left = 235.0 -margin_right = 263.0 +margin_left = 223.0 +margin_right = 251.0 margin_bottom = 22.0 rect_pivot_offset = Vector2( -4, 7 ) hint_tooltip = "Rotate object" diff --git a/material_maker/widgets/add_node_popup.gd b/material_maker/widgets/add_node_popup.gd index 73c8367..0a5bfe3 100644 --- a/material_maker/widgets/add_node_popup.gd +++ b/material_maker/widgets/add_node_popup.gd @@ -4,6 +4,7 @@ var libraries = [] var data = [] onready var itemlist : ItemList = $PanelContainer/VBoxContainer/ItemList onready var filter_line_edit : LineEdit = $PanelContainer/VBoxContainer/Filter +var quick_connect : int = -1 var insert_position : Vector2 func get_current_graph(): @@ -14,10 +15,10 @@ func _ready() -> void: if !add_library(lib_path): add_library("res://material_maker/library/base.json") add_library("user://library/user.json") - filter_line_edit.connect("text_changed" ,self,"update_list") - filter_line_edit.connect("text_entered",self,"filter_entered") - itemlist.connect("item_selected",self,"item_selected") - itemlist.connect("item_activated",self,"item_selected") + filter_line_edit.connect("text_changed", self, "update_list") + filter_line_edit.connect("text_entered", self, "filter_entered") + itemlist.connect("item_selected", self, "item_selected") + itemlist.connect("item_activated", self, "item_selected") update_list() func filter_entered(filter) -> void: @@ -29,10 +30,10 @@ func add_node(data) -> void: if quick_connect_node != null: var type = quick_connect_node.get_connection_output_type(quick_connect_slot) for new_slot in node.get_connection_input_count(): - if type == node.get_connection_input_type(new_slot): + #if type == node.get_connection_input_type(new_slot): #connect the first two slots with the same type - get_current_graph().connect_node(quick_connect_node.name, quick_connect_slot, node.name, new_slot) - break + get_current_graph().connect_node(quick_connect_node.name, quick_connect_slot, node.name, new_slot) + break quick_connect_node = null hide() @@ -59,8 +60,9 @@ func hide() -> void: clear() -func show() -> void: - .show() +func show_popup(qc : int = -1) -> void: + show() + quick_connect = qc update_list() filter_line_edit.grab_focus() var parent_rect = get_parent().get_parent().get_global_rect() @@ -76,6 +78,28 @@ func update_list(filter : String = "") -> void: for obj in library: if !obj.has("type"): continue + if quick_connect != -1: + var ref_obj = obj + if mm_loader.predefined_generators.has(obj.type): + ref_obj = mm_loader.predefined_generators[obj.type] + if ref_obj.has("shader_model"): + if ! ref_obj.shader_model.has("inputs") or ref_obj.shader_model.inputs.empty(): + continue + elif mm_io_types.types[ref_obj.shader_model.inputs[0].type].slot_type != quick_connect: + continue + elif ref_obj.has("nodes"): + var input_ports = [] + for n in ref_obj.nodes: + if n.name == "gen_inputs": + if input_ports.has("ports"): + input_ports = n.ports + break + if input_ports.empty() or mm_io_types.types[input_ports[0].type].slot_type != quick_connect: + continue + elif ref_obj.type == "comment" or ref_obj.type == "image" or ref_obj.type == "remote": + continue + elif (ref_obj.type == "convolution" or ref_obj.type == "debug" or ref_obj.type == "buffer" or ref_obj.type == "export" ) and quick_connect != 0: + continue var show : bool = true for f in filter.to_lower().split(" ", false): if f != "" && obj.tree_item.to_lower().find(f) == -1: diff --git a/material_maker/widgets/add_node_popup.tscn b/material_maker/widgets/add_node_popup.tscn index c6d4c42..236cee0 100644 --- a/material_maker/widgets/add_node_popup.tscn +++ b/material_maker/widgets/add_node_popup.tscn @@ -3,7 +3,7 @@ [ext_resource path="res://material_maker/widgets/add_node_popup.gd" type="Script" id=1] [node name="AddNodePopup" type="Popup"] -margin_right = 228.0 +margin_right = 275.0 margin_bottom = 319.0 mouse_filter = 1 script = ExtResource( 1 ) diff --git a/material_maker/widgets/gradient_editor.tscn b/material_maker/widgets/gradient_editor.tscn index 81fda03..fae87e4 100644 --- a/material_maker/widgets/gradient_editor.tscn +++ b/material_maker/widgets/gradient_editor.tscn @@ -78,18 +78,16 @@ rect_min_size = Vector2( 112, 17 ) mouse_filter = 2 theme = SubResource( 5 ) -[node name="Popup" type="Popup" parent="Gradient"] -margin_left = 47.0 -margin_top = 33.0 -margin_right = 353.0 -margin_bottom = 475.0 +[node name="Popup" type="PopupPanel" parent="Gradient"] +visible = true +margin_right = 318.0 +margin_bottom = 470.0 [node name="ColorPicker" type="ColorPicker" parent="Gradient/Popup"] margin_left = 4.0 margin_top = 4.0 -margin_right = 4.0 -margin_bottom = 4.0 -rect_scale = Vector2( 0.75, 0.75 ) +margin_right = 314.0 +margin_bottom = 466.0 [node name="Interpolation" type="OptionButton" parent="."] margin_left = 0.418457 diff --git a/material_maker/widgets/histogram/histogram.gd b/material_maker/widgets/histogram/histogram.gd new file mode 100644 index 0000000..d2ae909 --- /dev/null +++ b/material_maker/widgets/histogram/histogram.gd @@ -0,0 +1,10 @@ +extends Control + +func update_histogram() -> void: + pass + +func get_image_texture() -> ImageTexture: + return $ViewportImage/ColorRect.material.get_shader_param("tex") + +func get_histogram_texture() -> ImageTexture: + return $Control.material.get_shader_param("tex") diff --git a/material_maker/widgets/histogram/histogram.tscn b/material_maker/widgets/histogram/histogram.tscn new file mode 100644 index 0000000..02670ed --- /dev/null +++ b/material_maker/widgets/histogram/histogram.tscn @@ -0,0 +1,157 @@ +[gd_scene load_steps=14 format=2] + +[ext_resource path="res://material_maker/widgets/histogram/histogram.gd" type="Script" id=1] + +[sub_resource type="Shader" id=1] +resource_local_to_scene = true +code = "shader_type canvas_item; +render_mode blend_disabled; + +uniform sampler2D tex; + +void fragment() { + COLOR = texture(tex, UV); +} +" + +[sub_resource type="ImageTexture" id=2] +resource_local_to_scene = true + +[sub_resource type="ShaderMaterial" id=3] +resource_local_to_scene = true +shader = SubResource( 1 ) +shader_param/tex = SubResource( 2 ) + +[sub_resource type="Shader" id=4] +code = "shader_type canvas_item; +render_mode blend_disabled; + +uniform sampler2D tex; + +void fragment() { + vec4 sum = vec4(0.0); + for (int i = 0; i < 128; ++i) { + sum += step(abs(texture(tex, vec2(UV.x, float(i)/127.0))-UV.y), vec4(0.02)); + } + COLOR = sum/255.0; +} +" + +[sub_resource type="ViewportTexture" id=5] +viewport_path = NodePath("ViewportImage") + +[sub_resource type="ShaderMaterial" id=6] +resource_local_to_scene = true +shader = SubResource( 4 ) +shader_param/tex = SubResource( 5 ) + +[sub_resource type="Shader" id=7] +code = "shader_type canvas_item; +render_mode blend_disabled; + +uniform sampler2D tex; + +void fragment() { + vec4 sum = vec4(0.0); + for (int i = 0; i < 128; ++i) { + sum += texture(tex, vec2(float(i)/127.0, UV.x)); + } + COLOR = sum/255.0; +}" + +[sub_resource type="ViewportTexture" id=8] +viewport_path = NodePath("ViewportHistogram1") + +[sub_resource type="ShaderMaterial" id=9] +resource_local_to_scene = true +shader = SubResource( 7 ) +shader_param/tex = SubResource( 8 ) + +[sub_resource type="Shader" id=10] +code = "shader_type canvas_item; + +uniform sampler2D tex; +render_mode blend_disabled; + +void fragment() { + if (abs(fract(UV.y+0.05)) < 0.1) { + COLOR = vec4(vec3(UV.x), 1.0); + } else { + vec4 highest = vec4(0.0); + for (int i = 0; i < 128; ++i) { + highest = max(highest, texture(tex, vec2(float(i)/128.0, 0.0))); + } + vec4 value = step(vec4(0.95-UV.y)*highest/0.9, texture(tex, vec2(UV.x, 0.0))); + float alpha = step(0.1, dot(value, vec4(1.0))); + COLOR = vec4(mix(value.rgb, vec3(0.5), 0.3*value.a), alpha); + } +}" + +[sub_resource type="ViewportTexture" id=11] +flags = 4 +viewport_path = NodePath("ViewportHistogram2") + +[sub_resource type="ShaderMaterial" id=12] +resource_local_to_scene = true +shader = SubResource( 10 ) +shader_param/tex = SubResource( 11 ) + +[node name="Histogram" type="Control"] +margin_right = 64.0 +margin_bottom = 64.0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ViewportImage" type="Viewport" parent="."] +size = Vector2( 256, 256 ) +transparent_bg = true +hdr = false +usage = 0 +render_target_v_flip = true +render_target_update_mode = 3 + +[node name="ColorRect" type="ColorRect" parent="ViewportImage"] +material = SubResource( 3 ) +margin_right = 256.0 +margin_bottom = 128.0 +rect_min_size = Vector2( 256, 256 ) + +[node name="ViewportHistogram1" type="Viewport" parent="."] +size = Vector2( 128, 128 ) +own_world = true +transparent_bg = true +hdr = false +usage = 0 +render_target_v_flip = true +render_target_update_mode = 3 + +[node name="ColorRect" type="ColorRect" parent="ViewportHistogram1"] +material = SubResource( 6 ) +margin_right = 128.0 +margin_bottom = 128.0 +rect_min_size = Vector2( 128, 128 ) + +[node name="ViewportHistogram2" type="Viewport" parent="."] +size = Vector2( 128, 2 ) +transparent_bg = true +disable_3d = true +keep_3d_linear = true +usage = 0 +render_target_v_flip = true +render_target_update_mode = 3 + +[node name="ColorRect" type="ColorRect" parent="ViewportHistogram2"] +material = SubResource( 9 ) +margin_right = 128.0 +margin_bottom = 2.0 +rect_min_size = Vector2( 128, 2 ) + +[node name="Control" type="ColorRect" parent="."] +material = SubResource( 12 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/project.godot b/project.godot index e59eeec..b137d70 100644 --- a/project.godot +++ b/project.godot @@ -69,7 +69,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" @@ -177,7 +177,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" @@ -185,7 +185,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