def getValue(self): """Get the asset ID from this browser window""" show = str(self.__showEdit.text()) shot = str(self.__shotEdit.text()) asset = str(self.__assetEdit.text()) version = str(self.__versionEdit.text()) assetFields = { "show": show, "shot": shot, AssetAPI.kAssetFieldName: asset, AssetAPI.kAssetFieldVersion: version } assetPlugin = AssetAPI.GetDefaultAssetPlugin() assetId = assetPlugin.buildAssetId(assetFields) return assetId
def setValue(self, value): """ Given an asset ID. Set the Show, Shot, Asset and version in the UI. """ assetPlugin = AssetAPI.GetDefaultAssetPlugin() if not assetPlugin.isAssetId(value): return assetFields = assetPlugin.getAssetFields(value, True) self.__showEdit.setText(assetFields["show"]) self.__shotEdit.setText(assetFields["shot"]) self.__assetEdit.setText(assetFields[AssetAPI.kAssetFieldName]) self.__versionEdit.setText(assetFields[AssetAPI.kAssetFieldVersion]) if assetFields.get("protocol", "") == "sandbox": self.__protocolLabel.setText("sandbox://") else: self.__protocolLabel.setText("mock://")
def getValue(self): """Get the asset ID from this browser window""" show = str(self.__showEdit.text()) shot = str(self.__shotEdit.text()) asset = str(self.__assetEdit.text()) version = str(self.__versionEdit.text()) protocol = "asset" if self.__protocolLabel.text() == "sandbox://": protocol = "sandbox" assetFields = {"protocol" : protocol, "show" : show, "shot" : shot, AssetAPI.kAssetFieldName : asset, AssetAPI.kAssetFieldVersion : version} assetPlugin = AssetAPI.GetDefaultAssetPlugin() assetId = assetPlugin.buildAssetId(assetFields) return assetId
def __traverseItemTree(self, assetItem, treeParent, selectedKeys, openState, node=None): item = AssetListViewItem(treeParent, '') key = node selectable = True if not node: try: key = assetItem.getItemKey() selectable = assetItem.isSelectable() except Exception as exception: log.exception('Error accessing asset item %s: %s' % (assetItem, str(exception))) item.setItemData({ 'type': 'assetTree', 'assetItem': assetItem, 'key': key }) if selectable: item.setSelected(key in selectedKeys) item.setFlags( QtCore.Qt.ItemFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)) else: item.setFlags(QtCore.Qt.ItemFlags(QtCore.Qt.ItemIsEnabled)) defaultState = assetItem.getDefaultOpenState() expanded = openState.get(key, defaultState) item.setExpanded(expanded) try: assetId = assetItem.getAssetId() if assetId: assetPlugin = AssetAPI.GetDefaultAssetPlugin() if assetPlugin.isAssetId(assetId): fields = assetPlugin.getAssetFields(assetId, True) version = fields.get('version', None) resolvedVersion = assetPlugin.resolveAssetVersion( assetId, throwOnError=True) if version: item.setText(VERSION_COLUMN, version) item.setIcon( VERSION_COLUMN, UI4.Util.IconManager.GetIcon( 'Icons/heightAdjustDownHilite16.png')) if resolvedVersion: item.setText(RESOLVED_VERSION_COLUMN, resolvedVersion) except Exception as exception: log.exception('Error getting version of asset item %s: %s' % (assetItem, str(exception))) try: assetItem.setItemState(item) except Exception as exception: log.exception('Error setting state of asset item %s: %s' % (assetItem, str(exception))) if assetItem.isIgnorable() and assetItem.isIgnored(): item.setIcon(NAME_COLUMN, UI4.Util.IconManager.GetIcon('Icons/ignore16.png')) try: children = assetItem.getChildren() if children: for child in children: self.__traverseItemTree(child, item, selectedKeys, openState) except Exception as exception: log.exception('Error traversing children of asset item %s: %s' % (assetItem, str(exception))) try: assetItem.addNodeObservers(self.__addObserverNode) except Exception as exception: log.exception('Error adding node observer to asset item %s: %s' % (assetItem, str(exception))) return item
def getResult(self): assetFields = self.__widget.getAssetFields() assetPlugin = AssetAPI.GetDefaultAssetPlugin() return assetPlugin.buildAssetId(assetFields)
def _Populate(filepath, node, graveyard={}): """ Populate the casting sheet node with the contents of the casting sheet file pointed to by 'filepath'. Use the graveyard parameter to bring back locked nodes that were not part of the last set casting sheet version. """ # Create a new merge node # merge = NodegraphAPI.CreateNode('Merge') merge.setName('MergeCastingSheet') merge.setParent(node) mergeOut = merge.getOutputPort("out") # Connect the merge node # to this nodes output port # returnOut = node.getReturnPort("out") mergeOut.connect(returnOut) # Resolve the asset file path # assetPlugin = AssetAPI.GetDefaultAssetPlugin() # Iterate over all the entries # in the casting sheet loading # their respective nodes # GRID_WIDTH = 200 GRID_Y_OFFSET = 200 FIRST = 0 ID, NAME = (0, 1) for index, asset in enumerate(CastingSheetIO.Iterator(filepath)): assetId = asset[ID] assetName = asset[NAME] # If it exists in the 'graveyard'. # bring it back to life # child = graveyard.get(assetName, None) if not child: # Get hold of a plug-in that can load this asset # plugin_name = FindPluginFromAssetIdType(assetId) # Ensure that a matching plug-in was found # for the asset type # if plugin_name == None: log.error( "We were unable to find a plug-in to load the the asset '%s'." % (assetId)) else: # The location of the casting sheet asset in the scene graph # locationExpression = 'getParam("%s.castingInfo.name") + "/" + getNode(nodeName).getParent().castingInfo.name' % ( node.getName()) # Load it in # child = AssetModule.TriggerBatchCreateCallback( plugin_name, node, assetId, locationExpression) # We can try to set the name of the casting sheet item # but if there is already an item that exists in the scene # with that same name then we will be given a different name. # child.setName(assetName) # So store the casting sheet name on the node as a parameter. # We will use this later for synching. # setCastingParam(child, "name", assetName) setCastingParam(child, "locked", UNLOCK, NodegraphAPI.Parameter.createChildNumber) if child: # Re-parent the node # child.setParent(node) # Merge this input in # entry = merge.addInputPort(assetName) main = child.getOutputPortByIndex(FIRST) main.connect(entry) else: log.warning( "We were unable to create a new casting node for the casting sheet entry '%s' at '%s'." % (assetName, assetId))
def SyncCastingSheet(node, assetId): """ Sync the casting sheet node to the given asset. ------------------------------------------------------------------- Syncing steps Delete the merge node. Iterate over all of child nodes and ... - If they are locked: - Move the current node to the 'graveyard' group node. We are guaranteed that there will not be a node with the same casting name in this group node because if there had been it would have been in the casting sheet. - If they are not locked - Delete them For every node in the 'graveyard' node create an entry in a graveyard map. Create a new merge node. Iterate over all of the entries in the casting sheet: - If an asset of the given instance name exists in the graveyard map then: - re-parent the node under the casting sheet and use it - Otherwise: - Create a new node with the plug-in callback system Then connect the node to the merge node. Save the casting sheet asset id in to the parameter castingInfo.asset """ # Type check # nodeType = node.getType() if nodeType != "CastingSheet": log.error( "You are trying to delete a node that is not a casting sheet node") return # For the casting sheet we always # resolve the asset version in the asset id # immediately. # assetPlugin = AssetAPI.GetDefaultAssetPlugin() assetId = _ReplaceTagsWithNumbers(assetId) filepath = assetPlugin.resolveAsset(assetId) if not filepath: log.error( "Unable to resolve the casting sheet asset ID for '%s' in the casting sheet node '%s'" % (assetId, node.getName())) return # Check if we will be able to load # the asset ids casting sheet on file # if not _PopulatePreCondition(filepath): return # Ensure that the casting sheet node has a valid internal state # children = list(node.getChildren()) if not children: log.error( "Casting sheet node '%s' is in an invalid state it has no merge node or graveyard node, remove it and create a new one" % node.getName()) return # The graveyard node is always first, then the merge node. # graveyardNode = _GetGraveyardNode(node) mergeNode = _GetMergeNode(node) # This is done to support an assertion only. # It does not contribute to the functionality of this code. # takenGraveyardNames = set( (GetCastingName(child) for child in graveyardNode.getChildren())) # Get hold of the children before the # merge node is deleted # entries = _GetInputNodes(mergeNode) # In case the merge node doesn't exist # if mergeNode.getType() == "Merge": mergeNode.delete() # Everything else is a casting sheet entry # for child in entries: if IsLocked(child): assert GetCastingName(child) not in takenGraveyardNames child.setParent(graveyardNode) else: child.delete() # Create a casting name to node mapping # graveyard = [(GetCastingName(n), n) for n in graveyardNode.getChildren()] graveyard = dict(graveyard) # Populate the node with casting sheet entries # _Populate(filepath, node, graveyard) # Now store the asset id so that we know where this all came from # setCastingParam(node, "asset", assetId, hintsDict={'widget': 'assetIdInput'}) # Finally rebuild the layout # _LayoutContents(node)
def AddCastingSheet(importomaticNode, assetId, locationExpression=None): """ Load the chosen casting sheet specified by assetId to the location specified by locationExpression. """ # We can't do anything without a casting sheet asset id if assetId == None: log.error("No asset id given for new casting sheet") return # Resolve the asset file path # # Get hold of the primary asset plugin # so that we can resolve the casting sheet asset. assetPlugin = AssetAPI.GetDefaultAssetPlugin() filepath = assetPlugin.resolveAsset(assetId) if not filepath: log.error("Unable to resolve the casting sheet asset ID for '%s'" % assetId) return # Check if we will be able to load # the asset ids in the casting sheet on file if not _PopulatePreCondition(filepath): return # Store everything inside of the casting sheet group node = NodegraphAPI.CreateNode('Group') node.setName('CastingSheet') node.setType(CASTINGSHEET_TYPE) node.addOutputPort('out') returnOut = node.getReturnPort("out") # CastingSheet parameters - Scene graph location if locationExpression: setCastingStringParamExpression( node, "name", locationExpression, hintsDict={'widget': 'scenegraphLocation'}) # If a locationExpression wasn't given # default to a sensible place else: location = '/root/world/geo/%s' % node.getName() setCastingParam(node, "name", location, hintsDict={'widget': 'scenegraphLocation'}) # Create our graveyard node # This should be created first because it # never gets deleted graveyard = NodegraphAPI.CreateNode('Group') graveyard.setName('Graveyard') graveyard.setParent(node) # Read the casting sheet and populate # the casting sheet node. _Populate(filepath, node) # Now store the asset id so that we know where this all came from setCastingParam(node, "asset", assetId, hintsDict={'widget': 'assetIdInput'}) # Finally adjust the layout in the nodegraph ui _LayoutContents(node) return node
def AddScenegraphXmlGeometry(importomaticNode, assetId, locationExpression=None): filename = '' assetPlugin = AssetAPI.GetDefaultAssetPlugin() if assetPlugin.isAssetId(assetId): filename = assetPlugin.resolveAsset(assetId) else: return fileBase = os.path.basename(filename) rootParamName = os.path.splitext(fileBase)[0] # Parse XML to extract relevant information xmlTree = ET.parse(filename) xmlRoot = xmlTree.getroot() node = None # Find all instances of type reference rootInstanceList = xmlRoot.find("instanceList") if rootInstanceList is not None: rootInstance = rootInstanceList.find("instance") rootInstanceName = rootInstance.attrib["name"] rootInstanceType = rootInstance.attrib["type"] node = NodegraphAPI.CreateNode('Group') node.setName(rootParamName) # This seems a bit odd to set the name and then retrieve it but Katana # will change the name to a unique name which we can then extract uniqueRootName = node.getName() node.setType('ScenegraphXml') node.addOutputPort('out') xmlInNode = NodegraphAPI.CreateNode('ScenegraphXml_In', node) xmlInNode.getOutputPortByIndex(0).connect(node.getReturnPort('out')) # If the location parameter isn't # given try to intelligently guess one # if locationExpression: xmlInNode.getParameter('name').setExpression( locationExpression, True) else: baseLocation = xmlInNode.getParameter("name").getValue(0) location = baseLocation + '/' + uniqueRootName xmlInNode.getParameter('name').setValue(location, 0) xmlInNode.getParameter('asset').setValue(assetId, 0) basePath = os.path.dirname(filename) + os.sep assetInfoParam = node.getParameters().createChildGroup('assetInfo') assetInfoParam.createChildString('_ignore', 'False') assetInfoParam.createChildString('_sgPath', '/' + uniqueRootName) findInstances(rootInstanceList, assetInfoParam, node, basePath, "") BuildScenegraph(node) return node