def do_baking(self): try: ctl_instance = luna_rig.Control(self.control_field.text()) except Exception: Logger.exception( "Failed to create control instance from {0}".format( self.control_field.text())) raise RuntimeError("Invalid control object") step = self.step_field.value() if self.spaces_combobox.currentText() == self.custom_space_item_text: custom_object = self.custom_space_object_field.text() if not custom_object or not pm.objExists(custom_object): pm.displayError( "Invalid custom space object: {0}".format(custom_object)) return ctl_instance.bake_custom_space( custom_object, time_range=self.range_widget.get_range(), step=step) else: ctl_instance.bake_space( space_name=self.spaces_combobox.currentText(), time_range=self.range_widget.get_range(), step=step)
def write_pickle(path, data): try: with open(path, "wb") as new_file: pickle.dump(data, new_file) return True except IOError: Logger.exception("Failed to saved file: {0}".format(path)) return False
def run_all_tests(): test_suite = unittest.TestLoader().discover( start_dir=directories.TEST_DIR_PATH, pattern="*_test.py") Logger.info("Running {0} tests...".format(test_suite.countTestCases())) test_runner = unittest.TextTestRunner(verbosity=2, resultclass=TestResult) test_runner.failfast = False test_runner.buffer = Config.get(TestVars.buffer_output, default=True) test_runner.run(test_suite)
def __init__(self, components_list, parent=None): super(ControlsList, self).__init__(parent) if not isinstance(components_list, ComponentsListing): Logger.exception("Control list requires {0} instance.".format( ComponentsListing)) raise TypeError self.components_list = components_list # type: ComponentsListing self.create_widgets() self.create_layouts() self.create_connections()
def load_pickle(path): data = None try: with open(path, "rb") as read_file: data = pickle.load(read_file) except IOError: Logger.exception("Failed to open file {0}".format(path)) except Exception: Logger.exception("Failed to load file {0}".format(path)) return data
def update_items(self): self.clear() if self.general_types_enabled: self.addItem("All", luna_rig.Component) self.addItem("AnimComponent", luna_rig.AnimComponent) try: for type_name, meta_type in luna_rig.MetaNode.scene_types( of_type=self.base_type).items(): self.addItem(type_name, meta_type) except Exception: Logger.exception("{0}: Failed to update items".format(self))
def update_spaces_box(self): self.spaces_combobox.clear() try: control_instance = luna_rig.Control(self.control_field.text()) except Exception: Logger.exception("Failed to update {0} spaces".format( self.control_field.text())) return for space_name, space_index in control_instance.spaces: self.spaces_combobox.addItem(space_name, space_index) self.spaces_combobox.addItem(self.custom_space_item_text, None)
def remove_rig(self): selected = self.components_wgt.get_selected_components() if not selected or not isinstance(selected[-1], luna_rig.components.Character): pm.warning("Select Character component to remove rig.") return character = selected[-1] # type: luna_rig.components.Character char_name = character.name time_range = self.range_widget.get_range() character.remove(time_range=time_range) Logger.info("{0} rig successfully removed.".format(char_name))
def get_config_path(cls): """Get path to config file. Copy a default one if one doesn't exist. Returns: str: Path to config file """ if not os.path.isfile(cls.FILE_PATH): shutil.copy2(cls.DEFAULT_CONFIG_PATH, cls.FILE_PATH) Logger.debug("Default config copied to: {0}".format(cls.FILE_PATH)) return cls.FILE_PATH
def set(cls, path, silent=False): if not cls.is_project(path): Logger.error("Not a project: {0}".format(path)) return project_instance = cls(path) project_instance.update_meta() # Set enviroment variables and refresh HUD cls._INSTANCE = project_instance luna.workspace.Asset._INSTANCE = None if not silent: project_instance.__on_creation() return project_instance
def delete_oldest(directory, file_limit): all_files = [ "{0}/{1}".format(directory, child) for child in os.listdir(directory) ] if file_limit and len(all_files) > file_limit: try: oldest_file = min(all_files, key=os.path.getctime) os.remove(oldest_file) return oldest_file except Exception as e: Logger.exception("Failed to delete file {0}".format(oldest_file), exc_info=e) return None
def create(cls): Logger.info("Building marking menu...") cls._delete_old() pm.popupMenu(cls.NAME, mm=1, aob=1, button=2, ctl=1, alt=1, sh=0, p="viewPanes", pmo=0, pmc=cls.__populate) Logger.info("Successfully added marking menu: (CTL+ALT+MMB)")
def get_bake_components(self): components = [] if self.components_wgt.list.selectedItems(): for item in self.components_wgt.list.selectedItems(): if not item.data(1).is_animatable(): Logger.warning( "Non bakeable component selected {0}, skipping...". format(item.data(1))) else: components.append(item.data(1)) else: components = [ item.data(1) for item in pysisdeFn.qlist_all_items(self.components_wgt.list) if item.data(1).is_animatable() ] return components
def delete_temp_files(cls): """Delete the temp files in the cache and clear the cache.""" # If we don't want to keep temp files around for debugging purposes, delete them when # all tests in this TestCase have been run if Config.get(TestVars.delete_dirs, True): for d in cls.dirs_created: if os.path.isdir(d): shutil.rmtree(d) Logger.info("Deleted dir: {0}".format(d)) cls.dirs_created = [] if Config.get(TestVars.delete_files, default=True): for f in cls.files_created: if os.path.exists(f): os.remove(f) Logger.info("Deleted temp file: {0}".format(f)) cls.files_created = []
def load_json(path, string_data=False, object_pairs_hook=None): try: with open(path, "r") as json_file: if string_data: data = json.loads(json_file) # type:str else: data = json.load( json_file, object_pairs_hook=object_pairs_hook) # type:dict except IOError: Logger.exception("{0} is not a valid file path".format(path)) return None except BaseException: Logger.exception("Failed to load file {0}".format(path)) return None return data # type:dict
def create(cls, path, silent=False): if cls.is_project(path): Logger.error("Already a project: {0}".format(path)) return new_project = cls(path) # Create missing meta and tag files fileFn.create_missing_dir(new_project.path) fileFn.create_file(path=new_project.tag_path) creation_date = datetime.now().strftime("%d/%m/%Y %H:%M:%S") new_project.set_data("created", creation_date) # Set enviroment variables and refresh HUD cls._INSTANCE = new_project luna.workspace.Asset._INSTANCE = None if not silent: new_project.__on_creation() return new_project
def _add_external_tools(cls): register = fileFn.load_json(directories.EXTERNAL_TOOLS_REGISTER) found = set(register).intersection(set(pm.moduleInfo(lm=1))) if not found: return tools_menu = MenuUtil.addSubMenu(cls.MAIN_MENU_ID, label="External", tear_off=1, icon="") for tool in found: MenuUtil.addMenuItem( tools_menu, label=register[tool].get("label"), command=register[tool].get("command"), icon=register[tool].get("icon"), use_maya_icons=register[tool].get("useMayaIcon")) Logger.info("Added {0} to luna >> Tools menu".format(tool))
def create(cls): # Build main menu cls._delete_old() Logger.info("Building menu...") pm.menu(cls.MAIN_MENU_ID, label=cls.MAIN_MENU_LABEL, parent=cls.MAIN_WINDOW, tearOff=1) MenuUtil.addMenuItem(cls.MAIN_MENU_ID, divider=1, label="Tools") # Tools MenuUtil.addMenuItem(cls.MAIN_MENU_ID, label="Builder", command=tool_cmds.luna_builder, icon="builder.svg") MenuUtil.addMenuItem( cls.MAIN_MENU_ID, label="Transfer keyframes", command=lambda *args: luna.tools.TransferKeyframesDialog.display()) MenuUtil.addMenuItem( cls.MAIN_MENU_ID, label="Animation baker", command=lambda *args: luna.tools.AnimBakerDialog.display()) MenuUtil.addMenuItem( cls.MAIN_MENU_ID, label="Custom space tool", command=lambda *args: luna.tools.CustomSpaceTool.display()) cls._add_external_tools() # Developer tools cls._add_dev_menu() # Animation tools etc # MenuUtil.addMenuItem(cls.MAIN_MENU_ID, divider=1, label="Animation") # Help and config section MenuUtil.addMenuItem(cls.MAIN_MENU_ID, divider=1) MenuUtil.addMenuItem(cls.MAIN_MENU_ID, label="Configuration", command=tool_cmds.luna_configer, icon="config.svg") cls._add_help_menu()
def addMenuItem(parent=None, label="", command=_null_command, icon="", divider=False, option_box=False, check_box=False, use_maya_icons=False, var_name=None, default_value=False): if icon and not use_maya_icons: icon = fileFn.get_icon_path(icon) if divider: return pm.menuItem(p=parent, dl=label, i=icon, d=divider) elif option_box: return pm.menuItem(p=parent, l=label, i=icon, ob=option_box, c=command) elif check_box: if not var_name: Logger.error( "Menuitem: {0}::{1} is not connected to config!".format( parent, label)) return checkBox_value = Config.get(var_name, default_value) checkBox = pm.menuItem(p=parent, l=label, i=icon, cb=checkBox_value, c=partial(Config.set, var_name)) return checkBox else: return pm.menuItem(p=parent, l=label, i=icon, c=command)
def copy_empty_scene(new_path): """Copy empty scenes from luna's resource directory ot a given path. Scene version is based on current Maya version. Args: new_path (str): Full path to a new scene file location. Raises: IOError: If scene for selected maya version doesn't exist. """ if os.path.isfile(new_path): return source_path = os.path.join(directories.EMPTY_SCENES_PATH, "EmptyScene_Maya{0}.ma".format(pm.about(v=1))) Logger.debug("Copying file {0} to {1}".format(source_path, new_path)) if not os.path.isfile(source_path): raise IOError try: shutil.copy2(source_path, new_path) except Exception: Logger.exception("Failed to copy scene {0}".format(source_path))
def write_json(path, data={}, as_string=False, sort_keys=True): try: with open(path, "w") as json_file: if as_string: json_file.write( json.dumps(data, sort_keys=sort_keys, indent=4, separators=(",", ":"))) else: json.dump(data, json_file, indent=4) except IOError as e: Logger.exception("{0} is not a valid file path".format(path), exc_info=e) return None except BaseException: Logger.exception("Failed to write file {0}".format(path), exc_info=1) return None return path
def create(cls): hud_instance = None Logger.info("Building HUD...") cls.SECTION = Config.get(HudVars.section, default=7) cls.BLOCK = Config.get(HudVars.block, default=5) # Delete old cls.remove() try: hud_instance = pm.headsUpDisplay(cls.HUD_NAME, allowOverlap=True, section=cls.SECTION, block=cls.BLOCK, blockSize=cls.BLOCK_SIZE, labelFontSize=cls.FONT_SIZE, command=cls.get_hud_text, event=cls.UPDATE_EVENT) Logger.info("Successfully created HUD: {0}".format(cls.HUD_NAME)) except RuntimeError: Logger.error( "HUD position ({0}:{1}) is occupied by another HUD. Use configer to select other block/section." .format(cls.SECTION, cls.BLOCK)) return hud_instance
import pymel.core as pm import imp from functools import partial from luna import Logger DEBUG_MODE = Logger.get_level() == 10 try: import luna.tools from luna import Config from luna.static import directories from luna.interface.commands import tool_cmds from luna.interface.commands import help_cmds from luna.utils import devFn from luna.utils import fileFn from luna import TestVars except Exception as e: Logger.exception("Failed to import modules", exc_info=e) if DEBUG_MODE: try: imp.reload(tool_cmds) imp.reload(help_cmds) imp.reload(devFn) imp.reload(luna.tools) Logger.debug("Menu - reloaded command modules") except ImportError: Logger.exception("Failed to reload command modules") def _null_command(*args): pass
def refresh(cls): try: pm.headsUpDisplay(cls.HUD_NAME, r=1) except BaseException: Logger.warning("Failed to refresh {0}".format(cls.HUD_NAME))
def bake_to_rig(self): components = self.get_bake_components() time_range = self.range_widget.get_range() for each in components: each.bake_to_rig(time_range=time_range) Logger.info("Bake to rig complete.")
import os from collections import deque from datetime import datetime from luna import Logger import luna try: import luna.utils.fileFn as fileFn from luna import Config from luna import ProjectVars from luna.interface.hud import LunaHUD except Exception: Logger.exception("Failed to import modules") class Project(object): """ Base project class. Represents rigging project """ TAG_FILE = "luna.proj" _INSTANCE = None # type: Project def __repr__(self): return "{0}({1}): {2}".format(self.name, self.path, self.meta_data) def __init__(self, path): self.path = path # type: str @property def name(self): name = os.path.basename(self.path) # type:str
def is_project(cls, path): search_file = os.path.join(path, cls.TAG_FILE) Logger.debug("isProject check ({0}) - {1}".format( os.path.isfile(search_file), path)) return os.path.isfile(search_file)
def bake_and_detach(self): components = self.get_bake_components() time_range = self.range_widget.get_range() for each in components: each.bake_and_detach(time_range=time_range) Logger.info("Bake and detach complete.")
def open_docs(*args): Logger.debug("TODO: open luna docs")
def reset(cls): """ Reset config to default. Copies default config file with normal config name """ shutil.copy2(directories.DEFAULT_CONFIG_PATH, directories.CONFIG_PATH) Logger.info("luna config reset to default")