material = Material(material)
if self.use_textures:
- for p in material.properties.values():
+ for p in material.properties:
if p.texture:
tex_name = p.texture.image.name+".tex2d"
if tex_name not in resources:
raise Exception("Can't export unknown material type "+material.type)
st = Statement(material.type)
- for kw, p in material.properties.items():
- ss = self.create_property_statement(mat_res, p, kw, resources)
+ for p in material.properties:
+ ss = self.create_property_statement(mat_res, p, resources)
if ss:
st.sub.append(ss)
if self.use_textures:
- first_tex = (p.texture for p in material.properties.values() if p.texture).__next__()
+ first_tex = (p.texture for p in material.properties if p.texture).__next__()
if first_tex and not first_tex.default_filter:
from .export_texture import SamplerExporter
sampler_export = SamplerExporter()
return mat_res
- def create_property_statement(self, mat_res, prop, keyword, resources):
+ def create_property_statement(self, mat_res, prop, resources):
from .datafile import Statement
if self.use_textures and prop.texture:
tex_res = resources[prop.texture.image.name+".tex2d"]
from .util import basename
fn = basename(prop.texture.image.filepath)
if prop.texture.default_filter and fn:
- return Statement(keyword+"_map", fn)
+ return Statement(prop.tex_keyword, fn)
else:
- return mat_res.create_reference_statement(keyword+"_map", tex_res)
- elif prop.value is None:
+ return mat_res.create_reference_statement(prop.tex_keyword, tex_res)
+ elif not prop.keyword:
return
elif type(prop.value)==tuple:
- return Statement(keyword, *prop.value)
+ return Statement(prop.keyword, *prop.value)
else:
- return Statement(keyword, prop.value)
+ return Statement(prop.keyword, prop.value)
class MaterialMapExporter:
return (None, None)
class MaterialProperty:
- def __init__(self, value):
+ def __init__(self, keyword, tex_keyword, value):
+ self.keyword = keyword
+ self.tex_keyword = tex_keyword
self.value = value
self.texture = None
self.tex_usage = None
def set_from_input(self, node_tree, input_socket, alpha_socket=None):
- if type(self.value)==tuple:
- if alpha_socket:
- self.value = input_socket.default_value[:len(self.value)-1]+(alpha_socket.default_value,)
- else:
- self.value = input_socket.default_value[:len(self.value)]
- elif self.value is not None:
- self.value = input_socket.default_value
-
- from_node, _ = get_linked_node_and_socket(node_tree, input_socket)
- alpha_from = None
- if from_node:
- if from_node.type=='NORMAL_MAP':
- from_node, _ = get_linked_node_and_socket(node_tree, from_node.inputs["Color"])
-
- if alpha_socket:
- alpha_from, _ = get_linked_node_and_socket(node_tree, alpha_socket)
- if alpha_from and alpha_from!=from_node:
- raise Exception("Separate textures for color and alpha are not supported")
-
- if from_node.type=='TEX_IMAGE':
- self.texture = from_node
- if alpha_from:
- self.tex_usage = 'RGBA'
- elif type(self.value)==tuple:
- self.tex_usage = 'RGB'
+ if self.keyword:
+ if type(self.value)==tuple:
+ if alpha_socket:
+ self.value = input_socket.default_value[:len(self.value)-1]+(alpha_socket.default_value,)
else:
- self.tex_usage = 'GRAY'
+ self.value = input_socket.default_value[:len(self.value)]
else:
- raise Exception("Unsupported property input node type "+from_node.type)
+ self.value = input_socket.default_value
+
+ if self.tex_keyword:
+ from_node, _ = get_linked_node_and_socket(node_tree, input_socket)
+ alpha_from = None
+ if from_node:
+ if from_node.type=='NORMAL_MAP':
+ from_node, _ = get_linked_node_and_socket(node_tree, from_node.inputs["Color"])
+
+ if alpha_socket:
+ alpha_from, _ = get_linked_node_and_socket(node_tree, alpha_socket)
+ if alpha_from and alpha_from!=from_node:
+ raise Exception("Separate textures for color and alpha are not supported")
+
+ if from_node.type=='TEX_IMAGE':
+ self.texture = from_node
+ if alpha_from:
+ self.tex_usage = 'RGBA'
+ elif type(self.value)==tuple:
+ self.tex_usage = 'RGB'
+ else:
+ self.tex_usage = 'GRAY'
+ else:
+ raise Exception("Unsupported property input node type "+from_node.type)
class Material:
def __init__(self, material):
self.name = material.name
self.type = None
- self.properties = {}
+ self.properties = []
self.render_mode = material.render_mode
self.technique = material.technique
if self.render_mode=='BUILTIN':
raise Exception("Empty material can't use builtin rendering mode")
return
- elif surface_node.type!='BSDF_PRINCIPLED':
+ elif surface_node.type=='BSDF_PRINCIPLED':
+ self.type = "pbr"
+
+ base_color = self.create_property("base_color", (0.8, 0.8, 0.8, 1.0))
+ metalness = self.create_property("metalness", 0.0)
+ roughness = self.create_property("roughness", 0.5)
+ normal = self.create_property("normal")
+ emission = self.create_property("emission", (0.0, 0.0, 0.0))
+
+ base_color.set_from_input(material.node_tree, surface_node.inputs["Base Color"], surface_node.inputs["Alpha"])
+ metalness.set_from_input(material.node_tree, surface_node.inputs["Metallic"])
+ roughness.set_from_input(material.node_tree, surface_node.inputs["Roughness"])
+ normal.set_from_input(material.node_tree, surface_node.inputs["Normal"])
+ emission.set_from_input(material.node_tree, surface_node.inputs["Emission"])
+ else:
raise Exception("Unsupported surface node type "+surface_node.type)
- self.type = "pbr"
-
- base_color = self.properties["base_color"] = MaterialProperty((0.8, 0.8, 0.8, 1.0))
- metalness = self.properties["metalness"] = MaterialProperty(0.0)
- roughness = self.properties["roughness"] = MaterialProperty(0.5)
- normal = self.properties["normal"] = MaterialProperty(None)
- emission = self.properties["emission"] = MaterialProperty((0.0, 0.0, 0.0))
-
- base_color.set_from_input(material.node_tree, surface_node.inputs["Base Color"], surface_node.inputs["Alpha"])
- metalness.set_from_input(material.node_tree, surface_node.inputs["Metallic"])
- roughness.set_from_input(material.node_tree, surface_node.inputs["Roughness"])
- normal.set_from_input(material.node_tree, surface_node.inputs["Normal"])
- emission.set_from_input(material.node_tree, surface_node.inputs["Emission"])
-
sampler_settings = None
- for p in self.properties.values():
+ for p in self.properties:
if p.texture:
settings = (p.texture.default_filter, p.texture.interpolation, p.texture.use_mipmap, p.texture.max_anisotropy)
if sampler_settings is None:
elif settings!=sampler_settings:
raise Exception("Conflicting sampler settings in material textures")
+ def create_property(self, *args):
+ prop = None
+ if len(args)==1:
+ prop = MaterialProperty(None, args[0], None)
+ elif len(args)==2:
+ prop = MaterialProperty(args[0], args[0]+"_map", args[1])
+ else:
+ prop = MaterialProperty(*args)
+ self.properties.append(prop)
+ return prop
+
class MaterialMap:
def __init__(self, materials):