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 get_texture(texture_path, texture_type, report_invalid=False): """Creates and setup Texture and Image data on active Material. :param texture_path: Texture path :type texture_path: str :param texture_type: Texture type keyword :type texture_type: str :param report_invalid: flag indicating if invalid texture should be reported in 3d view :type report_invalid: bool """ # CREATE TEXTURE/IMAGE ID NAME teximag_id_name = _path.get_filename(texture_path, with_ext=False) # CREATE ABSOLUTE FILEPATH abs_texture_filepath = _path.get_abs_path(texture_path) # return None on non-existing texture file path if not abs_texture_filepath or not os.path.isfile(abs_texture_filepath): return None if abs_texture_filepath.endswith(".tobj"): abs_texture_filepath = _path.get_texture_path_from_tobj(abs_texture_filepath) # if not existing or none supported file if abs_texture_filepath is None or abs_texture_filepath[-4:] not in (".tga", ".png", ".dds"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) # take care of none existing paths referenced in tobj texture names if abs_texture_filepath: lprint("W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) else: lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file.", (texture_path,)) if report_invalid: lprint("", report_warnings=1, report_errors=1) return None texture = None if abs_texture_filepath and os.path.isfile(abs_texture_filepath): # find existing texture with this image if teximag_id_name in bpy.data.textures: # reuse existing image texture if possible postfix = 0 postfixed_tex = teximag_id_name while postfixed_tex in bpy.data.textures: img_exists = bpy.data.textures[postfixed_tex].image is not None if img_exists and _path.repair_path(bpy.data.textures[postfixed_tex].image.filepath) == _path.repair_path(abs_texture_filepath): texture = bpy.data.textures[postfixed_tex] break postfix += 1 postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3) # if texture wasn't found create new one if not texture: texture = bpy.data.textures.new(teximag_id_name, 'IMAGE') image = None # reuse existing image if possible postfix = 0 postfixed_img = teximag_id_name while postfixed_img in bpy.data.images: if _path.repair_path(bpy.data.images[postfixed_img].filepath) == _path.repair_path(abs_texture_filepath): image = bpy.data.images[postfixed_img] break postfix += 1 postfixed_img = teximag_id_name + "." + str(postfix).zfill(3) # if image wasn't found load it if not image: image = bpy.data.images.load(abs_texture_filepath) image.name = teximag_id_name # try to get relative path to the Blender file and set it to the image if bpy.data.filepath != '': # empty file path means blender file is not saved try: rel_path = _path.relative_path(os.path.dirname(bpy.data.filepath), abs_texture_filepath) except ValueError: # catch different mount paths: "path is on mount 'C:', start on mount 'E:'" rel_path = None if rel_path: image.filepath = rel_path # finally link image to texture texture.image = image image.use_alpha = True # set proper color space depending on texture type if texture_type == "nmap": # For TGA normal maps texture use Non-Color color space as it should be, # but for 16-bits PNG normal maps texture sRGB has to be used # otherwise Blender completely messes up normals calculation if texture.image.filepath.endswith(".tga"): texture.image.colorspace_settings.name = "Non-Color" else: texture.image.colorspace_settings.name = "sRGB" else: texture.image.colorspace_settings.name = "sRGB" # set usage of normal map if texture type is correct texture.use_normal_map = (texture_type == "nmap") if texture is None and texture_path.endswith(".tobj"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) if report_invalid: lprint("", report_warnings=1, report_errors=1) return texture
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 get_texture(texture_path, texture_type, report_invalid=False): """Creates and setup Texture and Image data on active Material. :param texture_path: Texture path :type texture_path: str :param texture_type: Texture type keyword :type texture_type: str :param report_invalid: flag indicating if invalid texture should be reported in 3d view :type report_invalid: bool """ # CREATE TEXTURE/IMAGE ID NAME teximag_id_name = _path.get_filename(texture_path, with_ext=False) # CREATE ABSOLUTE FILEPATH abs_texture_filepath = _path.get_abs_path(texture_path) # return None on non-existing texture file path if not abs_texture_filepath or not os.path.isfile(abs_texture_filepath): return None if abs_texture_filepath.endswith(".tobj"): abs_texture_filepath = _path.get_texture_path_from_tobj( abs_texture_filepath) # if not existing or none supported file if abs_texture_filepath is None or abs_texture_filepath[-4:] not in ( ".tga", ".png", ".dds"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) # take care of none existing paths referenced in tobj texture names if abs_texture_filepath: lprint( "W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) else: lprint( "W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file.", (texture_path, )) if report_invalid: lprint("", report_warnings=1, report_errors=1) return None texture = None if abs_texture_filepath and os.path.isfile(abs_texture_filepath): # find existing texture with this image if teximag_id_name in bpy.data.textures: # reuse existing image texture if possible postfix = 0 postfixed_tex = teximag_id_name while postfixed_tex in bpy.data.textures: img_exists = bpy.data.textures[postfixed_tex].image is not None if img_exists and _path.repair_path( bpy.data.textures[postfixed_tex].image.filepath ) == _path.repair_path(abs_texture_filepath): texture = bpy.data.textures[postfixed_tex] break postfix += 1 postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3) # if texture wasn't found create new one if not texture: texture = bpy.data.textures.new(teximag_id_name, 'IMAGE') image = None # reuse existing image if possible postfix = 0 postfixed_img = teximag_id_name while postfixed_img in bpy.data.images: if _path.repair_path( bpy.data.images[postfixed_img].filepath ) == _path.repair_path(abs_texture_filepath): image = bpy.data.images[postfixed_img] break postfix += 1 postfixed_img = teximag_id_name + "." + str(postfix).zfill(3) # if image wasn't found load it if not image: image = bpy.data.images.load(abs_texture_filepath) image.name = teximag_id_name # try to get relative path to the Blender file and set it to the image if bpy.data.filepath != '': # empty file path means blender file is not saved try: rel_path = _path.relative_path( os.path.dirname(bpy.data.filepath), abs_texture_filepath) except ValueError: # catch different mount paths: "path is on mount 'C:', start on mount 'E:'" rel_path = None if rel_path: image.filepath = rel_path # finally link image to texture texture.image = image image.use_alpha = True # set proper color space depending on texture type if texture_type == "nmap": # For TGA normal maps texture use Non-Color color space as it should be, # but for 16-bits PNG normal maps texture sRGB has to be used # otherwise Blender completely messes up normals calculation if texture.image.filepath.endswith(".tga"): texture.image.colorspace_settings.name = "Non-Color" else: texture.image.colorspace_settings.name = "sRGB" else: texture.image.colorspace_settings.name = "sRGB" # set usage of normal map if texture type is correct texture.use_normal_map = (texture_type == "nmap") if texture is None and texture_path.endswith(".tobj"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) lprint( "W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) if report_invalid: lprint("", report_warnings=1, report_errors=1) return texture
def get_texture_image(texture_path, texture_type, report_invalid=False): """Creates and returns image for given texture path and type. :param texture_path: Texture path :type texture_path: str :param texture_type: Texture type keyword :type texture_type: str :param report_invalid: flag indicating if invalid texture should be reported in 3d view :type report_invalid: bool :return: loaded image datablock to be used in SCS material :rtype: bpy.types.Image """ # get reflection image texture if texture_path.endswith(".tobj") and texture_type == "reflection": return get_reflection_image(texture_path, report_invalid=report_invalid) # CREATE TEXTURE/IMAGE ID NAME teximag_id_name = _path.get_filename(texture_path, with_ext=False) # CREATE ABSOLUTE FILEPATH abs_texture_filepath = _path.get_abs_path(texture_path) # return None on non-existing texture file path if not abs_texture_filepath or not os.path.isfile(abs_texture_filepath): return None if abs_texture_filepath.endswith(".tobj"): abs_texture_filepath = _path.get_texture_path_from_tobj(abs_texture_filepath) # if not existing or none supported file if abs_texture_filepath is None or abs_texture_filepath[-4:] not in (".tga", ".png", ".dds"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) # take care of none existing paths referenced in tobj texture names if abs_texture_filepath: lprint("W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) else: lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file.", (texture_path,)) if report_invalid: lprint("", report_warnings=1, report_errors=1) return None image = None if abs_texture_filepath and os.path.isfile(abs_texture_filepath): # reuse existing image texture if possible postfix = 0 postfixed_tex = teximag_id_name while postfixed_tex in bpy.data.images: img_exists = postfixed_tex in bpy.data.images if img_exists and _path.repair_path(bpy.data.images[postfixed_tex].filepath) == _path.repair_path(abs_texture_filepath): image = bpy.data.images[postfixed_tex] break postfix += 1 postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3) # if image wasn't found create new one if not image: image = None # reuse existing image if possible postfix = 0 postfixed_img = teximag_id_name while postfixed_img in bpy.data.images: if _path.repair_path(bpy.data.images[postfixed_img].filepath) == _path.repair_path(abs_texture_filepath): image = bpy.data.images[postfixed_img] break postfix += 1 postfixed_img = teximag_id_name + "." + str(postfix).zfill(3) # if image wasn't found load it if not image: image = bpy.data.images.load(abs_texture_filepath) image.name = teximag_id_name image.alpha_mode = 'CHANNEL_PACKED' # try to get relative path to the Blender file and set it to the image if bpy.data.filepath != '': # empty file path means blender file is not saved try: rel_path = _path.relative_path(os.path.dirname(bpy.data.filepath), abs_texture_filepath) except ValueError: # catch different mount paths: "path is on mount 'C:', start on mount 'E:'" rel_path = None if rel_path: image.filepath = rel_path if image is None and texture_path.endswith(".tobj"): if report_invalid: lprint("", report_warnings=-1, report_errors=-1) lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t %r", (texture_path, _path.readable_norm(abs_texture_filepath))) if report_invalid: lprint("", report_warnings=1, report_errors=1) return image