def description_from_id(context, space_type, idname, *, use_operator=True): # Used directly for tooltips. _cls, item, _index = ToolSelectPanelHelper._tool_get_by_id( context, space_type, idname) if item is None: return False # Custom description. description = item.description if description is not None: if callable(description): km = _keymap_from_item(context, item) return description(context, item, km) return tip_(description) # Extract from the operator. if use_operator: operator = item.operator if operator is None: if item.keymap is not None: km = _keymap_from_item(context, item) if km is not None: for kmi in km.keymap_items: if kmi.active: operator = kmi.idname break if operator is not None: import _bpy return tip_(_bpy.ops.get_rna_type(operator).description) return ""
def _draw_framerate_label(*args): # avoids re-creating text string each draw if RENDER_PT_dimensions._frame_rate_args_prev == args: return RENDER_PT_dimensions._frame_rate_ret fps, fps_base, preset_label = args if fps_base == 1.0: fps_rate = round(fps) else: fps_rate = round(fps / fps_base, 2) # TODO: Change the following to iterate over existing presets custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60}) if custom_framerate is True: fps_label_text = tip_("Custom (%.4g fps)") % fps_rate show_framerate = True else: fps_label_text = tip_("%.4g fps") % fps_rate show_framerate = (preset_label == "Custom") RENDER_PT_dimensions._frame_rate_args_prev = args RENDER_PT_dimensions._frame_rate_ret = args = (fps_label_text, show_framerate) return args
def execute(self, context): import os prefs = context.preferences wm = context.window_manager filename = bpy.path.ensure_ext(self.filename, ".sl") path_studiolights = bpy.utils.user_resource('DATAFILES', os.path.join("studiolights", "studio"), create=True) if not path_studiolights: self.report({'ERROR'}, "Failed to get Studio Light path") return {'CANCELLED'} filepath_final = os.path.join(path_studiolights, filename) if os.path.isfile(filepath_final): if not self.ask_overide: self.ask_overide = True return wm.invoke_props_dialog(self, width=600) else: for studio_light in prefs.studio_lights: if studio_light.name == filename: bpy.ops.preferences.studiolight_uninstall(index=studio_light.index) prefs.studio_lights.new(path=filepath_final) # print message msg = ( tip_("StudioLight Installed %r into %r") % (self.filename, str(path_studiolights)) ) print(msg) self.report({'INFO'}, msg) return {'FINISHED'}
def execute(self, context): import os import shutil prefs = context.preferences path_studiolights = os.path.join("studiolights", self.type.lower()) path_studiolights = bpy.utils.user_resource('DATAFILES', path_studiolights, create=True) if not path_studiolights: self.report({'ERROR'}, "Failed to create Studio Light path") return {'CANCELLED'} for e in self.files: shutil.copy(os.path.join(self.directory, e.name), path_studiolights) prefs.studio_lights.load(os.path.join(path_studiolights, e.name), self.type) # print message msg = (tip_("StudioLight Installed %r into %r") % (", ".join(e.name for e in self.files), path_studiolights)) print(msg) self.report({'INFO'}, msg) return {'FINISHED'}
def description(cls, _context, properties): nodetype = properties["type"] bl_rna = bpy.types.Node.bl_rna_get_subclass(nodetype) if bl_rna is not None: return tip_(bl_rna.description) else: return ""
def execute(self, context): import os import shutil prefs = context.preferences path_studiolights = os.path.join("studiolights", self.type.lower()) path_studiolights = bpy.utils.user_resource('DATAFILES', path_studiolights, create=True) if not path_studiolights: self.report({'ERROR'}, "Failed to create Studio Light path") return {'CANCELLED'} for e in self.files: shutil.copy(os.path.join(self.directory, e.name), path_studiolights) prefs.studio_lights.load(os.path.join(path_studiolights, e.name), self.type) # print message msg = ( tip_("StudioLight Installed %r into %r") % (", ".join(e.name for e in self.files), path_studiolights) ) print(msg) self.report({'INFO'}, msg) return {'FINISHED'}
def execute(self, context): import os preferences = context.preferences scene = context.scene view_layer = context.view_layer in_filepath = self.input_filepath out_filepath = self.output_filepath in_filepaths = [] out_filepaths = [] if in_filepath != '': # Denoise a single file if out_filepath == '': out_filepath = in_filepath in_filepaths.append(in_filepath) out_filepaths.append(out_filepath) else: # Denoise animation sequence with expanded frames matching # Blender render output file naming. in_filepath = scene.render.filepath if out_filepath == '': out_filepath = in_filepath # Backup since we will overwrite the scene path temporarily original_filepath = scene.render.filepath for frame in range(scene.frame_start, scene.frame_end + 1): scene.render.filepath = in_filepath filepath = scene.render.frame_path(frame=frame) in_filepaths.append(filepath) if not os.path.isfile(filepath): scene.render.filepath = original_filepath err_msg = tip_("Frame '%s' not found, animation must be complete") % filepath self.report({'ERROR'}, err_msg) return {'CANCELLED'} scene.render.filepath = out_filepath filepath = scene.render.frame_path(frame=frame) out_filepaths.append(filepath) scene.render.filepath = original_filepath # Run denoiser # TODO: support cancel and progress reports. import _cycles try: _cycles.denoise(preferences.as_pointer(), scene.as_pointer(), view_layer.as_pointer(), input=in_filepaths, output=out_filepaths) except Exception as e: self.report({'ERROR'}, str(e)) return {'FINISHED'} self.report({'INFO'}, "Denoising completed") return {'FINISHED'}
def execute(self, _context): import traceback import zipfile import os filepath = self.filepath path_app_templates = bpy.utils.user_resource( 'SCRIPTS', os.path.join("startup", "bl_app_templates_user"), create=True, ) if not path_app_templates: self.report({'ERROR'}, "Failed to get add-ons path") return {'CANCELLED'} if not os.path.isdir(path_app_templates): try: os.makedirs(path_app_templates, exist_ok=True) except: traceback.print_exc() app_templates_old = set(os.listdir(path_app_templates)) # check to see if the file is in compressed format (.zip) if zipfile.is_zipfile(filepath): try: file_to_extract = zipfile.ZipFile(filepath, 'r') except: traceback.print_exc() return {'CANCELLED'} if self.overwrite: for f in file_to_extract.namelist(): module_filesystem_remove(path_app_templates, f) else: for f in file_to_extract.namelist(): path_dest = os.path.join(path_app_templates, os.path.basename(f)) if os.path.exists(path_dest): self.report({'WARNING'}, "File already installed to %r\n" % path_dest) return {'CANCELLED'} try: # extract the file to "bl_app_templates_user" file_to_extract.extractall(path_app_templates) except: traceback.print_exc() return {'CANCELLED'} else: # Only support installing zipfiles self.report({'WARNING'}, "Expected a zip-file %r\n" % filepath) return {'CANCELLED'} app_templates_new = set(os.listdir(path_app_templates)) - app_templates_old # in case a new module path was created to install this addon. bpy.utils.refresh_script_paths() # print message msg = ( tip_("Template Installed (%s) from %r into %r") % (", ".join(sorted(app_templates_new)), filepath, path_app_templates) ) print(msg) self.report({'INFO'}, msg) return {'FINISHED'}
def execute(self, context): import addon_utils import traceback import zipfile import shutil import os pyfile = self.filepath if self.target == 'DEFAULT': # don't use bpy.utils.script_paths("addons") because we may not be able to write to it. path_addons = bpy.utils.user_resource('SCRIPTS', "addons", create=True) else: path_addons = context.preferences.filepaths.script_directory if path_addons: path_addons = os.path.join(path_addons, "addons") if not path_addons: self.report({'ERROR'}, "Failed to get add-ons path") return {'CANCELLED'} if not os.path.isdir(path_addons): try: os.makedirs(path_addons, exist_ok=True) except: traceback.print_exc() # Check if we are installing from a target path, # doing so causes 2+ addons of same name or when the same from/to # location is used, removal of the file! addon_path = "" pyfile_dir = os.path.dirname(pyfile) for addon_path in addon_utils.paths(): if os.path.samefile(pyfile_dir, addon_path): self.report({'ERROR'}, "Source file is in the add-on search path: %r" % addon_path) return {'CANCELLED'} del addon_path del pyfile_dir # done checking for exceptional case addons_old = {mod.__name__ for mod in addon_utils.modules()} # check to see if the file is in compressed format (.zip) if zipfile.is_zipfile(pyfile): try: file_to_extract = zipfile.ZipFile(pyfile, 'r') except: traceback.print_exc() return {'CANCELLED'} if self.overwrite: for f in file_to_extract.namelist(): module_filesystem_remove(path_addons, f) else: for f in file_to_extract.namelist(): path_dest = os.path.join(path_addons, os.path.basename(f)) if os.path.exists(path_dest): self.report({'WARNING'}, "File already installed to %r\n" % path_dest) return {'CANCELLED'} try: # extract the file to "addons" file_to_extract.extractall(path_addons) except: traceback.print_exc() return {'CANCELLED'} else: path_dest = os.path.join(path_addons, os.path.basename(pyfile)) if self.overwrite: module_filesystem_remove(path_addons, os.path.basename(pyfile)) elif os.path.exists(path_dest): self.report({'WARNING'}, "File already installed to %r\n" % path_dest) return {'CANCELLED'} # if not compressed file just copy into the addon path try: shutil.copyfile(pyfile, path_dest) except: traceback.print_exc() return {'CANCELLED'} addons_new = {mod.__name__ for mod in addon_utils.modules()} - addons_old addons_new.discard("modules") # disable any addons we may have enabled previously and removed. # this is unlikely but do just in case. bug [#23978] for new_addon in addons_new: addon_utils.disable(new_addon, default_set=True) # possible the zip contains multiple addons, we could disallow this # but for now just use the first for mod in addon_utils.modules(refresh=False): if mod.__name__ in addons_new: info = addon_utils.module_bl_info(mod) # show the newly installed addon. context.window_manager.addon_filter = 'All' context.window_manager.addon_search = info["name"] break # in case a new module path was created to install this addon. bpy.utils.refresh_script_paths() # print message msg = ( tip_("Modules Installed (%s) from %r into %r") % (", ".join(sorted(addons_new)), pyfile, path_addons) ) print(msg) self.report({'INFO'}, msg) return {'FINISHED'}
def execute(self, context): import os import subprocess from shlex import quote scene = context.scene rd = scene.render prefs = context.preferences fps_final = rd.fps / rd.fps_base preset = prefs.filepaths.animation_player_preset # file_path = bpy.path.abspath(rd.filepath) # UNUSED is_movie = rd.is_movie_format views_format = rd.image_settings.views_format if rd.use_multiview and views_format == 'INDIVIDUAL': view_suffix = rd.views.active.file_suffix else: view_suffix = "" # try and guess a command line if it doesn't exist if preset == 'CUSTOM': player_path = prefs.filepaths.animation_player else: player_path = guess_player_path(preset) if is_movie is False and preset in {'FRAMECYCLER', 'RV', 'MPLAYER'}: # replace the number with '#' file_a = rd.frame_path(frame=0, view=view_suffix) # TODO, make an api call for this frame_tmp = 9 file_b = rd.frame_path(frame=frame_tmp, view=view_suffix) while len(file_a) == len(file_b): frame_tmp = (frame_tmp * 10) + 9 file_b = rd.frame_path(frame=frame_tmp, view=view_suffix) file_b = rd.frame_path(frame=int(frame_tmp / 10), view=view_suffix) file = ("".join( (c if file_b[i] == c else "#") for i, c in enumerate(file_a))) del file_a, file_b, frame_tmp file = bpy.path.abspath(file) # expand '//' else: path_valid = True # works for movies and images file = rd.frame_path(frame=scene.frame_start, preview=scene.use_preview_range, view=view_suffix) file = bpy.path.abspath(file) # expand '//' if not os.path.exists(file): err_msg = tip_("File %r not found") % file self.report({'WARNING'}, err_msg) path_valid = False # one last try for full range if we used preview range if scene.use_preview_range and not path_valid: file = rd.frame_path(frame=scene.frame_start, preview=False, view=view_suffix) file = bpy.path.abspath(file) # expand '//' err_msg = tip_("File %r not found") % file if not os.path.exists(file): self.report({'WARNING'}, err_msg) cmd = [player_path] # extra options, fps controls etc. if scene.use_preview_range: frame_start = scene.frame_preview_start frame_end = scene.frame_preview_end else: frame_start = scene.frame_start frame_end = scene.frame_end if preset == 'INTERNAL': opts = [ "-a", "-f", str(rd.fps), str(rd.fps_base), "-s", str(frame_start), "-e", str(frame_end), "-j", str(scene.frame_step), "-c", str(prefs.system.memory_cache_limit), file, ] cmd.extend(opts) elif preset == 'DJV': opts = [ file, "-speed", str(fps_final), "-in_out", str(frame_start), str(frame_end), "-frame", str(scene.frame_current), "-time_units", "Frames" ] cmd.extend(opts) elif preset == 'FRAMECYCLER': opts = [file, "%d-%d" % (scene.frame_start, scene.frame_end)] cmd.extend(opts) elif preset == 'RV': opts = ["-fps", str(rd.fps), "-play", "[ %s ]" % file] cmd.extend(opts) elif preset == 'MPLAYER': opts = [] if is_movie: opts.append(file) else: opts += [ ("mf://" + file.replace("#", "?")), "-mf", "fps=%.4f" % fps_final, ] opts += ["-loop", "0", "-really-quiet", "-fs"] cmd.extend(opts) else: # 'CUSTOM' cmd.append(file) # launch it print("Executing command:\n ", " ".join(quote(c) for c in cmd)) try: subprocess.Popen(cmd) except Exception as e: err_msg = tip_( "Couldn't run external animation player with command %r\n%s" ) % (cmd, e) self.report( {'ERROR'}, err_msg, ) return {'CANCELLED'} return {'FINISHED'}
def execute(self, context): import subprocess from shlex import quote scene = context.scene rd = scene.render prefs = context.preferences fps_final = rd.fps / rd.fps_base preset = prefs.filepaths.animation_player_preset player_path = prefs.filepaths.animation_player # file_path = bpy.path.abspath(rd.filepath) # UNUSED is_movie = rd.is_movie_format # try and guess a command line if it doesn't exist if player_path == "": player_path = guess_player_path(preset) if is_movie is False and preset in {'FRAMECYCLER', 'RV', 'MPLAYER'}: # replace the number with '#' file_a = rd.frame_path(frame=0) # TODO, make an api call for this frame_tmp = 9 file_b = rd.frame_path(frame=frame_tmp) while len(file_a) == len(file_b): frame_tmp = (frame_tmp * 10) + 9 file_b = rd.frame_path(frame=frame_tmp) file_b = rd.frame_path(frame=int(frame_tmp / 10)) file = ("".join( (c if file_b[i] == c else "#") for i, c in enumerate(file_a))) del file_a, file_b, frame_tmp file = bpy.path.abspath(file) # expand '//' else: path_valid = True # works for movies and images file = rd.frame_path(frame=scene.frame_start, preview=scene.use_preview_range) file = bpy.path.abspath(file) # expand '//' if not os.path.exists(file): err_msg = tip_("File %r not found") % file self.report({'WARNING'}, err_msg) path_valid = False # one last try for full range if we used preview range if scene.use_preview_range and not path_valid: file = rd.frame_path(frame=scene.frame_start, preview=False) file = bpy.path.abspath(file) # expand '//' err_msg = tip_("File %r not found") % file if not os.path.exists(file): self.report({'WARNING'}, err_msg) cmd = [player_path] # extra options, fps controls etc. if scene.use_preview_range: frame_start = scene.frame_preview_start frame_end = scene.frame_preview_end else: frame_start = scene.frame_start frame_end = scene.frame_end if preset == 'INTERNAL': opts = [ "-a", "-f", str(rd.fps), str(rd.fps_base), "-s", str(frame_start), "-e", str(frame_end), "-j", str(scene.frame_step), file, ] cmd.extend(opts) elif preset == 'DJV': opts = [file, "-playback_speed", str(int(fps_final))] cmd.extend(opts) elif preset == 'FRAMECYCLER': opts = [file, f"{scene.frame_start:d}-{scene.frame_end:d}"] cmd.extend(opts) elif preset == 'RV': opts = ["-fps", str(rd.fps), "-play", f"[ {file:s} ]"] cmd.extend(opts) elif preset == 'MPLAYER': opts = [] if is_movie: opts.append(file) else: opts += [("mf://" + file.replace("#", "?")), "-mf", f"fps={fps_final:4f}"] opts += ["-loop", "0", "-really-quiet", "-fs"] cmd.extend(opts) else: # 'CUSTOM' cmd.append(file) # launch it print("Executing command:\n ", " ".join(quote(c) for c in cmd)) # workaround for boost 1.46, can be eventually removed. bug: [#32350] env_copy = os.environ.copy() if preset == 'INTERNAL': env_copy["LC_ALL"] = "C" # end workaround try: subprocess.Popen(cmd, env=env_copy) except Exception as e: err_msg = tip_( "Couldn't run external animation player with command %r\n%s" ) % (cmd, e) self.report( {'ERROR'}, err_msg, ) return {'CANCELLED'} return {'FINISHED'}