def play_scrub(multiplier): import time from PySide2.QtGui import QCursor mouse_last = hou.getenv("mouse", "0") mouse_last = float(mouse_last) mouse_now = QCursor().pos() time_now = time.time() time_last = hou.getenv("time", "0") time_last = float(time_last) time_diff = time_now - time_last mouse_now = round(mouse_now.x() / 10) if time_diff > 0.1: mouse_last = mouse_now skip = mouse_last - mouse_now skip = skip * multiplier if abs(skip) > 20: skip = skip * 2 frame_now = hou.frame() frame_now = hou.frame() - skip hou.setFrame(frame_now) hou.putenv("mouse", str(mouse_now)) hou.putenv("time", str(time_now))
def frame(node): fWrite = '.0001' fLoad = '.0001' if node: f = hou.frame() if node.parm("frame"): f = float(node.evalParm("frame")) timeRange = hou.playbar.timelineRange() if node.parm("f1"): f1 = float(int(node.evalParm("f1"))) else: f1 = timeRange[0] if node.parm("f2"): f2 = float(int(node.evalParm("f2"))) else: f2 = timeRange[1] if node.parm("f3"): f3 = float(node.evalParm("f3")) else: f = 1 fClampWrite = max(min(hou.frame(), f2), f1) fClampLoad = max(min(f, f2), f1) fIntWrite = "." + str(int(float(fClampWrite))).zfill(4) fIntLoad = "." + str(int(float(fClampLoad))).zfill(4) fDecWrite = str(fClampWrite % 1).strip("0") fDecLoad = str(fClampLoad % 1).strip("0") fWrite = fIntWrite + ("" if (float(fClampWrite) % 1 == 0) else fDecWrite) fLoad = fIntLoad + ("" if (float(fClampLoad) % 1 == 0) else fDecLoad) return fWrite, fLoad
def _getFrameRangeFromRopRecurse(rop): """Helper function for _getFrameRangeFromRop(). Recursively traverses nodes to find the desired frame range. """ import hou start_frame = None end_frame = None frame_incr = None if rop.type().name() == "merge": # For Merge ROPs, # the start frame is the min. start frame of its inputs, # the end frame is the max. end frame of its inputs, # and the increment is the min. increment of its inputs. for input_rop in rop.inputs(): in_start, in_end, in_inc = _getFrameRangeFromRopRecurse(input_rop) if start_frame is None or in_start < start_frame: start_frame = in_start if end_frame is None or in_end > end_frame: end_frame = in_end if frame_incr is None or in_inc < frame_incr: frame_incr = in_inc elif rop.type().name() == "fetch": # Get the frame range from the fetched ROP. source_rop = _getFetchedROP(rop) start_frame, end_frame, frame_incr = \ _getFrameRangeFromRopRecurse(source_rop) else: # Get the start, end and increment frame values. # If trange absent, we assume the full range. if (rop.parm('trange') is not None) and (rop.evalParm("trange") == 0): start_frame = int(hou.frame()) end_frame = int(hou.frame()) frame_incr = 1 elif rop.parmTuple("f") is not None: start_frame = int(rop.evalParm("f1")) end_frame = int(rop.evalParm("f2")) frame_incr = int(rop.evalParm("f3")) else: # The node does not have a frame range parameter set. # Try searching for the frame range on its input nodes. for input_node in rop.inputs(): start_frame, end_frame, frame_incr = \ _getFrameRangeFromRopRecurse(input_node) if start_frame is not None: break if frame_incr is not None and frame_incr <= 0: frame_incr = 1 return (start_frame, end_frame, frame_incr)
def update_object(self, node_object, node_context): self.cache_node.node = node_object self.cache_node.context = node_context self.cache_node.f_range = node_object.parm("trange").eval() self.cache_node.frame_increment = node_object.parm("f3").eval() self.cache_node.file_path = node_object.parm("sopoutput").rawValue() if node_context == "SOP": self.cache_node.file_path = node_object.parent().parm( "file").rawValue() if self.cache_node.f_range: self.cache_node.frame_start = int(node_object.parm("f1").eval()) self.cache_node.frame_end = int(node_object.parm("f2").eval()) else: self.cache_node.frame_start = int(hou.frame()) self.cache_node.frame_end = int(hou.frame())
def get_current_frame(): """ Return current Maya frame set in time slider :return: int """ return hou.frame()
def cache_path(mode='path'): node = hou.pwd() name = node.evalParm('cache_name') if node.evalParm('enable_version'): ver = '_v{0:0>3}'.format(node.evalParm('version')) else: ver = '' if node.evalParm('trange') > 0: frame = '.{0:0>4}'.format(int(hou.frame())) else: frame = '' ext = node.evalParm('ext') full_name = '{name}{ver}{frame}{ext}'.format(name=name, ver=ver, frame=frame, ext=ext) path = util.fix_path(os.path.join(node.evalParm('cache_dir'), full_name)) if mode == 'path': return path elif mode == 'name': return full_name else: return
def deleteExistingGhostAtFrame(self, ghost_geo_folder, ghost_mat_folder, ghosts): """Deletes a ghost at the current frame. INPUTS: ghosts -- selected objects ghost_mat_folder -- ghost shader network folder ghost_geo_folder -- ghost folder """ with hou.undos.group("Delete Ghost"): current_frame = hou.frame() for ghost in ghosts: ghost_name = ghost.name() existing_ghost_mat = hou.node( '/obj/InBetween_ghost_folder/ghost_shaders/' + ghost_name + '_ghost_mat' + '_frame_' + str(current_frame)) if existing_ghost_mat: for node in ghost_geo_folder.glob(ghost_name + "*" + '_frame_' + str(current_frame)): node.destroy() for mat in ghost_mat_folder.glob(ghost_name + '_ghost_mat' + '_frame_' + str(current_frame)): mat.destroy()
def destroy_archive(self): """Remove the archives of the disk and its dependencies.""" if not self.saveto_parm.eval(): return user_confirm = hou.ui.displayConfirmation( 'Do you want to remove cached archive(s)?', severity=hou.severityType.Warning, title='pxrlightarrays') if not user_confirm: return delayed_archive = self.find_node(parent=hou.node('/shop'), node_type='pxrdelayedreadarchive::22') if delayed_archive: geo_archive = self.find_node(parent=hou.node('/obj'), node_type='geo', archive=delayed_archive) if geo_archive: geo_archive.destroy() delayed_archive.destroy() with hou.InterruptableOperation( 'Performing', 'Removing archive(s)', open_interrupt_dialog=True) as operation: if self.time_range: for current_frame in self.frame_range: percent = current_frame / float(len(self.frame_range)) operation.updateLongProgress(percent, 'Frame: %s' % current_frame) saveto_parm = self.saveto_parm.evalAtFrame(current_frame) if os.path.exists(saveto_parm): os.remove(saveto_parm) else: operation.updateLongProgress(1, 'Frame: %s' % hou.frame()) if os.path.exists(self.saveto_parm.eval()): os.remove(self.saveto_parm.eval())
def set_frame_range(self, start_frame=1, end_frame=100, adjust_frame_range=False): """sets the frame range """ # -------------------------------------------- # set the timeline current_frame = hou.frame() if current_frame < start_frame: hou.setFrame(start_frame) elif current_frame > end_frame: hou.setFrame(end_frame) # for now use hscript, the python version is not implemented yet hou.hscript( 'tset `(' + str(start_frame) + '-1)/$FPS` `' + str( end_frame) + '/$FPS`' ) # -------------------------------------------- # Set the render nodes frame ranges if any # get the out nodes output_nodes = self.get_output_nodes() for output_node in output_nodes: output_node.setParms( {'trange': 0, 'f1': start_frame, 'f2': end_frame, 'f3': 1} )
def fetch_data_from_mantra_node(input_node): """Collects data form Mantra input node. Assumes that input node is Mantra node Args: input_node: hou.Node, Mantra node. Returns: {str, object}, Submission parameters. """ output_picture = input_node.parm('vm_picture').unexpandedString() result = dict( output_filename=os.path.basename(output_picture), renderer='mantra', renderer_version=hou.applicationVersion(), render_current_frame=False ) if input_node.parm('trange').evalAsString() == 'off': current_frame = hou.frame() result['frame_begin'] = current_frame result['frame_end'] = current_frame result['step'] = 1 # Resolution limits only apply to non- and limited-commercial, so "Render Current Frame" # isn't needed otherwise. result['render_current_frame'] = (hou.licenseCategory() != hou.licenseCategoryType.Commercial) else: result['frame_begin'] = input_node.parm('f1').eval() result['frame_end'] = input_node.parm('f2').eval() result['step'] = input_node.parm('f3').eval() return result
def render(self, preview=True): renderFolder = hou.getenv('HIP') + '/render' if not os.path.exists(renderFolder): os.makedirs(renderFolder) prevFrame = hou.frame() prevDelay = self.pane.delay() prevUpdateTime = self.pane.updateTime() prevPreview = self.pane.isPreviewOn() self.pane.setDelay(0) self.pane.setUpdateTime(0.2) self.pane.setPreview(preview) start = self.frames[0] end = self.frames[1] + 1 inc = self.frames[2] for frame in range(start, end, inc): hou.setFrame(frame) self.pane.resumeRender() time.sleep(self.renderTime) self.pane.pauseRender() self.saveFrame(frame) hou.setFrame(prevFrame) self.pane.setDelay(prevDelay) self.pane.setUpdateTime(prevUpdateTime) self.pane.setPreview(prevPreview)
def fetch_data_from_arnold_node(input_node): """Collects data form Arnold input node. Assumes that input node is Arnold node Args: input_node: hou.Node, Arnold node. Returns: {str, object}, Submission parameters. """ output_picture = input_node.parm('ar_picture').unexpandedString() result = dict( output_filename=os.path.basename(output_picture), renderer='arnold' ) if input_node.parm('trange').evalAsString() == 'off': current_frame = hou.frame() result['frame_begin'] = current_frame result['frame_end'] = current_frame result['step'] = 1 else: result['frame_begin'] = input_node.parm('f1').eval() result['frame_end'] = input_node.parm('f2').eval() result['step'] = input_node.parm('f3').eval() return result
def saveprojectAs(self): cur_desktop = hou.ui.curDesktop() scene = cur_desktop.paneTabOfType(hou.paneTabType.SceneViewer) a = hou.hipFile.name() k = a.split('/') hip = '' hip = hou.ui.selectFile(title='Save', file_type=hou.fileType.Hip, start_directory=self.projpath) if hip != '': hou.hipFile.save(file_name=hip) f = hou.frame() fn = hou.hipFile.basename().split('.') del fn[-1] filename = '.'.join(fn) path = hou.hipFile.path().split('/') del path[-1] filepath = '/'.join(path) + '/_thumbnails/' + filename + '.jpg' newpath = '/'.join(path) + '/_thumbnails' if not os.path.exists(newpath): os.makedirs(newpath) flip_options = scene.flipbookSettings().stash() flip_options.frameRange((f, f)) flip_options.useResolution(1) flip_options.resolution((500, 500)) flip_options.output(filepath) scene.flipbook(scene.curViewport(), flip_options) self.CreateInterface()
def set_frame_range(self, start_frame=1, end_frame=100, adjust_frame_range=False): """sets the frame range """ # -------------------------------------------- # set the timeline current_frame = hou.frame() if current_frame < start_frame: hou.setFrame(start_frame) elif current_frame > end_frame: hou.setFrame(end_frame) # for now use hscript, the python version is not implemented yet hou.hscript('tset `(' + str(start_frame) + '-1)/$FPS` `' + str(end_frame) + '/$FPS`') # -------------------------------------------- # Set the render nodes frame ranges if any # get the out nodes output_nodes = self.get_output_nodes() for output_node in output_nodes: output_node.setParms({ 'trange': 0, 'f1': start_frame, 'f2': end_frame, 'f3': 1 })
def save_edit(self): _current_hip = hou.hipFile.name() if len(_current_hip.split("/")) ==0: pass else: # 截图功能 _current_desktop = hou.ui.curDesktop() _scene_viewer = _current_desktop.paneTabOfType(hou.paneTabType.SceneViewer) _current_frame = hou.frame() _jpg_path = hou.hipFile.name().split(".")[0] _jpg_file_path = _jpg_path+".jpg" #getFlipbook _flip_options = _scene_viewer.flipbookSettings().stash() #SetFlipbook _flip_options.frameRange((_current_frame,_current_frame)) _flip_options.outputToMPlay(0) _flip_options.useResolution(1) _flip_options.resolution((500,500)) _flip_options.output(_jpg_file_path) #RunFlipbook _scene_viewer.flipbook(_scene_viewer.curViewport(), _flip_options) if self.text2.textColor().rgb()==4294901760: _documentation_path = _jpg_path+".txt" _documentation_text = self.text2.toPlainText() _f = open(_documentation_path, 'w') _f.write(_documentation_text) _f.close() else: pass
def fetch_data_from_mantra_node(input_node): """Collects data form Mantra input node. Assumes that input node is Mantra node Args: input_node: hou.Node, Mantra node. Returns: {str, object}, Submission parameters. """ output_picture = input_node.parm('vm_picture').unexpandedString() result = dict(output_filename=os.path.basename(output_picture), renderer='mantra', renderer_version=hou.applicationVersion(), render_current_frame=False) if input_node.parm('trange').evalAsString() == 'off': current_frame = hou.frame() result['frame_begin'] = current_frame result['frame_end'] = current_frame result['step'] = 1 # Resolution limits only apply to non- and limited-commercial, so "Render Current Frame" # isn't needed otherwise. result['render_current_frame'] = ( hou.licenseCategory() != hou.licenseCategoryType.Commercial) else: result['frame_begin'] = input_node.parm('f1').eval() result['frame_end'] = input_node.parm('f2').eval() result['step'] = input_node.parm('f3').eval() return result
def build_scriptargs(node=None): """Build relevant scriptargs for this action. :param node: Optionally rendering node. :type node: hou.RopNode :return: Data related to the running script parm. :rtype: dict """ frame_range = None if node is not None: trange_parm = node.parm("trange") if trange_parm is not None: if trange_parm.evalAsString() != "off": frame_range = node.evalParmTuple("f") scriptargs = { "node": node, "frame": hou.frame(), "frame_range": frame_range, "time": time.time(), } if node is not None: scriptargs["path"] = _get_target_file(node) return scriptargs
def pickGhostColor(self, color, alpha): """Change the color of the current ghost. INPUT: color -- color object from Color Editor alpha -- alpha from Color Editor """ new_color = QtGui.QColor.fromRgbF(color.rgb()[0], color.rgb()[1], color.rgb()[2]) self.ghostColorLabel.setStyleSheet("QLabel {background-color: " + new_color.name() + ";}") if hou.node("/obj/InBetween_ghost_folder/ghost_shaders/"): current_frame = hou.frame() ghost_mat_folder = hou.node( "/obj/InBetween_ghost_folder/ghost_shaders/") for shader in ghost_mat_folder.children(): shader_frame = shader.name().split("_")[-1] if shader_frame == str(current_frame): shader.setParms({ "ogl_specx": self.ghostColorLabel.palette().color( QtGui.QPalette.Base).redF(), "ogl_specy": self.ghostColorLabel.palette().color( QtGui.QPalette.Base).greenF(), "ogl_specz": self.ghostColorLabel.palette().color( QtGui.QPalette.Base).blueF() })
def process(self, context): for instance in context: # Skip invalid instance families if "render" not in instance.data.get("families", []): continue node = instance[0] # Get expected output files. files = [] if node.parm("trange").eval() == 0: frame = int(hou.frame()) files.append(node.parm("vm_picture").evalAtFrame(frame)) else: start = node.parm("f1").eval() end = node.parm("f2").eval() step = node.parm("f3").eval() for frame in range(int(start), int(end) + 1, int(step)): files.append(node.parm("vm_picture").evalAtFrame(frame)) # Get extension ext = os.path.splitext(files[0])[1] # Create output collection. collections = clique.assemble(files, minimum_items=1)[0] collection = None for col in collections: if col.format("{tail}") == ext: collection = col if collection: instance.data["render"] = collection.format()
def calculateValue(self, param): """Calculate the new key value based on the nieghbour key values and slider value coef. INPUTS: param -- current param OUTPUTS: calculatedValue -- new value """ currentFrame = hou.frame() self.deleteOldKeyframe(param) coef = float(self.valueSlider.value() ) / 100 #calculate a coefficient from a slider value prevKey = param.keyframesBefore(currentFrame)[ -1] #get value from the previous key nextKey = param.keyframesAfter(currentFrame)[ 0] #get value from the next key if prevKey.expression() == "constant()" or nextKey.expression( ) == "constant()": #if keyframe type is constant calculatedValue = self.getValueFromConstant( param ) #convert nieghbours to linear and get current parameter value else: calculatedValue = param.eval( ) #set the new key value to current parameter value if coef > 0: calculatedValue += (nextKey.value() - calculatedValue) * abs(coef) elif coef < 0: calculatedValue -= (calculatedValue - prevKey.value()) * abs(coef) else: calculatedValue = param.eval() return calculatedValue
def getBetweenKeyValue(self, param): """Calculate a value for the new key. INPUTS: param -- current param OUTPUTS: betweenKeyValue -- new value """ currentFrame = hou.frame() keysBefore = param.keyframesBefore(currentFrame) #get previous keys keysAfter = param.keyframesAfter(currentFrame) #get next keys #check if there's only one nieghbour key or no keys if keysBefore == () or keysAfter == (): betweenKeyValue = param.eval() #check if there's a key at current frame and no neighbour elif (keysBefore[-1].frame() == currentFrame and len(keysBefore) == 1) or (keysAfter[0].frame() == currentFrame and len(keysAfter) == 1): betweenKeyValue = param.eval() else: betweenKeyValue = self.calculateValue(param) return betweenKeyValue
def blend(self, blend): animEdit = None for pane in hou.ui.currentPaneTabs(): if pane.type() == hou.paneTabType.ChannelEditor: animEdit = pane if animEdit: graph = animEdit.graph() keyframes = graph.selectedKeyframes() # if there are keyframes selected # tween those if keyframes: for parm in keyframes.keys(): for key in keyframes[parm]: tween(parm, key.frame(), blend) return # otherwise, just use the scoped / visible channels at the current time scope = hou.hscript("chscope")[0] for x in scope.split(): chan = hou.parm(x) # only operate on channels that are visible in the graph editor if chan.isSelected(): with hou.undos.group('tweenmachine'): tween(chan, hou.frame(), blend)
def _getFrameRangeFromRop(rop): """Return a 3-tuple of start_frame, end_frame and frame_increment for the render frame range in the given ROP node.""" start_frame, end_frame, frame_incr = _getFrameRangeFromRopRecurse(rop) # If a frame range could not be found then just return the current frame # as the frame range. if start_frame is None or end_frame is None or frame_incr is None: print ("Warning: Could not determine frame range from '%s' node." \ " Using current frame instead.") % rop.path() import hou start_frame = int(hou.frame()) end_frame = int(hou.frame()) frame_incr = 1 return start_frame, end_frame, frame_incr
def getJobParameters( afnode, subblock = False, frame_range = None, prefix = ''): if VERBOSE: print 'Getting Job Parameters from "%s":' % afnode.path() # Process frame range: if frame_range is None: frame_first = hou.frame() frame_last = frame_first frame_inc = 1 frame_pertask = 1 else: frame_first, frame_last, frame_inc, frame_pertask = frame_range trange = afnode.parm('trange') if int(trange.eval()) > 0: frame_first = int( afnode.parm('f1').eval()) frame_last = int( afnode.parm('f2').eval()) frame_inc = int( afnode.parm('f3').eval()) frame_pertask = int( afnode.parm('frame_pertask').eval()) frame_range = frame_first, frame_last, frame_inc, frame_pertask params = [] connections = [] connections.extend( afnode.inputs()) nodes = [] for node in connections: if node is not None: nodes.append( node) if afnode.parm('cmd_add').eval(): nodes.append(None) nodes.reverse() dependmask = '' prevparams = [] for node in nodes: if node and node.isBypassed(): continue newparams = [] if node and node.type().name() == 'afanasy': newprefix = node.name() if prefix != '': newprefix = prefix + '_' + newprefix newparams = getJobParameters( node, True, frame_range, newprefix) dependmask = newprefix + '_.*' if newparams is None: return None else: newparams = getBlockParameters( afnode, node, subblock, prefix, frame_range) if newparams is None: return None dependmask = newparams[0].name for param in newparams: if not param.valid: return None if len(newparams): params.extend(newparams) else: return None if not afnode.parm('independent').eval() and dependmask != '': for prevparam in prevparams: prevparam.addDependMask( dependmask) prevparams = newparams # Last parameter needed to generate a job. if not subblock: params.append( BlockParameters( afnode, None, False, '', frame_range, True)) return params
def keysAtFrame(node, frame=hou.frame()): result = () for p in node.parms(): if p.keyframesInRange(frame, frame): result += (p, ) return result
def playrange_extend_spacing(direction): # list_sf, list_f = sim_cache_framelists() # index = sim_cache_precedent_index( hou.playbar.playbackRange()[0] ) # index = max (index + direction, 0) # frame_start = list_f[index] # frame_end = hou.playbar.playbackRange()[1] # hou.playbar.setPlaybackRange( frame_start, frame_end ) if direction == -1: frame_start = hou.frame() frame_end = hou.playbar.playbackRange()[1] if direction == 1: frame_end = hou.playbar.playbackRange()[0] frame_start = hou.frame() hou.playbar.setPlaybackRange(frame_start, frame_end)
def buildScriptArgs(node=None): """Build relevant scriptargs for this action.""" scriptargs = { "node": node, "frame": hou.frame(), "time": time.time(), } return scriptargs
def take_viewport_screenshot(self, output_path, extension): """ Take a screenshot of the viewport. Save the image at the given path with the given extension. """ camera_path = self.get_viewport_camera() frame = hou.frame() hou.hscript("viewwrite -f %d %d %s '%s'" % (frame, frame, camera_path, output_path)) self.software_print("Generated screenshot at path " + output_path)
def deleteOldKeyframe(self, param): """Delete old key at current frame. INPUTS: param -- parameter which keys must be deleted """ currentFrame = hou.frame() for key in param.keyframes(): #check all keys at given parm if key.frame( ) == currentFrame: #if its frame is the same as current param.deleteKeyframeAtFrame(currentFrame)
def process(self, instance): import math import hou node = instance[0] collection = instance.data["collection"] job_data = {} plugin_data = {} if "deadlineData" in instance.data: job_data = instance.data["deadlineData"]["job"].copy() plugin_data = instance.data["deadlineData"]["plugin"].copy() # Setting job data. job_data["Plugin"] = "Houdini" # Replace houdini frame padding with Deadline padding fmt = "{head}" + "#" * collection.padding + "{tail}" job_data["OutputFilename0"] = collection.format(fmt) job_data["Priority"] = instance.data["deadlinePriority"] job_data["Pool"] = instance.data["deadlinePool"] job_data["ConcurrentTasks"] = instance.data["deadlineConcurrentTasks"] # Frame range start_frame = int(node.parm("f1").eval()) end_frame = int(node.parm("f2").eval()) step_frame = int(node.parm("f3").eval()) if node.parm("trange").eval() == 0: start_frame = end_frame = int(hou.frame()) job_data["Frames"] = "{0}-{1}x{2}".format(start_frame, end_frame, step_frame) # Chunk size job_data["ChunkSize"] = instance.data["deadlineChunkSize"] if len(list(collection)) == 1: job_data["ChunkSize"] = str(end_frame) else: tasks = (end_frame - start_frame + 1.0) / step_frame chunks = (end_frame - start_frame + 1.0) / job_data["ChunkSize"] # Deadline can only handle 5000 tasks maximum if tasks > 5000 and chunks > 5000: job_data["ChunkSize"] = str(int(math.ceil(tasks / 5000.0))) # Setting plugin data plugin_data["OutputDriver"] = node.path() plugin_data["Version"] = str(hou.applicationVersion()[0]) plugin_data["IgnoreInputs"] = "0" plugin_data["SceneFile"] = instance.context.data["currentFile"] # Setting data data = {"job": job_data, "plugin": plugin_data} instance.data["deadlineData"] = data
def ghostShaderCreate(self, ghost_mat_folder, ghost_name): """Create a shader for a new ghost. INPUTS: ghost_mat_folder -- ghost shader network folder ghost_name -- object name from which a new ghost is created OUTPUTS: ghost_shader -- new ghost shader node """ with hou.undos.group("Create Ghost Shader"): current_frame = hou.frame() ghost_shader = ghost_mat_folder.createNode( 'vopmaterial', node_name=ghost_name + "_ghost_mat" + '_frame_' + str(current_frame)) parm_group = ghost_shader.parmTemplateGroup() parm_folder = hou.FolderParmTemplate("folder", "OpenGL") parm_folder.addParmTemplate( hou.FloatParmTemplate("ogl_spec", "Specular", 3)) parm_folder.addParmTemplate( hou.FloatParmTemplate("ogl_transparency", "Transparency", 1)) parm_folder.addParmTemplate( hou.FloatParmTemplate("ogl_ior", "IOR", 1)) parm_folder.addParmTemplate( hou.FloatParmTemplate("ogl_spec_intensity", "Intensity", 1)) parm_folder.addParmTemplate( hou.FloatParmTemplate("ogl_rough", "Roughness", 1)) parm_group.append(parm_folder) ghost_shader.setParmTemplateGroup(parm_group) ghost_shader.setParms({ "ogl_specx": self.ghostColorLabel.palette().color( QtGui.QPalette.Base).redF(), "ogl_specy": self.ghostColorLabel.palette().color( QtGui.QPalette.Base).greenF(), "ogl_specz": self.ghostColorLabel.palette().color( QtGui.QPalette.Base).blueF(), "ogl_transparency": 1, "ogl_ior": 1.06, "ogl_spec_intensity": 5, "ogl_rough": 0 }) ghost_shader.moveToGoodPosition() return ghost_shader
def get_time_commandline(node: hou.Node): time_type = node.parm("time_type").evalAsString() time = 0.0 (frame_start, frame_end, _) = node.parmTuple("f").eval() frame = hou.frame() if time_type == "range": time = (frame - frame_start) / (frame_end - frame_start) elif time_type == "range_loop": time = (frame - frame_start) / (frame_end - frame_start + 1.0) elif time_type == "custom": time = node.evalParm("time") return ["--set-value", f"$time@{time}"]
def set_frame_range(self, start_frame=1, end_frame=100, adjust_frame_range=False): """sets the frame range """ # -------------------------------------------- # set the timeline current_frame = hou.frame() if current_frame < start_frame: hou.setFrame(start_frame) elif current_frame > end_frame: hou.setFrame(end_frame) # for now use hscript, the python version is not implemented yet hou.hscript( 'tset `(' + str(start_frame) + '-1)/$FPS` `' + str( end_frame) + '/$FPS`' )
def process(self, context): import os import hou import clique for instance in context: # Skip invalid instance families if "render" not in instance.data.get("families", []): continue node = instance[0] # Get expected output files. files = [] if node.parm("trange").eval() == 0: frame = int(hou.frame()) files.append(node.parm("vm_picture").evalAtFrame(frame)) else: start = node.parm("f1").eval() end = node.parm("f2").eval() step = node.parm("f3").eval() for frame in range(int(start), int(end) + 1, int(step)): files.append(node.parm("vm_picture").evalAtFrame(frame)) # Get extension ext = os.path.splitext(files[0])[1] # Create output collection. collections = clique.assemble(files, minimum_items=1)[0] collection = None for col in collections: if col.format("{tail}") == ext: collection = col if collection: instance.data["render"] = collection.format()
def getJobParameters(afnode, subblock=False, frame_range=None, prefix=""): if VERBOSE: print('Getting Job Parameters from "%s":' % afnode.path()) # Process frame range: if frame_range is None: frame_first = hou.frame() frame_last = frame_first frame_inc = 1 else: frame_first, frame_last, frame_inc = frame_range trange = afnode.parm("trange") if int(trange.eval()) > 0: frame_first = int(afnode.parm("f1").eval()) frame_last = int(afnode.parm("f2").eval()) frame_inc = int(afnode.parm("f3").eval()) frame_range = frame_first, frame_last, frame_inc params = [] connections = [] connections.extend(afnode.inputs()) nodes = [] for node in connections: if node is not None: nodes.append(node) output_driver_path = afnode.parm("output_driver").eval() if output_driver_path: output_driver = hou.node(output_driver_path) if output_driver: nodes.insert(0, output_driver) else: hou.ui.displayMessage('Can`t find output drive node: "%s"' % output_driver_path) if afnode.parm("cmd_mode").eval(): nodes.append(None) nodes.reverse() dependmask = "" prevparams = [] for node in nodes: if node and node.isBypassed(): continue newparams = [] if node and node.type().name() == "afanasy": newprefix = node.name() if prefix != "": newprefix = prefix + "_" + newprefix newparams = getJobParameters(node, True, frame_range, newprefix) dependmask = newprefix + "_.*" if newparams is None: return None else: newparams = getBlockParameters(afnode, node, subblock, prefix, frame_range) if newparams is None: return None dependmask = newparams[0].name for param in newparams: if not param.valid: return None if len(newparams): params.extend(newparams) else: return None if not afnode.parm("independent").eval() and dependmask != "": for prevparam in prevparams: prevparam.addDependMask(dependmask) prevparams = newparams # Last parameter needed to generate a job. if not subblock: params.append(BlockParameters(afnode, None, False, "", frame_range, True)) return params
def render(node): prescript = ''' import KrakatoaSR import random ri = KrakatoaSR.Ri() ''' option = optionScript(node) framebegin = 'ri.FrameBegin({0})\n'.format(int(hou.frame())) cam = hou.node(node.parm('camera').eval()) outpath = node.parm('vm_picture').eval() display = 'ri.Display( "{outpath}", "file", "rgba" )'.format(outpath=outpath) print(display) resx,resy = cam.parmTuple('res').eval() aspect = cam.parm('aspect').eval() format = "ri.Format( {x}, {y}, {aspect} )".format(x=resx, y=resy, aspect=aspect) print(format) aperture = cam.parm('aperture').eval() aperture = min(aperture, aperture/resx*resy) # krakatoa uses renderman style focal = cam.parm('focal').eval() fov = math.degrees(2*math.atan(aperture/2/focal)) camtrans = cam.worldTransform().inverted()*hou.Matrix4([[1,0,0,0],[0,1,0,0],[0,0,-1,0],[0,0,0,1]]) camtrans = [str(i) for i in camtrans.asTuple()] cam_projection = 'ri.Projection( "perspective", "fov", {fov} )'.format(fov=fov) cam_transform = 'ri.Transform({transmatrix})'.format(transmatrix=','.join(camtrans)) worldbegin = '\nri.WorldBegin()' #Surface! # In houdini : object.worldTransform() prtfile = node.parm('scene_prt').evalAsString() objectscript = '''ri.AttributeBegin() ri.Surface( "Isotropic" ) ri.Transform(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1) ri.PointsFile("{0}") ri.AttributeEnd() '''.format(prtfile) worldend = 'ri.WorldEnd()' frameend = 'ri.FrameEnd()' ss = [] #scene script ss.append(prescript) ss.append(option) ss.append(framebegin) ss.append(display) ss.append(format) ss.append(cam_projection) ss.append(cam_transform) ss.append(worldbegin) ss.append(lightScript(node)) ss.append(objectscript) ss.append(worldend) ss.append(frameend) # make prt try: tmpobj = hou.node('/obj/tmp_krakatoa') tmpsop = tmpgeo.node('krakatoa_export') except: tmpobj = hou.node('/obj').createNode('geo') tmpobj.setName('tmp_krakatoa') tmpsop = tmpobj.createNode('object_merge') tmpsop.setName('krakatoa_export') ksops = hou.node('/obj').glob('krakatoa*') ksops = [i for i in ksops if i.isDisplayFlagSet()] tmpsop.parm('numobj').set(len(ksops)) for i, s in enumerate(ksops): parmname = 'objpath'+str(i+1) tmpsop.parm(parmname).set(s.path()) tmpgeo = tmpsop.geometry() tmpgeo.saveToFile(prtfile) tmpobj.destroy() # for debug turn this off # make scene description scenefile = node.parm('scene_description').evalAsString() with open(scenefile, 'w') as f: f.write('\n'.join(ss)) output,error = subprocess.Popen(['python', scenefile],stdout = subprocess.PIPE, stderr= subprocess.PIPE).communicate() print(error)
def __init__(self, afnode, ropnode, subblock, prefix, frame_range, for_job_only=False): if VERBOSE == 2: if ropnode: print('Initializing block parameters for "%s" from "%s"' % (ropnode.path(), afnode.path())) else: print('Initializing command block parameters from "%s"' % afnode.path()) # Init parameters: self.valid = False self.afnode = afnode self.ropnode = None self.subblock = subblock self.frame_pertask = 1 self.frame_sequential = 1 self.prefix = prefix self.preview = '' self.name = '' self.type = '' self.parser = '' self.cmd = '' self.cmd_useprefix = True self.dependmask = '' self.fullrangedepend = False self.numeric = True self.frame_first, self.frame_last, self.frame_inc = frame_range self.tasks_names = [] self.tasks_cmds = [] self.tasks_previews = [] # Parameters to restore ROP changes: self.soho_foreground = None self.soho_outputmode = None # ############################################################################ # Dict of parameters to restore ROP changes: added by DavidPower self.param_restoreList = {} # ############################################################################ # Get parameters: self.frame_pertask = int(afnode.parm('frame_pertask').eval()) self.frame_sequential = int(afnode.parm('frame_sequential').eval()) self.job_name = str(afnode.parm('job_name').eval()) self.start_paused = int(afnode.parm('start_paused').eval()) self.platform = str(afnode.parm('platform').eval()) self.subtaskdepend = int(afnode.parm('subtaskdepend').eval()) self.parser = self.afnode.parm('override_parser').eval() self.priority = -1 self.max_runtasks = -1 self.maxperhost = -1 self.maxruntime = -1 self.capacity = -1 self.capacity_min = -1 self.capacity_max = -1 self.hosts_mask = '' self.hosts_mask_exclude = '' self.depend_mask = '' self.depend_mask_global = '' if afnode.parm('enable_extended_parameters').eval(): self.priority = int(afnode.parm('priority').eval()) self.max_runtasks = int(afnode.parm('max_runtasks').eval()) self.maxperhost = int(afnode.parm('maxperhost').eval()) self.maxruntime = int(afnode.parm('maxruntime').eval()) self.capacity = int(afnode.parm('capacity').eval()) self.capacity_min = int( afnode.parm('capacity_coefficient1').eval()) self.capacity_max = int( afnode.parm('capacity_coefficient2').eval()) self.hosts_mask = str(afnode.parm('hosts_mask').eval()) self.hosts_mask_exclude = str( afnode.parm('hosts_mask_exclude').eval()) self.depend_mask = str(afnode.parm('depend_mask').eval()) self.depend_mask_global = str( afnode.parm('depend_mask_global').eval()) # Process frame range: opname = afnode.path() if afnode.parm('trange').eval() > 1: self.fullrangedepend = True if ropnode: opname = ropnode.path() trange = ropnode.parm('trange') if trange is not None: if int(trange.eval()) > 0: if ropnode.parm('f1') is not None: self.frame_first = int(ropnode.parm('f1').eval()) if ropnode.parm('f2') is not None: self.frame_last = int(ropnode.parm('f2').eval()) if ropnode.parm('f3') is not None: self.frame_inc = int(ropnode.parm('f3').eval()) if int(trange.eval()) > 1: self.fullrangedepend = True if self.frame_last < self.frame_first: hou.ui.displayMessage('Last frame < first frame for "%s"' % opname) return if self.frame_inc < 1: hou.ui.displayMessage('Frame increment < 1 for "%s"' % opname) return if self.frame_pertask < 1: hou.ui.displayMessage('Frames per task < 1 for "%s"' % opname) return # Process output driver type to construct a command: if ropnode: self.type = 'hbatch' if not isinstance(ropnode, hou.RopNode): hou.ui.displayMessage( '"%s" is not a ROP node' % ropnode.path() ) return self.ropnode = ropnode self.name = str(ropnode.name()) if self.prefix != '': self.name = '%s_%s' % (self.prefix, self.name) # Block type and preview: roptype = ropnode.type().name() if roptype == 'ifd': if not ropnode.parm('soho_outputmode').eval(): self.type = 'hbatch_mantra' vm_picture = ropnode.parm('vm_picture') if vm_picture is not None: self.preview = \ afcommon.patternFromPaths( vm_picture.evalAsStringAtFrame(self.frame_first), vm_picture.evalAsStringAtFrame(self.frame_last) ) elif roptype == 'rib': self.type = 'hbatch_prman' # Block command: self.cmd = 'hrender_af' if afnode.parm('ignore_inputs').eval(): self.cmd += ' -i' if self.capacity_min != -1 or self.capacity_max != -1: self.cmd += ' --numcpus ' + services.service.str_capacity self.cmd += ' -s @#@ -e @#@ --by %d -t "%s"' % ( self.frame_inc, afnode.parm('take').eval() ) self.cmd += ' "%(hipfilename)s"' self.cmd += ' "%s"' % ropnode.path() # Override service: override_service = self.afnode.parm('override_service').eval() if override_service is not None and len(override_service): self.type = override_service else: # Custom command driver: if int(afnode.parm('cmd_mode').eval()): # Command: cmd = self.afnode.parm('cmd_cmd') self.cmd = afcommon.patternFromPaths( cmd.evalAsStringAtFrame(self.frame_first), cmd.evalAsStringAtFrame(self.frame_last) ) # Name: self.name = self.afnode.parm('cmd_name').eval() if self.name is None or self.name == '': self.name = self.cmd.split(' ')[0] # Service: self.type = self.afnode.parm('cmd_service').eval() if self.type is None or self.type == '': self.type = self.cmd.split(' ')[0] # Parser: self.parser = self.afnode.parm('cmd_parser').eval() # Prefix: self.cmd_useprefix = \ int(self.afnode.parm('cmd_use_afcmdprefix').eval()) elif not for_job_only: hou.ui.displayMessage('Can\'t process "%s"' % afnode.path()) return # Try to set driver foreground mode if ropnode: trange = ropnode.parm('trange') soho_foreground = ropnode.parm('soho_foreground') if trange is not None and int(trange.eval()) == 0: # ############################################################################ # fixed [Render Current Frame] error # added by DavidPower # ############################################################################ self.frame_first = int(hou.frame()) self.frame_last = int(hou.frame()) # ############################################################################ if soho_foreground is not None: if soho_foreground.eval() == 0: try: soho_foreground.set(1) self.soho_foreground = 0 except: # TODO: too broad exception clause hou.ui.displayMessage( 'Set "Block Until Render Complete" on "%s" ' 'node' % ropnode.path() ) return # Try to create output folder: if self.preview != '' and afnode.parm('check_output_folder').eval(): folder = os.path.dirname( self.preview) if not os.path.isdir( folder): if hou.ui.displayMessage( folder, buttons=('Create','Abort'),default_choice=0,close_choice=1, title='Output Folder Does Not Exist',details=folder) == 0: try: os.makedirs(folder) except Exception as e: hou.ui.displayMessage( folder, buttons=('Abort',),default_choice=0,close_choice=1, title='Error Creating Output Folder',details=str(e)) return if not os.path.isdir( folder): hou.ui.displayMessage( folder, buttons=('Abort',),default_choice=0,close_choice=1, title='Can`t Create Output Folder',details=folder) return else: return self.valid = True
def getJobParameters(afnode, subblock=False, frame_range=None, prefix=''): if VERBOSE: print('Getting Job Parameters from "%s":' % afnode.path()) # Process frame range: if frame_range is None: frame_first = int(hou.frame()) frame_last = frame_first frame_inc = 1 else: frame_first, frame_last, frame_inc = frame_range trange = afnode.parm('trange') if int(trange.eval()) > 0: frame_first = int(afnode.parm('f1').eval()) frame_last = int(afnode.parm('f2').eval()) frame_inc = int(afnode.parm('f3').eval()) frame_range = frame_first, frame_last, frame_inc params = [] connections = [] connections.extend(afnode.inputs()) nodes = [] for node in connections: if node is not None: nodes.append(node) output_driver_path = afnode.parm('output_driver').eval() if output_driver_path: output_driver = hou.node(output_driver_path) if output_driver: nodes.insert(0, output_driver) else: hou.ui.displayMessage('Can`t find output drive node: "%s"' % output_driver_path) if afnode.parm('cmd_mode').eval(): nodes.append(None) nodes.reverse() dependmask = '' prevparams = [] for node in nodes: if node and node.isBypassed(): continue newparams = [] if node and node.type().name() == 'afanasy': newprefix = node.name() if prefix != '': newprefix = prefix + '_' + newprefix newparams = getJobParameters(node, True, frame_range, newprefix) dependmask = newprefix + '_.*' if newparams is None: return None elif node and node.type().name() == "wedge": wedgednode = None if node.inputs(): wedgednode = node.inputs()[0] else: wedgednode = node.node(node.parm("driver").eval()) if wedgednode == None: return None numWedges = computeWedge( node, node.type().name()) # we can remove nodetype check names = node.hdaModule().getwedgenames(node) for wedge in range(numWedges): # switching wedges like houdini do to get valid filenames hou.hscript('set WEDGE = ' + names[wedge]) hou.hscript('set WEDGENUM = ' + str(wedge)) hou.hscript('varchange') #add wedged node to next block block = getBlockParameters(afnode, wedgednode, subblock, "{}_{}".format(node.name(),wedge), frame_range)[0] block.auxargs += " --wedge " + node.path() + " --wedgenum " + str(wedge) newparams.append(block) # clear environment hou.hscript('set WEDGE = ') hou.hscript('set WEDGENUM = ') hou.hscript('varchange') else: newparams = \ getBlockParameters(afnode, node, subblock, prefix, frame_range) if newparams is None: return None dependmask = newparams[0].name for param in newparams: if not param.valid: param.doPost() return None if len(newparams): params.extend(newparams) else: return None if not afnode.parm('independent').eval() and dependmask != '': for prevparam in prevparams: prevparam.addDependMask(dependmask) prevparams = newparams # Last parameter needed to generate a job. if not subblock: params.append( BlockParameters(afnode, None, False, '', frame_range, True) ) return params