def sNew(name, components, colorSpace): """ Create a new SDUsage :param name: The name of the usage :type name: string :param components: The components of the usage :type components: string :param colorSpace: The color space of the usage :type colorSpace: string :rtype: SDUsage """ outSDUsage = ctypes.c_void_p() _res = sd.getContext().SDUsage_sNew( ctypes.create_string_buffer(name.encode('utf-8')), ctypes.create_string_buffer(components.encode('utf-8')), ctypes.create_string_buffer(colorSpace.encode('utf-8')), ctypes.byref(outSDUsage)) if _res != SDApiError.NoError.value: if _res == SDApiError.NoErrorOutputParamNotSet.value: return None raise APIException(SDApiError(_res)) constructor = sd.getContext().mTypeMap[SDAPIObject( sd.getContext(), outSDUsage, ownHandle=False).getClassName()] return constructor(sd.getContext(), outSDUsage.value, ownHandle=True)
def sNew(): """ Create new SDTypeFloat3 :rtype: SDTypeFloat3 """ outSDTypeFloat3 = ctypes.c_void_p() _res = sd.getContext().SDTypeFloat3_sNew(ctypes.byref(outSDTypeFloat3)) if _res != SDApiError.NoError.value: if _res == SDApiError.NoErrorOutputParamNotSet.value: return None raise APIException(SDApiError(_res)) constructor = sd.getContext().mTypeMap[SDAPIObject(sd.getContext(), outSDTypeFloat3, ownHandle=False).getClassName()] return constructor(sd.getContext(), outSDTypeFloat3.value, ownHandle=True)
def sNewFromSDTypeMatrix(sdTypeMatrix): """ Create a new SDValueMatrix from a SDTypeMatrix :param sdTypeMatrix: The type of the new matrix :type sdTypeMatrix: SDTypeMatrix :rtype: SDValueMatrix """ outValueMatrix = ctypes.c_void_p() _res = sd.getContext().SDValueMatrix_sNewFromSDTypeMatrix(sdTypeMatrix.mHandle, ctypes.byref(outValueMatrix)) if _res != SDApiError.NoError.value: if _res == SDApiError.NoErrorOutputParamNotSet.value: return None raise APIException(SDApiError(_res)) constructor = sd.getContext().mTypeMap[SDAPIObject(sd.getContext(), outValueMatrix, ownHandle=False).getClassName()] return constructor(sd.getContext(), outValueMatrix.value, ownHandle=True)
def _save_as(): """ Emulates the save as functionality from the package tool-bar """ ctx = sd.getContext() app = ctx.getSDApplication() pm = app.getPackageMgr() uiMgr = app.getQtForPythonUIMgr() main_window = uiMgr.getMainWindow() # find the Save as action under one of the explorers explorer = None explorers = main_window.findChildren(PySide2.QtWidgets.QDockWidget) for w in explorers: if "Explorer" in w.windowTitle(): explorer = w break if explorer: actions = explorer.widget().findChildren(PySide2.QtWidgets.QAction) for a in actions: if a.text() == "Save As...": a.trigger() break
def sNew(value): """ Create new SDValueInt4 :param value: The name of the enum type :type value: int4 :rtype: SDValueInt4 """ outSDValueInt4 = ctypes.c_void_p() _res = sd.getContext().SDValueInt4_sNew(ctypes.byref(value), ctypes.byref(outSDValueInt4)) if _res != SDApiError.NoError.value: if _res == SDApiError.NoErrorOutputParamNotSet.value: return None raise APIException(SDApiError(_res)) constructor = sd.getContext().mTypeMap[SDAPIObject(sd.getContext(), outSDValueInt4, ownHandle=False).getClassName()] return constructor(sd.getContext(), outSDValueInt4.value, ownHandle=True)
def sNew(sdGraph): """ Create a new SDGraphObjectPin instance in the specified graph :param sdGraph: The SDGraph that should contains the new SDGraphObjectPin :type sdGraph: SDGraph :rtype: SDGraphObjectPin """ outSDGraphObjectPin = ctypes.c_void_p() _res = sd.getContext().SDGraphObjectPin_sNew(sdGraph.mHandle, ctypes.byref(outSDGraphObjectPin)) if _res != SDApiError.NoError.value: if _res == SDApiError.NoErrorOutputParamNotSet.value: return None raise APIException(SDApiError(_res)) constructor = sd.getContext().mTypeMap[SDAPIObject(sd.getContext(), outSDGraphObjectPin, ownHandle=False).getClassName()] return constructor(sd.getContext(), outSDGraphObjectPin.value, ownHandle=True)
def execute_action(self, name, params, sg_publish_data): """ Execute a given action. The data sent to this be method will represent one of the actions enumerated by the generate_actions method. :param name: Action name string representing one of the items returned by generate_actions. :param params: Params data, as specified by generate_actions. :param sg_publish_data: Shotgun data dictionary with all the standard publish fields. :returns: No return value expected. """ app = self.parent app.log_debug( "Execute action called for action %s. " "Parameters: %s. Publish Data: %s" % (name, params, sg_publish_data) ) # resolve path # toolkit uses utf-8 encoded strings internally and SubstanceDesigner API expects # unicode so convert the path to ensure filenames containing complex # characters are supported path = self.get_publish_path(sg_publish_data).replace(os.path.sep, "/") if name in action_to_fn: ctx = sd.getContext() app = ctx.getSDApplication() pm = app.getPackageMgr() uiMgr = app.getQtForPythonUIMgr() current_graph = uiMgr.getCurrentGraph() if current_graph: pck = current_graph.getPackage() fn = action_to_fn[name] fn.sNewFromFile(pck, path, EmbedMethod.Linked)
def __init__(self, *args, **kwargs): app = sd.getContext().getSDApplication() uiMgr = app.getQtForPythonUIMgr() super(View, self).__init__(parent=uiMgr.getMainWindow(), *args, **kwargs) self.gui = NodePropertyTransferUI.Ui_Dialog() self.gui.setupUi(self)
def sNew(value): """ Create new SDValueString :param value: The name of the enum type :type value: string :rtype: SDValueString """ outSDValueString = ctypes.c_void_p() _res = sd.getContext().SDValueString_sNew(ctypes.create_string_buffer(value.encode('utf-8')), ctypes.byref(outSDValueString)) if _res != SDApiError.NoError.value: if _res == SDApiError.NoErrorOutputParamNotSet.value: return None raise APIException(SDApiError(_res)) constructor = sd.getContext().mTypeMap[SDAPIObject(sd.getContext(), outSDValueString, ownHandle=False).getClassName()] return constructor(sd.getContext(), outSDValueString.value, ownHandle=True)
def get_selection_node(cls): context = sd.getContext() sd_app = context.getSDApplication() ui_manager = sd_app.getQtForPythonUIMgr() node_list = ui_manager.getCurrentGraphSelection() return node_list
def __testSBSAR(self, aSDSBSARFilePath, aSDRefResources): sdSBSARPkg = sd.getContext().getSDApplication().getPackageMgr().loadUserPackage(aSDSBSARFilePath) self.assertTrue(sdSBSARPkg) resourcesFolder = sdSBSARPkg.findResourceFromUrl('Resources') self.assertTrue(resourcesFolder) self.assertTrue(isinstance(resourcesFolder, SDResourceFolder)) resources = resourcesFolder.getChildren(False) self.assertEqual(len(resources), len(aSDRefResources)) for sdResource in resources: sdResourceIdentifier = sdResource.getIdentifier() sdResourceIdentifier = sdResourceIdentifier.replace('.', '_').replace(' ', '_') # Look for the Reference SDResource refSDResource = None for res in aSDRefResources: resIdentifier = res.getIdentifier() if resIdentifier == sdResourceIdentifier: refSDResource = res break self.assertTrue(refSDResource) # Compare the file content between the original file on disk AND the fileContent retrieved from the refFilePath = refSDResource.getFilePath() refFileContent = None with open(refFilePath, "rb") as f: refFileContent = f.read() sdResourceContent = sdResource.getFileContent() self.assertEqual(len(sdResourceContent), len(refFileContent)) self.assertEqual(sdResourceContent, refFileContent)
def sNew(parent): """ Create a new SDMDLGraph under the specified parent :param parent: The parent data that will contains the newly created MDL graph. Can be SDPackage or SDResourceFolder :type parent: SDAPIObject :rtype: SDMDLGraph """ outResource = ctypes.c_void_p() _res = sd.getContext().SDMDLGraph_sNew(parent.mHandle, ctypes.byref(outResource)) if _res != SDApiError.NoError.value: if _res == SDApiError.NoErrorOutputParamNotSet.value: return None raise APIException(SDApiError(_res)) constructor = sd.getContext().mTypeMap[SDAPIObject(sd.getContext(), outResource, ownHandle=False).getClassName()] return constructor(sd.getContext(), outResource.value, ownHandle=True)
def _save_as(self): ctx = sd.getContext() app = ctx.getSDApplication() pm = app.getPackageMgr() uiMgr = app.getQtForPythonUIMgr() try: import PySide2 except: pass # find the Save as action under one of the explorers explorer = None explorers = main.findChildren(PySide2.QtWidgets.QDockWidget, "areaA_1") for w in explorers: if "Explorer" in w.windowTitle(): explorer = w break if explorer: actions = explorer.widget().findChildren(PySide2.QtWidgets.QAction) for a in actions: if a.text() == "Save As...": a.trigger() break
def runTest(self): context = sd.getContext() srcPackageFileName = 'test_export.sbs' sdPackage = tools.loadSDPackage(context, srcPackageFileName) self.assertTrue(sdPackage, 'Fail to load package') sbsarFilePath = os.path.join(tools.getTestOutputDir(__file__), 'test_new_content_output.sbsar') if os.path.isfile(sbsarFilePath): logger.debug('Remove existing file: ' + sbsarFilePath) os.remove(sbsarFilePath) self.assertFalse(os.path.isfile(sbsarFilePath)) logger.debug('Export package to: ' + sbsarFilePath) sdSBSARExporter = SDSBSARExporter.sNew() sdSBSARExporter.setExposeRandomSeed(False) sdSBSARExporter.exportPackageToSBSAR(sdPackage, sbsarFilePath) # Check that sbsar file exist self.assertTrue(os.path.isfile(sbsarFilePath)) # Check file size statinfo = os.stat(sbsarFilePath) self.assertTrue(statinfo.st_size > 0)
def runTest(self): context = sd.getContext() moduleMgr = context.getSDApplication().getModuleMgr() self.assertTrue(moduleMgr) # Check Serialization logFileDir = tools.getAssetsDir() currentFileBaseName = io.getFileBaseName(__file__) referenceFile = os.path.join(logFileDir, currentFileBaseName + '.txt') # Serialize All SDModules dumpLines = DataSerializer().serializeSDModules(moduleMgr) # Convert To Lines newLines = tools.createFileLines(dumpLines) # ------------------------------------------------ # For development only # createReferenceFile = False createReferenceFile = True if createReferenceFile: # Write lines to reference file tools.writeLinesToFile(referenceFile, newLines) # ------------------------------------------------ # Read reference file lines referenceLines = tools.readLinesFromFile(referenceFile) # Compare Lines tools.compareLines(self, referenceLines, newLines)
def runTest(self): context = sd.getContext() sdPkgMgr = context.getSDApplication().getPackageMgr() sdModuleMgr = context.getSDApplication().getModuleMgr() # Display Root paths originalRootPaths = self.__getMDLRootPaths() for path in originalRootPaths: logger.debug('Root Path: %s' % path) # Add root path assetsDir = tools.getAssetsDir() newMdlRootPath = os.path.join(assetsDir, 'mdl') sdModuleMgr.addRootPath('mdl', newMdlRootPath) # Check path exist in the root paths self.assertTrue(newMdlRootPath in self.__getMDLRootPaths()) # Create New Package sdPkg = sdPkgMgr.newUserPackage() sdMDLGraph = SDMDLGraph.sNew(sdPkg) sdMDLNode = sdMDLGraph.newNode('mdl::test::test_function()') # Check the node has been properly created self.assertTrue(sdMDLNode) # Remove root path sdModuleMgr.removeRootPath('mdl', newMdlRootPath) self.assertTrue(newMdlRootPath not in self.__getMDLRootPaths())
def run(self, aContext): # Put your code here sdContext = sd.getContext() sdApplication = sdContext.getSDApplication() pkgManager = sdApplication.getPackageMgr() #pkg = pkgManager.loadUserPackage("S:/MEGA/Projects/Substance/2018/01_MudGrass/Grass.sbs") pkg = pkgManager.getUserPackageFromFilePath( "S:/MEGA/Projects/Substance/2018/01_MudGrass/Grass.sbs") sbsCompGraph = pkg.findResourceFromUrl("Mud") sbsCompGraph.compute() for sbsCompOutputNode in sbsCompGraph.getOutputNodes(): #print(sbsCompOutputNode) for sdOutputProperty in sbsCompOutputNode.getProperties( SDPropertyCategory.Output): #print(sdOutputProperty.getLabel()) sdPropertyValue = sbsCompOutputNode.getPropertyValue( sdOutputProperty) #print(sdPropertyVale) sdTexture = sdPropertyValue.toSDTexture() filename = os.path.abspath( 'S:/MEGA/Projects/Substance/2018/01_MudGrass/tex/' + sdOutputProperty.getLabel() + ".png") sdTexture.save(filename) pass
def __getMDLRootPaths(self): context = sd.getContext() sdModuleMgr = context.getSDApplication().getModuleMgr() newRootPaths = [] for p in sdModuleMgr.getRootPaths('mdl'): newRootPaths.append(p.get()) return newRootPaths
def sGetAvailablePrimitiveDefinitions(): """ Get all available primitive definitions. A primitive is a predefined scene provided by Designer (Cube, Sphere, Plane, ...) :rtype: SDArray[SDDefinition] """ outArray = ctypes.c_void_p() _res = sd.getContext( ).SDResourceScene_sGetAvailablePrimitiveDefinitions( ctypes.byref(outArray)) if _res != SDApiError.NoError.value: if _res == SDApiError.NoErrorOutputParamNotSet.value: return None raise APIException(SDApiError(_res)) constructor = sd.getContext().mTypeMap[SDAPIObject( sd.getContext(), outArray, ownHandle=False).getClassName()] return constructor(sd.getContext(), outArray.value, ownHandle=True)
def _save_package(pck, path): """ Save the package to the supplied path. """ ctx = sd.getContext() app = ctx.getSDApplication() pm = app.getPackageMgr() pm.savePackageAs(pck, path)
def getApp() -> SDApplication: """Helper function to retrive the SDApplication :return: the substance designer application instance :rtype: SDApplication """ context = sd.getContext() return context.getSDApplication()
def initializeSDPlugin(): app = sd.getContext().getSDApplication() uiMgr = app.getQtForPythonUIMgr() menu = uiMgr.newMenu(menuTitle="Lsystem", objectName=MENU_NAME) act = QtWidgets.QAction("Convert Selected", menu) act.triggered.connect(convert_selected_lsystem_nodes) menu.addAction(act)
def initializeSDPlugin(): ctx = sd.getContext() app = ctx.getSDApplication() uiMgr = app.getQtForPythonUIMgr() if uiMgr: global graphViewCreatedCallbackID graphViewCreatedCallbackID = uiMgr.registerGraphViewCreatedCallback( partial(onNewGraphViewCreated, uiMgr=uiMgr))
def sNew(typeId, valueAsString): """ Create new value from a custom type :param typeId: The type name :type typeId: string :param valueAsString: The string representation of the value that matches the specified type name :type valueAsString: string :rtype: SDValueCustom """ outSDValueCustom = ctypes.c_void_p() _res = sd.getContext().SDValueCustom_sNew(ctypes.create_string_buffer(typeId.encode('utf-8')), ctypes.create_string_buffer(valueAsString.encode('utf-8')), ctypes.byref(outSDValueCustom)) if _res != SDApiError.NoError.value: if _res == SDApiError.NoErrorOutputParamNotSet.value: return None raise APIException(SDApiError(_res)) constructor = sd.getContext().mTypeMap[SDAPIObject(sd.getContext(), outSDValueCustom, ownHandle=False).getClassName()] return constructor(sd.getContext(), outSDValueCustom.value, ownHandle=True)
def uninitializeSDPlugin(): ctx = sd.getContext() app = ctx.getSDApplication() uiMgr = app.getQtForPythonUIMgr() if uiMgr: global graphViewCreatedCallbackID uiMgr.unregisterCallback(graphViewCreatedCallbackID) NodeAlignmentToolBar.removeAllToolbars()
def scan_scene(self): """ The scan scene method is executed once at startup and its purpose is to analyze the current scene and return a list of references that are to be potentially operated on. The return data structure is a list of dictionaries. Each scene reference that is returned should be represented by a dictionary with three keys: - "attr": The filename attribute of the 'node' that is to be operated on. Most DCCs have a concept of a node, attribute, path or some other way to address a particular object in the scene. - "type": The object type that this is. This is later passed to the update method so that it knows how to handle the object. - "path": Path on disk to the referenced object. Toolkit will scan the list of items, see if any of the objects matches any templates and try to determine if there is a more recent version available. Any such versions are then displayed in the UI as out of date. """ app = self.parent engine = app.engine # Introspect the substance designer scene for read and write nodes # so we can gather the filenames available. refs = [] pck_manager = sd.getContext().getSDApplication().getPackageMgr() pcks = pck_manager.getUserPackages() for pck in pcks: ref_path = pck.getFilePath() if ref_path: refs.append({ "node": BreakdownSceneItem(pck, "package"), "type": "package", "path": ref_path, }) resources = pck.getChildrenResources(True) for resource in resources: ref_path = resource.getFilePath() if ref_path: refs.append({ "node": BreakdownSceneItem(resource, "resource"), "type": "resource", "path": ref_path, }) return refs
def display_error(msg): # Add a handler to redirect logging to Designer's console panel. ctx = sd.getContext() logger.addHandler(ctx.createRuntimeLogHandler()) substancedesigner.qCritical(msg) t = time.asctime(time.localtime()) message = "%s - Shotgun Error | %s engine | %s " % (t, APPLICATION_NAME, msg) print(message)
def main(): samplesPyFiles = tools.getPyFiles(io.getFileDir(__file__), 'sample_') sdContext = sd.getContext() index = 0 for samplePyFile in samplesPyFiles: index += 1 tools.printSeparator() print('[%d/%d] Running sample: %s' % (index, len(samplesPyFiles), samplePyFile)) __runSample(sdContext, samplePyFile) tools.printSeparator()
def sFromFile(filename): """ Create a new texture from the specified file :param filename: The image absolute file path :type filename: string :rtype: SDTexture """ outSDTexture = ctypes.c_void_p() _res = sd.getContext().SDTexture_sFromFile( ctypes.create_string_buffer(filename.encode('utf-8')), ctypes.byref(outSDTexture)) if _res != SDApiError.NoError.value: if _res == SDApiError.NoErrorOutputParamNotSet.value: return None raise APIException(SDApiError(_res)) constructor = sd.getContext().mTypeMap[SDAPIObject( sd.getContext(), outSDTexture, ownHandle=False).getClassName()] return constructor(sd.getContext(), outSDTexture.value, ownHandle=True)
def __btnPathClick(self, btn): ctx = sd.getContext() app = ctx.getSDApplication() uiMgr = app.getQtForPythonUIMgr() window = uiMgr.getMainWindow() fileName = QFileDialog.getExistingDirectory(window, "Open a folder", expanduser("~"), QFileDialog.ShowDirsOnly) if fileName: self.widget.txt_path.setText(fileName)