def __init__(self): self.item_gui = None self.modify_publish = None self.material_publish = None self.hair_publish = None self.cloth_publish = None environment = Environment() self.user = environment.get_user()
def __init__(self, filepath): ''' creates a Body instance describing the asset or shot stored in the given filepath ''' self._env = Environment() self._filepath = filepath self._pipeline_file = os.path.join(filepath, Body.PIPELINE_FILENAME) if not os.path.exists(self._pipeline_file): raise EnvironmentError('not a valid body: ' + self._pipeline_file + ' does not exist') self._datadict = pipeline_io.readfile(self._pipeline_file)
def go(self): environment = Environment() self.reference_dir = environment.get_reference_geo_dir() files = os.listdir(self.reference_dir) self.item_gui = sfl.SelectFromList( l=files, parent=maya_main_window(), title="Select reference actor(s) to import", multiple_selection=True) self.item_gui.submitted.connect(self.results)
def publish_hda(self): project = Project() environment = Environment() user = environment.get_user() selectedHDA = self.selectedHDA src = self.src body = self.body asset_type = body.get_type() inside = selectedHDA.node("inside") modify = inside.node("modify") material = inside.node("material") hair = inside.node("hair") cloth = inside.node("cloth") if asset_type == AssetType.CHARACTER: geo = inside.node("geo") geo_inside = geo.node("inside") modify = geo_inside.node("modify") material = geo_inside.node("material") departments_to_publish = [] if not modify is None: departments_to_publish.append("modify") if not material is None: departments_to_publish.append("material") if not hair is None: departments_to_publish.append("hair") if not cloth is None: departments_to_publish.append("cloth") if body is None: qd.error("Asset not found in pipe.") return comment = "publish by " + str(user.get_username( )) + " in departments " + str(departments_to_publish) for department in departments_to_publish: inside = self.get_inside_node(asset_type, department, selectedHDA) node = inside.node(department) src = node.type().definition().libraryFilePath() self.publish_src_node_to_department(src, node, department, user, comment) success_message = "Success! Published to " + str( departments_to_publish) self.print_success_message(success_message) return "published to " + str(departments_to_publish)
def results(self, values): selection = str(values[0]) shot = Project().get_body(selection) comp_element = shot.get_element(Department.COMP) self.publishes = comp_element.list_publishes() os.environ["DCC_NUKE_ASSET_NAME"] = selection if not self.publishes: # has not been imported. Import it first. shot_importer = importer.NukeImporter() shot_importer.shot_results([selection]) return else: # get the latest publish username = Environment().get_current_username() try: filepath = comp_element.checkout(username) except: filepath = comp_element.get_last_publish()[3] if os.path.exists(filepath): qd.info("Opening file, please wait.") nuke.scriptOpen(filepath) else: qd.error("Couldn't find the file.")
def shot_comment(self, value): comment = value if comment is None: comment = "publish by " + str( user.get_username()) + " in department " + str(department) chosen_asset = self.chosen_asset project = Project() self.body = project.get_body(chosen_asset) department = Department.LIGHTING element = self.body.get_element(department) #, Element.DEFAULT_NAME) hou.hipFile.save() src = hou.hipFile.name() #Publish user = Environment().get_user() pipeline_io.set_permissions(src) dst = self.publish_element(element, user, src, comment) pipeline_io.set_permissions(dst) message = "Successfully published " + str(self.body.get_name()) + "!" self.print_success_message(message)
def department_results(self, value): chosen_department = value[0] prepare_scene_file(quick_publish=self.quick_publish, body=self.body, department=chosen_department) print("value: ", value) print("dept: ", chosen_department) if chosen_department == Department.RIG: self.export = False # get the element for the model dept and the user, and using that publish selected_element = self.body.get_element(chosen_department) user = Environment().get_user() # get the comment comment = qd.input("Comment for publish") if comment is None: comment = "No comment." post_publish(selected_element, user, self.export, published=True, comment=comment) setPublishEnvVar(self.body.get_name(), chosen_department) qd.info("Asset published successfully.", "Success")
def tool_results(self, value): tool_name = value[0] source = os.path.join(Environment().get_hda_dir(), str(tool_name) + ".hda") hou.hda.installFile(source) obj = hou.node("/obj") try: hda = obj.createNode(tool_name) except: try: out = hou.node("/out") hda = out.createNode(tool_name) except Exception as e: qd.error("Could not find the correct context for tool: " + str(tool_name), details=str(e)) return definition = hou.hdaDefinition(hda.type().category(), hda.type().name(), source) definition.setPreferred(True) hda.allowEditingOfContents() try: hda.setName(tool_name) except: print( str(tool_name) + " cloned but could not be renamed correctly.") layout_object_level_nodes()
def __init__(self): self.asset_gui = None # The order in which these nodes appear is the order they will be created in self.dcc_geo_departments = [Department.MODIFY, Department.MATERIAL] self.dcc_character_departments = [Department.HAIR, Department.CLOTH] self.all_departments = [ Department.MODIFY, Department.MATERIAL, Department.HAIR, Department.CLOTH ] # The source HDA's are currently stored inside the pipe source code. self.hda_path = Environment().get_otl_dir() # We define the template HDAs definitions here, for use in the methods below self.hda_definitions = { Department.MATERIAL: hou.hdaDefinition(hou.sopNodeTypeCategory(), "dcc_material", os.path.join(self.hda_path, "dcc_material.hda")), Department.MODIFY: hou.hdaDefinition(hou.sopNodeTypeCategory(), "dcc_modify", os.path.join(self.hda_path, "dcc_modify.hda")), Department.HAIR: hou.hdaDefinition(hou.objNodeTypeCategory(), "dcc_hair", os.path.join(self.hda_path, "dcc_hair.hda")), Department.CLOTH: hou.hdaDefinition(hou.objNodeTypeCategory(), "dcc_cloth", os.path.join(self.hda_path, "dcc_cloth.hda")) } # By default, we ignore "Asset Controls", so that we can put things in there without them being promoted. # See: inherit_parameters() method self.default_ignored_folders = ["Asset Controls"]
def __init__(self, filepath=None): """ create an element instance describing the element stored in the given filepath. if none given, creates an empty instance. """ self._env = Environment() self.app_ext = None if filepath is not None: self.load_pipeline_file(filepath) cache_dir = self.get_cache_dir() if not os.path.exists(cache_dir): pipeline_io.mkdir(cache_dir) else: self._filepath = None self._pipeline_file = None self._datadict = None
def get_production_scripts(): create_production_init() scripts_dir = Environment().get_tools_dir() scripts_json = os.path.join(scripts_dir, "maya_scripts.json") json_file = file(scripts_json) data = json.loads(json_file.read()) return data["scripts"]
def prepare_scene_file(quick_publish=False, department=None, body=None): scene_prep(quick_publish, body=body, department=department) file_path = Environment().get_user_workspace() file_path = os.path.join(file_path, 'untitled.mb') file_path = pipeline_io.version_file(file_path) mc.file(rename=file_path) print("saving file: ", file_path) mc.file(save=True)
def run(self): self.environment = Environment() self.project = Project() hda_dir = self.environment.get_hda_dir() # GET LIST OF CAMERAS self.cameraList = hou.node('/').recursiveGlob( '*', hou.nodeTypeFilter.ObjCamera) cameraNameList = [camera.name() for camera in self.cameraList] self.item_gui = sfl.SelectFromList( l=cameraNameList, parent=houdini_main_window(), title="Select cameras to snapshot from", multiple_selection=True) self.item_gui.submitted.connect(self.camera_results) print self.item_gui
def prepare_scene_file(): filePath = mc.file(q=True, sceneName=True) if not filePath: filePath = Environment().get_user_workspace() filePath = os.path.join(filePath, 'untitled.mb') filePath = pipeline_io.version_file(filePath) mc.file(rename=filePath) mc.file(save=True)
def non_gui_publish_hda(hda=None, comment='N/A'): if hda is None: print('Error with asset') project = Project() environment = Environment() user = environment.get_current_username() hdaName = hda.type().name() department = None if str(hda) not in Department.ALL: print 'v1 asset' department = Department.ASSEMBLY else: department = str(hda) asset_name = hdaName.replace("_" + department, "") if department not in [ Department.ASSEMBLY, Department.HDA ] else hdaName.replace("_main", "") body = project.get_body(asset_name) if body is None: qd.error('No asset in pipe') return #TODO: publish tools if body.is_tool(): print(asset_name + ' is tool') return department = Department.HDA hda_src = hda.type().definition().libraryFilePath() print hda_src element = body.get_element(department, Element.DEFAULT_NAME, force_create=True) try: hda.type().definition().updateFromNode(hda) except hou.OperationFailed, e: qd.error('There was a problem publishing the HDA to the pipeline.\n', details=str(e)) return
def publish_content_hda(self, node): node_name = node.type().name() index = node_name.rfind('_') asset_name = node_name[:index] department = node_name[index + 1:] self.body = Project().get_body(asset_name) src = node.type().definition().libraryFilePath() user = Environment().get_user() comment = "publish by " + str( user.get_username()) + " in department " + str(department) self.publish_src_node_to_department(src, node, department, user, comment) success_message = "Success! Published " + asset_name + " to " + str( department) self.print_success_message(success_message)
def import_template(self): self.templates_dir = Environment().get_templates_dir() files = os.listdir(self.templates_dir) self.item_gui = sfl.SelectFromList( l=files, parent=utils.get_main_window(), title="Select template(s) to import", multiple_selection=True) self.item_gui.submitted.connect(self.template_results)
def shot_results(self, value): chosen_asset = value[0] project = Project() self.body = project.get_body(chosen_asset) department = Department.LIGHTING element = self.body.get_element(department) #, Element.DEFAULT_NAME) hou.hipFile.save() src = hou.hipFile.name() #Publish user = Environment().get_user() comment = "publish by " + str( user.get_username()) + " in department " + str(department) dst = self.publish_element(element, user, src, comment) message = "Successfully published " + str(self.body.get_name()) + "!" self.print_success_message(message)
def commit_conversions(self): # Find all boxes that have nodes that were made by the conversion script boxes = [] for item in hou.selectedItems(): if not isinstance(item, hou.NetworkBox): continue # If the box doesn't have two nodes in it, it's definitely not ours nodes = item.nodes() if len(nodes) != 2: continue # If neither is named _new and/or neither is named _old, it's not one of ours if not "_new" in nodes[0].name() and not "_new" in nodes[1].name(): continue if not "_old" in nodes[0].name() and not "_old" in nodes[1].name(): continue # If the assets are not named the same, it's not one of ours print nodes[0].name()[:-4] print nodes[1].name()[:-4] if nodes[0].name()[:-4] != nodes[1].name()[:-4]: continue # If it passed the tests, add it to the list of network boxes we can work with boxes.append(item) print boxes # Don't go on unless there's a valid network box if len(boxes) < 1: qd.error( "There aren't any network boxes created by the conversion script." ) return for box in boxes: old_node = next( (node for node in box.nodes() if "_old" in node.name()), None) new_node = next( (node for node in box.nodes() if "_new" in node.name()), None) old_hda = old_node.type().definition() old_hda.setIcon(Environment().get_project_dir() + '/pipe/tools/_resources/1.png') publish.non_gui_publish_go(old_node, "Converted to V2") for child in new_node.allSubChildren(): if "_material" in child.type().name( ) or "_modify" in child.type().name(): publish.non_gui_publish_go(child, "Converted from V1")
def results(self, values): shot_name = str(values[0]) shot = Project().get_body(shot_name) comp_element = shot.get_element(Department.COMP) user_workspace = Environment().get_user_workspace() temp_filepath = os.path.join(user_workspace, shot_name + ".nk") # filepath = nuke.toNode("root").name() #grab name of file they're working on nuke.scriptSave(temp_filepath) print("filepath: ", temp_filepath) user = Environment().get_current_username() comment = qd.input("Comment for publish") if comment is None: comment = "Publish by " + str(user) + " in comp." comp_element.publish(user, temp_filepath, comment) os.environ["DCC_NUKE_ASSET_NAME"] = shot_name qd.info(shot_name + " published successfully.")
def create_asset_xml(): project = Project() asset_list = project.list_props_and_actors() filename = os.path.join(Environment().get_project_dir(), "production/props_and_actors.xml") open(filename, "w").close() # wipe the file f = open(filename, "a") # open the file for appending write_to_file(f, filename, "<channel>\n") for asset in asset_list: text = "\t<item>" + str(asset) + "</item>\n" write_to_file(f, filename, text) write_to_file(f, filename, "</channel>\n") f.close()
class SnapshotTool: def __init__(self): pass def run(self): self.environment = Environment() self.project = Project() hda_dir = self.environment.get_hda_dir() # GET LIST OF CAMERAS self.cameraList = hou.node('/').recursiveGlob( '*', hou.nodeTypeFilter.ObjCamera) cameraNameList = [camera.name() for camera in self.cameraList] self.item_gui = sfl.SelectFromList( l=cameraNameList, parent=houdini_main_window(), title="Select cameras to snapshot from", multiple_selection=True) self.item_gui.submitted.connect(self.camera_results) print self.item_gui def camera_results(self, value): print(str(value)) cameras = [cam for cam in self.cameraList if cam.name() in value] cur_desktop = hou.ui.curDesktop() desktop = cur_desktop.name() panetab = cur_desktop.paneTabOfType(hou.paneTabType.SceneViewer) persp = panetab.curViewport().name() for cam in cameras: panetab.curViewport().setCamera(cam) default_filename = cam.name() + '_screenshot.jpg' persp = panetab.curViewport().name() filename = hou.ui.selectFile( start_directory=Project().get_submission_location(), title='Select Screenshot File', default_value=default_filename, file_type=hou.fileType.Image) if filename is not None: frame = hou.frame() hou.hscript("viewwrite -f %d %d %s '%s'" % (frame, frame, (desktop + "." + panetab.name() + ".world." + persp), filename))
def results(self, value): type = value[0] name = self.name # determine if asset was created or not. created = True if name is None or type is None: created = False if created: scene_file, new_file = get_scene_file() print("scene file, new file: ", scene_file, new_file) check_unsaved_changes() project = Project() body = project.create_asset(name, asset_type=type) if body == None: # print a message about failure/duplicate qd.error("Asset with name " + str(name) + " already exists in pipeline.") else: prepare_scene_file(body=body) department = "model" asset_list = body.list_elements(department) selected_element = body.get_element(department) user = Environment().get_user() print("name :", str(name)) print("department: ", department) setPublishEnvVar(name, department) post_publish(selected_element, user, self.export, published=True, comment="First publish!") qd.info("Asset created successfully!", "Success") else: qd.error("Asset creation failed.")
def results(self, value): type = value[0] name = self.name # determine if asset was created or not. created = True if name is None or type is None: created = False if created: project = Project() body = project.create_asset(name, asset_type=type) if body == None: # print a message about failure/duplicate qd.error("Asset with name " + str(name) + " already exists in pipeline.") else: prepare_scene_file() # show the gui, get the element. To list elements, get the body and get the department department = "model" # hard-coding model for now since this is Maya asset_list = body.list_elements(department) # get the element for the model dept and the user, and using that publish selected_element = body.get_element("model") user = Environment().get_user() post_publish( selected_element, user, published=True, comment="First commit." ) # FIXME: WE NEED TO FIGURE OUT TO WHICH DEPARTMENT(S) WE ACTUALLY NEED TO PUBLISH TO qd.info("Asset created successfully!", "Success") else: qd.error("Asset creation failed.")
def create_from_current(self): script_name = qd.input("Enter a name for this template: ") if not script_name or script_name == u'': return templates_dir = Environment().get_templates_dir() temp_filepath = os.path.join(templates_dir, script_name + ".nk") basename = os.path.basename(temp_filepath) templates_in_dir = os.listdir(templates_dir) print("templates: ", templates_in_dir) if basename in templates_in_dir: overwrite = qd.yes_or_no( str(script_name) + " already exists. Overwrite it?") if overwrite: nuke.scriptSave(temp_filepath) qd.info("Template created successfully!") else: nuke.scriptSave(temp_filepath) qd.info("Template created successfully!") print("filepath: ", temp_filepath)
def __init__(self, parent, dept_list=Department.ALL): super(CheckoutWindow, self).__init__() self.parent = parent self.project = Project() self.environment = Environment() self.initUI(dept_list)
class CheckoutWindow(QtWidgets.QWidget): finished = QtCore.Signal() def __init__(self, parent, dept_list=Department.ALL): super(CheckoutWindow, self).__init__() self.parent = parent self.project = Project() self.environment = Environment() self.initUI(dept_list) def initUI(self, dept_list): #define gui elements self.resize(WINDOW_WIDTH,WINDOW_HEIGHT) self.setWindowTitle('Checkout') self.dept_tabs = QtWidgets.QTabWidget() self.dept_list = dept_list self.result = None #create checkbox to show only published assets self.show_published = QtWidgets.QCheckBox("Display only assets or shots with previous publishes") self.show_published.setCheckState(QtCore.Qt.Unchecked) self.show_published.stateChanged.connect(self.changeBodyCheckoutVisibility) #create Tabs self.createTabs() #create buttons self.checkout_button = QtWidgets.QPushButton('Checkout') self.checkout_button.clicked.connect(self.checkout) self.cancel_button = QtWidgets.QPushButton('Cancel') self.cancel_button.clicked.connect(self.close) #create button layout button_layout = QtWidgets.QHBoxLayout() button_layout.addWidget(self.checkout_button) button_layout.addWidget(self.cancel_button) self.img = QtWidgets.QLabel() banner_path = os.path.join(os.environ['MEDIA_PROJECT_DIR'], 'pipe', 'am', 'gui', '_resources', 'film-banner.jpg') pixmap = QtGui.QPixmap(banner_path) scaled = pixmap.scaledToWidth(self.size().width()) self.img.setPixmap(scaled) #create main layout main_layout = QtWidgets.QVBoxLayout() self.setLayout(main_layout) main_layout.addWidget(self.img) main_layout.setSpacing(5) # main_layout.setMargin(6) main_layout.addWidget(self.dept_tabs) main_layout.addWidget(self.show_published) main_layout.addLayout(button_layout) self.show() #Recursivly goes through the asset's file name def recurseTree(self, treeItem, array, asset): #This is for setting bottom level text attributes if len(array) == 0: treeItem.setText(1,asset) treeItem.setTextColor(0,"#3c83f9") font = QtGui.QFont() font.setPointSize(12) font.setBold(False) treeItem.setFont(0,font) return else: #This is for setting parent level text attributes and settin up the structure item = QtWidgets.QTreeWidgetItem(array[0]) item.setText(0,array[0]) item.setText(1,"This is not a file") item.setTextColor(0,"#d0d0d0") font = QtGui.QFont() font.setPointSize(11) font.setBold(True) item.setFont(0,font) skip = False # this is to check if the child already exists for i in range(0,treeItem.childCount()): if treeItem.child(i).text(0) == item.text(0): item = treeItem.child(i) skip = True if skip == False: # Executes if the child doesnt already exist treeItem.addChild(item) newArray = array[1:] self.recurseTree(item, newArray,asset) return def createTabs(self): #remember the current index so that we can restore it when we create the tabs currIndex = self.dept_tabs.currentIndex() #clear out the old tabs self.dept_tabs.clear() #create tabs for dept in self.dept_list: tab = DepartmentTab(self) self.dept_tabs.addTab(tab, dept) tab_layout = QtWidgets.QHBoxLayout() element_list = QtWidgets.QTreeWidget() element_list.setColumnCount(1) commentBox = QtWidgets.QTextEdit() commentBox.setReadOnly(False) tab.commentBox = commentBox if dept in Department.ASSET_DEPTS: for asset in self.project.list_assets(): #print(asset) if not self.show_published.isChecked() or self.hasPreviousPublish(asset, dept): asset_array = asset.split("_") firstelement = element_list.findItems(asset_array[0], 0, 0) if not firstelement: item = QtWidgets.QTreeWidgetItem(asset_array[0]) item.setText(0,asset_array[0]) item.setTextColor(0,"#d0d0d0") font = QtGui.QFont() font.setPointSize(11) font.setBold(True) item.setFont(0,font) self.recurseTree(item, asset_array[1:],asset) element_list.insertTopLevelItem(0,item) else: self.recurseTree(firstelement[0], asset_array[1:],asset) element_list.currentItemChanged.connect(self.set_current_item) elif dept in Department.SHOT_DEPTS: for shot in self.project.list_shots(): #print(shot) if not self.show_published.isChecked() or self.hasPreviousPublish(shot, dept): shot_array = shot.split("_") firstelement = element_list.findItems(shot_array[0], 0, 0) if not firstelement: item = QtWidgets.QTreeWidgetItem(shot_array[0]) item.setText(0,shot_array[0]) item.setTextColor(0,"#d0d0d0") font = QtGui.QFont() font.setPointSize(11) font.setBold(True) item.setFont(0,font) self.recurseTree(item, shot_array[1:],shot) element_list.insertTopLevelItem(0,item) else: self.recurseTree(firstelement[0], shot_array[1:],shot) element_list.currentItemChanged.connect(self.set_current_item) elif dept in Department.CROWD_DEPTS: for crowdCycle in self.project.list_crowd_cycles(): if not self.show_published.isChecked() or self.hasPreviousPublish(crowdCycle, dept): crowdCycle_array = crowdCycle.split("_") firstelement = element_list.findItems(crowdCycle_array[0], 0, 0) if not firstelement: item = QtWidgets.QTreeWidgetItem(crowdCycle_array[0]) item.setText(0,crowdCycle_array[0]) item.setTextColor(0,"#d0d0d0") font = QtGui.QFont() font.setPointSize(11) font.setBold(True) item.setFont(0,font) self.recurseTree(item, crowdCycle_array[1:],crowdCycle) element_list.insertTopLevelItem(0,item) else: self.recurseTree(firstelement[0], crowdCycle_array[1:],crowdCycle) element_list.currentItemChanged.connect(self.set_current_item) tab_layout.addWidget(element_list) tab_layout.addWidget(commentBox) tab.setLayout(tab_layout) #restore the previous index self.dept_tabs.setCurrentIndex(currIndex) def hasPreviousPublish(self, body, department): asset_obj = self.project.get_body(body) element_obj = asset_obj.get_element(department) last_publish = element_obj.get_last_publish() if last_publish is None: return False return True def changeBodyCheckoutVisibility(self): #recreate tabs the with the new check option self.createTabs() def set_current_item(self, index): current_dept = self.dept_list[self.dept_tabs.currentIndex()] if current_dept in Department.ASSET_DEPTS: self.current_item = str(index.text(1)) elif current_dept in Department.SHOT_DEPTS: self.current_item = str(index.text(1)) elif current_dept in Department.CROWD_DEPTS: self.current_item = str(index.text(1)) #TODO what the heck? Why do we have three identical results from three different conditions? What are we trying to accomplish here? Admitadly the last one I added just following the crowd. asset_obj = self.project.get_body(self.current_item) element_obj = asset_obj.get_element(current_dept) last_publish = element_obj.get_last_publish() last_publish_comment = None if last_publish is not None: last_publish_comment = "Last published {0} by {1} \n \"{2}\"".format(last_publish[1], last_publish[0], last_publish[2]) else: last_publish_comment = "No publishes for this element" currentTab = self.dept_tabs.currentWidget() currentTab.commentBox.setText(last_publish_comment) def checkout(self): """ Checks out the currently selected item :return: """ current_user = self.environment.get_current_username() current_dept = self.dept_list[self.dept_tabs.currentIndex()] asset_obj = self.project.get_body(self.current_item) element_obj = asset_obj.get_element(current_dept,force_create=True) element_path = element_obj.checkout(current_user) if element_path != None: self.result = element_path self.close() def closeEvent(self, event): self.finished.emit() event.accept()
''' Welcome to the Maya shelf script! If you'd like to add a shelf button, you can add it to shelf.json. Follow the example of the other buttons in there. Remember, the icon should be a .svg and the function must be implemented in the specified tool location ''' import pymel.core as pm import os import sys import json from pipe.am.environment import Environment from pipe.tools.mayatools.utils.reload_scripts import * environment = Environment() PROJ = environment.get_project_name() SHELF_DIR = os.environ.get('MAYA_SHELF_DIR') ICON_DIR = os.environ.get('MAYA_ICONS_DIR') ''' Shelf building code. You shouldn't have to edit anything below these lines. If you want to add a new shelf item, follow the instructions at the top of this file. ''' def load_shelf(): delete_shelf() ReloadScripts().go() gShelfTopLevel = pm.mel.eval(
import os,sys,subprocess sys.path.insert(0,'../shelf/scripts') import checkout from pipe.am.project import Project from pipe.am.environment import Environment, Department from pipe.am.element import Element from pipe.am.body import Body, Asset, Shot, AssetType import maya.standalone maya.standalone.initialize(name='python') import maya.cmds as cmds project=Project() environment=Environment() asset_dir=project.get_assets_dir() for i,asset in enumerate(project.list_assets(AssetType.PROP)): asset_obj=project.get_body(asset) element_obj = asset_obj.get_element(Department.MODEL,force_create=True) element_path = element_obj.checkout(environment.get_current_username()) cmds.file(rename='/tmp/lol'+str(i)+'.mb') cmds.file(save=True) checkout.non_gui_open(element_path,asset)
class Element: """ Abstract class describing elements that make up an asset or shot body. """ PIPELINE_FILENAME = ".element" DEFAULT_NAME = "main" DEFAULT_CACHE_DIR = "cache" DEFAULT_RENDER_DIR = "render" NAME = "name" PARENT = "parent" DEPARTMENT = "department" LATEST_VERSION = "latest_version" ASSIGNED_USER = "******" PUBLISHES = "publishes" START_DATE = "start_date" END_DATE = "end_date" APP_EXT = "app_ext" CACHE_EXT = "cache_ext" CACHE_FILEPATH = "cache_filepath" CHECKOUT_USERS = "checkout_users" NOTES = "notes" # @staticmethod def create_new_dict(self, name, department, parent_name): """ populate a dictionary with defaults for all the fields needed to create a new element """ datadict = {} datadict[Element.NAME] = name datadict[Element.PARENT] = parent_name datadict[Element.DEPARTMENT] = department datadict[Element.LATEST_VERSION] = -1 datadict[Element.ASSIGNED_USER] = "" datadict[Element.PUBLISHES] = [] datadict[Element.START_DATE] = "" datadict[Element.END_DATE] = "" datadict[Element.APP_EXT] = self.app_ext datadict[Element.CACHE_EXT] = "" datadict[Element.CACHE_FILEPATH] = "" datadict[Element.CHECKOUT_USERS] = [] datadict[Element.NOTES] = [] return datadict def __init__(self, filepath=None): """ create an element instance describing the element stored in the given filepath. if none given, creates an empty instance. """ self._env = Environment() self.app_ext = None if filepath is not None: self.load_pipeline_file(filepath) cache_dir = self.get_cache_dir() if not os.path.exists(cache_dir): pipeline_io.mkdir(cache_dir) else: self._filepath = None self._pipeline_file = None self._datadict = None def set_app_ext(self, extension): self.app_ext = extension def load_pipeline_file(self, filepath): """ load the pipeline file that describes this element """ self._filepath = filepath self._pipeline_file = os.path.join(filepath, self.PIPELINE_FILENAME) if not os.path.exists(self._pipeline_file): raise EnvironmentError("not a valid element: " + self._pipeline_file + " does not exist") self._datadict = pipeline_io.readfile(self._pipeline_file) def _update_pipeline_file(self): pipeline_io.writefile(self._pipeline_file, self._datadict) def get_name(self): return self._datadict[self.NAME] def get_parent(self): return self._datadict[self.PARENT] def get_dir(self): """ return the directory all data for this element is stored in """ return self._filepath def get_department(self): return self._datadict[self.DEPARTMENT] def get_long_name(self): """ return a string describing a unique name for this asset: {the parent body's name}_{this element's department}_{this element's name} """ return self.get_parent() + "_" + self.get_department( ) + "_" + self.get_name() def get_short_name(self): """ return a string describing a the name for this asset: {the parent body's name}_{this element's name} in this version the department is not included consider it the name for all parts of the asset """ return self.get_parent() + "_" + self.get_name() def get_assigned_user(self): """ returns the username (string) of the assigned user """ return self._datadict[self.ASSIGNED_USER] def get_last_publish(self): """ return a tuple describing the latest publish: (username, timestamp, comment, filepath) """ latest_version = self._datadict[self.LATEST_VERSION] if (latest_version < 0): return None return self._datadict[self.PUBLISHES][latest_version] def list_publishes(self): """ return a list of tuples describing all publishes for this element. each tuple contains the following: (username, timestamp, comment, filepath) """ return self._datadict[self.PUBLISHES] def get_last_note(self): """ return the latest note created for this element as a string """ if (len(self._datadict[self.NOTES]) > 0): return self._datadict[self.NOTES][-1] else: return "" def list_notes(self): """ return a list of all notes that have beeen created for this element """ return self._datadict[self.NOTES] def get_start_date(self): return self._datadict[self.START_DATE] def get_end_date(self): return self._datadict[self.END_DATE] def get_app_ext(self): """ return the extension of the application files for this element (including the period) e.g. the result for an element that uses maya would return ".mb" """ return self._datadict[self.APP_EXT] def get_app_filename(self): """ return the name of the application file for this element. This is just the basename of the file, not the absolute filepath. """ return str(self.get_long_name()) + str(self.get_app_ext()) def get_app_filepath(self): """ return the absolute filepath of the application file for this element """ filename = self.get_app_filename() return os.path.join(self._filepath, filename) def get_version_dir(self, version): """ return the path to the directory of the given version """ return os.path.join(self._filepath, ".v%04d" % version) def get_cache_ext(self): """ return the extension of the cache files for this element (including the period) e.g. the result for an element that uses alembic caches would return ".abc" """ return self._datadict[self.CACHE_EXT] def get_cache_dir(self): # return self._datadict[self.CACHE_FILEPATH] return os.path.join(self._filepath, self.DEFAULT_CACHE_DIR) def get_render_dir(self): render_dir = os.path.join(self._filepath, self.DEFAULT_RENDER_DIR) if not os.path.exists(render_dir): pipeline_io.mkdir(render_dir) return render_dir def list_checkout_users(self): """ return a list of the usernames of all users who have checked out this element """ return self._datadict[self.CHECKOUT_USERS] def update_assigned_user(self, username): """ Update the user assigned to this element. username -- the username (string) of the new user to be assigned """ old_username = self._datadict[self.ASSIGNED_USER] if (old_username == username): return self._datadict[self.ASSIGNED_USER] = username self._update_pipeline_file() if old_username: old_user = self._env.get_user(old_username) if old_user and old_user.has_email(): subject = self.get_long_name() + " reassigned to " + username message = "you are no longer assigned to " + self.get_long_name( ) + "." self._env.sendmail([old_user.get_email()], subject, message) new_user = self._env.get_user(username) if new_user and new_user.has_email(): subject = self.get_long_name() + " assigned" message = "you have been assigned to work on " + self.get_long_name( ) + "." start = self.get_start_date() if start: message = message + " you can start on " + start + "." end = self.get_end_date() if end: message = message + " the end date is " + end + "." note = self.get_last_note() if note: message = message + " note: " + note self._env.sendmail([new_user.get_email()], subject, message) def update_start_date(self, date): """ Update the start date of this element. date -- the new start date """ self._datadict[self.START_DATE] = date self._update_pipeline_file() def update_end_date(self, date): """ Update the end date of this element. date -- the new end date """ self._datadict[self.END_DATE] = date self._update_pipeline_file() def update_checkout_users(self, username): """ add the given username to the checkout_users list, if they aren't already in it. """ if username not in self._datadict[self.CHECKOUT_USERS]: self._datadict[self.CHECKOUT_USERS].append(username) self._update_pipeline_file() def update_notes(self, note): """ add the given note to the note list """ self._datadict[self.NOTES].append(note) self._update_pipeline_file() def get_checkout_dir(self, username): """ return the directory this element would be copied to during checkout for the given username """ return os.path.join(self._env.get_users_dir(), username, self.get_long_name()) def checkout(self, username): """ Copies the element to the given user's work area in a directory with the following name: {the parent body's name}_{this element's department}_{this element's name} Adds username to the list of checkout users. username -- the username (string) of the user performing this action Returns the absolute filepath to the copied file. If this element has no app file, the returned filepath will not exist. """ checkout_dir = self.get_checkout_dir(username) if not os.path.exists(checkout_dir): pipeline_io.mkdir(checkout_dir) datadict = Checkout.create_new_dict(username, self.get_parent(), self.get_department(), self.get_name()) pipeline_io.writefile( os.path.join(checkout_dir, Checkout.PIPELINE_FILENAME), datadict) checkout = Checkout(checkout_dir) app_file = self.get_app_filepath() checkout_file = pipeline_io.version_file( os.path.join(checkout_dir, self.get_app_filename())) if os.path.exists(app_file): shutil.copyfile(app_file, checkout_file) checkout.add_operation(checkout_file) self.update_checkout_users(username) return checkout_file def publish(self, username, src, comment, status=None): """ Replace the applcation file of this element. Create a new version with the new file. Store the result of this operation as a new publish. username -- the username of the user performing this action src -- a string representing the file to be placed in the new version comment -- description of changes made in this publish """ if not os.path.exists(src): raise EnvironmentError("file does not exist: " + src) self._datadict[self.APP_EXT] = os.path.splitext(src)[1] dst = self.get_app_filepath() timestamp = pipeline_io.timestamp() try: shutil.copyfile(src, dst) except Exception, e: print(str(e)) new_version = self._datadict[self.LATEST_VERSION] + 1 self._datadict[self.LATEST_VERSION] = new_version new_version_dir = self.get_version_dir(new_version) pipeline_io.mkdir(new_version_dir) shutil.copy(src, new_version_dir) # get the filepath for this publish and add it to list of publishes old_filepath, new_filename = os.path.split(src) new_publish = os.path.join(new_version_dir, new_filename) pipeline_io.set_permissions(new_publish) self._datadict[self.PUBLISHES].append( (username, timestamp, comment, new_publish)) if status is not None: pass self._update_pipeline_file() dst_addresses = [] for checkout_username in self.list_checkout_users(): try: checkout_user = self._env.get_user(checkout_username) except: print('User ' + str(checkout_username) + ' does not exist.') continue if checkout_user and checkout_user.has_email( ) and checkout_username != username: dst_addresses.append(checkout_user.get_email()) if dst_addresses: subject = self.get_long_name() + " new publish" publish_user = self._env.get_user(username) message = publish_user.get_fullname( ) + " has published a new version of " + self.get_long_name() if comment != "": message += "\ncomment: " + comment self._env.sendmail(dst_addresses, subject, message) return dst