def generateGeometry(self, path='',element=None): ''' Function for generating geometry for Maya files. Creates the following output formats: .obj @return: True if all files were created successfully False if some files were not created @post: Missing filenames are printed out to both the Maya terminal as well as presented in a Maya confirm dialog. ''' path = os.path.dirname(mc.file(q=True, sceneName=True)) if not os.path.exists (os.path.join(path, 'cache')): os.makedirs(os.path.join(path, 'cache')) ABCPATH = os.path.join(path, 'cache', 'abcFiles') if os.path.exists(ABCPATH): shutil.rmtree(ABCPATH) filePath = mc.file(q=True, sceneName=True) fileDir = os.path.dirname(filePath) abcFilePath = self.getElementCacheDirectory(fileDir, element) if abcFilePath is None: return False selection = mc.ls(geometry=True, visible=True) selection_long = mc.ls(geometry=True, visible=True, long=True) project = Project() if element is None: checkout = project.get_checkout(path) if checkout is None: qd.error('There was a problem exporting the alembic to the correct location. Checkout the asset again and try one more time.') return None body = project.get_body(checkout.get_body_name()) element = body.get_element(checkout.get_department_name(), checkout.get_element_name()) else: body = project.get_body(element.get_parent()) # We decided to try exporting all the geo into one alembic file instead of many. This is the line that does many # abcs = abcExport(selection_long, ABCPATH) # if body.is_asset(): # if body.get_type() == AssetType.SET: # abcs = self.abcExportLoadedReferences(ABCPATH) # else: # abcs = self.abcExportAll(element.get_long_name(), ABCPATH) # else: abcs = self.abcExportAll(element.get_long_name(), ABCPATH) if not len(self.checkFiles(abcs)) == 0: return False return True
def rollback_element(self, node, department, name): self.node = node self.department = department project = Project() body = project.get_body(name) element = body.get_element(department) self.publishes = element.list_publishes() print("publishes: ", self.publishes) if not self.publishes: qd.error("There have been no publishes for this department. Rollback failed.") return # make the list a list of strings, not tuples self.sanitized_publish_list = [] for publish in self.publishes: path = publish[3] file_ext = path.split('.')[-1] if not file_ext == "hda" and not file_ext =="hdanc": continue label = publish[0] + " " + publish[1] + " " + publish[2] self.sanitized_publish_list.append(label) self.item_gui = sfl.SelectFromList(l=self.sanitized_publish_list, parent=houdini_main_window(), title="Select publish to clone") self.item_gui.submitted.connect(self.publish_selection_results)
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 results(self, value): print("Final value: ", value[0]) filename = value[0] project = Project() body = project.get_body(filename) element = body.get_element("model") filepath = body.get_filepath() self.publishes = element.list_publishes() print("publishes: ", self.publishes) print("path: ", filepath) # make the list a list of strings, not tuples self.sanitized_publish_list = [] for publish in self.publishes: path = publish[3] file_ext = path.split('.')[-1] if not file_ext == "mb": continue label = publish[0] + " " + publish[1] + " " + publish[2] self.sanitized_publish_list.append(label) self.item_gui = sfl.SelectFromList( l=self.sanitized_publish_list, parent=maya_utils.maya_main_window(), title="Select publish to clone") self.item_gui.submitted.connect(self.publish_selection_results)
def confirmWritePropReference(self, body=None): filepath = pm.sceneName() fileDir = os.path.dirname(filepath) project = Project() if not body: checkout = project.get_checkout(fileDir) bodyName = checkout.get_body_name() body = project.get_body(bodyName) if body.is_asset() and body.get_type() == AssetType.PROP: element = body.get_element(Department.MODEL) filepath = os.path.join(project.get_assets_dir(), element.get_cache_dir()) assemblies = pm.ls(assemblies=True) pm.select(pm.listCameras(), replace=True) cameras = pm.selected() pm.select([]) non_cameras = [ assembly for assembly in assemblies if assembly not in cameras ] self.exportPropJSON(filepath, non_cameras[0], isReference=False, name=body.get_name()) print("JSON references written successfully.")
def shot_results(self, value): shot_name = value[0] project = Project() body = project.get_body(shot_name) element = body.get_element("lighting") self.publishes = element.list_publishes() print("publishes: ", self.publishes) if not self.publishes: # has not been imported. Import it first. importer = Importer() importer.import_shot([shot_name]) return # make the list a list of strings, not tuples self.sanitized_publish_list = [] for publish in self.publishes: path = publish[3] file_ext = path.split('.')[-1] if not file_ext == "hip" and not file_ext == "hipnc": continue label = publish[0] + " " + publish[1] + " " + publish[2] self.sanitized_publish_list.append(label) self.item_gui = sfl.SelectFromList(l=self.sanitized_publish_list, parent=houdini_main_window(), title="Select publish to clone") self.item_gui.submitted.connect(self.publish_selection_results)
def asset_results(self, value): chosen_asset = value[0] project = Project() self.frame_range = qd.input("Enter frame range (as numeric input) or leave blank if none:") if self.frame_range is None or self.frame_range == u'': self.frame_range = 1 self.frame_range = str(self.frame_range) if not self.frame_range.isdigit(): qd.error("Invalid frame range input. Setting to 1.") self.body = project.get_body(chosen_asset) self.body.set_frame_range(self.frame_range) department_list = [] asset_type = self.body.get_type() if str(asset_type) == 'prop': department_list = self.body.prop_export_departments() self.department_results(department_list) elif str(asset_type) == 'character': department_list = self.body.char_export_departments() elif str(asset_type) == 'set': department_list = self.body.set_export_departments() elif str(asset_type) == 'shot': department_list = self.body.shot_export_departments() self.item_gui = sfl.SelectFromList(l=department_list, multiple_selection=True, parent=maya_main_window(), title="Select department(s) for this export: ") self.item_gui.submitted.connect(self.department_results)
def export(self, element, selection=None, startFrame=None, endFrame=None): project = Project() bodyName = element.get_parent() body = project.get_body(bodyName) abcFilePath = element.get_cache_dir() self.element = element if startFrame is None: startFrame = pm.playbackOptions(q=True, animationStartTime=True) if endFrame is None: endFrame = pm.playbackOptions(q=True, animationEndTime=True) if body.is_shot(): startFrame -= 1 endFrame = int(endFrame) endFrame += 1 endFrame = str(endFrame) files = self.exportReferences(abcFilePath, tag='DCC_Alembic_Export_Flag', startFrame=startFrame, endFrame=endFrame) if self.cameras: files.extend(self.export_cameras(body, startFrame, endFrame)) elif body.is_asset(): if body.get_type() == AssetType.SET: files = self.exportReferences(abcFilePath) else: files = self.exportAll(abcFilePath, tag='DCC_Alembic_Export_Flag', element=element) elif body.is_crowd_cycle(): files = self.exportAll(abcFilePath, tag='DCC_Alembic_Export_Flag', startFrame=startFrame, endFrame=endFrame, element=element) if not files: #Maybe this is a bad distinction but None is if it was canceled or something and empty is if it went but there weren't any alembics if files is None: return qd.error( 'No alembics were exported. Make sure the top-level group is tagged.' ) return for abcFile in files: os.system('chmod 774 ' + abcFile) exported_asset_names = "" for file in files: asset_file_name = str(file).rpartition('/')[2] exported_asset_names += asset_file_name + '\n' qd.info("Alembics exported successfully: " + '\n' + exported_asset_names) return files
def asset_results(self, value): chosen_asset = value[0] project = Project() self.body = project.get_body(chosen_asset) self.comment = qd.HoudiniInput(parent=houdini_main_window(), title="Any comments?") self.comment.submitted.connect(self.publish_hda)
def auto_export(self, asset_name): project = Project() body = project.get_body(asset_name) element = body.get_element(Department.TEXTURE) cache_dir = element.get_cache_dir() fbx_filepath = os.path.join(cache_dir, element.get_long_name() + '.fbx') print("Fbx filepath: ", fbx_filepath) pm.mel.FBXExport(f=fbx_filepath)
def asset_results(self, asset): self.selected_asset = asset[0] project = Project() self.body = project.get_body(self.selected_asset) parent, instances = self.create_hda(self.selected_asset) layout_object_level_nodes() print("created ", instances, " in ", parent)
def getElementCacheDirectory(self, path, element=None): if element is None: project = Project() checkout = project.get_checkout(path) if checkout is None: qd.error('There was a problem exporting the alembic to the correct location. Checkout the asset again and try one more time.') return None body = project.get_body(checkout.get_body_name()) element = body.get_element(checkout.get_department_name(), checkout.get_element_name()) return element.get_cache_dir()
def asset_results(self, value): print("Selected asset: ", value[0]) filename = value[0] project = Project() self.body = project.get_body(filename) department_paths = self.get_department_paths(self.body) from pipe.tools.houtools.assembler.assembler import Assembler # we put import here to avoid cross import issue #63 FIXME node, created_instances = Assembler().create_hda( filename, body=self.body, department_paths=department_paths) layout_object_level_nodes() return node, created_instances
def asset_results(self, value): chosen_asset = value[0] project = Project() self.body = project.get_body(chosen_asset) start_frame = mc.playbackOptions(q=True, min=True) end_frame = mc.playbackOptions(q=True, max=True) playblast_element = self.body.get_element(Department().RENDER) playblast_dir = playblast_element.get_render_dir() playblast_filename = chosen_asset + "_playblast.mov" path = os.path.join(playblast_dir, playblast_filename) self.simpleBlast(start_frame, end_frame, path) qd.info("Playblast created at " + str(path))
def results(self, value): print("Final value: ", value[0]) filename = value[0] project = Project() body = project.get_body(filename) self.body = body type = body.get_type() element = self.get_element_option(type, body) if self.quick: latest = element.get_last_publish() if not latest: qd.error("There have been no publishes in this department.") return else: selected_scene_file = latest[3] self.open_scene_file(selected_scene_file) return if element is None: qd.warning("Nothing was cloned.") return self.publishes = element.list_publishes() print("publishes: ", self.publishes) if not self.publishes: qd.error( "There have been no publishes in this department. Maybe you meant model?" ) return # make the list a list of strings, not tuples self.sanitized_publish_list = [] for publish in self.publishes: path = publish[3] file_ext = path.split('.')[-1] if not file_ext == "mb": continue label = publish[0] + " " + publish[1] + " " + publish[2] self.sanitized_publish_list.append(label) self.item_gui = sfl.SelectFromList(l=self.sanitized_publish_list, parent=maya_main_window(), title="Select publish to clone") self.item_gui.submitted.connect(self.publish_selection_results)
def asset_results(self, value): chosen_asset = value[0] project = Project() self.body = project.get_body(chosen_asset) asset_type = self.body.get_type() if asset_type == AssetType.ACTOR or asset_type == AssetType.PROP: self.export = True department_list = get_departments_by_type(asset_type) self.item_gui = sfl.SelectFromList( l=department_list, parent=maya_main_window(), title="Select department for this publish") self.item_gui.submitted.connect(self.department_results)
def confirmWriteShotReferences(self, body=None): filePath = pm.sceneName() filDir = os.path.dirname(filePath) proj = Project() if not body: checkout = proj.get_checkout(fileDir) bodyName = checkout.get_body_name() body = proj.get_body(bodyName) if body.is_shot(): print("SHOT OK") element = body.get_element(Department.ANIM) refsFilePath = os.path.join(Project().get_assets_dir(), element.get_cache_dir()) self.export_shot(refsFilePath) else: print("NOT A SHOT") qd.error('No set found in current scene.')
def export(self, element, selection=None, startFrame=None, endFrame=None): project = Project() bodyName = element.get_parent() body = project.get_body(bodyName) abcFilePath = element.get_cache_dir() self.element = element #TODO we don't want to put them into the element cache right away. We want to put them in a seperate place and then copy them over later. if startFrame is None: startFrame = pm.playbackOptions(q=True, animationStartTime=True) if endFrame is None: endFrame = pm.playbackOptions(q=True, animationEndTime=True) if body.is_shot(): startFrame -= 5 endFrame = int(endFrame) endFrame += 5 endFrame = str(endFrame) files = self.exportReferences(abcFilePath, tag='DCC_Alembic_Export_Flag', startFrame=startFrame, endFrame=endFrame) # result = qd.yes_or_no('Are there any crowds that need to be exported?') # if result: # self.exportCrowd(abcFilePath, 'DCC_Crowd_Agent_Flag', tag='DCC_Alembic_Export_Flag', startFrame=startFrame, endFrame=endFrame) elif body.is_asset(): if body.get_type() == AssetType.SET: files = self.exportReferences(abcFilePath) else: files = self.exportAll(abcFilePath, tag='DCC_Alembic_Export_Flag', element=element) elif body.is_crowd_cycle(): files = self.exportAll(abcFilePath, tag='DCC_Alembic_Export_Flag', startFrame=startFrame, endFrame=endFrame, element=element) if not files: #Maybe this is a bad distinction but None is if it was canceled or something and empty is if it went but there weren't any alembics if files is None: return qd.error('No alembics were exported. Make sure the top-level group is tagged.') return for abcFile in files: os.system('chmod 774 ' + abcFile) #TODO install the geometry print 'These are the files that we are returning', files return files
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 get_body_and_export(self, chosen_asset, export_all=False): project = Project() self.body = project.get_body(chosen_asset) try: print("asset type: " + self.body.get_type()) except: qd.error( "Error: Asset does not have a valid type. Was it created properly?" ) type = self.body.get_type() if type == AssetType.PROP or type == AssetType.ACTOR: creases = qd.yes_or_no("Does this asset use creases?") if creases: self.crease = True if type == AssetType.SHOT: export_all = False self.frame_range = qd.input("How many frames are in this shot?") if self.frame_range is None or self.frame_range == u'': self.frame_range = 1 self.frame_range = str(self.frame_range) if not self.frame_range.isdigit(): qd.error("Invalid frame range input. Setting to 1.") else: self.frame_range = 1 self.body.set_frame_range(self.frame_range) asset_type = self.body.get_type() department_list = get_departments_by_type(asset_type, export=True) if export_all: # tag top level nodes nodes = get_top_level_nodes() print("top level: ", nodes) for node in nodes: tag_node_with_flag(node, "DCC_Alembic_Export_Flag") self.department_results(department_list)
def confirmWriteSetReferences(self, body=None): filePath = pm.sceneName() fileDir = os.path.dirname(filePath) proj = Project() if not body: checkout = proj.get_checkout(fileDir) bodyName = checkout.get_body_name() body = proj.get_body(bodyName) if body.is_asset(): if body.get_type() == AssetType.SET: print("SET OK") element = body.get_element(Department.MODEL) refsFilePath = os.path.join(Project().get_assets_dir(), element.get_cache_dir()) self.exportReferences(refsFilePath) qd.info("JSON references written successfully.") else: print("NOT A SET") qd.error('No set found in current scene.')
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 writeXML(assetName='None', context='OBJ'): project = Project() asset_body = project.get_body(assetName) icon = os.path.join('$JOB', 'pipe', 'tools', '_resources', '2.png') if not asset_body.is_asset(): print('error me this') raise Exception('Failed to generate XML for: ' + assetName + ' \n Object is not an Asset') global baseXML xml = Template(baseXML).substitute(NAME=assetName, LABEL=assetName.replace('_', ' ').title(), ICON=icon, CONTEXT=context) try: path = os.path.join(project.get_assets_dir(), assetName) path = os.path.join(path, assetName + '.shelf') file = open(path, 'w') file.write(xml) file.close() if not os.path.exists(project.get_tabs_dir()): os.makedirs(project.get_tabs_dir()) sym = os.path.join(project.get_tabs_dir(), assetName + '.shelf') if os.path.exists(sym): os.unlink(sym) os.link(path, sym) except Exception as e: print e raise Exception('Failed to generate XML for: ' + assetName)
def set_results(self, value): set_name = value[0] project = Project() self.body = project.get_body(set_name) obj = hou.node("/obj") set = obj.node(set_name) if set is None: qd.error( "No set found with that name. Please check naming and try again." ) return print("set: ", set) inside = set.node("inside") children = inside.children() set_file = os.path.join(Project().get_assets_dir(), set_name, "model", "main", "cache", "whole_set.json") set_data = [] try: with open(set_file) as f: set_data = json.load(f) except Exception as error: qd.error("No valid JSON file for " + str(set_name)) return items_in_set = [] for item in set_data: item_name = item['asset_name'] item_version = item['version_number'] items_in_set.append(item_name) # TODO: for each child, make sure that it exists in whole_set.json, or add it if it doesn't, or remove it if it does not child_names = [] for child in children: child_path = child.path() name = child_path.split('/')[-1].lower() child_names.append(name) for item in set_data: if str(item['asset_name']) not in child_names: set_data.remove(item) for child in children: print("child: ", child) inside = child.node("inside") out = inside.node("OUT") set_transform = inside.node("set_dressing_transform") child_path = child.path() name = child_path.split('/')[-1].lower() child_body = project.get_body(name) if child_body is None: qd.warning( str(name) + " not found in pipe. Please check that node is named correctly." ) continue # get transform parms: t is translate, r rotate and s scale (with associated x,y,z vals) tx, ty, tz = self.get_transform(set_transform, "tx", "ty", "tz") rx, ry, rz = self.get_transform(set_transform, "rx", "ry", "rz") sx, sy, sz = self.get_transform(set_transform, "sx", "sy", "sz") latest_file, latest_version = self.body.get_latest_json_version( name) if latest_version == int(9): new_version = 0 else: new_version = int(latest_version) + 1 prop_file = os.path.join( Project().get_assets_dir(), set_name, "model", "main", "cache", str(name) + "_" + str(latest_version) + ".json") if name in items_in_set: print("set contains asset: " + str(name)) try: with open(prop_file) as f: prop_data = json.load(f) except Exception as error: qd.warning("No valid JSON file for " + str(name) + ". Skipping changes made to this asset.") continue for set_item in set_data: if str(set_item['asset_name']) == str(name): set_item['version_number'] = new_version break else: print(str(name) + " not found in set file.") path = self.get_prim_path(out) prop_data = { "asset_name": name, "version_number": 0, "path": str(path), "a": [0, 0, 0], "b": [0, 0, 0], "c": [0, 0, 0] } set_data.append({"asset_name": str(name), "version_number": 0}) new_version = 0 new_prop_file = os.path.join( Project().get_assets_dir(), set_name, "model", "main", "cache", str(name) + "_" + str(new_version) + ".json") # get a b and c from prop_data file. Each is an array of size 3, representing x,y,z coords a = prop_data['a'] b = prop_data['b'] c = prop_data['c'] self.update_points_by_geo(out, a, b, c) # put the updated coords back into prop_data prop_data['a'] = a prop_data['b'] = b prop_data['c'] = c # TODO: add a commit and a publish for this set print("prop data (updated): ", prop_data) updated_prop_data = json.dumps(prop_data) outfile = open(new_prop_file, "w") outfile.write(updated_prop_data) outfile.close() print("prop file updated for " + str(name)) self.clear_transform(set_transform) self.update_version_number(child, new_version) import_node = child.node("import") read_from_json = import_node.node("read_from_json") read_from_json.parm("reload").pressButton() outfile = open(set_file, "w") print("set data: ", set_data) updated_set_data = json.dumps(set_data) outfile.write(updated_set_data) outfile.close() qd.info("Set " + str(set_name) + " published successfully!")
def set_results(self, value): set_name = value[0] project = Project() self.body = project.get_body(set_name) obj = hou.node("/obj") set = obj.node(set_name) if set is None: qd.error( "No set found with that name. Please check naming and try again." ) return #migrate transforms for all the children to set_dressing_transform self.update_set_dressing_transform(set) #create children list (list of houdini objects) print("set: ", set) inside = set.node("inside") children = inside.children() set_file = os.path.join(Project().get_assets_dir(), set_name, "model", "main", "cache", "whole_set.json") ''' The idea here is to get the set data from whole_set.json, get the set data from Houdini, and then compare the two. Here are the possible scenarios: 1. There are items in the JSON file that aren't in the Houdini Set -remove the item from the Json file -remove the item's json files 2. There are items in the Houdini Set that aren't in the JSON file -Add those to the JSON file ''' items_to_delete = [] set_data = [] items_in_set = [] items_to_delete, set_data, items_in_set = self.get_set_comparable_lists( children, set_file) self.delete_asset_json(items_to_delete, set_name) # TODO: To allow adding multiple copies of the same prop to a set in houdini, we'll want to add as many copies to the whole_set.json file # for child_name in child_names: # child = inside.node(child_name) # get the child node # inside = child.node("inside") # modify = inside.node("modify") # modify_name = modify.type().name() # name = modify_name.split("_")[0].lower() # # if name not in items_in_set: # set_data.append print("starting to work on children\n") for child in children: #find if it is scaled (set to big scale) and initialize variables---------------------------------------------------------- #inside #import_node #out #set_transform #current_version #name isScaled = False print("child: " + str(child)) print("current set_data: " + str(set_data)) if child.type().name() == "dcc_geo": inside = child.node("inside") import_node = child.node("import") if child.parm("Scale_Object").evalAsInt() == 1: child.parm("Scale_Object").set(0) isScaled = True else: inside = child.node("inside") geo = inside.node("geo") inside = geo.node("inside") import_node = geo.node("import") out = inside.node("OUT") set_transform = inside.node("set_dressing_transform") current_version = child.parm("version_number").evalAsInt() #need a asset number or letter (I honestly just need to name it something and have that reflected in houdini) #import_number = child.parm("import_number").evalAsInt name = child.parm("asset_name").evalAsString() #--------------------------------------------------------------------------------------------------------------------------- child_body = project.get_body(name) if child_body is None: qd.warning( str(name) + " not found in pipe. Please check that node is named correctly." ) continue cache_dir = os.path.join(Project().get_assets_dir(), set_name, "model", "main", "cache") print("filepath: ", cache_dir) latest_version, version_string = self.body.version_prop_json( name, cache_dir) print('latest version: ', latest_version) new_version = latest_version latest_version -= 1 prop_file = os.path.join( cache_dir, str(name) + "_" + str(current_version) + ".json") print("prop file: ", prop_file) #will have to change items_in_set to be checked if name in items_in_set: print("set contains asset: " + str(name)) try: with open(prop_file) as f: prop_data = json.load(f) except Exception as error: print("No valid JSON file for " + str(name) + ". Skipping changes made to this asset.") continue for set_item in set_data: if str(set_item['asset_name']) == str(name): if set_item['version_number'] <= current_version: print("updating ", set_item, " with version ", new_version) set_item['version_number'] = new_version break else: # create blank prop data and add it to the set print(str(name) + " not found in set file.") path = self.get_prim_path(out) prop_data = { "asset_name": name, "version_number": 0, "path": str(path), "a": [0, 0, 0], "b": [0, 0, 0], "c": [0, 0, 0] } set_data.append({"asset_name": str(name), "version_number": 0}) print("appended set_data: " + str(set_data)) new_version = 0 items_in_set.append(name) print("current set_data: " + str(set_data)) new_prop_file = os.path.join( Project().get_assets_dir(), set_name, "model", "main", "cache", str(name) + "_" + str(new_version) + ".json") # get a b and c from prop_data file. Each is an array of size 3, representing x,y,z coords a = prop_data['a'] b = prop_data['b'] c = prop_data['c'] self.update_points_by_geo(out, prop_data['path'], a, b, c) # put the updated coords back into prop_data prop_data['a'] = a prop_data['b'] = b prop_data['c'] = c prop_data['version_number'] = new_version # TODO: add a commit and a publish for this set print("prop data (updated): ", prop_data) updated_prop_data = json.dumps(prop_data) outfile = open(new_prop_file, "w") outfile.write(updated_prop_data) outfile.close() print("prop file updated for " + str(name)) print("") self.clear_transform(set_transform) self.set_space(child, set_name, name, new_version) if isScaled: child.parm("Scale_Object").set(1) #reloading the new data that was written try: read_from_json = import_node.node("read_from_json") read_from_json.parm("reload").pressButton() except: print("no nodes are in the set, cannot read from JSON") #rewriting the whole_set json file outfile = open(set_file, "w") print("set data: ", set_data) updated_set_data = json.dumps(set_data) outfile.write(updated_set_data) outfile.close() qd.info("Set " + str(set_name) + " published successfully!")
def set_results(self, value): set_name = value[0] project = Project() self.body = project.get_body(set_name) obj = hou.node("/obj") set = obj.node(set_name) if set is None: qd.error( "No set found with that name. Please check naming and try again." ) return print("set: ", set) inside = set.node("inside") children = inside.children() set_file = os.path.join(Project().get_assets_dir(), set_name, "model", "main", "cache", "whole_set.json") set_data = [] try: with open(set_file) as f: set_data = json.load(f) except Exception as error: qd.error("No valid JSON file for " + str(set_name)) return items_in_set = [] for item in set_data: item_name = item['asset_name'] item_version = item['version_number'] items_in_set.append(item_name) child_names = [] for child in children: child_path = child.path() first_char_to_lower = lambda s: s[:1].lower() + s[1:] if s else '' name = child_path.split('/')[-1] name = first_char_to_lower(name) child_names.append(name) print("child names; ", child_names) for item in set_data: if str(item['asset_name']) not in child_names: set_data.remove(item) # TODO: To allow adding multiple copies of the same prop to a set in houdini, we'll want to add as many copies to the whole_set.json file # for child_name in child_names: # child = inside.node(child_name) # get the child node # inside = child.node("inside") # modify = inside.node("modify") # modify_name = modify.type().name() # name = modify_name.split("_")[0].lower() # # if name not in items_in_set: # set_data.append for child in children: if child.type().name() == "dcc_geo": inside = child.node("inside") import_node = child.node("import") else: inside = child.node("inside") geo = inside.node("geo") inside = geo.node("inside") import_node = geo.node("import") out = inside.node("OUT") set_transform = inside.node("set_dressing_transform") current_version = child.parm("version_number").evalAsInt() name = child.parm("asset_name").evalAsString() child_body = project.get_body(name) if child_body is None: qd.warning( str(name) + " not found in pipe. Please check that node is named correctly." ) continue # get transform parms: t is translate, r rotate and s scale (with associated x,y,z vals) tx, ty, tz = self.get_transform(set_transform, "tx", "ty", "tz") rx, ry, rz = self.get_transform(set_transform, "rx", "ry", "rz") sx, sy, sz = self.get_transform(set_transform, "sx", "sy", "sz") cache_dir = os.path.join(Project().get_assets_dir(), set_name, "model", "main", "cache") print("filepath: ", cache_dir) latest_version, version_string = self.body.version_prop_json( name, cache_dir) print('latest version: ', latest_version) new_version = latest_version latest_version -= 1 prop_file = os.path.join( cache_dir, str(name) + "_" + str(current_version) + ".json") print("prop file: ", prop_file) if name in items_in_set: print("set contains asset: " + str(name)) try: with open(prop_file) as f: prop_data = json.load(f) except Exception as error: qd.warning("No valid JSON file for " + str(name) + ". Skipping changes made to this asset.") continue for set_item in set_data: if str(set_item['asset_name']) == str(name): if set_item['version_number'] <= current_version: print("updating ", set_item, " with version ", new_version) set_item['version_number'] = new_version break else: print(str(name) + " not found in set file.") path = self.get_prim_path(out) prop_data = { "asset_name": name, "version_number": 0, "path": str(path), "a": [0, 0, 0], "b": [0, 0, 0], "c": [0, 0, 0] } set_data.append({"asset_name": str(name), "version_number": 0}) new_version = 0 items_in_set.append(name) new_prop_file = os.path.join( Project().get_assets_dir(), set_name, "model", "main", "cache", str(name) + "_" + str(new_version) + ".json") # get a b and c from prop_data file. Each is an array of size 3, representing x,y,z coords a = prop_data['a'] b = prop_data['b'] c = prop_data['c'] self.update_points_by_geo(out, a, b, c) # put the updated coords back into prop_data prop_data['a'] = a prop_data['b'] = b prop_data['c'] = c prop_data['version_number'] = new_version # TODO: add a commit and a publish for this set print("prop data (updated): ", prop_data) updated_prop_data = json.dumps(prop_data) outfile = open(new_prop_file, "w") outfile.write(updated_prop_data) outfile.close() print("prop file updated for " + str(name)) self.clear_transform(set_transform) self.set_space(child, set_name, name, new_version) read_from_json = import_node.node("read_from_json") read_from_json.parm("reload").pressButton() outfile = open(set_file, "w") print("set data: ", set_data) updated_set_data = json.dumps(set_data) outfile.write(updated_set_data) outfile.close() qd.info("Set " + str(set_name) + " published successfully!")
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) print 'Done'
def non_gui_publish(self, asset_name, department): project = Project() self.body = project.get_body(asset_name) self.department_results([department])
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()
class ElementBrowser(QtWidgets.QWidget): ASSETS = "Assets" #SHOTS = "Shots" BODY_DATA_COLUMN = 1 BODY_DESCRIPTION_COLUMN = 7 @staticmethod def dark_palette(): palette = QtGui.QPalette() base_color = QtGui.QColor(39,39,39) alt_color = QtGui.QColor(30,30,30) text_color = QtGui.QColor(192,192,192) highlight_color = QtGui.QColor(57,86,115) highlight_text_color = QtCore.Qt.white disabled_alt_color = QtGui.QColor(49,49,49) disabled_base_color = QtGui.QColor(40,40,40) disabled_text_color = QtGui.QColor(100,100,100) palette.setColor(QtGui.QPalette.Window, base_color) palette.setColor(QtGui.QPalette.WindowText, text_color) palette.setColor(QtGui.QPalette.Base, base_color) palette.setColor(QtGui.QPalette.AlternateBase, alt_color) palette.setColor(QtGui.QPalette.ToolTipBase, alt_color) palette.setColor(QtGui.QPalette.ToolTipText, text_color) palette.setColor(QtGui.QPalette.Button, base_color) palette.setColor(QtGui.QPalette.ButtonText, text_color) palette.setColor(QtGui.QPalette.Text, text_color) palette.setColor(QtGui.QPalette.Highlight, highlight_color) palette.setColor(QtGui.QPalette.HighlightedText, highlight_text_color) palette.setColor(QtGui.QPalette.Disabled, QtGui.QPalette.Window, disabled_base_color) palette.setColor(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, disabled_text_color) palette.setColor(QtGui.QPalette.Disabled, QtGui.QPalette.Base, disabled_text_color) palette.setColor(QtGui.QPalette.Disabled, QtGui.QPalette.AlternateBase, disabled_alt_color) palette.setColor(QtGui.QPalette.Disabled, QtGui.QPalette.Button, disabled_base_color) palette.setColor(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, disabled_text_color) palette.setColor(QtGui.QPalette.Disabled, QtGui.QPalette.Text, disabled_text_color) return palette def __init__(self): QtWidgets.QWidget.__init__(self) self.setWindowTitle("Element Browser") self.setGeometry(0, 0, REF_WINDOW_WIDTH, REF_WINDOW_HEIGHT) self.palette = self.dark_palette() self.setPalette(self.palette) # initialize project self.project = Project() self.user_list = self.project.list_users() self.user_completer = QtWidgets.QCompleter(self.user_list) #filters self.filter_label = QtWidgets.QLabel("Filter by: ") self.dept_filter_label = QtWidgets.QLabel("Department") self.dept_filter_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.dept_filter = QtWidgets.QComboBox() self.dept_filter.addItem("all") for each in Department.ALL: self.dept_filter.addItem(each) self.dept_list = Department.ALL self.type_filter_label = QtWidgets.QLabel("Asset Type") self.type_filter_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.type_filter = QtWidgets.QComboBox() self.type_filter.addItem("all") for each in AssetType.ALL: self.type_filter.addItem(each) self.name_filter_label = QtWidgets.QLabel("Name") self.name_filter_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.name_filter = QtWidgets.QLineEdit() # menu bar self.menu_bar = QtWidgets.QMenuBar() self.view_menu = QtWidgets.QMenu("View") self.menu_bar.addMenu(self.view_menu) self.expand_action = self.view_menu.addAction("Expand All") self.user_list_action = self.view_menu.addAction("User Directory") self.theme_action = self.view_menu.addAction("Default Theme") self.theme_action.setCheckable(True) # asset/shot menu self.body_menu = QtWidgets.QComboBox() self.body_menu.addItem(self.ASSETS) #self.body_menu.addItem(self.SHOTS) self.current_body = self.ASSETS self._set_bodies() # new button self.new_button = QtWidgets.QPushButton("New") # refresh button self.refresh_button = QtWidgets.QPushButton("Refresh") # tree self.tree = QtWidgets.QTreeWidget() self.tree.setItemDelegate(TreeGridDelegate(self.tree)) self.columnCount = 8 self.tree.setColumnCount(self.columnCount) tree_header = QtWidgets.QTreeWidgetItem(["name", "", "assigned", "status", "start", "end", "publish", "note"]) self.tree.setHeaderItem(tree_header) tree_header_view = self.tree.header() tree_header_view.resizeSection(4, 120) tree_header_view.resizeSection(5, 120) self.init_tree = [None]*self.columnCount self.init_tree[0] = self.init_name self.init_tree[1] = self.init_dept self.init_tree[2] = self.init_assigned_user self.init_tree[3] = self.init_status self.init_tree[4] = self.init_start_date self.init_tree[5] = self.init_end_date self.init_tree[6] = self.init_last_publish self.init_tree[7] = self.init_note self._build_tree() self.update_tree = [None]*self.columnCount self.update_tree[0] = self.update_name self.update_tree[1] = self.update_dept self.update_tree[2] = self.update_assigned_user self.update_tree[3] = self.update_status self.update_tree[4] = self.update_start_date self.update_tree[5] = self.update_end_date self.update_tree[6] = self.update_last_publish self.update_tree[7] = self.update_note # status bar self.status_bar = QtWidgets.QStatusBar() # connect events self.expand_action.triggered.connect(self._expand_all) self.user_list_action.triggered.connect(self._show_user_directory) self.theme_action.triggered.connect(self._toggle_theme) self.body_menu.currentIndexChanged.connect(self._body_changed) self.new_button.clicked.connect(self._new_body) self.refresh_button.clicked.connect(self._refresh) self.tree.itemExpanded.connect(self._load_elements) self.tree.itemChanged.connect(self._item_edited) self.dept_filter.currentIndexChanged.connect(self._dept_filter_changed) self.name_filter.editingFinished.connect(self._filter_by_name) self.type_filter.currentIndexChanged.connect(self._refresh) # layout layout = QtWidgets.QVBoxLayout(self) layout.setSpacing(5) layout.setMargin(6) options_layout = QtWidgets.QGridLayout() options_layout.addWidget(self.body_menu, 0, 0) options_layout.addWidget(self.new_button, 0, 1) options_layout.addWidget(self.refresh_button, 0, 3) options_layout.setColumnMinimumWidth(0, 100) options_layout.setColumnMinimumWidth(1, 100) options_layout.setColumnMinimumWidth(3, 100) options_layout.setColumnStretch(2, 1) filter_layout = QtWidgets.QGridLayout() filter_layout.addWidget(self.filter_label, 0, 0) filter_layout.addWidget(self.dept_filter_label, 0, 1) filter_layout.addWidget(self.dept_filter, 0, 2) filter_layout.addWidget(self.name_filter_label, 0, 3) filter_layout.addWidget(self.name_filter, 0, 4) filter_layout.addWidget(self.type_filter_label, 0, 5) filter_layout.addWidget(self.type_filter, 0, 6) filter_layout.setColumnMinimumWidth(0, 50) filter_layout.setColumnMinimumWidth(1, 100) filter_layout.setColumnMinimumWidth(2, 100) filter_layout.setColumnMinimumWidth(3, 100) filter_layout.setColumnMinimumWidth(4, 100) filter_layout.setColumnMinimumWidth(5, 100) filter_layout.setColumnMinimumWidth(6, 100) filter_layout.setColumnStretch(7, 1) layout.addWidget(self.menu_bar) layout.addLayout(options_layout) layout.addWidget(self.tree) layout.addLayout(filter_layout) layout.addWidget(self.status_bar) self.setLayout(layout) request_email.check_user_email(self) def _build_tree(self): self.tree.clear() tree_state = self.tree.blockSignals(True) for body in self.bodies: if(str(self.name_filter.text()) in body): tree_item = QtWidgets.QTreeWidgetItem([body]) self.tree.addTopLevelItem(tree_item) tree_flags = tree_item.flags() tree_item.setFlags(tree_flags | QtCore.Qt.ItemIsEditable) # for col in xrange(self.columnCount): # tree_item.setBackground(col, QtWidgets.QColor(30,30,30)) body_obj = self.project.get_body(body) self._load_body(body_obj, tree_item) tree_item.addChild(QtWidgets.QTreeWidgetItem()) # empty item self.tree.blockSignals(tree_state) def _load_body(self, body, item): tree_state = self.tree.blockSignals(True) item.setText(0, body.get_name()) namelabel = TreeLabel(body.get_name()) self.tree.setItemWidget(item, 0, namelabel) if self.current_body==self.ASSETS: body_type = body.get_type() item.setText(self.BODY_DATA_COLUMN, body_type) combobox = TreeComboBoxItem(item, self.BODY_DATA_COLUMN) type_idx = 0 for idx, type in enumerate(AssetType.ALL): combobox.addItem(type) if type == body_type: type_idx = idx combobox.setCurrentIndex(type_idx) self.tree.setItemWidget(item, self.BODY_DATA_COLUMN, combobox) #elif self.current_body==self.SHOTS: # item.setText(self.BODY_DATA_COLUMN, str(body.get_frame_range())) else: self.status_bar.showMessage("Error: unknown body type") description_edit = TreeLineEdit(body.get_description(), item, self.BODY_DESCRIPTION_COLUMN) self.tree.setItemWidget(item, self.BODY_DESCRIPTION_COLUMN, description_edit) for col in range(self.BODY_DATA_COLUMN+1, self.columnCount-1): # disable remaining columns emptylabel = TreeLabel() self.tree.setItemWidget(item, col, emptylabel) self.tree.blockSignals(tree_state) def _load_elements(self, item): tree_state = self.tree.blockSignals(True) body = str(item.text(0)) body_obj = self.project.get_body(body) elements = [] for dept in self.dept_list: dept_elements = body_obj.list_elements(dept) for dept_element in dept_elements: elements.append((dept, dept_element)) item.takeChildren() # clear children for dept, element in elements: element_obj = body_obj.get_element(dept, element) child_item = QtWidgets.QTreeWidgetItem() item.addChild(child_item) child_item.setFlags(child_item.flags() | QtCore.Qt.ItemIsEditable) for col, init in enumerate(self.init_tree): init(element_obj, child_item, col) self.tree.blockSignals(tree_state) def _expand_all(self): # self.tree.expandAll() count = self.tree.topLevelItemCount() for i in xrange(count): item = self.tree.topLevelItem(i) self.tree.expandItem(item) def _show_user_directory(self): user_directory = UserListDialog(self) user_directory.show() def _toggle_theme(self): checked = self.theme_action.isChecked() if not checked: self.palette = self.dark_palette() else: self.palette = QtGui.QPalette() self.setPalette(self.palette) def _set_bodies(self): if self.current_body == self.ASSETS: asset_filter = None if(self.type_filter.currentIndex()): asset_filter_str = str(self.type_filter.currentText()) asset_filter = (Asset.TYPE, operator.eq, asset_filter_str) self.bodies = self.project.list_assets(asset_filter) #elif self.current_body == self.SHOTS: # self.bodies = self.project.list_shots() else: self.bodies = [] def _item_edited(self, item, column): parent = item.parent() if parent is not None: body = str(parent.text(0)) body_obj = self.project.get_body(body) element = str(item.text(0)) dept = str(item.text(1)) element_obj = body_obj.get_element(dept, element) self.update_tree[column](element_obj, item, column) # self.tree.resizeColumnToContents(column) else: body = str(item.text(0)) body_obj = self.project.get_body(body) if column==self.BODY_DATA_COLUMN: self._update_body_data(body_obj, item) elif column==self.BODY_DESCRIPTION_COLUMN: self._update_body_description(body_obj, item) def _refresh(self): # TODO: maintain expanded rows on refresh self._set_bodies() self._build_tree() self.status_bar.clearMessage() def _body_changed(self, index): self.current_body = str(self.body_menu.itemText(index)) if(self.body_menu.currentIndex()): self.type_filter.setEnabled(False) self.type_filter_label.setEnabled(False) else: self.type_filter.setEnabled(True) self.type_filter_label.setEnabled(True) self._refresh() def _dept_filter_changed(self): if(self.dept_filter.currentIndex()): self.dept_list = [str(self.dept_filter.currentText())] else: self.dept_list = Department.ALL self._refresh() def _filter_by_name(self): self._refresh() # target = str(self.name_filter.text()) # for i in reversed(xrange(self.tree.topLevelItemCount())): # if (target not in self.tree.topLevelItem(i).text(0)): # self.tree.takeTopLevelItem(i) def _new_body(self): from byugui import new_body_gui self.new_body_dialog = new_body_gui.CreateWindow(self) if self.current_body == self.ASSETS: self.new_body_dialog.setCurrentIndex(self.new_body_dialog.ASSET_INDEX) #elif self.current_body == self.SHOTS: # self.new_body_dialog.setCurrentIndex(self.new_body_dialog.SHOT_INDEX) self.new_body_dialog.finished.connect(self._refresh) def _update_body_data(self, body, item): if self.current_body==self.ASSETS: body.update_type(str(item.text(self.BODY_DATA_COLUMN))) #elif self.current_body==self.SHOTS: # body.update_frame_range(int(item.text(self.BODY_DATA_COLUMN))) else: self.status_bar.showMessage("Error: unknown body type") def _update_body_description(self, body, item): body.update_description(str(item.text(self.BODY_DESCRIPTION_COLUMN))) def _valid_date(self, date): try: date_obj = datetime.datetime.strptime(date, "%Y-%m-%d").date() return str(date_obj) except ValueError: self.status_bar.showMessage(date+" not a valid date, please use format: YYYY-MM-DD") return None def init_name(self, element, item, column): item.setText(column, element.get_name()) namelabel = TreeLabel(element.get_name()) self.tree.setItemWidget(item, column, namelabel) def init_dept(self, element, item, column): item.setText(column, element.get_department()) deptlabel = TreeLabel(element.get_department()) self.tree.setItemWidget(item, column, deptlabel) def init_assigned_user(self, element, item, column): user = element.get_assigned_user() item.setText(column, user) lineedit = TreeLineEdit(user, item, column) lineedit.setCompleter(self.user_completer) self.tree.setItemWidget(item, column, lineedit) def init_status(self, element, item, column): item.setText(column, element.get_status()) combobox = TreeComboBoxItem(item, column) element_type = element.get_status() type_idx = 0 for idx, type in enumerate(Status.ALL): combobox.addItem(type) if type == element_type: type_idx = idx combobox.setCurrentIndex(type_idx) self.tree.setItemWidget(item, column, combobox) def init_start_date(self, element, item, column): start_date = element.get_start_date() item.setText(column, " "+start_date) start_dateedit = TreeDateEdit(start_date, item, column, self.tree) self.tree.setItemWidget(item, column, start_dateedit) def init_end_date(self, element, item, column): end_date = element.get_end_date() item.setText(column, " "+end_date) end_dateedit = TreeDateEdit(end_date, item, column, self.tree) self.tree.setItemWidget(item, column, end_dateedit) def init_last_publish(self, element, item, column): publish = element.get_last_publish() if publish is not None: item.setText(column, publish[0]+", "+publish[1]+", "+publish[2]) else: item.setText(column, "") def init_note(self, element, item, column): item.setText(column, element.get_last_note()) def update_name(self, element, item, column): self.status_bar.showMessage("can't change name") def update_dept(self, element, item, column): self.status_bar.showMessage("can't change department") def update_assigned_user(self, element, item, column): user = str(item.text(column)) if user in self.user_list: element.update_assigned_user(user) self.status_bar.clearMessage() else: self.tree.itemWidget(item, column).setText(element.get_assigned_user()) self.status_bar.showMessage('"' + user + '" is not a valid username') def update_status(self, element, item, column): element.update_status(str(item.text(column))) self.status_bar.clearMessage() def update_start_date(self, element, item, column): date_str = str(item.text(column)) valid_date_str = self._valid_date(date_str) if valid_date_str: element.update_start_date(valid_date_str) item.setText(column, " "+date_str) self.status_bar.clearMessage() else: self.init_start_date(element, item, column) def update_end_date(self, element, item, column): date_str = str(item.text(column)) valid_date_str = self._valid_date(date_str) if valid_date_str: element.update_end_date(valid_date_str) item.setText(column, " "+date_str) self.status_bar.clearMessage() else: self.init_end_date(element, item, column) def update_last_publish(self, element, item, column): self.status_bar.showMessage("can't modify publish data") self.init_last_publish(element, item, column) def update_note(self, element, item, column): element.update_notes(str(item.text(column))) self.status_bar.clearMessage()