def save_file(log, fname=None): if fname is None: fname = "temp" file_path = fname if HOST == STANDALONE: from tentaculo.api import standalone standalone.message_function("save_file", [file_path]) elif HOST == MAYA or HOST == MAYA2: mc.file(rename=file_path) file_path = mc.file(save=True, type="mayaAscii") elif HOST == NUKE: nuke.scriptSaveAs(file_path, overwrite=1) elif HOST == HOUDINI: hou.hipFile.setName(file_path) hou.hipFile.save() elif HOST == MAX: MaxPlus.FileManager.Save(file_path) elif HOST == C4D: doc = c4d.documents.GetActiveDocument() if doc is not None: c4d.documents.SaveDocument(doc, str(file_path), c4d.SAVEDOCUMENTFLAGS_0, c4d.FORMAT_C4DEXPORT) elif HOST == BLENDER: bpy.ops.wm.save_mainfile(filepath=file_path) elif HOST == KATANA: KatanaFile.Save(file_path) return file_path
def execute(self, operation, file_path, **kwargs): """ Main hook entry point :operation: String Scene operation to perform :file_path: String File path to use if the operation requires it (e.g. open) :returns: Depends on operation: 'current_path' - Return the current scene file path as a String all others - None """ if operation == "current_path": # return the current scene path return FarmAPI.GetKatanaFileName() elif operation == "open": # do new scene as Maya doesn't like opening # the scene it currently has open! KatanaFile.Load(file_path) elif operation == "save": current_file = FarmAPI.GetKatanaFileName() # save the current scene: KatanaFile.Save(current_file)
def _save_session(path): """ Save the current session to the supplied path. """ # Ensure that the folder is created when saving KatanaFile.Save( path )
def save_query(log): cancel = False if HOST == STANDALONE: from tentaculo.api import standalone cancel = standalone.message_function("save_query")[0] elif HOST == MAYA or HOST == MAYA2: file_name = mc.file(query=True, sceneName=True) need_save = mc.file(query=True, modified=True) if len(file_name) > 0 and need_save: ret = mc.confirmDialog(title='Closing file', message='Save current file?', messageAlign='center', button=['Yes', 'No', 'Cancel'], defaultButton='Yes', cancelButton='Cancel', dismissString='Cancel') if ret == "Yes": mc.file(save=True, type="mayaAscii") elif ret == "Cancel": cancel = True elif HOST == NUKE: cancel = not nuke.scriptClose() elif HOST == HOUDINI: need_save = hou.hipFile.hasUnsavedChanges() if need_save: hou.hipFile.clear() cancel = hou.hipFile.hasUnsavedChanges() elif HOST == MAX: cancel = not MaxPlus.FileManager.CheckForSave() elif HOST == C4D: doc = c4d.documents.GetActiveDocument() if doc is not None and doc.GetChanged(): cancel = not c4d.documents.SaveDocument( doc, doc.GetDocumentPath() + "/" + doc.GetDocumentName(), c4d.SAVEDOCUMENTFLAGS_DIALOGSALLOWED, c4d.FORMAT_C4DEXPORT) elif HOST == BLENDER: if bpy.data.is_dirty: bpy.ops.wm.save_mainfile(check_existing=True) cancel = bpy.data.is_dirty elif HOST == KATANA: if KatanaFile.IsFileDirty(): mb = UI4.App.Application.QtGui.QMessageBox(app_window()) mb.setText("Closing file") mb.setInformativeText("Save current file?") mb.setStandardButtons( UI4.App.Application.QtGui.QMessageBox.Yes | UI4.App.Application.QtGui.QMessageBox.No | UI4.App.Application.QtGui.QMessageBox.Cancel) ret = mb.exec_() if ret == UI4.App.Application.QtGui.QMessageBox.Yes: KatanaFile.Save( NodegraphAPI.NodegraphGlobals.GetProjectAssetID()) cancel = ret == UI4.App.Application.QtGui.QMessageBox.Cancel return not cancel
def displaySaveDialog(self): fname = str( QFileDialog.getSaveFileName(self, 'Save file', '/s/prodanim/asterix2', "Katana files (*.katana)")) if fname == '': print 'No file has been saved' else: KatanaFile.Save(fname) print 'Saving : ' + fname
def add_new_cp_uv(): node=cku.get_lgt_shot_maker_node() if cku.get_node_children_by_name(node,'CopyUv_\d*$') or \ cku.get_node_children_by_name(node,'CopyUV_\d*$'): return old_cp=cku.get_node_children_by_name(node,'CopyUv_Ani_Srf_\d*',operation=lambda x:x.setBypassed(True)) if old_cp: new_cp_op=cku.replace_me_with(old_cp[0], new_node='CopyUV_Lc', bypass_old_node=True) if new_cp_op: print '\n\nAdd new copy uv op node to fix srf v000 transfering uv bug.\n\n' new_cp_op.setName('CopyUV_') KatanaFile.Save(FarmAPI.GetKatanaFileName())
def execute(self, work_template, primary_task, secondary_tasks, progress_cb, **kwargs): """ Main hook entry point :param work_template: template This is the template defined in the config that represents the current work file :param primary_task: The primary task that was published by the primary publish hook. Passed in here for reference. :param secondary_tasks: The list of secondary tasks that were published by the secondary publish hook. Passed in here for reference. :param progress_cb: Function A progress callback to log progress during pre-publish. Call: progress_cb(percentage, msg) to report progress to the UI :returns: None :raises: Raise a TankError to notify the user of a problem """ # get the engine name from the parent object (app/engine/etc.) engine_name = self.parent.engine.name progress_cb(0, "Versioning up the scene file") # get the current scene path: scene_path = os.path.abspath(FarmAPI.GetKatanaFileName()) # increment version and construct new file name: progress_cb(25, "Finding next version number") fields = work_template.get_fields(scene_path) next_version = self._get_next_work_file_version(work_template, fields) fields["version"] = next_version new_scene_path = work_template.apply_fields(fields) # log info self.parent.log_debug("Version up work file %s --> %s..." % (scene_path, new_scene_path)) # rename and save the file progress_cb(50, "Saving the scene file") KatanaFile.Save(new_scene_path) progress_cb(100)
def save_katana_scene(katana_scene, force=False): ''' :description to save the current scene, force true is to overwrite the scene, if scene exists :param katana_scene <str> :param force <bool> :example from core import scene scene.save_katana_scene() ''' if os.path.isfile(katana_scene) and not force: print '#warnings: already found katana scene' return if not os.path.isdir(os.path.dirname(katana_scene)): os.makedirs(os.path.dirname(katana_scene)) KatanaFile.Save(katana_scene, extraOptionsDict=None) print '#info: save katana scene', katana_scene return True
def create_file(log, filepath, origin_path=None): dir = os.path.dirname(filepath) if not os.path.exists(dir): raise Exception('{0} does not exist'.format(dir)) if origin_path is None: origin_path = filepath if HOST == STANDALONE: from tentaculo.api import standalone standalone.message_function("create_file", [filepath]) elif HOST == MAYA or HOST == MAYA2: check_workspace_maya(log, origin_path) mc.file(new=True, force=True) mc.file(rename=filepath) mc.file(save=True, type="mayaAscii") elif HOST == NUKE: nuke.scriptClear() nuke.scriptSaveAs(filepath, overwrite=1) elif HOST == HOUDINI: hou.hipFile.clear(suppress_save_prompt=True) hou.hipFile.save(filepath) elif HOST == MAX: MaxPlus.FileManager.Reset(noPrompt=True) MaxPlus.FileManager.Save(filepath) elif HOST == C4D: c4d.documents.CloseAllDocuments() newDoc = c4d.documents.BaseDocument() c4d.documents.InsertBaseDocument(newDoc) c4d.documents.SaveDocument(newDoc, str(filepath), c4d.SAVEDOCUMENTFLAGS_0, c4d.FORMAT_C4DEXPORT) c4d.documents.LoadFile(str(filepath)) elif HOST == BLENDER: bpy.ops.wm.read_homefile() bpy.ops.wm.save_mainfile(filepath=filepath, check_existing=False) elif HOST == KATANA: KatanaFile.New() KatanaFile.Save(filepath) return filepath
def execute(self, operation, file_path, context, parent_action, file_version, read_only, **kwargs): """Main hook entry point. Args: operation (str): Scene operation to perform file_path (str): File path to use if the operation requires it (e.g. open) context (sgtk.Context): The context the file operation is being performed in. parent_action (str): Action that this scene operation is being executed for. This can be one of: - "open_file" - "new_file" - "save_file_as" - "version_up" file_version: The version/revision of the file to be opened. If this is ``None`` then the latest version should be opened. read_only (bool): Specifies if the file should be opened read-only or not Returns: object: Depending on ``operation``: - 'current_path': Current scene file path as a ``str`` - 'reset': ``True`` if scene was reset to an empty state, otherwise ``False`` - all others: ``None`` """ if operation == "current_path": # return the current scene path return file_path elif operation == "open": KatanaFile.Load(file_path) elif operation == "save": if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) KatanaFile.Save(file_path) elif operation == "save_as": if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) KatanaFile.Save(file_path) elif operation == "reset": while KatanaFile.IsFileDirty(): # Changes have been made to the scene res = QtGui.QMessageBox.question( None, "Save your scene?", "Your scene has unsaved changes. Save before proceeding?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel) if res == QtGui.QMessageBox.Cancel: return False elif res == QtGui.QMessageBox.No: break else: if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) KatanaFile.Save( file_path) # TODO: warning: this may not work... return True
def _save_as(): scene_path = FarmAPI.GetKatanaFileName() KatanaFile.Save( scene_path )
def execute(self, task, work_template, comment, thumbnail_path, sg_task, progress_cb, **kwargs): """ Main hook entry point :param task: Primary task to be published. This is a dictionary containing the following keys: { item: Dictionary This is the item returned by the scan hook { name: String description: String type: String other_params: Dictionary } output: Dictionary This is the output as defined in the configuration - the primary output will always be named 'primary' { name: String publish_template: template tank_type: String } } :param work_template: template This is the template defined in the config that represents the current work file :param comment: String The comment provided for the publish :param thumbnail: Path string The default thumbnail provided for the publish :param sg_task: Dictionary (shotgun entity description) The shotgun task to use for the publish :param progress_cb: Function A progress callback to log progress during pre-publish. Call: progress_cb(percentage, msg) to report progress to the UI :returns: Path String Hook should return the path of the primary publish so that it can be passed as a dependency to all secondary publishes :raises: Hook should raise a TankError if publish of the primary task fails """ # TODO: This may not be the best choice of function, as it returns an Asset ID. # When using the default Asset manager (file path) it'll work, though. scene_path = FarmAPI.GetKatanaFileName() # Find dependendies (TODO) dependencies = [] # This should be a list of file paths, I think # use templates to convert to publish path: output = task["output"] fields = work_template.get_fields(scene_path) fields["TankType"] = output["tank_type"] publish_template = output["publish_template"] publish_path = publish_template.apply_fields(fields) if os.path.exists(publish_path): raise TankError("The published file named '%s' already exists!" % publish_path) # save the scene: progress_cb(10.0, "Saving the scene") self.parent.log_debug("Saving the scene...") KatanaFile.Save(scene_path) # copy the file: progress_cb(50.0, "Copying the file") try: publish_folder = os.path.dirname(publish_path) self.parent.ensure_folder_exists(publish_folder) self.parent.log_debug("Copying %s --> %s..." % (scene_path, publish_path)) self.parent.copy_file(scene_path, publish_path, task) except Exception, e: raise TankError("Failed to copy file from %s to %s - %s" % (scene_path, publish_path, e))
def recoverScript(katanaFile=None, logsFile=None, jsonFile): from Katana import KatanaFile, NodegraphAPI if katanaFile is not None: KatanaFile.Load(katanaFile) katana_file = katanaFile logs_file = logsFile file_name = NodegraphAPI.GetRootNode().getParameter( 'katanaSceneName').getValue(0) katana_file = os.path.join(getVersoonUpKatanaDir(katana_file), file_name) #~ version up katana_file = katana_path[:-3] + "{:03}".format(int(katana_path[-3:]) + 1) infile = open(jsonFile, 'r') json_data = json.load(infile) infile.close() #~ loops all nodes for node_name in json_data: node = NodegraphAPI.GetNode(node_name) node_data = json_data[node_name] mx_shader_name = node_data[0] mx_shader_data = node_data[1] #~ loops all parameters for para_data in mx_shader_data: #~ read data from json data enable = para_data[0] name = para_data[1] connected = para_data[2] value = para_data[3] #~ translate data translate_shader = SHADERMAPPING[mx_shader_name][0] translate_para_list = SHADERMAPPING[mx_shader_name][1] translate_name = translate_para_list[name] #~ set new shader type node.checkDynamicParameters() if translate_shader != mx_shader_name: node.getParameter('nodeType').setValue(translate_shader, 0) node.checkDynamicParameters() if translate_shader != mx_shader_name: from Katana import CacheManager CacheManager.flush(isNodeGraphLoading=False) #~ if node connected to other if connected: if not mx_shader_name in SHADERMAPPING: continue connected_node = NodegraphAPI.GetNode(value) out_port = connected_node.getOutputPorts()[0] in_port = node.getInputPort(translate_name) node.getInputPort(translate_name).connect(out_port) #~ recover parameter value else: if not enable: continue node.checkDynamicParameters() para_enable = node.getParameter('parameters.%s.enable' % translate_name) para_enable.setValue(1, 0) para_value = node.getParameter('parameters.%s.value' % translate_name) node.checkDynamicParameters() if para_value.getType() == "numberArray": children = para_value.getChildren() for i in range(0, len(value)): children[i].setValue(value[i], 0) elif para_value.getType() == "number": para_value.setValue(float(value[0]), 0) else: para_value.setValue(str(value[0]), 0) KatanaFile.Save(katana_path) if logsFile is not None: JobRecord(logs_file, katana_file)
def execute(self, operation, file_path, context, parent_action, file_version, read_only, **kwargs): """ Main hook entry point :param operation: String Scene operation to perform :param file_path: String File path to use if the operation requires it (e.g. open) :param context: Context The context the file operation is being performed in. :param parent_action: This is the action that this scene operation is being executed for. This can be one of: - open_file - new_file - save_file_as - version_up :param file_version: The version/revision of the file to be opened. If this is 'None' then the latest version should be opened. :param read_only: Specifies if the file should be opened read-only or not :returns: Depends on operation: 'current_path' - Return the current scene file path as a String 'reset' - True if scene was reset to an empty state, otherwise False all others - None """ if operation == "current_path": # return the current scene path return file_path elif operation == "open": KatanaFile.Load(file_path) elif operation == "save": if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) KatanaFile.Save(file_path) elif operation == "save_as": if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) KatanaFile.Save(file_path) elif operation == "reset": while KatanaFile.IsFileDirty(): # Changes have been made to the scene res = QtGui.QMessageBox.question( None, "Save your scene?", "Your scene has unsaved changes. Save before proceeding?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel) if res == QtGui.QMessageBox.Cancel: return False elif res == QtGui.QMessageBox.No: break else: if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) KatanaFile.Save( file_path) # TODO: warning: this may not work... return True
def execute(self, operation, file_path, context, parent_action, file_version, read_only, **kwargs): """ Main hook entry point :param operation: String Scene operation to perform :param file_path: String File path to use if the operation requires it (e.g. open) :param context: Context The context the file operation is being performed in. :param parent_action: This is the action that this scene operation is being executed for. This can be one of: - open_file - new_file - save_file_as - version_up :param file_version: The version/revision of the file to be opened. If this is 'None' then the latest version should be opened. :param read_only: Specifies if the file should be opened read-only or not :returns: Depends on operation: 'current_path' - Return the current scene file path as a String 'reset' - True if scene was reset to an empty state, otherwise False all others - None """ if file_path: file_path = file_path.replace("/", os.path.sep) if operation == "current_path": # return the current script path return "/path/here".replace("/", os.path.sep) # TODO!! elif operation == "open": # open the specified script KatanaFile.Load(file_path) elif operation == "save": # save the current script: if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) KatanaFile.Save(file_path) # TODO: warning: this may not work... elif operation == "save_as": if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) KatanaFile.Save(file_path) elif operation == "reset": """ Reset the scene to an empty state """ while KatanaFile.IsFileDirty(): # Changes have been made to the scene res = QtGui.QMessageBox.question( None, "Save your scene?", "Your scene has unsaved changes. Save before proceeding?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel) if res == QtGui.QMessageBox.Cancel: return False elif res == QtGui.QMessageBox.No: break else: if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) KatanaFile.Save( file_path) # TODO: warning: this may not work... return True # Create a new engine instance from the existing one, with the new context # Specify "shot_step" environment if the current context specifies a step if context.step: env = context.tank.pipeline_configuration.get_environment( "shot_step", context=context) # Otherwise, just get a "project" level context else: env = context.tank.pipeline_configuration.get_environment( "project", context=context) name = "tk-katana" # TODO: Get this properly? new_katana_engine = engine.KatanaEngine(context.tank, context, name, env) new_katana_engine.add_katana_menu()
def initExport(option): dependencyList = FarmAPI.GetSortedDependencyList()[0] filepath = FarmAPI.GetKatanaFileName() # TODO - validity check saved = FarmAPI.IsSceneValid(FarmAPI.NODES_ALL) if not saved: # errormsg = FarmAPI.GetErrorMessages() result = UI4.Widgets.MessageBox.Warning('Unsaved Changes', 'Save your file', acceptText='Save', cancelText='Cancel') if result == 0: # Save KatanaFile.Save(filepath) else: # cancel return # TODO - Get Katana version katanaVersion = "2.54" rendererVersion = "21.4" # get renderservice renderer = dependencyList['service'] requ_lics = '' if renderer == 'arnold': rendererVersion = RenderingAPI.RendererInfo.GetPlugin( 'ArnoldRendererInfo').getRegisteredRendererVersion() extension = '.ass' requ_lics += 'Arnold;' elif renderer == 'prman': rendererVersion = RenderingAPI.RendererInfo.GetPlugin( 'PRManRendererInfo').getRegisteredRendererVersion() renderer = 'RenderMan' extension = '.rib' requ_lics += 'RenderMan;' else: UI4.Widgets.MessageBox.Warning('Unsupported Renderer', 'Unknown Renderer') return use_yeti = dependencyList['useYetiLic'] if use_yeti: requ_lics += "Yeti" software = 'Katana' software = 'Katana' if option == 'local': software = renderer # print 'dependency list ', dependencyList fileDir = dependencyList['outputFolder'] # print 'FILEDDIR ', fileDir fileName = dependencyList['fileName'] if fileName == '': UI4.Widgets.MessageBox.Warning('Warning', 'Add a name parameter') return # tmp name for xml and katana farm file xmlFileName = getNewTempFileName(fileDir, fileName) tmpFile = open(xmlFileName, 'w') dst = tmpFile.name[:-4] + '.katana' comment_file = tmpFile.name[:-4] + '_comment.txt' comment = '' use_comment = dependencyList['useComment'] if use_comment: comment = dependencyList['comment'] with open(comment_file, 'w') as f: f.write(comment) if (option == 'local'): # check file/dir if not os.path.isdir(fileDir): if UI4.Widgets.MessageBox.Warning('Warning', 'Directory does not exist.\n' + fileDir + '\n\nCreate it?', acceptText='Yes', cancelText='No'): return else: os.mkdir(fileDir) sceneName = os.path.join(fileDir, fileName) + '_<FN4>' + extension else: sceneName = dst # sceneName = FarmAPI.GetKatanaFileName() # check framerange framerange = dependencyList['range'] if framerange is None: UI4.Widgets.MessageBox.Warning('Warning', 'Add a valid framerange') return startframe = int(framerange[0]) endframe = int(framerange[1]) if endframe <= startframe: UI4.Widgets.MessageBox.Warning('Warning', 'Add a valid framerange') return # distribution check threadCount = int(dependencyList['useThreads']) if threadCount <= 0: UI4.Widgets.MessageBox.Warning('Warning', 'You must use at least one thread') return availableThreads = multiprocessing.cpu_count() if (threadCount > availableThreads) and (option == 'local'): UI4.Widgets.MessageBox.Warning( 'Warning', 'Your machine is restricted to max.' + str(availableThreads)) return packageSize = int(dependencyList['packageSize']) if packageSize <= 0: UI4.Widgets.MessageBox.Warning('Warning', 'Add a valid packageSize') return # denoiser post script flags if int(dependencyList['useRendermanDenoiserPostScript']) == 1: filter = dependencyList['denoiseFilter'] filter_cmd = 'denoise -v variance -f {}'.format(filter) if dependencyList['useFilterOverride']: filter_override = dependencyList['denoiseFilterOverride'] for override in filter_override: filter_cmd += '+{}'.format(override) # create job newJob = rrJob() if (option == 'local'): newJob.version = rendererVersion else: newJob.version = katanaVersion newJob.rendererVersionName = renderer newJob.rendererVersion = rendererVersion newJob.software = software newJob.renderer = renderer newJob.RequiredLicenses = requ_lics #"Yeti" # TODO newJob.sceneName = sceneName newJob.sceneDatabaseDir = "" newJob.seqStart = startframe newJob.seqEnd = endframe newJob.seqStep = dependencyList['stepSize'] # TODO - get dynamic newJob.seqFileOffset = 0 newJob.seqFrameSet = "" newJob.imageWidth = 99 # TODO - get dynamic newJob.imageHeight = 99 newJob.imageDir = fileDir newJob.imageFileName = fileName + '_####_variance.exr' newJob.imageFramePadding = 4 # TODO - get dynamic newJob.imageExtension = "" # ".exr" # TODO get dynamic newJob.imagePreNumberLetter = "" newJob.imageSingleOutput = False newJob.imageStereoR = "" newJob.imageStereoL = "" newJob.sceneOS = getOSString() # TODO - get dynamic newJob.camera = "" newJob.layer = dependencyList['name'] newJob.channel = "" newJob.maxChannels = 0 newJob.channelFileName = [] newJob.channelExtension = [] newJob.isActive = False newJob.sendAppBit = "" newJob.preID = "" newJob.waitForPreID = "" if dependencyList['useRendermanDenoiserPostScript']: newJob.CustomA = filter_cmd else: newJob.CustomA = "" newJob.CustomB = "comment: {}".format(comment) newJob.CustomC = "" newJob.LocalTexturesFile = "" newJob.rrSubmitVersion = "%rrVersion%" newJob.packageSize = packageSize newJob.threadCount = threadCount newJob.renderNode = dependencyList['name'] # write xml file root = newJob.writeToXMLstart(None) job = newJob.writeToXMLJob(root) newJob.writeToXMLEnd(tmpFile, root) # copy katanna recipie shutil.copy(filepath, dst) # submit job if option == 'local': # start control session for local conversion scriptDir = os.path.dirname(os.path.realpath(__file__)) sessionScript = os.path.join(scriptDir, 'session/ControlSessions.py') subp = subprocess.Popen(['python', sessionScript, tmpFile.name, dst], close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) elif option == 'farm': os.system(getRRSubmitterPath() + " \"" + xmlFileName + "\"")
def passedLgtShotSimplifyNode(self): lgtsimplifynode=NodegraphAPI.GetNode('LgtShotSimplify_') if lgtsimplifynode: lgtsimplifynode.setBypassed(True) KatanaFile.Save(FarmAPI.GetKatanaFileName()) print "setBypassed ok"