def optimize_scenery(script_settings): try: # instantiate the msfsProject and create the necessary resources if it does not exist msfs_project = MsfsProject(script_settings.projects_path, script_settings.project_name, script_settings.definition_file, script_settings.author_name, script_settings.sources_path) check_configuration( script_settings, msfs_project, check_optimisation=True, check_lily_texture_packer=script_settings.bake_textures_enabled) if script_settings.backup_enabled: msfs_project.backup( Path(os.path.abspath(__file__)).stem.replace( SCRIPT_PREFIX, str())) clean_scene() msfs_project.optimize(script_settings) if script_settings.build_package_enabled: build_package(msfs_project, script_settings) pr_bg_green("Script correctly applied" + CEND) except ScriptError as ex: error_report = "".join(ex.value) isolated_print(constants.EOL + error_report) pr_bg_red("Script aborted" + CEND) except RuntimeError as ex: isolated_print(constants.EOL + str(ex)) pr_bg_red("Script aborted" + CEND)
def split_tiles(script_settings): try: # instantiate the msfsProject and create the necessary resources if it does not exist msfs_project = MsfsProject(script_settings.projects_path, script_settings.project_name, script_settings.definition_file, script_settings.author_name, script_settings.sources_path) check_configuration(script_settings, msfs_project) if script_settings.backup_enabled: msfs_project.backup( Path(os.path.abspath(__file__)).stem.replace( SCRIPT_PREFIX, str())) msfs_project.split_tiles() if script_settings.build_package_enabled: build_package(msfs_project, script_settings) pr_bg_green("Script correctly applied" + constants.CEND) except ScriptError as ex: error_report = str().join(ex.value) isolated_print(constants.EOL + error_report) pr_bg_red("Script aborted" + constants.CEND) except RuntimeError as ex: isolated_print(constants.EOL + str(ex)) pr_bg_red("Script aborted" + constants.CEND)
def clean_scene(): if not bpy.data: return bpy.ops.object.select_all(action=SELECT_ACTION) for block in bpy.data.meshes: if block.users == 0: bpy.data.meshes.remove(block) for block in bpy.data.materials: if block.users == 0: bpy.data.materials.remove(block) for block in bpy.data.textures: if block.users == 0: bpy.data.textures.remove(block) for block in bpy.data.images: if block.users == 0: bpy.data.images.remove(block) bpy.ops.object.delete() # Now cycles through the dangling datablocks and remove them. for me in bpy.data.meshes: if not remove_mesh_from_memory(me.name): isolated_print("Unable to remove [%s]." % me.name) print(EOL) print("3d scene cleaned", EOL)
def fix_tiles_lightning_issues(self, settings): isolated_print(EOL) lods = [lod for tile in self.tiles.values() for lod in tile.lods] pbar = ProgressBar(list(lods), title="FIX TILES LIGHTNING ISSUES") for lod in lods: lod.optimization_in_progress = False lod.prepare_for_msfs() pbar.update("%s lightning issues fixed" % lod.name)
def backup(self, backup_subfolder, all_files=True): isolated_print(EOL) self.backup_files(backup_subfolder) if all_files: self.backup_tiles(backup_subfolder) self.backup_colliders(backup_subfolder) self.backup_scene_objects(backup_subfolder) self.backup_shapes(backup_subfolder)
def export_to_optimized_gltf_files(file, texture_folder, use_selection=False): isolated_print("export to", file, "with associated textures", EOL) bpy.ops.export_scene.gltf(export_format=GLTF_SEPARATE_EXPORT_FORMAT, export_extras=True, filepath=file, export_texture_dir=texture_folder, use_selection=use_selection) model_file = MsfsGltf(file) model_file.add_optimization_tag() model_file.dump()
def check_lily_texture_packer_availability(settings, warning_msg=str()): texture_packer_enabled = False try: if LILY_TEXTURE_PACKER_ADDON in bpy.context.preferences.addons: texture_packer_enabled = True pr_ok_green( str("Lily texture packer enabled").ljust(RESULT_MSG_LENGTH)) except: pass if not texture_packer_enabled: pr_ko_orange( str("Lily texture packer disabled").ljust(RESULT_MSG_LENGTH)) settings.bake_textures_enabled = False isolated_print( CORANGE + warning_msg + " Lily texture packer is not enabled in your blender addons. Baking of the tile textures is disabled" + CEND + EOL)
def update(self, description=str()): if self.range <= 0: return self.idx += 1 progress = self.idx / self.range block = int(round(self.length * progress)) description = DONE_PROCESS if progress >= 1 else description msg = self.__get_color(progress) + "\r[{0}] {1}%: {2}".format( "\u25A0" * block + "-" * (self.length - block), round(progress * 100, 2), description + CEND) sys.stdout = sys.__stdout__ sys.stdout.write(msg.ljust(MSG_LENGTH)) sys.stdout.flush() sys.stdout = open(os.devnull, 'w') time.sleep(self.sleep) if progress >= 1: isolated_print(EOL)
def init_msfs_scenery_project(script_settings): try: print_title("INIT SCENERY PROJECT") # instantiate the msfsProject and create the necessary resources if it does not exist MsfsProject(script_settings.projects_path, script_settings.project_name, script_settings.definition_file, script_settings.author_name, script_settings.sources_path, init_structure=True) pr_bg_green("Script correctly applied" + constants.CEND) except ScriptError as ex: error_report = "".join(ex.value) isolated_print(constants.EOL + error_report) pr_bg_red("Script aborted" + constants.CEND) except RuntimeError as ex: isolated_print(constants.EOL + str(ex)) pr_bg_red("Script aborted" + constants.CEND)
def optimize(self, settings): isolated_print(EOL) dest_format = settings.output_texture_format src_format = JPG_TEXTURE_FORMAT if dest_format == PNG_TEXTURE_FORMAT else PNG_TEXTURE_FORMAT lods = [lod for tile in self.tiles.values() for lod in tile.lods] self.__convert_tiles_textures(src_format, dest_format) self.update_min_size_values(settings) # some tile lods are not optimized if self.__optimization_needed(): self.__create_optimization_folders() self.__optimize_tile_lods(self.__retrieve_lods_to_process()) pbar = ProgressBar(list(lods), title="PREPARE THE TILES FOR MSFS") for lod in lods: lod.folder = os.path.dirname( lod.folder) if self.__optimization_needed() else lod.folder lod.optimization_in_progress = False lod.prepare_for_msfs() pbar.update("%s prepared for msfs" % lod.name) self.objects_xml.update_objects_position(self, settings)
def compress_built_package(script_settings): try: # instantiate the msfsProject and create the necessary resources if it does not exist msfs_project = MsfsProject(script_settings.projects_path, script_settings.project_name, script_settings.definition_file, script_settings.author_name, script_settings.sources_path, fast_init=True) check_configuration(script_settings, msfs_project, check_built_package=True, check_compressonator=True) isolated_print(EOL) print_title("COMPRESS BUILT PACKAGE") msfs_project.compress_built_package(script_settings) if script_settings.build_package_enabled: build_package(msfs_project, script_settings) pr_bg_green("Script correctly applied" + constants.CEND) except ScriptError as ex: error_report = "".join(ex.value) isolated_print(constants.EOL + error_report) pr_bg_red("Script aborted" + constants.CEND) except RuntimeError as ex: isolated_print(constants.EOL + str(ex)) pr_bg_red("Script aborted" + constants.CEND)
def optimize(self, bake_textures_enabled, output_texture_format): model_files = [model_file for model_file in Path(self.folder).glob(GLTF_FILE_PATTERN) if not self.__is_optimized(model_file)] if not model_files: return new_gltf = os.path.join(os.path.dirname(self.folder), Path(self.folder).name + GLTF_FILE_EXT) # Import the gltf files located in the object folder import_model_files(model_files) if bake_textures_enabled and self.has_unbaked_textures(): isolated_print("bake textures for", self.name) bake_texture_files(self.folder, self.name + "." + output_texture_format) isolated_print("fix bounding box for", self.name) fix_object_bounding_box() export_to_optimized_gltf_files(new_gltf, TEXTURE_FOLDER) if os.path.isfile(new_gltf): shutil.rmtree(self.folder) self.folder = os.path.dirname(self.folder) self.optimization_in_progress = False self.__retrieve_gltf_resources()
def __convert_tiles_textures(self, src_format, dest_format): textures = self.__retrieve_tiles_textures(src_format) if textures: isolated_print( src_format + " texture files detected in the tiles of the project! Try to install pip, then convert them" ) print_title("INSTALL PILLOW") install_python_lib("Pillow") pbar = ProgressBar(textures, title="CONVERT " + src_format.upper() + " TEXTURE FILES TO " + dest_format.upper()) for texture in textures: file = texture.file if not texture.convert_format(src_format, dest_format): raise ScriptError( "An error was detected while converting texture files in " + self.texture_folder + " ! Please convert them to " + dest_format + " format prior to launch the script, or remove them") else: pbar.update("%s converted to %s" % (file, dest_format))
def clean(self): isolated_print(EOL) self.__clean_objects(self.tiles) self.__clean_objects(self.colliders) self.__clean_objects(self.objects)
def update_objects_position(self, settings): isolated_print(EOL) self.objects_xml.update_objects_position(self, settings)
def check_configuration(settings, msfs_project, check_optimisation=False, check_lily_texture_packer=False, check_built_package=False, check_compressonator=False): error_msg = "Configuration error found ! " warning_msg = "Configuration warning ! " print_title("CHECK CONFIGURATION FOR " + msfs_project.project_name + " PROJECT") # check if the projects folder exists if not os.path.isdir(msfs_project.parent_path): pr_ko_red(str("projects_path value").ljust(RESULT_MSG_LENGTH)) raise ScriptError( error_msg + "The folder containing your projects (" + msfs_project.parent_path + ") was not found. Please check the projects_path value") pr_ok_green(str("projects_path value").ljust(RESULT_MSG_LENGTH)) # check the projects name if not os.path.isdir(msfs_project.project_folder): pr_ko_red(str("project_name value").ljust(RESULT_MSG_LENGTH)) raise ScriptError(error_msg + "Project folder " + msfs_project.project_folder + " not found. Please check the project_name value") pr_ok_green(str("project_name value").ljust(RESULT_MSG_LENGTH)) # check if the msfs_project file is reachable if not os.path.isfile(msfs_project.project_definition_xml_path): pr_ko_red(str("project_file_name value").ljust(RESULT_MSG_LENGTH)) raise ScriptError( error_msg + "Project file (" + msfs_project.project_definition_xml_path + ") not found. Please check the project_file_name value") pr_ok_green(str("project_file_name value").ljust(RESULT_MSG_LENGTH)) # check if the fspackagetool.exe file is reachable if not os.path.isfile(settings.msfs_build_exe_path): pr_ko_orange(str("msfs_build_exe_path value").ljust(RESULT_MSG_LENGTH)) settings.build_package_enabled = False isolated_print( CORANGE + warning_msg + settings.msfs_build_exe_path + " bin file not found. Automatic package building is disabled" + CEND + EOL) else: pr_ok_green(str("msfs_build_exe_path value").ljust(RESULT_MSG_LENGTH)) # check if the package definitions folder exists if not os.path.isdir(msfs_project.package_definitions_folder): pr_ko_red( str("package_definitions_folder value").ljust(RESULT_MSG_LENGTH)) raise ScriptError( error_msg + "The folder containing the package definitions of the msfs_project (" + msfs_project.package_definitions_folder + ") was not found. Please check the package_definitions_folder value" ) pr_ok_green( str("package_definitions_folder value").ljust(RESULT_MSG_LENGTH)) # check if the package definitions file name is reachable if not os.path.isfile(msfs_project.package_definitions_xml_path): pr_ko_red( str("package_definitions_file_name value").ljust( RESULT_MSG_LENGTH)) raise ScriptError( error_msg + "Package definitions file (" + msfs_project.package_definitions_xml_path + ") not found. Please check the package_definitions_file_name value" ) pr_ok_green( str("package_definitions_file_name value").ljust(RESULT_MSG_LENGTH)) # check if the objects folder exists if not os.path.isdir(msfs_project.model_lib_folder): pr_ko_red(str("objects_folder value").ljust(RESULT_MSG_LENGTH)) raise ScriptError( error_msg + "The folder containing the objects of the msfs_project (" + msfs_project.model_lib_folder + ") was not found. Please check the objects_folder value") pr_ok_green(str("objects_folder value").ljust(RESULT_MSG_LENGTH)) # check if the folder containing the description files of the scene exists if not os.path.isdir(msfs_project.scene_folder): pr_ko_red(str("scene_folder value").ljust(RESULT_MSG_LENGTH)) raise ScriptError( error_msg + "The folder containing the description files of the scene (" + msfs_project.scene_folder + ") was not found. Please check the scene_folder value") pr_ok_green(str("scene_folder value").ljust(RESULT_MSG_LENGTH)) # check if the description file of the scene is reachable if not os.path.isfile(msfs_project.scene_objects_xml_file_path): pr_ko_red(str("scene_file_name value").ljust(RESULT_MSG_LENGTH)) raise ScriptError( error_msg + "Description file of the scene (" + msfs_project.scene_objects_xml_file_path + ") not found. Please check the scene_file_name value") pr_ok_green(str("scene_file_name value").ljust(RESULT_MSG_LENGTH)) # check if the folder containing the textures of the scene exists if not os.path.isdir(msfs_project.texture_folder): pr_ko_red(str("textures_folder value").ljust(RESULT_MSG_LENGTH)) raise ScriptError( error_msg + "The folder containing the textures of the scene (" + msfs_project.texture_folder + ") was not found. Please check the textures_folder value") pr_ok_green(str("textures_folder value").ljust(RESULT_MSG_LENGTH)) if check_optimisation: if not install_python_lib("Pillow"): pr_ko_red(str("Pillow lib installation").ljust(RESULT_MSG_LENGTH)) raise ScriptError( error_msg + "Pillow python lib is not correctly installed. Please check what can prevent this library to be installed correctly" ) pr_ok_green(str("Pillow lib installation").ljust(RESULT_MSG_LENGTH)) # check if Lily texture packer is installed if check_lily_texture_packer and settings.bake_textures_enabled: check_lily_texture_packer_availability(settings, warning_msg=warning_msg) if check_built_package: # check if the folder containing project package exists if not os.path.isdir(msfs_project.built_project_package_folder): pr_ko_red( str("built_project_package_folder value").ljust( RESULT_MSG_LENGTH)) raise ScriptError( error_msg + "The folder containing built package of the project (" + msfs_project.built_project_package_folder + ") was not found. Please check the built_project_package_folder value" ) pr_ok_green( str("built_project_package_folder value").ljust(RESULT_MSG_LENGTH)) if check_compressonator: # check if the compressonatorcli.exe file is reachable if not os.path.isfile(settings.compressonator_exe_path): pr_ko_red( str("compressonator_exe_path value").ljust(RESULT_MSG_LENGTH)) raise ScriptError( error_msg + settings.compressonator_exe_path + "file was not found. Please check the compressonator_exe_path value or install compressonator" ) else: pr_ok_green( str("compressonator_exe_path value").ljust(RESULT_MSG_LENGTH))