def execute(self, context): scs_globals = _get_scs_globals() if self.type == "DefaultExportPath": obj = context.scene.scs_props prop = "default_export_filepath" elif self.type == "GameObjectExportPath": obj = context.active_object.scs_props prop = "scs_root_object_export_filepath" elif self.type == "GameObjectAnimExportPath": obj = _object_utils.get_scs_root( context.active_object).scs_props prop = "scs_root_object_anim_export_filepath" else: obj = context.active_object.scs_props prop = "scs_skeleton_custom_export_dirpath" if _path_utils.startswith(self.directory, scs_globals.scs_project_path): setattr( obj, prop, _path_utils.relative_path(scs_globals.scs_project_path, self.directory)) else: setattr(obj, prop, "//") self.report({ 'ERROR' }, "Selected path is not within SCS Project Base Path,\npath will be reset to SCS Project Base Path instead." ) return {'CANCELLED'} return {'FINISHED'}
def execute(self, context): scs_globals = _get_scs_globals() if self.type == "DefaultExportPath": obj = context.scene.scs_props prop = "default_export_filepath" elif self.type == "GameObjectExportPath": obj = context.active_object.scs_props prop = "scs_root_object_export_filepath" elif self.type == "GameObjectAnimExportPath": obj = _object_utils.get_scs_root(context.active_object).scs_props prop = "scs_root_object_anim_export_filepath" else: obj = context.active_object.scs_props prop = "scs_skeleton_custom_export_dirpath" if _path_utils.startswith(self.directory, scs_globals.scs_project_path): setattr(obj, prop, _path_utils.relative_path(scs_globals.scs_project_path, self.directory)) else: setattr(obj, prop, "//") self.report({'ERROR'}, "Selected path is not within SCS Project Base Path,\npath will be reset to SCS Project Base Path instead.") return {'CANCELLED'} return {'FINISHED'}
def execute(self, context): lprint("D " + self.bl_idname, report_errors=-1, report_warnings=-1) if not _path_utils.startswith(self.directory, _get_scs_globals().scs_project_path): message = "E Selected path is not inside SCS Project Base Path! Animation can't be exported to this directory." lprint(message) self.report({'ERROR'}, message[2:]) return {'CANCELLED'} armature = context.active_object scs_root_obj = _object_utils.get_scs_root(armature) anim_inventory = scs_root_obj.scs_object_animation_inventory skeleton_filepath = _path_utils.get_skeleton_relative_filepath( armature, self.directory, scs_root_obj.name) if 0 <= self.index < len(anim_inventory): anim = anim_inventory[self.index] _export.pia.export(scs_root_obj, armature, anim, self.directory, skeleton_filepath) lprint("", report_errors=1, report_warnings=1) return {'FINISHED'}
def execute(self, context): """Set Material Substance library filepath.""" scs_globals = _get_scs_globals() if _path_utils.startswith(self.filepath, scs_globals.scs_project_path): self.filepath = _path_utils.relative_path(scs_globals.scs_project_path, self.filepath) scs_globals.matsubs_library_rel_path = self.filepath return {'FINISHED'}
def execute(self, context): """Set Hookup directory path.""" scs_globals = _get_scs_globals() if _path_utils.startswith(self.directory, scs_globals.scs_project_path): self.directory = _path_utils.relative_path(scs_globals.scs_project_path, self.directory) scs_globals.hookup_library_rel_path = self.directory return {'FINISHED'}
def execute(self, context): """Set Traffic Rules library filepath.""" scs_globals = _get_scs_globals() if _path_utils.startswith(self.filepath, scs_globals.scs_project_path): self.filepath = _path_utils.relative_path(scs_globals.scs_project_path, self.filepath) scs_globals.traffic_rules_library_rel_path = self.filepath return {'FINISHED'}
def execute(self, context): """Set Sign directory path.""" scs_globals = _get_scs_globals() if _path_utils.startswith(self.filepath, scs_globals.scs_project_path): self.filepath = _path_utils.relative_path(scs_globals.scs_project_path, self.filepath) scs_globals.sign_library_rel_path = self.filepath return {'FINISHED'}
def execute(self, context): """Set Sign directory path.""" scs_globals = _get_scs_globals() if _path_utils.startswith(self.filepath, scs_globals.scs_project_path): self.filepath = _path_utils.relative_path( scs_globals.scs_project_path, self.filepath) scs_globals.sign_library_rel_path = self.filepath return {'FINISHED'}
def execute(self, context): """Set Material Substance library filepath.""" scs_globals = _get_scs_globals() if _path_utils.startswith(self.filepath, scs_globals.scs_project_path): self.filepath = _path_utils.relative_path( scs_globals.scs_project_path, self.filepath) scs_globals.matsubs_library_rel_path = self.filepath return {'FINISHED'}
def execute(self, context): """Set Hookup directory path.""" scs_globals = _get_scs_globals() if _path_utils.startswith(self.directory, scs_globals.scs_project_path): self.directory = _path_utils.relative_path( scs_globals.scs_project_path, self.directory) scs_globals.hookup_library_rel_path = self.directory return {'FINISHED'}
def execute(self, context): """Set Traffic Rules library filepath.""" scs_globals = _get_scs_globals() if _path_utils.startswith(self.filepath, scs_globals.scs_project_path): self.filepath = _path_utils.relative_path( scs_globals.scs_project_path, self.filepath) scs_globals.traffic_rules_library_rel_path = self.filepath return {'FINISHED'}
def execute(self, context): lprint("D " + self.bl_idname, report_errors=-1, report_warnings=-1) if not _path_utils.startswith(self.directory, _get_scs_globals().scs_project_path): message = "E Selected path is not inside SCS Project Base Path! Animation can't be exported to this directory." lprint(message) self.report({'ERROR'}, message[2:]) return {'CANCELLED'} armature = context.active_object scs_root_obj = _object_utils.get_scs_root(armature) anim_inventory = scs_root_obj.scs_object_animation_inventory skeleton_filepath = _path_utils.get_skeleton_relative_filepath(armature, self.directory, scs_root_obj.name) if 0 <= self.index < len(anim_inventory): anim = anim_inventory[self.index] _export.pia.export(scs_root_obj, armature, anim, self.directory, skeleton_filepath) lprint("", report_errors=1, report_warnings=1) return {'FINISHED'}
def batch_export(operator_instance, init_obj_list, name_suffix="", menu_filepath=None): """This function calls other sorting functions and depending on the resulting output dictionary it exports all available 'SCS Game Objects' into specified locations. :param operator_instance: operator from within this function is called (used for report) :type operator_instance: bpy.types.Operator :param init_obj_list: initial object list which should be exported :type init_obj_list: tuple of Blender objects :param name_suffix: files name suffix (exchange format is using .ef) :type name_suffix: str :param menu_filepath: filepath used from menu export :type menu_filepath: str """ lprint("", report_errors=-1, report_warnings=-1 ) # Clear the 'error_messages' and 'warning_messages' game_objects_dict = _object_utils.sort_out_game_objects_for_export( init_obj_list) # exclude game objects that were manually omitted from export by property game_objects_dict = _object_utils.exclude_switched_off(game_objects_dict) if game_objects_dict: scs_game_objects_exported = [] scs_game_objects_rejected = [] global_filepath = _path_utils.get_global_export_path() for root_object in game_objects_dict: if not _name_utils.is_valid_scs_root_object_name(root_object.name): lprint( "E Rejecting Game Object with invalid SCS Root Object name: %r.\n\t " "Only a-z, A-Z, 0-9 and \"._-\" characters can be used." % root_object.name) scs_game_objects_rejected.append("> \"" + root_object.name + "\"") continue game_object_list = game_objects_dict[root_object] if len(game_object_list) == 0: lprint( "E Rejecting empty Game Object with SCS Root Object name: %r\n\t " + "Game Object has to have at least one mesh object or model locator!", (root_object.name, )) scs_game_objects_rejected.append("> \"" + root_object.name + "\"") continue # GET CUSTOM FILE PATH custom_filepath = _path_utils.get_custom_scs_root_export_path( root_object) # MAKE FINAL FILEPATH if menu_filepath: filepath = _path_utils.readable_norm(menu_filepath) filepath_message = "Export path selected in file browser:\n\t \"" + filepath + "\"" elif custom_filepath: filepath = _path_utils.readable_norm(custom_filepath) filepath_message = "Custom export path used for \"" + root_object.name + "\" is:\n\t \"" + filepath + "\"" else: filepath = _path_utils.readable_norm(global_filepath) filepath_message = "Default export path used for \"" + root_object.name + "\":\n\t \"" + filepath + "\"" scs_project_path = _path_utils.readable_norm( _get_scs_globals().scs_project_path) if os.path.isdir(filepath) and _path_utils.startswith( filepath, scs_project_path) and scs_project_path != "": # EXPORT ENTRY POINT export_success = pix.export(filepath, name_suffix, root_object, game_object_list) if export_success: scs_game_objects_exported.append("> \"" + root_object.name + "\" exported to: '" + filepath + "'") else: scs_game_objects_rejected.append("> \"" + root_object.name + "\"") else: if filepath: message = ( "No valid export path found!\n\t " + "Export path does not exists or it's not inside SCS Project Base Path.\n\t " + "SCS Project Base Path:\n\t \"" + scs_project_path + "\"\n\t " + filepath_message) else: message = "No valid export path found! Please check 'SCS Project Base Path' first." lprint('E ' + message) operator_instance.report({'ERROR'}, message.replace("\t", "").replace( " ", "")) return {'CANCELLED'} if not lprint( "\nI Export procces completed, summaries are printed below!", report_errors=True, report_warnings=True): operator_instance.report( {'INFO'}, "Export successfully completed, exported %s game object(s)!" % len(scs_game_objects_exported)) bpy.ops.wm.scs_tools_show_3dview_report( 'INVOKE_DEFAULT', abort=True) # abort 3d view reporting operator if len(scs_game_objects_exported) > 0: message = "EXPORTED GAME OBJECTS (" + str( len(scs_game_objects_exported) ) + "):\n\t " + "=" * 26 + "\n\t " for scs_game_object_export_message in scs_game_objects_exported: message += scs_game_object_export_message + "\n\t " message += "=" * 26 lprint("I " + message) if len(scs_game_objects_rejected) > 0: message = "REJECTED GAME OBJECTS (" + str( len(scs_game_objects_rejected) ) + "):\n\t " + "=" * 26 + "\n\t " for scs_game_object_export_message in scs_game_objects_rejected: message += scs_game_object_export_message + "\n\t " message += "=" * 26 lprint("I " + message) if len(scs_game_objects_exported) + len( scs_game_objects_rejected) == 0: message = "Nothing to export! Please setup at least one SCS Root Object." lprint('E ' + message) operator_instance.report({'ERROR'}, message) return {'CANCELLED'} else: message = "No Game Objects to export because:\n\t " \ "1. Selection export is used and none of selected objects belongs to any SCS Game Object or\n\t " \ "2. all of the SCS Root Objects were manually exluded from export or\n\t " \ "3. there is no SCS Root Objects in the scene." lprint('E ' + message) operator_instance.report({'ERROR'}, message.replace("\n\t ", "\n")) return {'CANCELLED'} return {'FINISHED'}
def batch_export(operator_instance, init_obj_list, menu_filepath=None): """This function calls other sorting functions and depending on the resulting output dictionary it exports all available 'SCS Game Objects' into specified locations. :param operator_instance: operator from within this function is called (used for report) :type operator_instance: bpy.types.Operator :param init_obj_list: initial object list which should be exported :type init_obj_list: tuple of Blender objects :param menu_filepath: filepath used from menu export :type menu_filepath: str """ lprint("", report_errors=-1, report_warnings=-1) # Clear the 'error_messages' and 'warning_messages' game_objects_dict = _object_utils.sort_out_game_objects_for_export(init_obj_list) # exclude game objects that were manually omitted from export by property game_objects_dict = _object_utils.exclude_switched_off(game_objects_dict) if game_objects_dict: scs_game_objects_exported = [] scs_game_objects_rejected = [] global_filepath = _path_utils.get_global_export_path() for root_object in game_objects_dict: # update root object location to invoke update tagging on it and # then update scene to make sure all children objects will have all transforms up to date # NOTE: needed because Blender doesn't update objects on invisible layers on it's own root_object.location = root_object.location for scene in bpy.data.scenes: scene.update() game_object_list = game_objects_dict[root_object] # GET CUSTOM FILE PATH custom_filepath = _path_utils.get_custom_scs_root_export_path(root_object) # MAKE FINAL FILEPATH if menu_filepath: filepath = menu_filepath filepath_message = 'Export path selected in file browser:\n\t "' + filepath + '"' elif custom_filepath: filepath = custom_filepath filepath_message = 'Custom export path used for "' + root_object.name + '" is:\n\t "' + filepath + '"' else: filepath = global_filepath filepath_message = 'Default export path used for "' + root_object.name + '":\n\t "' + filepath + '"' scs_project_path = _get_scs_globals().scs_project_path if ( os.path.isdir(filepath) and _path_utils.startswith(filepath, scs_project_path) and scs_project_path != "" ): # EXPORT ENTRY POINT export_success = pix.export(filepath, root_object, game_object_list) if export_success: scs_game_objects_exported.append('> "' + root_object.name + "\" exported to: '" + filepath + "'") else: scs_game_objects_rejected.append('> "' + root_object.name + '"') else: if filepath: message = ( "No valid export path found!\n\t " + "Export path does not exists or it's not inside SCS Project Base Path.\n\t " + 'SCS Project Base Path:\n\t "' + scs_project_path + '"\n\t ' + filepath_message ) else: message = 'No valid export path found! Please check "SCS Project Base Path" first.' lprint("E " + message) operator_instance.report({"ERROR"}, message.replace("\t", "").replace(" ", "")) return {"CANCELLED"} if not lprint( "\nI Export procces completed, summaries are printed below!", report_errors=True, report_warnings=True ): operator_instance.report({"INFO"}, "Export successfully completed!") bpy.ops.wm.show_3dview_report("INVOKE_DEFAULT", abort=True) # abort 3d view reporting operator if len(scs_game_objects_exported) > 0: print("\n\nEXPORTED GAME OBJECTS (" + str(len(scs_game_objects_exported)) + "):\n" + "=" * 26) for scs_game_object_export_message in scs_game_objects_exported: print(scs_game_object_export_message) if len(scs_game_objects_rejected) > 0: print("\n\nREJECTED GAME OBJECTS (" + str(len(scs_game_objects_rejected)) + "):\n" + "=" * 26) for scs_game_object_export_message in scs_game_objects_rejected: print(scs_game_object_export_message) if len(scs_game_objects_exported) + len(scs_game_objects_rejected) == 0: message = "Nothing to export! Please set at least one 'SCS Root Object'." lprint("E " + message) operator_instance.report({"ERROR"}, message) return {"CANCELLED"} else: message = ( "No 'SCS Root Object' present or all of them were manually exluded from export in their settings.\n\t " "(For more information, please refer to 'SCS Blender Tools' documentation.)" ) lprint("E " + message) operator_instance.report({"ERROR"}, message.replace("\n\t ", "\n")) return {"CANCELLED"} return {"FINISHED"}
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 batch_export(operator_instance, init_obj_list, menu_filepath=None): """This function calls other sorting functions and depending on the resulting output dictionary it exports all available 'SCS Game Objects' into specified locations. :param operator_instance: operator from within this function is called (used for report) :type operator_instance: bpy.types.Operator :param init_obj_list: initial object list which should be exported :type init_obj_list: tuple of Blender objects :param menu_filepath: filepath used from menu export :type menu_filepath: str """ lprint("", report_errors=-1, report_warnings=-1 ) # Clear the 'error_messages' and 'warning_messages' game_objects_dict = _object_utils.sort_out_game_objects_for_export( init_obj_list) # exclude game objects that were manually omitted from export by property game_objects_dict = _object_utils.exclude_switched_off(game_objects_dict) if game_objects_dict: scs_game_objects_exported = [] scs_game_objects_rejected = [] global_filepath = _path_utils.get_global_export_path() for root_object in game_objects_dict: # update root object location to invoke update tagging on it and # then update scene to make sure all children objects will have all transforms up to date # NOTE: needed because Blender doesn't update objects on invisible layers on it's own root_object.location = root_object.location for scene in bpy.data.scenes: scene.update() game_object_list = game_objects_dict[root_object] # GET CUSTOM FILE PATH custom_filepath = _path_utils.get_custom_scs_root_export_path( root_object) # MAKE FINAL FILEPATH if menu_filepath: filepath = menu_filepath filepath_message = "Export path selected in file browser:\n\t \"" + filepath + "\"" elif custom_filepath: filepath = custom_filepath filepath_message = "Custom export path used for \"" + root_object.name + "\" is:\n\t \"" + filepath + "\"" else: filepath = global_filepath filepath_message = "Default export path used for \"" + root_object.name + "\":\n\t \"" + filepath + "\"" scs_project_path = _get_scs_globals().scs_project_path if os.path.isdir(filepath) and _path_utils.startswith( filepath, scs_project_path) and scs_project_path != "": # EXPORT ENTRY POINT export_success = pix.export(filepath, root_object, game_object_list) if export_success: scs_game_objects_exported.append("> \"" + root_object.name + "\" exported to: '" + filepath + "'") else: scs_game_objects_rejected.append("> \"" + root_object.name + "\"") else: if filepath: message = ( "No valid export path found!\n\t " + "Export path does not exists or it's not inside SCS Project Base Path.\n\t " + "SCS Project Base Path:\n\t \"" + scs_project_path + "\"\n\t " + filepath_message) else: message = "No valid export path found! Please check \"SCS Project Base Path\" first." lprint('E ' + message) operator_instance.report({'ERROR'}, message.replace("\t", "").replace( " ", "")) return {'CANCELLED'} if not lprint( "\nI Export procces completed, summaries are printed below!", report_errors=True, report_warnings=True): operator_instance.report({'INFO'}, "Export successfully completed!") bpy.ops.wm.show_3dview_report( 'INVOKE_DEFAULT', abort=True) # abort 3d view reporting operator if len(scs_game_objects_exported) > 0: print("\n\nEXPORTED GAME OBJECTS (" + str(len(scs_game_objects_exported)) + "):\n" + "=" * 26) for scs_game_object_export_message in scs_game_objects_exported: print(scs_game_object_export_message) if len(scs_game_objects_rejected) > 0: print("\n\nREJECTED GAME OBJECTS (" + str(len(scs_game_objects_rejected)) + "):\n" + "=" * 26) for scs_game_object_export_message in scs_game_objects_rejected: print(scs_game_object_export_message) if len(scs_game_objects_exported) + len( scs_game_objects_rejected) == 0: message = "Nothing to export! Please set at least one 'SCS Root Object'." lprint('E ' + message) operator_instance.report({'ERROR'}, message) return {'CANCELLED'} else: message = "No 'SCS Root Object' present or all of them were manually exluded from export in their settings.\n\t " \ "(For more information, please refer to 'SCS Blender Tools' documentation.)" lprint('E ' + message) operator_instance.report({'ERROR'}, message.replace("\n\t ", "\n")) return {'CANCELLED'} return {'FINISHED'}
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