def testStandardAttributeConversion( self ) : torus = self.createTorus() color = torus.createOutputNode( "color" ) color.parm( "colortype" ).set( 2 ) rest = color.createOutputNode( "rest" ) scale = rest.createOutputNode( "attribcreate" ) scale.parm( "name1" ).set( "pscale" ) scale.parm( "value1v1" ).setExpression( "$PT" ) uvunwrap = scale.createOutputNode( "uvunwrap" ) converter = IECoreHoudini.FromHoudiniPolygonsConverter( uvunwrap ) result = converter.convert() if hou.applicationVersion()[0] >= 15 : self.assertEqual( result.keys(), [ "Cs", "P", "Pref", "s", "t", "width" ] ) else : self.assertEqual( result.keys(), [ "Cs", "P", "Pref", "s", "t", "varmap", "width" ] ) self.assertTrue( result.arePrimitiveVariablesValid() ) self.assertEqual( result["P"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( result["Pref"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) sData = result["s"].data tData = result["t"].data geo = uvunwrap.geometry() uvs = geo.findVertexAttrib( "uv" ) i = 0 for prim in geo.prims() : verts = list(prim.vertices()) verts.reverse() for vert in verts : uvValues = vert.attribValue( uvs ) self.assertAlmostEqual( sData[i], uvValues[0] ) self.assertAlmostEqual( tData[i], 1 - uvValues[1] ) i += 1 converter["convertStandardAttributes"].setTypedValue( False ) result = converter.convert() if hou.applicationVersion()[0] >= 15 : self.assertEqual( result.keys(), [ "Cd", "P", "pscale", "rest", "uv" ] ) else : self.assertEqual( result.keys(), [ "Cd", "P", "pscale", "rest", "uv", "varmap" ] ) self.assertTrue( result.arePrimitiveVariablesValid() ) self.assertEqual( result["P"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( result["rest"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) uvData = result["uv"].data geo = uvunwrap.geometry() uvs = geo.findVertexAttrib( "uv" ) i = 0 for prim in geo.prims() : verts = list(prim.vertices()) verts.reverse() for vert in verts : uvValues = vert.attribValue( uvs ) self.assertAlmostEqual( uvData[i][0], uvValues[0] ) self.assertAlmostEqual( uvData[i][1], uvValues[1] ) i += 1
def testStandardAttributeConversion( self ) : points = self.createPoints() color = points.createOutputNode( "color" ) color.parm( "colortype" ).set( 2 ) rest = color.createOutputNode( "rest" ) scale = rest.createOutputNode( "attribcreate" ) scale.parm( "name1" ).set( "pscale" ) scale.parm( "value1v1" ).setExpression( "$PT" ) converter = IECoreHoudini.FromHoudiniPointsConverter( scale ) result = converter.convert() if hou.applicationVersion()[0] >= 15 : self.assertEqual( result.keys(), [ "Cs", "N", "P", "Pref", "width" ] ) else : self.assertEqual( result.keys(), [ "Cs", "N", "P", "Pref", "varmap", "width" ] ) self.assertTrue( result.arePrimitiveVariablesValid() ) self.assertEqual( result["P"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( result["Pref"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( result["N"].data.getInterpretation(), IECore.GeometricData.Interpretation.Normal ) converter["convertStandardAttributes"].setTypedValue( False ) result = converter.convert() if hou.applicationVersion()[0] >= 15 : self.assertEqual( result.keys(), [ "Cd", "N", "P", "pscale", "rest" ] ) else : self.assertEqual( result.keys(), [ "Cd", "N", "P", "pscale", "rest", "varmap" ] ) self.assertTrue( result.arePrimitiveVariablesValid() ) self.assertEqual( result["P"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( result["rest"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( result["N"].data.getInterpretation(), IECore.GeometricData.Interpretation.Normal )
def testWeldUVs( self ) : torus = self.createTorus() uvunwrap = torus.createOutputNode( "uvunwrap" ) converter = IECoreHoudini.FromHoudiniPolygonsConverter( uvunwrap ) result = converter.convert() if hou.applicationVersion()[0] >= 15 : self.assertEqual( result.keys(), [ "P", "uv" ] ) else : self.assertEqual( result.keys(), [ "P", "uv", "varmap" ] ) self.assertTrue( result.arePrimitiveVariablesValid() ) self.assertEqual( result["uv"].data.getInterpretation(), IECore.GeometricData.Interpretation.UV ) self.assertEqual( result["uv"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.FaceVarying ) uvData = result["uv"].data uvIndices = result["uv"].indices geo = uvunwrap.geometry() uvs = geo.findVertexAttrib( "uv" ) i = 0 for prim in geo.prims() : verts = list(prim.vertices()) verts.reverse() for vert in verts : uvValues = vert.attribValue( uvs ) self.assertAlmostEqual( uvData[ uvIndices[i] ][0], uvValues[0] ) self.assertAlmostEqual( uvData[ uvIndices[i] ][1], uvValues[1] ) i += 1 converter["weldUVs"].setTypedValue( False ) result = converter.convert() if hou.applicationVersion()[0] >= 15 : self.assertEqual( result.keys(), [ "P", "uv" ] ) else : self.assertEqual( result.keys(), [ "P", "uv", "varmap" ] ) self.assertTrue( result.arePrimitiveVariablesValid() ) self.assertEqual( result["uv"].data.getInterpretation(), IECore.GeometricData.Interpretation.UV ) self.assertEqual( result["uv"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.FaceVarying ) uvData = result["uv"].data self.assertEqual( result["uv"].indices, None ) geo = uvunwrap.geometry() uvs = geo.findVertexAttrib( "uv" ) i = 0 for prim in geo.prims() : verts = list(prim.vertices()) verts.reverse() for vert in verts : uvValues = vert.attribValue( uvs ) self.assertAlmostEqual( uvData[i][0], uvValues[0] ) self.assertAlmostEqual( uvData[i][1], uvValues[1] ) i += 1
def __init__(self, name="", version=None): super(Houdini, self).__init__(name, version) from stalker import Repository # re initialize repo vars for repo in Repository.query.all(): env_var_name = repo.env_var value = repo.path self.set_environment_variable(env_var_name, value) self.name = '%s%s.%s' % (self.name, hou.applicationVersion()[0], hou.applicationVersion()[1])
def init_engine(self): """ Main initialization entry point. """ self.log_debug("%s: Initializing..." % self) if hou.applicationVersion()[0] < 12: raise tank.TankError( "Your version of Houdini is not supported. Currently, Toolkit only supports version 12+" ) # Support OS X on 14+ only if sys.platform == "darwin" and hou.applicationVersion()[0] < 14: raise tank.TankError( "Your version of Houdini is not supported on OS X. Currently, " "Toolkit only supports version 14+ on OS X.") try: hou_ver_str = ".".join([str(v) for v in hou.applicationVersion()]) self.log_user_attribute_metric("Houdini version", hou_ver_str) except: # ignore all errors. ex: using a core that doesn't support metrics pass # keep track of if a UI exists self._ui_enabled = hasattr(hou, 'ui') # pyside is integrated as of houdini 14. if hou.applicationVersion()[0] >= 14: self._integrated_pyside = True self._ui_type = "PySide" self.log_debug("Using integrated PySide.") else: self._integrated_pyside = False self._ui_type = None # add our built-in pyside to the python path when on windows if not self._integrated_pyside and sys.platform == "win32": py_ver = sys.version_info[0:2] if py_ver == (2, 6): pyside_path = os.path.join(self.disk_location, "resources", "pyside112_py26_win64") sys.path.append(pyside_path) self.log_debug("Using bundled PySide: %s" % (pyside_path, )) elif py_ver == (2, 7): pyside_path = os.path.join(self.disk_location, "resources", "pyside121_py27_win64") sys.path.append(pyside_path) self.log_debug("Using bundled PySide: %s" % (pyside_path, )) else: self.log_warning("PySide not bundled for python %d.%d" % (py_ver[0], py_ver[1]))
def __init__(self, name="", version=None): super(Houdini, self).__init__(name, version) from stalker import Repository # re initialize repo vars for repo in Repository.query.all(): env_var_name = repo.env_var value = repo.path self.set_environment_variable(env_var_name, value) # TODO: remove the following line # export old env var self.set_environment_variable("REPO%s" % repo.id, value) self.name = '%s%s.%s' % (self.name, hou.applicationVersion()[0], hou.applicationVersion()[1])
def apply_stylesheet(self): import hou self._changing_stylesheet = True try: # This is only safe in pre-H16. If we do this in 16 it destroys # some styling in Houdini itself. if self.parent() and hou.applicationVersion() < (16, 0, 0): self.parent().setStyleSheet("") engine._apply_external_styleshet(bundle, self) # Styling in H16+ is very different than in earlier versions of # Houdini. The result is that we have to be more careful about # behavior concerning stylesheets, because we might bleed into # Houdini itself if we change qss on parent objects or make use # of QStyles on the QApplication. # # Below, we're combining the engine-level qss with whatever is # already assigned to the widget. This means that the engine # styling is helping patch holes in any app- or framework-level # qss that might have already been applied. if hou.applicationVersion() >= (16, 0, 0): qss_file = engine._get_engine_qss_file() with open(qss_file, "rt") as f: qss_data = f.read() qss_data = engine._resolve_sg_stylesheet_tokens( qss_data) qss_data = qss_data.replace( "{{ENGINE_ROOT_PATH}}", engine._get_engine_root_path()) self.setStyleSheet(self.styleSheet() + qss_data) self.update() # We have some funky qss behavior in H16 that requires us to # kick the parent's stylesheet by reassigning it as is. Not # sure what causes the problem, but this does resolve it. The # original symptoms were some widgets not changing after applying # the engine's stylesheet, while others did. if self.parent(): self.parent().setStyleSheet(self.parent().styleSheet()) except Exception as e: engine.logger.warning( "Unable to re-apply stylesheet for panel: %s %s" % (title, e)) finally: self._changing_stylesheet = False self._stylesheet_applied = True
def init_engine(self): """ Main initialization entry point. """ self.log_debug("%s: Initializing..." % self) if hou.applicationVersion()[0] < 12: raise tank.TankError("Your version of Houdini is not supported. Currently, Toolkit only supports version 12+") # Support OS X on 14+ only if sys.platform == "darwin" and hou.applicationVersion()[0] < 14: raise tank.TankError( "Your version of Houdini is not supported on OS X. Currently, " "Toolkit only supports version 14+ on OS X.") try: hou_ver_str = ".".join([str(v) for v in hou.applicationVersion()]) self.log_user_attribute_metric("Houdini version", hou_ver_str) except: # ignore all errors. ex: using a core that doesn't support metrics pass # keep track of if a UI exists self._ui_enabled = hasattr(hou, 'ui') # pyside is integrated as of houdini 14. if hou.applicationVersion()[0] >= 14: self._integrated_pyside = True self._ui_type = "PySide" self.log_debug("Using integrated PySide.") else: self._integrated_pyside = False self._ui_type = None # add our built-in pyside to the python path when on windows if not self._integrated_pyside and sys.platform == "win32": py_ver = sys.version_info[0:2] if py_ver == (2, 6): pyside_path = os.path.join(self.disk_location, "resources", "pyside112_py26_win64") sys.path.append(pyside_path) self.log_debug("Using bundled PySide: %s" % (pyside_path,)) elif py_ver == (2, 7): pyside_path = os.path.join(self.disk_location, "resources", "pyside121_py27_win64") sys.path.append(pyside_path) self.log_debug("Using bundled PySide: %s" % (pyside_path,)) else: self.log_warning("PySide not bundled for python %d.%d" % (py_ver[0], py_ver[1]))
def fetch_data_from_simulation_node(input_node): """Collects data from simulation input node. Assumes that input node is a simulation node Args: input_node: hou.Node, a simulation node. Returns: {str, object}, Submission parameters. """ output_parm_names = dict(output='dopoutput', filecache='file') parm_name = output_parm_names.get(input_node.type().name()) output_dir = input_node.parm(parm_name).unexpandedString() result = dict(output_filename=os.path.basename(output_dir), renderer='simulation', renderer_version=hou.applicationVersion(), render_current_frame=False) 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 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 add_spare_parameters(self, target): vtuple = hou.applicationVersion() rfhtree = hou.getenv("RFHTREE") renderobjnames = ["geo"] rendercamnames = ["cam"] if target.type().name() in renderobjnames: path = rfhtree + "/18.5.351/soho/parameters/geoparms.ds" elif target.type().name() in rendercamnames: path = rfhtree + "/18.5.351/soho/parameters/camparms.ds" else: return None grp = target.parmTemplateGroup() spareparms = hou.ParmTemplateGroup() with open(path) as file: ds = file.read() spareparms.setToDialogScript(ds) for template in spareparms.parmTemplates(): grp.append(template) try: target.parmsInFolder(("RenderMan",)) except: target.setParmTemplateGroup(grp) if target.type().name() == "geo": hou.hscript("opproperty %s prman23geo *" % target.path()) elif target.type().name() == "cam": hou.hscript("opproperty %s prman23cam *" % target.path())
def findIcons(self): if hou.applicationVersion()[0] < 15: for category in os.listdir(self.path): for ico in os.listdir(os.path.join(self.path, category)): iconPath = os.path.join( os.path.join(self.path, category, ico)) iconName = '_'.join([category, os.path.splitext(ico)[0]]) self.icons[iconName] = QPixmap(iconPath) else: zf = zipfile.ZipFile(self.path, 'r') for f in zf.namelist(): if f.startswith('old'): continue if os.path.splitext(f)[-1] == '.svg': svg = QSvgRenderer(QByteArray(zf.read(f))) if not svg.isValid(): continue pixmap = QPixmap(iconSize, iconSize) painter = QPainter() painter.begin(pixmap) pixmap.fill(QColor(Qt.black)) svg.render(painter) painter.end() category, ico = f.split('/') iconName = '_'.join([category, os.path.splitext(ico)[0]]) self.icons[iconName] = pixmap zf.close()
def show_dialog(self, title, bundle, widget_class, *args, **kwargs): """ Shows a modeless dialog. Overridden from base class. """ from sgtk.platform.qt import QtCore, QtGui # In houdini, the script editor runs in a custom thread. Any commands executed here # which are calling UI functionality may cause problems with QT. Check that we are # running in the main thread if QtCore.QThread.currentThread() != QtGui.QApplication.instance().thread(): self.execute_in_main_thread(self.logger.error, "Error creating dialog: You can only launch UIs " "in the main thread. Try using the execute_in_main_thread() method.") return # create the dialog: dialog, widget = self._create_dialog_with_widget(title, bundle, widget_class, *args, **kwargs) # show the dialog: dialog.show() # I don't have an answer to why this does what it does. We have # a situation in H16 where some aspects of our widgets can't be # styled...the changes just don't have any impact. However, if # we re-apply the parent's stylesheet, unchanged, after we show # our dialog, those styling changes we've applied either as part # of the app's style.qss, or tk-houdini's, everything sticks the # way it should. if hou.applicationVersion() >= (16, 0, 0): dialog.parent().setStyleSheet(dialog.parent().styleSheet()) # lastly, return the instantiated widget return widget
def fetch_data_from_simulation_node(input_node): """Collects data from simulation input node. Assumes that input node is a simulation node Args: input_node: hou.Node, a simulation node. Returns: {str, object}, Submission parameters. """ output_parm_names = dict( output='dopoutput', filecache='file') parm_name = output_parm_names.get(input_node.type().name()) output_dir = input_node.parm(parm_name).unexpandedString() result = dict( output_filename=os.path.basename(output_dir), renderer='simulation', renderer_version=hou.applicationVersion(), render_current_frame=False ) 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 _panels_supported(self): """ Returns True if panels are supported for current Houdini version. """ ver = hou.applicationVersion() # first version where saving python panel in desktop was fixed if sys.platform.startswith("darwin"): # We have some serious painting problems with Python panes in # H16 that are specific to OS X. We have word out to SESI, and # are waiting to hear back from them as to how we might be able # to proceed. Until that is sorted out, though, we're going to # have to disable panel support on OS X for H16. Our panel apps # appear to function just fine in dialog mode. # # Update: H17 resolves some of the issues, but we still have problems # with item delegates not rendering consistently in the Shotgun Panel's # entity views. if ver >= (16, 0, 0): return False if ver >= (15, 0, 272): return True return False
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 testContextCreator( self ) : # test generic creation n = IECoreHoudini.FnProceduralHolder.create( "test", "parameterTypes" ) self.assertEqual( n.path(), "/obj/test/test" ) # test contextArgs outside UI mode fallback to generic behaviour contextArgs = { "toolname" : "ieProceduralHolder" } n2 = IECoreHoudini.FnProceduralHolder.create( "test", "parameterTypes", contextArgs=contextArgs ) self.assertEqual( n2.path(), "/obj/test1/test" ) # test parent arg geo = hou.node( "/obj" ).createNode( "geo", run_init_scripts=False ) n3 = IECoreHoudini.FnProceduralHolder.create( "test", "parameterTypes", parent=geo, contextArgs=contextArgs ) self.assertEqual( n3.path(), "/obj/geo1/test" ) # test automatic conversion contextArgs["shiftclick"] = True n4 = IECoreHoudini.FnProceduralHolder.create( "test", "parameterTypes", parent=geo, contextArgs=contextArgs ) self.assertEqual( n4.path(), "/obj/geo1/test1" ) self.assertEqual( len(n4.outputConnectors()[0]), 1 ) self.assertEqual( n4.outputConnectors()[0][0].outputNode().type().name(), "ieCortexConverter" ) # test automatic conversion and output connections mountain = geo.createNode( "mountain" ) contextArgs["outputnodename"] = mountain.path() n5 = IECoreHoudini.FnOpHolder.create( "test", "parameterTypes", parent=geo, contextArgs=contextArgs ) self.assertEqual( n5.path(), "/obj/geo1/test2" ) self.assertEqual( len(n5.outputConnectors()[0]), 1 ) converter = n5.outputConnectors()[0][0].outputNode() self.assertEqual( converter.type().name(), "ieCortexConverter" ) self.assertEqual( len(converter.outputConnectors()[0]), 1 ) outputNode = converter.outputConnectors()[0][0].outputNode() self.assertEqual( outputNode.type().name(), "mountain::2.0" if hou.applicationVersion()[0] >= 16 else "mountain" ) self.assertEqual( outputNode, mountain )
def setUp(self): IECoreHoudini.TestCase.setUp(self) self.__torusTestFile = "test/IECoreHoudini/data/torus.cob" if hou.applicationVersion( )[0] < 14 else "test/IECoreHoudini/data/torusH14.cob" self.__torusNormalsTestFile = "test/IECoreHoudini/data/torus_with_normals.cob" if not os.path.exists("test/opHolder_testData"): os.mkdir("test/opHolder_testData")
def __createHoudiniQGLWidget(cls, format): try: import hou except ImportError: # we're not in houdini - createQGLWidget() will just make a # normal widget. return None import IECoreHoudini # Prior to Houdini 14 we are running embedded on the hou.ui idle loop, # so we needed to force the Houdini GL context to be current, and share # it, similar to how we do this in Maya. if hou.applicationVersion()[0] < 14: return cls.__createHostedQGLWidget( format, IECoreHoudini.makeMainGLContextCurrent) # In Houdini 14 and beyond, Qt is the native UI, and we can access # Houdini's shared QGLWidget directly, provided we are using a recent # Cortex version. return QtOpenGL.QGLWidget(format, shareWidget=GafferUI._qtObject( IECoreHoudini.sharedGLWidget(), QtOpenGL.QGLWidget))
def findIcons(self): if hou.applicationVersion()[0] < 15: for category in os.listdir(self.path): for ico in os.listdir(os.path.join(self.path, category)): iconPath = os.path.join(os.path.join(self.path, category, ico)) iconName = '_'.join([category, os.path.splitext(ico)[0]]) self.icons[iconName] = QPixmap(iconPath) else: zf = zipfile.ZipFile(self.path, 'r') for f in zf.namelist(): if f.startswith('old'):continue if os.path.splitext(f)[-1] == '.svg': svg = QSvgRenderer(QByteArray(zf.read(f))) if not svg.isValid(): continue pixmap = QPixmap(iconSize, iconSize) painter = QPainter() painter.begin(pixmap) pixmap.fill(QColor(Qt.black)) svg.render(painter) painter.end() category, ico = f.split('/') iconName = '_'.join([category, os.path.splitext(ico)[0]]) self.icons[iconName] = pixmap zf.close()
def version_creator(): """Helper function for version_creator UI for Houdini """ # connect to db do_db_setup() import logging from stalker import log log.logging_level = logging.WARNING from anima.ui import version_creator from anima.env import houdini reload(houdini) reload(version_creator) h = houdini.Houdini() logger.setLevel(logging.WARNING) if hou.applicationVersion()[0] <= 13: version_creator.UI( environment=h ) else: version_creator.UI( environment=h, executor=Executor() )
def __init__(self, parent_node, snippetcontext): super(InvalidContextError, self).__init__("this snippet has '%s' context" % snippetcontext) self.__necontext = getChildContext(parent_node, hou.applicationVersion()) self.__snippetcontext = snippetcontext self.__node = parent_node
def init_engine(self): """ Main initialization entry point. """ self.log_debug("%s: Initializing..." % self) if hou.applicationVersion()[0] < 12: raise tank.TankError( "Your version of Houdini is not supported. Currently, Toolkit only supports version 12+" ) # keep track of if a UI exists self._ui_enabled = hasattr(hou, 'ui') # add our built-in pyside to the python path when on windows if sys.platform == "win32": py_ver = sys.version_info[0:2] if py_ver == (2, 6): pyside_path = os.path.join(self.disk_location, "resources", "pyside112_py26_win64") sys.path.append(pyside_path) elif py_ver == (2, 7): pyside_path = os.path.join(self.disk_location, "resources", "pyside121_py27_win64") sys.path.append(pyside_path) else: self.log_warning("PySide not bundled for python %d.%d" % (py_ver[0], py_ver[1]))
def __init__(self): super(iconsWidgetClass, self).__init__() self.setStyleSheet("background:#323232;") # custom bg color self.vLy = QVBoxLayout(self) self.fLy = QHBoxLayout() self.vLy.addLayout(self.fLy) label = QLabel('Filter: ') self.fLy.addWidget(label) self.clear_btn = QPushButton('') self.clear_btn.setIcon(hou.ui.createQtIcon('BUTTONS_remove')) self.clear_btn.clicked.connect(self.fill) self.clear_btn.setFixedSize(QSize(20, 20)) self.fLy.addWidget(self.clear_btn) @self.clear_btn.clicked.connect def clearFilter(): if self.filter.text(): self.filter.setText('') self.fill() self.filter = QLineEdit() self.filter.returnPressed.connect(self.fill) self.fLy.addWidget(self.filter) self.search_btn = QPushButton('Search') self.search_btn.clicked.connect(self.fill) self.fLy.addWidget(self.search_btn) # self.btn = QPushButton('Clear') # self.btn.clicked.connect(self.clearList) # self.vLy.addWidget(self.btn) self.scrollArea = QScrollArea(self) self.vLy.addWidget(self.scrollArea) self.scrollArea.setWidgetResizable(True) self.sawc = QFrame() self.ly = QVBoxLayout(self.sawc) self.scrollArea.setWidget(self.sawc) hfs = hou.getenv('HFS') if hou.applicationVersion()[0] < 15: path = os.path.join(hfs, 'houdini/help/icons/large') else: path = os.path.join(hfs, 'houdini/help/icons.zip') self.icons = {} self.content = None if os.path.exists(path): self.path = path self.findIcons() self.fill() else: err = QLabel('Icons not found!') err.setStyleSheet('font-size:25px;') err.setAlignment(Qt.AlignHCenter | Qt.AlignTop) self.ly.addWidget(err)
def EmitDataChanged(self, index): # The PySide2 version of the dataChanged signal requires a # 3rd argument. Check the houdini version number to determine # whether to use the PySide or PySide2 version. if hou.applicationVersion()[0] >= 16: self.dataChanged.emit(index, index, []) else: self.dataChanged.emit(index, index)
def get_hou_major_version(): """ A wrapper for returning Houdini's major version Returns: String: Returns a string containing Houdini's major version number. E.g. '15' """ return str(hou.applicationVersion()[0])
def hcopyweb(): qapp = QApplication.instance() try: nodes = hou.selectedItems() except: nodes = hou.selectedNodes() enctype = hpasteoptions.getOption('hpasteweb.encryption_type', 'None') key = None encparms = {} if enctype == 'AES-CBC': key = ''.join([ random.choice(string.ascii_letters + string.digits) for x in xrange(AES.block_size) ]) encparms = {'mode': AES.MODE_CBC} enctype = 'AES' elif enctype.lower() == 'none' or enctype == '': enctype = None if enctype is not None and key is None: print('Warning: unknown encryption method, disabling encryption') enctype = None try: s = nodesToString(nodes, encryption_type=enctype, key=key, **encparms) except RuntimeError as e: hou.ui.displayMessage("Error: %s" % str(e.message), severity=hou.severityType.Error) return except RuntimeWarning as e: # da heck? hou.ui.displayMessage("Warning: %s" % str(e.message), severity=hou.severityType.Warning) #except Exception as e: # hou.ui.displayMessage("Internal Error: %s %s" % (str(type(e)), str(e.message)), severity=hou.severityType.Error) # return if isinstance(qapp, QApplication): qapp.setOverrideCursor(qtc.Qt.WaitCursor) try: s = webPack(s) except Exception as e: hou.ui.displayMessage(e.message, severity=hou.severityType.Error, title='error') return finally: if isinstance(qapp, QApplication): qapp.restoreOverrideCursor() # append key to snippet if enctype is not None: s = key + '!' + s if hou.applicationVersion()[0] > 15: hou.ui.copyTextToClipboard(s) else: qapp.clipboard().setText(s) hou.ui.setStatusMessage("Success: Cloud link copied to clipboard!")
def hpasteweb(pane=None): qapp = QApplication.instance() if hou.applicationVersion()[0] > 15: s = hou.ui.getTextFromClipboard() else: s = qapp.clipboard().text() if isinstance(qapp, QApplication): qapp.setOverrideCursor(qtc.Qt.WaitCursor) # check for compression key key = None if '!' in s: key, s = s.split('!', 1) try: s = webUnpack(s) except Exception as e: hou.ui.displayMessage(e.message, severity=hou.severityType.Error, title='error') return finally: if isinstance(qapp, QApplication): qapp.restoreOverrideCursor() try: stringToNodes(s, ne=pane, key=key) except InvalidContextError as e: nec, snc = e.contexts() if snc == 'Sop' and nec == 'Object': if hou.ui.displayMessage("Error: %s" % str(e.message), severity=hou.severityType.Warning, buttons=('Create geo node', 'Cancel'), default_choice=0, close_choice=1) == 0: geonode = e.node().createNode('geo') if pane is not None: geonode.setPosition(pane.cursorPosition()) stringToNodes(s, hou_parent=geonode, key=key) else: hou.ui.displayMessage("Error: %s" % str(e.message), severity=hou.severityType.Error) return except WrongKeyLengthError as e: hou.ui.displayMessage("Bad key length: %s. Check if you copied hpaste link correctly" % str(e.message), severity=hou.severityType.Error) return except NoKeyError as e: hou.ui.displayMessage("This snippet is encrypted and requires a key: %s. Check if you copied hpaste link correctly. key in the link usually goes in front of the snippet, separated by '!'" % str(e.message), severity=hou.severityType.Error) return except WrongKeyError as e: hou.ui.displayMessage("Wrong key: %s. Check if you copied hpaste link correctly" % str(e.message), severity=hou.severityType.Error) return except RuntimeError as e: hou.ui.displayMessage("Error: %s" % str(e.message), severity=hou.severityType.Error) return except RuntimeWarning as e: hou.ui.displayMessage("Warning: %s" % str(e.message), severity=hou.severityType.Warning) #except Exception as e: # hou.ui.displayMessage("Internal Error: %s" % str(e.message), severity=hou.severityType.Error) # return hou.ui.setStatusMessage("Success: Nodes pasted!") # hpasteweb(kwargs['pane'])
def exec_(self, app, dialog): self.application = app if hou.applicationVersion()[0] <= 15: self.application.setStyle('CleanLooks') else: self.application.setStyle('Fusion') hou.ui.addEventLoopCallback(self.processEvents) dialog.exec_()
def sm_render_getDeadlineParams(self, origin, dlParams, homeDir): dlParams["pluginInfoFile"] = os.path.join( homeDir, "temp", "houdini_plugin_info.job" ) dlParams["jobInfoFile"] = os.path.join(homeDir, "temp", "houdini_submit_info.job" ) dlParams["jobInfos"]["Plugin"] = "Houdini" dlParams["jobInfos"]["Comment"] = "Prism-Submission-Houdini_%s" % origin.className dlParams["pluginInfos"]["OutputDriver"] = origin.node.path() dlParams["pluginInfos"]["IgnoreInputs"] = "True" if int(self.core.rfManagers["Deadline"].deadlineCommand( ["-version",] ).split(".")[0][1:]) > 9: dlParams["pluginInfos"]["Version"] = "%s.%s" % (hou.applicationVersion()[0], hou.applicationVersion()[1]) else: dlParams["pluginInfos"]["Version"] = hou.applicationVersion()[0] if hasattr(origin, "chb_resOverride") and origin.chb_resOverride.isChecked(): dlParams["pluginInfos"]["Width"] = origin.sp_resWidth.value() dlParams["pluginInfos"]["Height"] = origin.sp_resHeight.value()
def exec_(self, app, dialog): self.application = app app_version = hou.applicationVersion()[0] if app_version <= 15: self.application.setStyle('CleanLooks') elif 15 < app_version <= 17: self.application.setStyle('Fusion') hou.ui.addEventLoopCallback(self.processEvents) dialog.exec_()
def need_to_change_theme(self): import hou if '*' in self.theme_gb.title(): if hou.applicationVersion()[0] >= 16: a = QMessageBox.question(self, 'Unsaved changes', 'Undo changes in the theme "%s"?' % self.theme['name']) else: a = QMessageBox.question(self, 'Unsaved changes', 'Undo changes in the theme "%s"?' % self.theme['name'], QMessageBox.Yes | QMessageBox.No) return a == QMessageBox.Yes return True
def get_output_path(cls, node): """ Returns the evaluated output path for the supplied node. """ output_parm = node.parm(cls.NODE_OUTPUT_PATH_PARM) if hou.applicationVersion()[0] >= 18: return hou.text.expandString(output_parm.evalAsString()) else: return hou.expandString(output_parm.evalAsString())
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 generate_completes(force=False): # check parsed functions cache_file = vex_settings.get_autocomplete_cache_file() if os.path.exists(cache_file) and not force: return True # get vcc vcc = os.path.join(hou.getenv('HFS'), 'bin', 'vcc').replace('/','\\') if os.name == 'nt': vcc = vcc + '.exe' if not os.path.exists(vcc): return False # generate new funcs = {} attrs = {} process = QProcess() process.start(' '.join([vcc, '-X'])) process.waitForFinished() lines = str(process.readAll()).split('\n') for context in lines: if context: process.start(' '.join([vcc, '-X', context])) process.waitForFinished() context_lines = str(process.readAll()) # variables variables = re.search(r'Global Variables:(.*)Control Statements:', context_lines, re.DOTALL) if variables: lines = variables.group(1).strip().split('\n') for l in lines: s = l.split() if len(s)==3: attrs[s[-1]] = s[-2] # functions pat = r'^\s*(\w+\[?\]?)\s(\w+)(\(.+\))' for l in context_lines.split('\n'): func = re.findall(pat, str(l)) if func: f_name = func[0][1] f_args = func[0][2] if f_name in funcs: if not f_args in funcs[f_name].get('args', []): funcs[f_name]['args'].append(f_args) else: funcs[f_name] = {'args': [f_args]} # parse help if Houdini 15 if hou.applicationVersion()[0] >= 15: funcs = parse_help(funcs) # save to cache if os.path.exists(cache_file): comp = json.load(open(cache_file)) else: comp = {} comp['functions'] = funcs comp['attributes'] = attrs json.dump(comp, open(cache_file, 'w')) return True
def __init__(self): super(iconsWidgetClass, self).__init__() self.vLy = QVBoxLayout(self) self.fLy = QHBoxLayout() self.vLy.addLayout(self.fLy) label = QLabel('Filter: ') self.fLy.addWidget(label) self.clear_btn = QPushButton('') self.clear_btn.setIcon(hou.ui.createQtIcon('BUTTONS_remove')) self.clear_btn.clicked.connect(self.fill) self.clear_btn.setFixedSize(QSize(20,20)) self.fLy.addWidget(self.clear_btn) @self.clear_btn.clicked.connect def clearFilter(): if self.filter.text(): self.filter.setText('') self.fill() self.filter = QLineEdit() self.filter.returnPressed.connect(self.fill) self.fLy.addWidget(self.filter) self.search_btn = QPushButton('Search') self.search_btn.clicked.connect(self.fill) self.fLy.addWidget(self.search_btn) # self.btn = QPushButton('Clear') # self.btn.clicked.connect(self.clearList) # self.vLy.addWidget(self.btn) self.scrollArea = QScrollArea(self) self.vLy.addWidget(self.scrollArea) self.scrollArea.setWidgetResizable(True) self.sawc = QFrame() self.ly = QVBoxLayout(self.sawc) self.scrollArea.setWidget(self.sawc) hfs = hou.getenv('HFS') if hou.applicationVersion()[0] < 15: path = os.path.join(hfs,'houdini/help/icons/large') else: path = os.path.join(hfs,'houdini/help/icons.zip') self.icons = {} self.content = None if os.path.exists(path): self.path = path self.findIcons() self.fill() else: err = QLabel('Icons not found!') err.setStyleSheet('font-size:25px;') err.setAlignment(Qt.AlignHCenter|Qt.AlignTop) self.ly.addWidget(err)
def post_app_init(self): """ Init that runs after all apps have been loaded. """ tk_houdini = self.import_module("tk_houdini") bootstrap = tk_houdini.bootstrap if bootstrap.g_temp_env in os.environ: if self.has_ui: # setup houdini menus menu_file = os.path.join(os.environ[bootstrap.g_temp_env], 'MainMenuCommon') # as of houdini 12.5 add .xml if hou.applicationVersion() > (12, 5, 0): menu_file = menu_file + ".xml" menu = tk_houdini.MenuGenerator(self) if not os.path.exists(menu_file): # just create the xml for the menus menu.create_menu(menu_file) # get map of id to callback self._callback_map = menu.callback_map() # Figure out the tmp OP Library path for this session oplibrary_path = os.environ[bootstrap.g_temp_env].replace( "\\", "/") # Setup the OTLs that need to be loaded for the Toolkit apps self._load_otls(oplibrary_path) if self.has_ui: # startup Qt from tank.platform.qt import QtGui from tank.platform.qt import QtCore app = QtGui.QApplication.instance() if app is None: # create the QApplication sys.argv[0] = 'Shotgun' app = QtGui.QApplication(sys.argv) app.setQuitOnLastWindowClosed(False) app.setApplicationName(sys.argv[0]) # tell QT to interpret C strings as utf-8 utf8 = QtCore.QTextCodec.codecForName("utf-8") QtCore.QTextCodec.setCodecForCStrings(utf8) # set the stylesheet self._initialize_dark_look_and_feel() tk_houdini.python_qt_houdini.exec_(app)
def __init__(self, name="", extensions=None, version=None): super(Houdini, self).__init__(name, extensions, version) from stalker import Repository # re initialize repo vars for repo in Repository.query.all(): env_var_name = repo.env_var value = repo.path self.set_environment_variable(env_var_name, value) self.name = '%s%s' % (self.name, hou.applicationVersion()[0])
def apply_stylesheet(self): import hou self._changing_stylesheet = True try: # This is only safe in pre-H16. If we do this in 16 it destroys # some styling in Houdini itself. if self.parent() and hou.applicationVersion() < (16, 0, 0): self.parent().setStyleSheet("") engine._apply_external_styleshet(bundle, self) # Styling in H16+ is very different than in earlier versions of # Houdini. The result is that we have to be more careful about # behavior concerning stylesheets, because we might bleed into # Houdini itself if we change qss on parent objects or make use # of QStyles on the QApplication. # # Below, we're combining the engine-level qss with whatever is # already assigned to the widget. This means that the engine # styling is helping patch holes in any app- or framework-level # qss that might have already been applied. if hou.applicationVersion() >= (16, 0, 0): qss_file = engine._get_engine_qss_file() with open(qss_file, "rt") as f: qss_data = f.read() qss_data = engine._resolve_sg_stylesheet_tokens(qss_data) qss_data = qss_data.replace("{{ENGINE_ROOT_PATH}}", engine._get_engine_root_path()) self.setStyleSheet(self.styleSheet() + qss_data) self.update() # We have some funky qss behavior in H16 that requires us to # kick the parent's stylesheet by reassigning it as is. Not # sure what causes the problem, but this does resolve it. The # original symptoms were some widgets not changing after applying # the engine's stylesheet, while others did. if self.parent(): self.parent().setStyleSheet(self.parent().styleSheet()) except Exception, e: engine.logger.warning( "Unable to re-apply stylesheet for panel: %s %s" % (title, e) )
def _panels_supported(self): """ Returns True if panels are supported for current Houdini version. """ ver = hou.applicationVersion() # first version where saving python panel in desktop was fixed if ver >= (15, 0, 272): return True return False
def post_app_init(self): """ Init that runs after all apps have been loaded. """ tk_houdini = self.import_module("tk_houdini") bootstrap = tk_houdini.bootstrap if bootstrap.g_temp_env in os.environ: if self.has_ui: # setup houdini menus menu_file = os.path.join(os.environ[bootstrap.g_temp_env], 'MainMenuCommon') # as of houdini 12.5 add .xml if hou.applicationVersion() > (12, 5, 0): menu_file = menu_file + ".xml" menu = tk_houdini.MenuGenerator(self) if not os.path.exists(menu_file): # just create the xml for the menus menu.create_menu(menu_file) # get map of id to callback self._callback_map = menu.callback_map() # Figure out the tmp OP Library path for this session oplibrary_path = os.environ[bootstrap.g_temp_env].replace("\\", "/") # Setup the OTLs that need to be loaded for the Toolkit apps self._load_otls(oplibrary_path) if self.has_ui: # startup Qt from tank.platform.qt import QtGui from tank.platform.qt import QtCore app = QtGui.QApplication.instance() if app is None: # create the QApplication sys.argv[0] = 'Shotgun' app = QtGui.QApplication(sys.argv) app.setQuitOnLastWindowClosed(False) app.setApplicationName(sys.argv[0]) # tell QT to interpret C strings as utf-8 utf8 = QtCore.QTextCodec.codecForName("utf-8") QtCore.QTextCodec.setCodecForCStrings(utf8) # set the stylesheet self._initialize_dark_look_and_feel() tk_houdini.python_qt_houdini.exec_(app)
def create_menu(self, xml_path): """ Create the Shotgun Menu """ import hou # houdini 15+ allows for dynamic menu creation, so do that if possible. # otherwise, fallback to the static menu if hou.applicationVersion()[0] >= 15: self._engine.log_debug("Constructing dynamic Shotgun menu.") self._create_dynamic_menu(xml_path) else: self._engine.log_debug("Constructing static Shotgun menu.") self._create_static_menu(xml_path)
def torus( self ) : obj = hou.node( "/obj" ) geo = obj.createNode( "geo", run_init_scripts=False ) torus = geo.createNode( "torus" ) facet = torus.createOutputNode( "facet" ) facet.parm( "postnml" ).set( True ) mountain = facet.createOutputNode( "mountain" ) if hou.applicationVersion()[0] >= 16: mountain.parm("offsetx").setExpression("$FF") else: mountain.parm("offset1").setExpression( "$FF" ) return mountain
def testStandardAttributeConversion( self ) : merge = self.buildScene() color = merge.createOutputNode( "color" ) color.parm( "colortype" ).set( 2 ) rest = color.createOutputNode( "rest" ) scale = rest.createOutputNode( "attribcreate" ) scale.parm( "name1" ).set( "pscale" ) scale.parm( "value1v1" ).setExpression( "$PT" ) uvunwrap = scale.createOutputNode( "uvunwrap" ) converter = IECoreHoudini.FromHoudiniGroupConverter( uvunwrap ) result = converter.convert() for child in result.children() : if hou.applicationVersion()[0] >= 15 : self.assertEqual( child.keys(), ['Cs', 'P', 'Pref', 'accel', 'born', 'event', 'generator', 'generatorIndices', 'id', 'life', 'nextid', 'parent', 'pstate', 's', 'source', 't', 'v', 'width'] ) else : self.assertEqual( child.keys(), ['Cs', 'P', 'Pref', 'accel', 'born', 'event', 'generator', 'generatorIndices', 'id', 'life', 'nextid', 'parent', 'pstate', 's', 'source', 't', 'v', 'varmap', 'width'] ) self.assertTrue( child.arePrimitiveVariablesValid() ) self.assertEqual( child["P"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( child["Pref"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( child["accel"].data.getInterpretation(), IECore.GeometricData.Interpretation.Vector ) self.assertEqual( child["v"].data.getInterpretation(), IECore.GeometricData.Interpretation.Vector ) converter["convertStandardAttributes"].setTypedValue( False ) result = converter.convert() for child in result.children() : if hou.applicationVersion()[0] >= 15 : self.assertEqual( child.keys(), ['Cd', 'P', 'accel', 'born', 'event', 'generator', 'generatorIndices', 'id', 'life', 'nextid', 'parent', 'pscale', 'pstate', 'rest', 'source', 'uv', 'v'] ) else : self.assertEqual( child.keys(), ['Cd', 'P', 'accel', 'born', 'event', 'generator', 'generatorIndices', 'id', 'life', 'nextid', 'parent', 'pscale', 'pstate', 'rest', 'source', 'uv', 'v', 'varmap'] ) self.assertTrue( child.arePrimitiveVariablesValid() ) self.assertEqual( child["P"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( child["rest"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( child["accel"].data.getInterpretation(), IECore.GeometricData.Interpretation.Vector ) self.assertEqual( child["v"].data.getInterpretation(), IECore.GeometricData.Interpretation.Vector )
def testAnimatingGeometry( self ) : curves = self.createCurves( 4 ) mountain = curves.createOutputNode( "mountain" ) if hou.applicationVersion()[0] >= 16: mountain.parm("offsetx").setExpression( "$FF" ) else: mountain.parm( "offset1" ).setExpression( "$FF" ) converter = IECoreHoudini.FromHoudiniCurvesConverter( mountain ) hou.setFrame( 1 ) result1 = converter.convert() hou.setFrame( 2 ) converter = IECoreHoudini.FromHoudiniCurvesConverter( mountain ) result2 = converter.convert() self.assertNotEqual( result1["P"].data, result2["P"].data ) self.assertNotEqual( result1, result2 )
def init_engine(self): """ Main initialization entry point. """ self.logger.debug("%s: Initializing..." % self) if hou.applicationVersion()[0] < 14: raise sgtk.TankError( "Your version of Houdini is not supported. Currently, Toolkit " "only supports version 14+." ) # keep track of if a UI exists self._ui_enabled = hasattr(hou, 'ui')
def pre_app_init(self): """ Called at startup, but after QT has been initialized. """ if not self._ui_enabled: return if hou.applicationVersion()[0] >= 15: # In houdini 15+, we can use the dynamic menus and shelf api to # properly handle cases where a file is loaded outside of a SG # context. Make sure the timer that looks for current file changes # is running. tk_houdini = self.import_module("tk_houdini") tk_houdini.ensure_file_change_timer_running()
def testInterpretation( self ) : merge = self.buildScene() converter = IECoreHoudini.FromHoudiniGroupConverter( merge ) result = converter.convert() expectedKeys = ['Cs', 'P', 'accel', 'born', 'event', 'generator', 'generatorIndices', 'id', 'life', 'nextid', 'parent', 'pstate', 'source', 'v', 'varmap'] if hou.applicationVersion()[0] >= 13 : expectedKeys.remove( "varmap" ) for child in result.children() : self.assertTrue( child.isInstanceOf( IECore.TypeId.Primitive ) ) self.assertEqual( sorted(child.keys()), expectedKeys ) self.assertEqual( child["P"].data.getInterpretation(), IECore.GeometricData.Interpretation.Point ) self.assertEqual( child["accel"].data.getInterpretation(), IECore.GeometricData.Interpretation.Vector ) self.assertEqual( child["life"].data.getInterpretation(), IECore.GeometricData.Interpretation.None ) self.assertEqual( child["v"].data.getInterpretation(), IECore.GeometricData.Interpretation.Vector )
def addSopTags( node, tag, primRange ) : if hou.applicationVersion()[0] > 15: group = node.createOutputNode( "grouprange" ) group.parm("groupname1").set(tag) group.parm("start1").set(primRange[0]) group.parm("end1").set(primRange[1]) group.parm("selecttotal1").set(1) group.parm("method1").set(0) group.setRenderFlag(True) else: group = node.createOutputNode("group") group.parm( "crname" ).set( tag ) group.parm( "groupop" ).set( 1 ) # by range group.parm( "rangestart" ).set( primRange[0] ) group.parm( "rangeend" ).deleteAllKeyframes() group.parm( "rangeend" ).set( primRange[1] ) group.parm( "select2" ).set( 1 ) group.setRenderFlag( True )
def testNumericPresetMenus( self ) : # at present, Int/FloatParameters only support presetsOnly presets, due to the limitations of hou.MenuParmTemplate ( holder, fn ) = self.testOpHolder() holder.createInputNode( 0, "box" ) fn.setOp( "parameters/primitives/preset", 1 ) parm = holder.parm( "parm_switch" ) self.failUnless( isinstance( parm, hou.Parm ) ) template = parm.parmTemplate() self.failUnless( isinstance( template, hou.MenuParmTemplate ) ) # the int values are stored as strings in this crazy Houdini world self.assertEqual( template.menuItems(), ( "20", "30" ) ) self.assertEqual( template.menuLabels(), ( "A", "B" ) ) self.assertEqual( template.defaultValue(), 0 ) self.assertEqual( template.defaultValueAsString(), "20" ) self.assertEqual( parm.eval(), 0 ) self.assertEqual( parm.evalAsString(), "20" ) # but on the op values are really the ints we require op = fn.getOp() self.assertEqual( op["switch"].getTypedValue(), 20 ) parm.set( 1 ) holder.cook() self.assertEqual( op["switch"].getTypedValue(), 30 ) # Houdini 16 does not allow ordered menu parms to be set to non-menu items # if the parm is set to an index, and the index doesn't exist, then the parm is set to the closest item menu if hou.applicationVersion()[0] < 16: parm.set( 2 ) self.assertRaises( hou.OperationFailed, holder.cook ) parm.set( -1 ) self.assertRaises( hou.OperationFailed, holder.cook ) parm.set( 0 ) holder.cook() self.failUnless( not holder.errors() ) newHolder = holder.parent().createNode( "ieOpHolder" ) newFn = IECoreHoudini.FnOpHolder( newHolder ) op["switch"].setTypedValue( 30 ) newFn.setOp( op ) newParm = newHolder.parm( "parm_switch" ) self.assertEqual( newParm.eval(), 1 ) self.assertEqual( newParm.evalAsString(), "30" )
def update_complete_list(self, names=None): self.clear() if names: for i, n in enumerate(names): item = QListWidgetItem(self) # h14 if hou.applicationVersion()[0] <= 14: label = CompleterLabel(n, i%2, self) self.setItemWidget(item, label) else: # h15 item.setText(n.name) item.setData(32, n) self.addItem(item) self.setCurrentRow(0) self.showMe() else: self.hideMe() self.e.update()
def __init__(self, text, parent, desk): super(container, self).__init__() hbox = QHBoxLayout(self) hbox.setSpacing(0) hbox.setContentsMargins(0,0,0,0) # input widget self.edit = inputWidget.inputClass(parent, desk) self.edit.executeSignal.connect(parent.executeSelected) if text: self.edit.addText(text) # if not context == 'hou': # line number if context == 'hou': import hou if hou.applicationVersion()[0] > 14: hbox.addWidget(self.edit) return self.lineNum = numBarWidget.lineNumberBarClass(self.edit, self) hbox.addWidget(self.lineNum) hbox.addWidget(self.edit)
def testAnimatingGeometry( self ) : obj = hou.node( "/obj" ) geo = obj.createNode( "geo", run_init_scripts=False ) torus = geo.createNode( "torus" ) facet = geo.createNode( "facet" ) facet.parm("postnml").set(True) mountain = geo.createNode( "mountain" ) if hou.applicationVersion()[0] >= 16: mountain.parm( "offsetx" ).setExpression( "$FF" ) else: mountain.parm("offset1").setExpression( "$FF" ) facet.setInput( 0, torus ) mountain.setInput( 0, facet ) converter = IECoreHoudini.FromHoudiniPolygonsConverter( mountain ) hou.setFrame( 1 ) mesh1 = converter.convert() hou.setFrame( 2 ) converter = IECoreHoudini.FromHoudiniPolygonsConverter( mountain ) mesh2 = converter.convert() self.assertNotEqual( mesh1["P"].data, mesh2["P"].data ) self.assertNotEqual( mesh1, mesh2 )