def reload_tobj_settings(material, tex_type): """Relaods TOBJ settings on given texture type of material. If tobj doesn't exists it does nothing. :param material: material :type material: bpy.types.Material :param tex_type: texture type :type tex_type: str """ shader_texture_str = "shader_texture_" + tex_type shader_texture_filepath = getattr(material.scs_props, shader_texture_str) tobj_file = _path.get_tobj_path_from_shader_texture( shader_texture_filepath) if tobj_file: settings, map_type = _tobj_imp.get_settings_and_type(tobj_file) # intentionally set ID property directly to avoid update function invoke material.scs_props[shader_texture_str + "_settings"] = int(settings, 2) setattr(material.scs_props, shader_texture_str + "_map_type", map_type) setattr(material.scs_props, shader_texture_str + "_tobj_load_time", str(os.path.getmtime(tobj_file)))
def reload_tobj_settings(material, tex_type): """Relaods TOBJ settings on given texture type of material. If tobj doesn't exists it does nothing. :param material: material :type material: bpy.types.Material :param tex_type: texture type :type tex_type: str """ shader_texture_str = "shader_texture_" + tex_type shader_texture_filepath = getattr(material.scs_props, shader_texture_str) tobj_file = _path.get_tobj_path_from_shader_texture(shader_texture_filepath) if tobj_file: settings, map_type = _tobj_imp.get_settings_and_type(tobj_file) # intentionally set ID property directly to avoid update function invoke material.scs_props[shader_texture_str + "_settings"] = int(settings, 2) setattr(material.scs_props, shader_texture_str + "_map_type", map_type) setattr(material.scs_props, shader_texture_str + "_tobj_load_time", str(os.path.getmtime(tobj_file)))
def get_texture_path_from_material(material, texture_type, export_path): """Get's relative path for Texture section of tobj from given texture_type. If tobj is not yet created it also creates tobj for it. :param material: Blender material :type material: bpy.types.Material :param texture_type: type of texture which should be readed from material (example "texture_base") :type texture_type: str :return: relative path for Texture section data of PIT material :rtype: str """ # overwrite tobj value directly if specified if getattr(material.scs_props, "shader_" + texture_type + "_use_imported", False): return getattr(material.scs_props, "shader_" + texture_type + "_imported_tobj", "") # use tobj value from shader preset if texture is locked and has default value if "scs_shader_attributes" in material and "textures" in material[ "scs_shader_attributes"]: for tex_entry in material["scs_shader_attributes"]["textures"].values( ): if "Tag" in tex_entry and texture_type in tex_entry["Tag"]: if "Lock" in tex_entry and tex_entry["Lock"] == "True": if "Value" in tex_entry and tex_entry["Value"] != "": return tex_entry["Value"] # CALCULATING TOBJ AND TEXTURE PATHS texture_raw_path = getattr(material.scs_props, "shader_" + texture_type, "NO PATH") tobj_rel_filepath = tobj_abs_filepath = texture_abs_filepath = "" scs_project_path = _get_scs_globals().scs_project_path.rstrip("\\").rstrip( "/") extensions, texture_raw_path = _path_utils.get_texture_extens_and_strip_path( texture_raw_path) for ext in extensions: if texture_raw_path.startswith("//"): # relative # search for relative path inside current scs project base and # possible dlc/mod parent folders; use first found for infix in ("", "../base/", "../../base/"): curr_path = os.path.join(scs_project_path, infix + texture_raw_path[2:] + ext) if os.path.isfile(curr_path): tobj_rel_filepath = texture_raw_path.replace("//", "/") # if tobj is used by user then get texture path from tobj # otherwise get tobj path from texture path if ext == ".tobj": tobj_abs_filepath = curr_path texture_abs_filepath = _path_utils.get_texture_path_from_tobj( curr_path) else: tobj_abs_filepath = _path_utils.get_tobj_path_from_shader_texture( curr_path, check_existance=False) texture_abs_filepath = curr_path break # break searching for texture if texture was found if tobj_rel_filepath != "": break elif ext != ".tobj" and os.path.isfile(texture_raw_path + ext): # absolute texture_raw_path_with_ext = texture_raw_path + ext # if we are exporting somewhere into SCS Project Base Path texture still can be saved if scs_project_path != "" and _path_utils.startswith( export_path, scs_project_path): tex_dir, tex_filename = os.path.split( texture_raw_path_with_ext) tobj_filename = tex_filename + ".tobj" # copy texture beside exported files try: shutil.copy2(texture_raw_path_with_ext, os.path.join(export_path, tex_filename)) except OSError as e: # ignore copying the same file # NOTE: happens if absolute texture paths are used # even if they are referring to texture inside scs project path if type(e).__name__ != "SameFileError": raise e # copy also TOBJ if exists texture_raw_tobj_path = str(tex_dir) + os.sep + tobj_filename if os.path.isfile(texture_raw_tobj_path): shutil.copy2(texture_raw_tobj_path, os.path.join(export_path, tobj_filename)) # get copied TOBJ relative path to current scs project path tobj_rel_filepath = "" if export_path != scs_project_path: tobj_rel_filepath = os.sep + os.path.relpath( export_path, scs_project_path) tobj_rel_filepath = tobj_rel_filepath + os.sep + tobj_filename[: -5] tobj_abs_filepath = os.path.join(export_path, tobj_filename) texture_abs_filepath = texture_raw_path_with_ext break else: lprint( "E Can not properly export texture %r from material %r!\n\t " + "Make sure you are exporting somewhere into Project Base Path and texture is properly set!", (texture_raw_path, material.name)) return "" else: lprint( "E Texture file %r from material %r doesn't exists inside current Project Base Path.\n\t " + "TOBJ won't be exported and reference will remain empty, expect problems!", (texture_raw_path, material.name)) return "" # CREATE TOBJ FILE if not os.path.isfile(tobj_abs_filepath): # only if it does not exists yet # export tobj only if file of texture exists if os.path.isfile(texture_abs_filepath): texture_name = os.path.basename( _path_utils.strip_sep(texture_abs_filepath)) _tobj.export(tobj_abs_filepath, texture_name, set()) else: lprint( "E Texture file %r from material %r doesn't exists, TOBJ can not be exported!", (texture_raw_path, material.name)) # make sure that Windows users will export proper paths tobj_rel_filepath = tobj_rel_filepath.replace("\\", "/") return tobj_rel_filepath
def _draw_shader_texture(layout, mat, split_perc, texture, read_only): """Draws texture box with it's properties. :param layout: layout to draw attribute to :type layout: bpy.types.UILayout :param mat: material from which data should be displayed :type mat: bpy.types.Material :param split_perc: split percentage for attribute name/value :type split_perc: float :param texture: texture data :type texture: dict :param read_only: if texture should be read only :type read_only: bool """ tag = texture.get('Tag', None) hide_state = texture.get('Hide', None) tag_id = tag.split(':') tag_id_string = tag_id[1] texture_type = tag_id_string[8:] shader_texture_id = str('shader_' + tag_id_string) if hide_state == 'True': return texture_box = layout.box().column( ) # create column for compact display with alignment header_split = texture_box.row(align=True).split(percentage=0.5) header_split.label(texture_type.title(), icon="TEXTURE_SHADED") if hasattr(mat.scs_props, shader_texture_id): shader_texture = mat.scs_props.get(shader_texture_id, "") # imported tobj boolean switch (only for imported shaders) use_imported_tobj = getattr(mat.scs_props, shader_texture_id + "_use_imported", False) if read_only: row = header_split.row(align=True) row.alignment = 'RIGHT' row.prop(mat.scs_props, shader_texture_id + "_use_imported") if use_imported_tobj: texture_row = texture_box.row(align=True) item_space = texture_row.split(percentage=split_perc, align=True) item_space.label("TOBJ Path:") item_space = item_space.split( percentage=1 / (1 - split_perc + 0.000001) * 0.1, align=True) props = item_space.operator("material.scs_looks_wt", text="WT") props.property_str = shader_texture_id item_space.prop(mat.scs_props, shader_texture_id + "_imported_tobj", text="") # disable whole texture layout if it's locked texture_box.enabled = not mat.scs_props.get( shader_texture_id + "_locked", False) texture_row = texture_box.row(align=True) item_space = texture_row.split(percentage=split_perc, align=True) # in case of custom tobj value texture is used only for preview if read_only and use_imported_tobj: item_space.label("Preview Tex:") else: item_space.label("Texture:") layout_box_col = item_space.column(align=True) layout_box_row = layout_box_col.row(align=True) if shader_texture: texture_icon = 'TEXTURE' else: texture_icon = 'MATPLANE' # MARK INVALID SLOTS if _path_utils.is_valid_shader_texture_path(shader_texture): layout_box_row.alert = False else: layout_box_row.alert = True texture_icon = 'NONE' # info operator will have icon, so texture path should use none # MARK EMPTY SLOTS if shader_texture == "": layout_box_row.alert = True layout_box_row = layout_box_row.split( percentage=1 / (1 - split_perc + 0.000001) * 0.1, align=True) props = layout_box_row.operator("material.scs_looks_wt", text="WT") props.property_str = shader_texture_id layout_box_row = layout_box_row.row(align=True) layout_box_row.prop(mat.scs_props, shader_texture_id, text='', icon=texture_icon) if layout_box_row.alert: # add info operator when texture path is invalid _shared.draw_warning_operator( layout_box_row, title="Texture Not Found", message= "Texture with given path doesn't exists or SCS Project Base Path is not properly set!" ) props = layout_box_row.operator( 'material.scs_select_shader_texture_filepath', text='', icon='FILESEL') props.shader_texture = shader_texture_id # DYNAMIC ID SAVE (FOR FILE REQUESTER) # ADDITIONAL TEXTURE SETTINGS if (not read_only or (read_only and not use_imported_tobj)) and texture_box.enabled: tobj_filepath = _path_utils.get_tobj_path_from_shader_texture( shader_texture) if not tobj_filepath: layout_box_inner_col = layout_box_col.row(align=True) item_space = layout_box_inner_col.column(align=True) props = item_space.operator("material.scs_create_tobj", icon="NEW", text="") props.texture_type = texture_type # creating extra column->row so it can be properly disabled as tobj doesn't exists item_space = layout_box_inner_col.column(align=True).row( align=True) else: item_space = layout_box_col.row(align=True) # enable settings only if tobj exists and map type of the tobj is 2d item_space.enabled = tobj_filepath is not None and getattr( mat.scs_props, shader_texture_id + "_map_type", "") == "2d" if tobj_filepath: mtime = str(os.path.getmtime(tobj_filepath)) item_space.alert = (mtime != getattr( mat.scs_props, shader_texture_id + "_tobj_load_time", "NOT FOUND")) else: item_space.alert = True props = item_space.operator("material.scs_reload_tobj", icon="LOAD_FACTORY", text="") props.texture_type = texture_type item_space.prop_menu_enum( mat.scs_props, str('shader_' + tag_id_string + '_settings'), icon='SETTINGS', ) # UV LAYERS FOR TEXTURE uv_mappings = getattr(mat.scs_props, "shader_" + tag_id_string + "_uv", None) if len(uv_mappings) > 0: texture_row = texture_box.row(align=True) item_space = texture_row.split(percentage=split_perc, align=True) if read_only: item_space.label("Preview UV Map:") else: item_space.label("Mapping:") layout_box_col = item_space.column(align=True) for mapping in uv_mappings: item_space_row = layout_box_col.row(align=True) # add info about normal map uv mapping property in case of imported shader if read_only and tag_id_string == "texture_nmap": preview_nmap_msg = str( "Maping value for normal maps is in the case of imported shader\n" "also used for defining uv map layer for tangent calculations!\n" "If the uv map is not provided first entry from Mappings list above will be used!" ) _shared.draw_warning_operator(item_space_row, "Mapping Info", preview_nmap_msg, icon="INFO") # add ensuring operator for norma map uv mapping if tag_id_string == "texture_nmap": props = item_space_row.operator( "mesh.scs_ensure_active_uv", text="", icon="FILE_REFRESH") props.mat_name = mat.name props.uv_layer = uv_mappings[0].value if mapping.value and mapping.value != "" and mapping.value in bpy.context.active_object.data.uv_layers: icon = "GROUP_UVS" else: icon = "ERROR" item_space_row.prop_search( data=mapping, property="value", search_data=bpy.context.active_object.data, search_property='uv_layers', text="", icon=icon, ) else: texture_box.row().label('Unsupported Shader Texture Type!', icon="ERROR")
def _get_texture_path_from_material(material, texture_type, export_path): """Get's relative path for Texture section of tobj from given texture_type. If tobj is not yet created it also creates tobj for it. :param material: Blender material :type material: bpy.types.Material :param texture_type: type of texture which should be readed from material (example "texture_base") :type texture_type: str :return: relative path for Texture section data of PIT material :rtype: str """ # overwrite tobj value directly if specified if getattr(material.scs_props, "shader_" + texture_type + "_use_imported", False): return getattr(material.scs_props, "shader_" + texture_type + "_imported_tobj", "") # use tobj value from shader preset if texture is locked and has default value if "scs_shader_attributes" in material and "textures" in material["scs_shader_attributes"]: for tex_entry in material["scs_shader_attributes"]["textures"].values(): if "Tag" in tex_entry and texture_type in tex_entry["Tag"]: if "Lock" in tex_entry and tex_entry["Lock"] == "True": if "Value" in tex_entry and tex_entry["Value"] != "": return tex_entry["Value"] # CALCULATING TOBJ AND TEXTURE PATHS texture_raw_path = getattr(material.scs_props, "shader_" + texture_type, "NO PATH") tobj_rel_filepath = tobj_abs_filepath = texture_abs_filepath = "" scs_project_path = _get_scs_globals().scs_project_path.rstrip("\\").rstrip("/") extensions, texture_raw_path = _path_utils.get_texture_extens_and_strip_path(texture_raw_path) for ext in extensions: if texture_raw_path.startswith("//"): # relative # search for relative path inside current scs project base and # possible dlc/mod parent folders; use first found for infix in ("", "../base/", "../../base/"): curr_path = os.path.join(scs_project_path, infix + texture_raw_path[2:] + ext) if os.path.isfile(curr_path): tobj_rel_filepath = texture_raw_path.replace("//", "/") # if tobj is used by user then get texture path from tobj # otherwise get tobj path from texture path if ext == ".tobj": tobj_abs_filepath = curr_path texture_abs_filepath = _path_utils.get_texture_path_from_tobj(curr_path) else: tobj_abs_filepath = _path_utils.get_tobj_path_from_shader_texture(curr_path, check_existance=False) texture_abs_filepath = curr_path break # break searching for texture if texture was found if tobj_rel_filepath != "": break elif ext != ".tobj" and os.path.isfile(texture_raw_path + ext): # absolute texture_raw_path_with_ext = texture_raw_path + ext # if we are exporting somewhere into SCS Project Base Path texture still can be saved if scs_project_path != "" and _path_utils.startswith(export_path, scs_project_path): tex_dir, tex_filename = os.path.split(texture_raw_path_with_ext) tobj_filename = tex_filename + ".tobj" # copy texture beside exported files try: shutil.copy2(texture_raw_path_with_ext, os.path.join(export_path, tex_filename)) except OSError as e: # ignore copying the same file # NOTE: happens if absolute texture paths are used # even if they are referring to texture inside scs project path if type(e).__name__ != "SameFileError": raise e # copy also TOBJ if exists texture_raw_tobj_path = str(tex_dir) + os.sep + tobj_filename if os.path.isfile(texture_raw_tobj_path): shutil.copy2(texture_raw_tobj_path, os.path.join(export_path, tobj_filename)) # get copied TOBJ relative path to current scs project path tobj_rel_filepath = "" if export_path != scs_project_path: tobj_rel_filepath = os.sep + os.path.relpath(export_path, scs_project_path) tobj_rel_filepath = tobj_rel_filepath + os.sep + tobj_filename[:-5] tobj_abs_filepath = os.path.join(export_path, tobj_filename) texture_abs_filepath = texture_raw_path_with_ext break else: lprint("E Can not properly export texture %r from material %r!\n\t " + "Make sure you are exporting somewhere into Project Base Path and texture is properly set!", (texture_raw_path, material.name)) return "" else: lprint("E Texture file %r from material %r doesn't exists inside current Project Base Path.\n\t " + "TOBJ won't be exported and reference will remain empty, expect problems!", (texture_raw_path, material.name)) return "" # CREATE TOBJ FILE if not os.path.isfile(tobj_abs_filepath): # only if it does not exists yet # export tobj only if file of texture exists if os.path.isfile(texture_abs_filepath): texture_name = os.path.basename(_path_utils.strip_sep(texture_abs_filepath)) _tobj.export(tobj_abs_filepath, texture_name, set()) else: lprint("E Texture file %r from material %r doesn't exists, TOBJ can not be exported!", (texture_raw_path, material.name)) # make sure that Windows users will export proper paths tobj_rel_filepath = tobj_rel_filepath.replace("\\", "/") return tobj_rel_filepath
def set_shader_data_to_material(material, section, is_import=False, override_back_data=True): """Used to set up material properties from given shader data even via UI or on import. :param material: blender material to which section data should be set :type material: bpy.types.Material :param section: new material data presented with Material section of PIX files :type section: io_scs_tools.internals.structure.SectionData :param is_import: flag indication if shader data are set from import process :type is_import: bool :param override_back_data: flag indication if back data for UI shall be overwritten :type override_back_data: bool """ preset_effect = section.get_prop_value("Effect") # check shader flags for attr in section.props: if attr[0] == "Flags": material.scs_props.enable_aliasing = not attr[1] == 1 # Flags: 1 #DISABLE ALIASING break attributes = {} textures = {} attribute_i = 0 texture_i = 0 used_attribute_types = {} # attribute types used by current shader used_texture_types = {} # texture types used by current shader and should be overlooked during clearing of texture slots for item in section.sections: if item.type == "Attribute": attribute_data = {} for prop in item.props: key, value = prop # # GETTING RID OF "[" AND "]" CHARS... if type(value) is str: value = value.replace("[", "").replace("]", "") attribute_data[key] = value attribute_type = attribute_data['Tag'] attributes[str(attribute_i)] = attribute_data attribute_i += 1 used_attribute_types[attribute_type] = attribute_data elif item.type == "Texture": texture_data = {} for prop in item.props: # print(' prop: "%s"' % str(prop)) texture_data[prop[0]] = prop[1] # APPLY SECTION TEXTURE VALUES texture_type = texture_data['Tag'].split(':')[1] tex_type = texture_type[8:] used_texture_types[tex_type] = texture_data textures[str(texture_i)] = texture_data texture_i += 1 scs_props_keys = material.scs_props.keys() # if overriding back data also make sure to clear attribute values for current shader # to prevent storing of unused values from blend data block # NOTE: looks also takes into account that all the unused properties are omitted from scs_props dict if override_back_data: for key in scs_props_keys: is_key_used = False if key.startswith("shader_attribute"): for used_attribute in used_attribute_types: if used_attribute in key[16:]: is_key_used = True if key.startswith("shader_texture"): for used_tex_type in used_texture_types: if used_tex_type in key[14:]: is_key_used = True # delete only unused shader keys everything else should stay in the place # as those keys might be used in some other way if not is_key_used and key.startswith("shader_"): lprint("D Unsetting property from material in set_shader_data %s:", (key,)) material.scs_props.property_unset(key) # apply used attributes created_attributes = {} for attribute_type in used_attribute_types.keys(): attribute_data = used_attribute_types[attribute_type] # acquire old attribute value if exists and not importing old_value = None if "shader_attribute_" + attribute_type in scs_props_keys and not is_import: old_value = getattr(material.scs_props, "shader_attribute_" + attribute_type) if attribute_type in ("diffuse", "specular", "env_factor", "fresnel", "tint"): if not old_value: material.scs_props["shader_attribute_" + attribute_type] = attribute_data['Value'] created_attributes[attribute_type] = material.scs_props["shader_attribute_" + attribute_type] elif attribute_type in ("shininess", "add_ambient", "reflection", "reflection2", "shadow_bias", "tint_opacity", "queue_bias"): if not old_value: material.scs_props["shader_attribute_" + attribute_type] = attribute_data['Value'][0] created_attributes[attribute_type] = material.scs_props["shader_attribute_" + attribute_type] elif attribute_type.startswith("aux") and hasattr(material.scs_props, "shader_attribute_" + attribute_type): auxiliary_prop = getattr(material.scs_props, "shader_attribute_" + attribute_type, None) # NOTE : invalidate old value if size of existing auxiliary property is different # then size of new one overwrite it anyway, because otherwise we will might access # values that doesn't exists but they should, for example: # switching from "eut2.dif.spec.weight.mult2" to "eut2.dif.spec.weight.mult2.weight2" if len(auxiliary_prop) != len(attribute_data['Value']): old_value = None if not old_value: # clean old values possible left from previous shader while len(auxiliary_prop) > 0: auxiliary_prop.remove(0) for val in attribute_data['Value']: item = auxiliary_prop.add() item['value'] = val item['aux_type'] = attribute_type created_attributes[attribute_type] = material.scs_props["shader_attribute_" + attribute_type] elif attribute_type == "substance": if not old_value: material.scs_props.substance = attribute_data['Value'][0] # if shader attribute properties are still unset reset it to default if material.scs_props.substance == _MAT_consts.unset_substance and "substance" not in material.scs_props.keys(): material.scs_props.substance = "None" # collect old uv mappings per tex_coord values and delete them from material (they will be set back later) # NOTE: we have to create extra iteration for uv mappings collecting # as multiple texture types can use same tex coord and we have to make sure # to collect them before we apply any texture data back to material. old_texture_mappings = {} for tex_type in used_texture_types: texture_mappings = getattr(material.scs_props, "shader_texture_" + tex_type + "_uv") if override_back_data: while len(texture_mappings) > 0: # save only set uv mapping tex_cord:value pairs if texture_mappings[0].value != "": old_texture_mappings[texture_mappings[0].tex_coord] = texture_mappings[0].value texture_mappings.remove(0) # apply used textures created_textures = {} created_tex_settings = {} created_tex_mappings = [] for tex_type in used_texture_types: # skip unknown texture type if tex_type not in material.scs_props.get_texture_types().keys(): lprint("D Trying to apply unknown texture type to SCS material: %r", (tex_type,)) continue texture_data = used_texture_types[tex_type] # always set texture lock attribute # important to set it always as some texture might get unlocked in preset and # selecting same present again has to unlock that texture texture_locked = False if "Lock" in texture_data: texture_locked = bool(texture_data["Lock"]) setattr(material.scs_props, "shader_texture_" + tex_type + "_locked", texture_locked) texture_mappings = getattr(material.scs_props, "shader_texture_" + tex_type + "_uv") # if shader is imported try to create custom tex coord mappings on material if material.scs_props.active_shader_preset_name == "<imported>" and "scs_tex_aliases" in material: custom_maps = material.scs_props.custom_tex_coord_maps for tex_coord_key in sorted(material["scs_tex_aliases"].keys()): if _invetory.get_index(custom_maps, "tex_coord_" + tex_coord_key) == -1: new_map = custom_maps.add() new_map.name = "tex_coord_" + tex_coord_key new_map.value = material["scs_tex_aliases"][tex_coord_key] # add one mapping field for using it as a preview uv layer in case of imported shader mapping = texture_mappings.add() mapping.texture_type = tex_type mapping.tex_coord = -1 # if there is an info about mapping in shader use it (in case of imported material this condition will fall!) elif "TexCoord" in texture_data: for tex_coord_i, tex_coord in enumerate(texture_data['TexCoord']): tex_coord = int(tex_coord) if tex_coord != -1: mapping = texture_mappings.add() mapping['texture_type'] = tex_type mapping['tex_coord'] = tex_coord # apply uv mappings either from imported data or from old mappings of previous shader if "scs_tex_aliases" in material: # scs_tex_aliases are present only on import # if mesh is corrupted then tex aliases won't be filled in properly in material from PIM importer, # so report error and skip creation of texture mapping for current tex_coord. if str(tex_coord) not in material["scs_tex_aliases"]: lprint("E Material %r is missing texture coordinate aliases, some UV mappings in Material Textures will remain empty!", (material.name,)) continue mapping['value'] = material["scs_tex_aliases"][str(tex_coord)] created_tex_mappings.append((tex_type, mapping.value, tex_coord)) elif tex_coord in old_texture_mappings: mapping['value'] = old_texture_mappings[tex_coord] created_tex_mappings.append((tex_type, mapping.value, tex_coord)) # set texture file to current texture scs_texture_str = _path.get_scs_texture_str(texture_data['Value']) # apply texture path if not empty and not yet set, except if import is going on # NOTE: during import bitmap has to be applied even if empty # because otherwise texture from previous look might be applied if (scs_texture_str != "" and getattr(material.scs_props, "shader_texture_" + tex_type, "") == "") or is_import: material.scs_props["shader_texture_" + tex_type] = scs_texture_str created_textures[tex_type] = get_texture_image(scs_texture_str, tex_type) if is_import: # only if shader is imported then make sure that by default imported values will be used if material.scs_props.active_shader_preset_name == "<imported>": setattr(material.scs_props, "shader_texture_" + tex_type + "_use_imported", True) setattr(material.scs_props, "shader_texture_" + tex_type + "_imported_tobj", texture_data['Value']) # if property is still unset reset it to empty if getattr(material.scs_props, "shader_texture_" + tex_type, "") == _MAT_consts.unset_bitmap_filepath: material.scs_props["shader_texture_" + tex_type] = "" else: final_tex_str = getattr(material.scs_props, "shader_texture_" + tex_type, "") created_textures[tex_type] = get_texture_image(final_tex_str, tex_type) if is_import and not override_back_data: if created_textures[tex_type] is None: lprint("E Can't find texture nor TOBJ inside SCS Project Base Path: %r", (final_tex_str,)) # now try to retrive settings for the textures from TOBJ if tex_type in created_textures and created_textures[tex_type]: final_tex_str = getattr(material.scs_props, "shader_texture_" + tex_type, "") tobj_abs_path = _path.get_tobj_path_from_shader_texture(final_tex_str) settings, map_type = _tobj_imp.get_settings_and_type(tobj_abs_path) created_tex_settings[tex_type] = settings # override shader data for identifying used attributes and textures in UI if override_back_data: shader_data = {'effect': preset_effect, 'attributes': attributes, 'textures': textures} material["scs_shader_attributes"] = shader_data # setup nodes for 3D view visualization _shader.setup_nodes(material, preset_effect, created_attributes, created_textures, created_tex_settings, override_back_data) # setup uv mappings to nodes later trough dedicated function, so proper validation is made on tex coord bindings for mapping_data in created_tex_mappings: # data[0] = texture type; # data[1] = uv mapping value; # data[2] = tex coord value _shader.set_uv(material, mapping_data[0], mapping_data[1], mapping_data[2])
def _draw_shader_texture(layout, mat, split_perc, texture, read_only): """Draws texture box with it's properties. :param layout: layout to draw attribute to :type layout: bpy.types.UILayout :param mat: material from which data should be displayed :type mat: bpy.types.Material :param split_perc: split percentage for attribute name/value :type split_perc: float :param texture: texture data :type texture: dict :param read_only: if texture should be read only :type read_only: bool """ tag = texture.get('Tag', None) hide_state = texture.get('Hide', None) tag_id = tag.split(':') tag_id_string = tag_id[1] texture_type = tag_id_string[8:] shader_texture_id = str('shader_' + tag_id_string) if hide_state == 'True': return texture_box = layout.box().column() # create column for compact display with alignment header_split = texture_box.row(align=True).split(percentage=0.5) header_split.label(texture_type.title(), icon="TEXTURE_SHADED") if hasattr(mat.scs_props, shader_texture_id): shader_texture = mat.scs_props.get(shader_texture_id, "") # imported tobj boolean switch (only for imported shaders) use_imported_tobj = getattr(mat.scs_props, shader_texture_id + "_use_imported", False) if read_only: row = header_split.row(align=True) row.alignment = 'RIGHT' row.prop(mat.scs_props, shader_texture_id + "_use_imported") if use_imported_tobj: texture_row = texture_box.row(align=True) item_space = texture_row.split(percentage=split_perc, align=True) item_space.label("TOBJ Path:") item_space = item_space.split(percentage=1 / (1 - split_perc + 0.000001) * 0.1, align=True) props = item_space.operator("material.scs_looks_wt", text="WT") props.property_str = shader_texture_id item_space.prop(mat.scs_props, shader_texture_id + "_imported_tobj", text="") # disable whole texture layout if it's locked texture_box.enabled = not mat.scs_props.get(shader_texture_id + "_locked", False) texture_row = texture_box.row(align=True) item_space = texture_row.split(percentage=split_perc, align=True) # in case of custom tobj value texture is used only for preview if read_only and use_imported_tobj: item_space.label("Preview Tex:") else: item_space.label("Texture:") layout_box_col = item_space.column(align=True) layout_box_row = layout_box_col.row(align=True) if shader_texture: texture_icon = 'TEXTURE' else: texture_icon = 'MATPLANE' # MARK INVALID SLOTS if _path_utils.is_valid_shader_texture_path(shader_texture): layout_box_row.alert = False else: layout_box_row.alert = True texture_icon = 'ERROR' # MARK EMPTY SLOTS if shader_texture == "": layout_box_row.alert = True layout_box_row = layout_box_row.split(percentage=1 / (1 - split_perc + 0.000001) * 0.1, align=True) props = layout_box_row.operator("material.scs_looks_wt", text="WT") props.property_str = shader_texture_id layout_box_row = layout_box_row.row(align=True) layout_box_row.prop(mat.scs_props, shader_texture_id, text='', icon=texture_icon) props = layout_box_row.operator('material.scs_select_shader_texture_filepath', text='', icon='FILESEL') props.shader_texture = shader_texture_id # DYNAMIC ID SAVE (FOR FILE REQUESTER) # ADDITIONAL TEXTURE SETTINGS if (not read_only or (read_only and not use_imported_tobj)) and texture_box.enabled: tobj_filepath = _path_utils.get_tobj_path_from_shader_texture(shader_texture) if not tobj_filepath: layout_box_inner_col = layout_box_col.row(align=True) item_space = layout_box_inner_col.column(align=True) props = item_space.operator("material.scs_create_tobj", icon="NEW", text="") props.texture_type = texture_type # creating extra column->row so it can be properly disabled as tobj doesn't exists item_space = layout_box_inner_col.column(align=True).row(align=True) else: item_space = layout_box_col.row(align=True) # enable settings only if tobj exists and map type of the tobj is 2d item_space.enabled = tobj_filepath is not None and getattr(mat.scs_props, shader_texture_id + "_map_type", "") == "2d" if tobj_filepath: mtime = str(os.path.getmtime(tobj_filepath)) item_space.alert = (mtime != getattr(mat.scs_props, shader_texture_id + "_tobj_load_time", "NOT FOUND")) else: item_space.alert = True props = item_space.operator("material.scs_reload_tobj", icon="LOAD_FACTORY", text="") props.texture_type = texture_type item_space.prop_menu_enum( mat.scs_props, str('shader_' + tag_id_string + '_settings'), icon='SETTINGS', ) # UV LAYERS FOR TEXTURE uv_mappings = getattr(mat.scs_props, "shader_" + tag_id_string + "_uv", None) if len(uv_mappings) > 0: texture_row = texture_box.row(align=True) item_space = texture_row.split(percentage=split_perc, align=True) if read_only: item_space.label("Preview UV Map:") else: item_space.label("Mapping:") layout_box_col = item_space.column(align=True) for mapping in uv_mappings: item_space_row = layout_box_col.row(align=True) # add info about normal map uv mapping property in case of imported shader if read_only and tag_id_string == "texture_nmap": preview_nmap_msg = str("Maping value for normal maps is in the case of imported shader\n" "also used for defining uv map layer for tangent calculations!\n" "If the uv map is not provided first entry from Mappings list above will be used!") _shared.draw_warning_operator(item_space_row, "Mapping Info", preview_nmap_msg, icon="INFO") # add ensuring operator for norma map uv mapping if tag_id_string == "texture_nmap": props = item_space_row.operator("mesh.scs_ensure_active_uv", text="", icon="FILE_REFRESH") props.mat_name = mat.name props.uv_layer = uv_mappings[0].value if mapping.value and mapping.value != "" and mapping.value in bpy.context.active_object.data.uv_layers: icon = "GROUP_UVS" else: icon = "ERROR" item_space_row.prop_search( data=mapping, property="value", search_data=bpy.context.active_object.data, search_property='uv_layers', text="", icon=icon, ) else: texture_box.row().label('Unsupported Shader Texture Type!', icon="ERROR")