From 7d56f89e98dfc6db7c4b3bd3dc156a78137275af Mon Sep 17 00:00:00 2001 From: agastyafx Date: Tue, 20 Dec 2022 09:55:30 +0530 Subject: [PATCH] USD_v01_Core Single, Variant, and SubSOPvariant is working --- EditListUI.py | 107 +++++++++++++++ Generate_USD_02_Variant_Asset.py | 171 ++++++++++++++++++++++++ Get_Bridge_Asset_2.py | 104 ++++++++++++++ Get_Maps_v01_02.py | 68 ++++++++++ Help_UI.py | 14 ++ MaterialXSubnet_v01_02.py | 163 ++++++++++++++++++++++ Set_Desktop_Layout_InitiateUSD.py | 22 +++ USDConverterUI_2.py | 166 +++++++++++++++++++++++ bin/DEV/Generate_USD.py | 64 +++++++++ bin/DEV/Generate_USD_02_Single_Asset.py | 130 ++++++++++++++++++ bin/DEV/Get_Bridge_Asset.py | 20 +++ bin/DEV/Get_Maps_v01_01.py | 84 ++++++++++++ bin/DEV/MaterialXSubnet_v01_01.py | 108 +++++++++++++++ bin/DEV/USDConverterUI.py | 133 ++++++++++++++++++ bin/icons/USDLogo400x400.png | Bin 0 -> 13646 bytes bin/icons/help.png | Bin 0 -> 932 bytes bin/icons/main.png | Bin 0 -> 673 bytes bin/preset/exportpath.csv | 1 + master_conversion_USD.py | 70 ++++++++++ 19 files changed, 1425 insertions(+) create mode 100644 EditListUI.py create mode 100644 Generate_USD_02_Variant_Asset.py create mode 100644 Get_Bridge_Asset_2.py create mode 100644 Get_Maps_v01_02.py create mode 100644 Help_UI.py create mode 100644 MaterialXSubnet_v01_02.py create mode 100644 Set_Desktop_Layout_InitiateUSD.py create mode 100644 USDConverterUI_2.py create mode 100644 bin/DEV/Generate_USD.py create mode 100644 bin/DEV/Generate_USD_02_Single_Asset.py create mode 100644 bin/DEV/Get_Bridge_Asset.py create mode 100644 bin/DEV/Get_Maps_v01_01.py create mode 100644 bin/DEV/MaterialXSubnet_v01_01.py create mode 100644 bin/DEV/USDConverterUI.py create mode 100644 bin/icons/USDLogo400x400.png create mode 100644 bin/icons/help.png create mode 100644 bin/icons/main.png create mode 100644 bin/preset/exportpath.csv create mode 100644 master_conversion_USD.py diff --git a/EditListUI.py b/EditListUI.py new file mode 100644 index 0000000..c66f0b4 --- /dev/null +++ b/EditListUI.py @@ -0,0 +1,107 @@ +import sys, os +from PySide2.QtCore import Qt +from PySide2.QtWidgets import QApplication, QPushButton, QListWidget, QVBoxLayout, QHBoxLayout, QWidget, QMessageBox, QLineEdit + +SRC_PATH = "M:\\Notes\\Tools\\USD_Megascan_Importer" + +class ExportPathVarUI(QWidget): + def __init__(self, parentWidget): + super().__init__() + self._parent = parentWidget + self._ui() + + def _ui(self): + self.setWindowTitle("Path Variable") + self.setWindowFlags(Qt.WindowStaysOnTopHint) + # self.setMaximumWidth() + + vbox = QVBoxLayout(self) + self.listWidget = QListWidget() + self.addVarLine = QLineEdit("Add Export Path Here") + RemoveSelected = QPushButton("Remove Selected") + Reset = QPushButton("Reset") + Add = QPushButton("Add") + Save = QPushButton("Save") + + RemoveSelected.clicked.connect(self.Remove_was_clicked) + Reset.clicked.connect(self.Reset_was_clicked) + Save.clicked.connect(self.Save_was_clicked) + Add.clicked.connect(self.Add_was_clicked) + + hbox1 = QHBoxLayout() + hbox2 = QHBoxLayout() + hbox1.addWidget(self.addVarLine) + hbox1.addWidget(Add) + hbox2.addWidget(RemoveSelected) + hbox2.addWidget(Reset) + hbox2.addWidget(Save) + + self.listWidget.addItems(self._getList()) ## Reading all items + + self.listWidget.itemDoubleClicked.connect(self.onClicked) + + vbox.addWidget(self.listWidget) + vbox.addLayout(hbox1) + vbox.addLayout(hbox2) + self.setLayout(vbox) + + def Reset_was_clicked(self): + self.listWidget.clear() + self.listWidget.addItem("$HIP/usd/assets") + + def Save_was_clicked(self, parentWidget): + if self.listWidget.count() == 0: + QMessageBox.critical(self, "Need atleast one Variable", "Export Path Variable list should atleast contain one variable. Reset if you want to continue with default path ($HIP/usd)") + + self._parent.SetPathPrefixCombo.clear() # clearing the combobox + with open(self.exportPathPresetFile, "w") as file: + for i in range(self.listWidget.count()): + file.write((self.listWidget.item(i).text()) + ",") + print(self.listWidget.item(i).text()) + self._parent.SetPathPrefixCombo.addItem(self.listWidget.item(i).text()) + + print (self._parent.SetPathPrefixCombo.itemText(2)) + # # parentWidget.SetPathPrefixSelection.addItems(self._getList()) + + self.close() + + def Remove_was_clicked(self): + for i in self.listWidget.selectedItems(): + self.listWidget.takeItem(self.listWidget.row(i)) + + def Add_was_clicked(self): + if self.addVarLine.text() != "Add Export Path Here" and self.addVarLine.text().rstrip() != "": + self.listWidget.addItem(self.addVarLine.text().strip()) + + def onClicked(self, item): + QMessageBox.information(self, "Info", item.text()) + + def _getList(self): + if not os.path.exists(SRC_PATH + "\\bin"): + os.makedirs(SRC_PATH + "\\bin") + if not os.path.exists(SRC_PATH + "\\bin\\preset"): + os.makedirs(SRC_PATH + "\\bin\\preset") + + ## Create a default file if it doesn't exists + self.exportPathPresetFile = SRC_PATH + "\\bin\\preset\\exportpath.csv" + if not os.path.exists(self.exportPathPresetFile): + print("it not exist") + with open(self.exportPathPresetFile, "w") as file: + file.write("$HIP/usd/assets,") + # file.write("$JIP/USD,") + + ## Get List + with open(self.exportPathPresetFile, "r") as file: + for line in file: + return line.split(",")[:-1] + + +def main(): + app = QApplication(sys.argv) + ex = ExportPathVarUI() + ex.show() + app.exec_() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/Generate_USD_02_Variant_Asset.py b/Generate_USD_02_Variant_Asset.py new file mode 100644 index 0000000..6180ca8 --- /dev/null +++ b/Generate_USD_02_Variant_Asset.py @@ -0,0 +1,171 @@ +import hou + +class USD_Asset_Builder(): + def __init__(self, asset_name, asset_path, export_prefix= "$HIP/usd/assets"): + self.ASSET_NAME = asset_name + self.ASSET_PATH = asset_path + self.EXPORT_PATH = export_prefix + # self.ASSET_NAME = ASSET_NAME + ## Check if the asset Stager Exists and use it if it does + if hou.node("/stage/MS_Asset_USD_Processor") == None: + Asset_Stager = hou.node("/stage").createNode("lopnet", "MS_Asset_USD_Processor") + Asset_Stager.setUserData("nodeinfo_boxPos", "0") + self.i = int(Asset_Stager.userData("nodeinfo_boxPos")) + print("i = ", self.i) + else: + print("Asset is being imported in /stage/MS_Asset_USD_Processor") + Asset_Stager = hou.node("/stage/MS_Asset_USD_Processor") + self.i = int(Asset_Stager.userData("nodeinfo_boxPos")) + print("i = ", self.i) + + self.Stager = Asset_Stager + + ## Create a basic component builder + self.asset_compGeo = Asset_Stager.createNode("componentgeometry", self.ASSET_NAME + "_cGeo") + self.asset_compMat = Asset_Stager.createNode("componentmaterial", self.ASSET_NAME + "_cMat") + self.asset_matLib = Asset_Stager.createNode("materiallibrary", self.ASSET_NAME + "_cMLib") + self.asset_compOut = Asset_Stager.createNode("componentoutput", self.ASSET_NAME + "_cOut") + + self.asset_compMat.setFirstInput(self.asset_compGeo) + self.asset_compMat.setNextInput(self.asset_matLib) + self.asset_compOut.setNextInput(self.asset_compMat) + self.asset_compMat.setGenericFlag(hou.nodeFlag.Display, True) + # time.sleep(3) + self.asset_compOut.setGenericFlag(hou.nodeFlag.Display, True) + + + # Global Component Output Settings + self.asset_matLib.parm("matpathprefix").set("/ASSET/mtl/") + self.asset_compMat.parm("variantname").set("Default_MS_Mat") + self.asset_compMat.parm("primpattern1").set("*") + self.asset_compOut.parm("thumbnailmode").set(2) + self.asset_compOut.parm("res1").set(256) + self.asset_compOut.parm("res2").set(256) + self.asset_compOut.parm("autothumbnail").set(True) + + self.Stager_nodes = [self.asset_compGeo, self.asset_compMat, self.asset_compOut, self.asset_matLib] + + + + ## Set Network Box + def _create_netBox(self, *args): + self.Stager.layoutChildren() + + self.netbox = self.Stager.createNetworkBox(self.ASSET_NAME) + self.netbox.setComment(self.ASSET_NAME) + + for arg in args: + self.netbox.addItem(arg) + + self.netbox.fitAroundContents() + + self.i+=1 + self.netbox.setPosition(hou.Vector2((self.i%5)*8,-(self.i//5)*8)) + self.Stager.setUserData("nodeinfo_boxPos", str(self.i)) + + #-----------------------------------------------------------# + # Set Single Mesh Export + def setMeshExport(self, IndividualVarLayer = False): + """Class Method sets file paths for exports and runs the export commands + IndividualVarLayer creates individual variant Layers for LAG + """ + if IndividualVarLayer: + self.asset_compOut.parm("variantlayers").set(True) + + # Setting Component Output Parameters + self.asset_compOut.parm("rootprim").set("/" + self.ASSET_NAME) + self.asset_compOut.parm("lopoutput").set(self.EXPORT_PATH + "/" + self.ASSET_NAME + "/" + self.asset_compOut.parm("filename").eval()) + + buttonPath = self.asset_compOut.path() + "/execute" + hou.parm(buttonPath).pressButton() + + buttonPath = self.asset_compOut.path() + "/addtogallery" + hou.parm(buttonPath).pressButton() + self.asset_compOut.parm("loadfromdisk").set(True) + + #-----------------------------------------------------------# + # Sets the Object import into the Component Geometry + def singleGeoImport(self, meshPath = None, asst_comp_geo = None, polyreducepercent = 10, netbox = True): + """ + asst_comp_geo by default is set to Stager compGeo1 + meshPath by default set to self.ASSET_PATH + polyreducepercent = 10 + netBox = True : Creates a netbox by default. + """ + if asst_comp_geo is None: + asst_comp_geo = self.asset_compGeo + + if meshPath is None: + meshPath = self.ASSET_PATH + + # Component Geometry + asset_compGeo_Inner = hou.node(asst_comp_geo.path() + "/sopnet/geo") + + obj_merge = asset_compGeo_Inner.createNode("object_merge") + obj_merge.parm("objpath1").set(meshPath) + hou.node(asst_comp_geo.path() + "/sopnet/geo" + "/default").setNextInput(obj_merge) + polyreduce = obj_merge.createOutputNode("polyreduce::2.0") + polyreduce.parm("percentage").set(polyreducepercent) + hou.node(asst_comp_geo.path() + "/sopnet/geo" + "/proxy").setNextInput(polyreduce) + hou.node(asst_comp_geo.path() + "/sopnet/geo" + "/simproxy").setNextInput(polyreduce) + + asset_compGeo_Inner.layoutChildren() + if netbox: + self._create_netBox(*self.Stager_nodes) + + + def variantSOPsGeoImport(self, iterLength): + """Mesh with Multiple LOD0 SOP""" + for_start = self.asset_compGeo.createOutputNode("begincontextoptionsblock", self.ASSET_NAME + "_forStart") + asset_compGeo2 = self.Stager.createNode("componentgeometry", self.ASSET_NAME + "_cGeoVarImports") + compGeoVariants = for_start.createOutputNode("componentgeometryvariants", self.ASSET_NAME + "_cGeoVar") + compGeoVariants.setNextInput(asset_compGeo2) + for_end = self.Stager.createNode("foreach", self.ASSET_NAME + "_forEnd") + for_end.setInput(2, compGeoVariants) + setVariant = for_end.createOutputNode("setvariant") + setVariant.setGenericFlag(hou.nodeFlag.Bypass, True) + self.asset_compMat.insertInput(0, setVariant) + + self.asset_compGeo.parm("geovariantname").set("Var1") + asset_compGeo2.parm("geovariantname").set("Var`@ITERATIONVALUE`") + + for_end.parm("iterations").set(100) + for_end.parm("iterrange").set("range") + for_end.parm("firstiteration").set(2) + for_end.parm("lastiteration").set(iterLength) + + self.Stager_nodes.extend([for_start, asset_compGeo2, compGeoVariants, for_end, setVariant]) + + # Setting the compGeo1 + self.singleGeoImport(meshPath = (self.ASSET_PATH + "/Var1_LOD0"), netbox= False) + # Setting the compGeo1 + + self.singleGeoImport((self.ASSET_PATH + "/`chsop(\"../../../geovariantname\")`_LOD0"), asset_compGeo2) + + def variantSub_SOPGeoImport(self, iterLength): + """Mesh with Multiple LOD0 SOP""" + for_start = self.asset_compGeo.createOutputNode("begincontextoptionsblock", self.ASSET_NAME + "_forStart") + asset_compGeo2 = self.Stager.createNode("componentgeometry", self.ASSET_NAME + "_cGeoVarImports") + compGeoVariants = for_start.createOutputNode("componentgeometryvariants", self.ASSET_NAME + "_cGeoVar") + compGeoVariants.setNextInput(asset_compGeo2) + for_end = self.Stager.createNode("foreach", self.ASSET_NAME + "_forEnd") + for_end.setInput(2, compGeoVariants) + setVariant = for_end.createOutputNode("setvariant") + setVariant.setGenericFlag(hou.nodeFlag.Bypass, True) + self.asset_compMat.insertInput(0, setVariant) + + self.asset_compGeo.parm("geovariantname").set("Var1") + asset_compGeo2.parm("geovariantname").set("Var`@ITERATIONVALUE`") + + for_end.parm("iterations").set(100) + for_end.parm("iterrange").set("range") + for_end.parm("firstiteration").set(0) + for_end.parm("lastiteration").set(iterLength) + + self.Stager_nodes.extend([for_start, asset_compGeo2, compGeoVariants, for_end, setVariant]) + + # Setting the compGeo1 + self.singleGeoImport(meshPath = (self.ASSET_PATH + "/*_00_LOD0"), netbox= False) + # Setting the compGeo1 + + self.singleGeoImport((self.ASSET_PATH + "/*_`padzero(2, @ITERATIONVALUE)`_LOD0"), asset_compGeo2) diff --git a/Get_Bridge_Asset_2.py b/Get_Bridge_Asset_2.py new file mode 100644 index 0000000..9dffd60 --- /dev/null +++ b/Get_Bridge_Asset_2.py @@ -0,0 +1,104 @@ +import hou + +class MS_Asset(): + """ + This Class only returns the path of the MS Asset Geometry(s), MS Asset Material or Number of Variants + """ + def __init__(self): + self.ms_asset = hou.selectedNodes()[0] + + def __str__(self): + return str(self.ms_asset) + + #--------- Asset Name---------# + def get_MS_name(self): + return str(self.ms_asset) + + #--------- Asset Path---------# + def get_MS_Path(self): + return self.ms_asset.path() + + #--------- Get MS Asset Single Geo Node ---------# + def get_SingleMeshAssetGeo(self): + """Return the Geo Node inside MS asset Subnet""" + for child in self.ms_asset.children(): + if child.name() == "Asset_Geometry": + return child.path() + + #--------- Get MS Asset Mat Node ---------# + def get_AssetMat(self): + """Return the Mat Node inside MS asset Subnet""" + for child in self.ms_asset.children(): + if child.name() == "Asset_Material": + return child.children()[0].path() + + #--------- Get MS Asset Single Geo Node ---------# + def get_SOPVariantMeshesGeo(self): + """Return the inside MS asset Subnet's SOP based LOD0 variants""" + + newChildrenList = [] # LOD0 SOPS meshes are added in this list + children = self.ms_asset.children() + + for i in range(len(children)): + if str(children[i]).rfind("_LOD0") != -1: # -1 if not found + newChildrenList.append(children[i]) + + return len(newChildrenList) + + #--------- Get MS Asset Single Geo Node ---------# + def get_SubSOPVariantMeshesGeo(self): + """Returns the number of subSop LOD0 variants""" + + newChildrenList = [] # _LOD0 nulls from _LOD0 SOP meshes are added in this list + children = hou.node(self.ms_asset.path() + "/lod0").children() + + for i in range(len(children)): + if str(children[i]).rfind("_LOD0") != -1: # -1 if not found + newChildrenList.append(children[i]) + return len(newChildrenList) + + +class MS_Asset_Data(MS_Asset): + def __init__(self): + super().__init__() + + + def Check_is_MS_Asset(self): + if self.get_AssetMat() == None: + check = False + else: + check = True + + return check + + def SingleMeshData(self): + """Returns (AssetName, Asset_Geo_Path, Asset_Mat_Path)""" + + self.MS_Name = self.get_MS_name() + self.MS_GeoPath = self.get_SingleMeshAssetGeo() + self.MS_MatPath = self.get_AssetMat() + + return(self.MS_Name, self.MS_GeoPath, self.MS_MatPath) + + def SOPvariantsData(self): + """Returns (AssetName, Asset_Geo_Path, Asset_Mat_Path, IterationRange)""" + + self.MS_Name = self.get_MS_name() + self.MS_GeoPath = self.get_MS_Path() + self.MS_MatPath = self.get_AssetMat() + self.IterationRange = self.get_SOPVariantMeshesGeo() + + return(self.MS_Name, self.MS_GeoPath, self.MS_MatPath, self.IterationRange) + + def SubSOPvariantsData(self): + """Returns (AssetName, Asset_Geo_Path, Asset_Mat_Path, IterationRange)""" + + self.MS_Name = self.get_MS_name() + self.MS_GeoPath = self.get_MS_Path() + "/lod0" + self.MS_MatPath = self.get_AssetMat() + self.IterationRange = self.get_SubSOPVariantMeshesGeo() + + return(self.MS_Name, self.MS_GeoPath, self.MS_MatPath, self.IterationRange) + + +# print(MS_Asset_Data().Check_is_MS_Asset()) \ No newline at end of file diff --git a/Get_Maps_v01_02.py b/Get_Maps_v01_02.py new file mode 100644 index 0000000..d88fa0a --- /dev/null +++ b/Get_Maps_v01_02.py @@ -0,0 +1,68 @@ +""" + STATUS: V01_02 In Progress + Feature/Purpose: Created Textures class which returns dict object + """ + +import hou, os + +class Texture_Files(): + def __init__(self): + self.tex_maps = { + "alb" : "", + "rough" : "", + "metal" : "", + "spec" : "", + "opac" :"", + "nrml" : "", + "disp" : "", + } + + def __str__(self) -> str: + string = "" + for tex in self.tex_maps: + string += tex + " = " + self.tex_maps[tex] + "\n" + return string + + def extractMaps(self): + return self.tex_maps + + #-----------------------------------------------------------# + # Get Maps From Node + + def GetMapsFromNode(self, prinMatShader): + """ + :param prinMatShader: Dest Path for creating materialX subnet + :type prinMatShader: matnet + + :raise TypeError: if folderPath not str + :rtype: dictionary + """ + + if prinMatShader.type().name() != "principledshader::2.0": + print("Not a principle shader") + return None + + self.tex_maps["alb"] = prinMatShader.parm("basecolor_texture").eval() + self.tex_maps["rough"] = prinMatShader.parm("rough_texture").eval() + self.tex_maps["metal"] = prinMatShader.parm("metallic_texture").eval() + self.tex_maps["spec"] = prinMatShader.parm("reflect_texture").eval() + self.tex_maps["opac"] = prinMatShader.parm("opaccolor_texture").eval() + self.tex_maps["nrml"] = prinMatShader.parm("baseNormal_texture").eval() + self.tex_maps["disp"] = prinMatShader.parm("dispTex_texture").eval() + + # safety strip + for tex in self.tex_maps: + self.tex_maps[tex] = self.tex_maps[tex].strip() + # print(self.tex_maps[tex]) + + return self.tex_maps + + +def main(): + + shader = hou.selectedNodes()[0] + texture = Texture_Files() + texture.GetMapsFromNode(shader) + print(texture.extractMaps()) + print(texture) + diff --git a/Help_UI.py b/Help_UI.py new file mode 100644 index 0000000..da6732a --- /dev/null +++ b/Help_UI.py @@ -0,0 +1,14 @@ +from PySide2.QtWidgets import QWidget, QLabel, QApplication +from PySide2.QtCore import Qt +from PySide2.QtGui import QIcon + +SRC_PATH = "M:\\Notes\\Tools\\USD_Megascan_Importer" + +class HelpUI(QLabel): + def __init__(self): + super().__init__() + self.setWindowFlags(Qt.WindowStaysOnTopHint) + self.setWindowTitle("Help - Megascan USD Asset Converter") + self.setWindowIcon(QIcon(SRC_PATH + "\\bin\\icons\\main.png")) + + self.setText("[TIP] You can set a $VAR = /MS_USD_Path and use it as a common USD Library Directory for Export") diff --git a/MaterialXSubnet_v01_02.py b/MaterialXSubnet_v01_02.py new file mode 100644 index 0000000..9e03a80 --- /dev/null +++ b/MaterialXSubnet_v01_02.py @@ -0,0 +1,163 @@ +""" + STATUS: V01_02 Working + Feature/Purpose: Should create texture nodes based on the dict + +""" +import hou +# print("----------------------------") +# hou.node("/obj").deleteItems(hou.node("/obj").children()) + + +#-----------------------------------------------------------# +# Create MaterialX Subnet + +def create_MTLX_Subnet(matcontext, mapsDict, matXName = "Converted"): + """ + :param matContext: Dest Path for creating materialX subnet + :type matContext: matnet + + :param mapsDict: Dest Path for creating materialX subnet + :type mapsDict: Dictionary + + :raise TypeError: if not a matnet object + :rtype: Boolean + """ + + # Removing any whitespaces characters + for tex in mapsDict: + mapsDict[tex] = mapsDict[tex].strip() + # print(mapsDict[tex]) + + print("matcontex : " + matcontext.type().name()) + if (matcontext.type().name() != "matnet" and matcontext.type().name() != "materiallibrary" and matcontext.type().name() != "assignmaterial" and matcontext.type().name() != "editmaterial"): + print("ERROR :create_MTLX_Subnet requires Matnet/ materiallibrary/ assignmaterial/ editmaterial Object as input for create_MTLX_Subnet") + return False + + mtlxSubnet = matcontext.createNode("subnet", matXName + "_materialX") + + children = mtlxSubnet.allSubChildren() + mtlxSubnet.deleteItems(children) + + # Define Outer Surface + surfaceOutput = mtlxSubnet.createNode("subnetconnector") + surfaceOutput.setName("Surface_Output") + surfaceOutput.parm("connectorkind").set("output") + surfaceOutput.parm("parmname").set("surface") + surfaceOutput.parm("parmlabel").set("surface") + surfaceOutput.parm("parmtype").set("surface") + + + # Discplacement Output + displacementOutput = mtlxSubnet.createNode("subnetconnector") + displacementOutput.setName("Displacement_Output") + displacementOutput.parm("connectorkind").set("output") + displacementOutput.parm("parmname").set("Displacement") + displacementOutput.parm("parmlabel").set("Displacement") + displacementOutput.parm("parmtype").set("displacement") + + # Mtlx_Standard_Surface + mtlxStandard = mtlxSubnet.createNode("mtlxstandard_surface") + surfaceOutput.setInput(0, mtlxStandard) + + IMG_TEX_NODE = "mtlximage" + + + # Albedo + if len(mapsDict["alb"]) > 0: + albedo = mtlxSubnet.createNode(IMG_TEX_NODE, "Albedo") + albedo.parm("file").set(mapsDict["alb"]) + mtlxStandard.setNamedInput("base_color", albedo, "out") + + # Roughness + if len(mapsDict["rough"]) > 0: + roughness = mtlxSubnet.createNode(IMG_TEX_NODE, "Roughness") + roughness.parm("signature").set("float") + roughness.parm("file").set(mapsDict["rough"]) + mtlxStandard.setNamedInput("specular_roughness", roughness, "out") + + # Metallic + if len(mapsDict["metal"]) > 0: + metallic = mtlxSubnet.createNode(IMG_TEX_NODE, "Metallic") + metallic.parm("signature").set("float") + metallic.parm("file").set(mapsDict["metal"]) + mtlxStandard.setNamedInput("metalness", metallic, "out") + + # SPECULAR + if len(mapsDict["spec"]) > 0: + specular = mtlxSubnet.createNode(IMG_TEX_NODE, "Specular") + specular.parm("signature").set("float") + specular.parm("file").set(mapsDict["spec"]) + mtlxStandard.setNamedInput("specular", specular, "out") + + #OPACITY + if len(mapsDict["opac"]) > 0: + opacity = mtlxSubnet.createNode(IMG_TEX_NODE, "Opacity") + opacity.parm("file").set(mapsDict["opac"]) + mtlxStandard.setNamedInput("opacity", opacity, "out") + + # Normals + if len(mapsDict["nrml"]) > 0: + normal = mtlxSubnet.createNode(IMG_TEX_NODE, "Normals") + normal.parm("file").set(mapsDict["nrml"]) + normal_map = mtlxSubnet.createNode("mtlxnormalmap") + normal_map.setNamedInput("in", normal, "out") + mtlxStandard.setNamedInput("normal", normal_map, "out") + + # Displacement + if len(mapsDict["disp"]) > 0: + displacement_tex = mtlxSubnet.createNode(IMG_TEX_NODE, "Displacement") + displacement_tex.parm("signature").set("float") + displacement_tex.parm("file").set(mapsDict["disp"]) + displacement_remap = mtlxSubnet.createNode("mtlxremap") + displacement = mtlxSubnet.createNode("mtlxdisplacement") + + displacementOutput.setNamedInput("suboutput", displacement, "out") + displacement.setNamedInput("displacement", displacement_remap, "out") + displacement_remap.setNamedInput("in", displacement_tex, "out") + + displacement_remap.parm("outlow").set(-0.7) + displacement_remap.parm("outhigh").set(0.3) + displacement.parm("scale").set(0.05) + + # LAYOUT + mtlxSubnet.layoutChildren() + mtlxSubnet.setGenericFlag(hou.nodeFlag.Material, True) + return True +#-----------------------------------------------------------# + +def Test(): + maps = { + "alb" : "M:/Megascans Library/Downloaded/3dplant/plants_3d_rbtnZ/Textures/Atlas/pjxvi_4K_Albedo.jpg", + "rough" : "M:/Megascans Library/Downloaded/3dplant/plants_3d_rbtnZ/Textures/Atlas/pjxvi_4K_Roughness.jpg", + "metal" : "M:/Megascans Library/Downloaded/3dplant/plants_3d_rbtnZ/Textures/Atlas/pjxvi_4K_Roughness.jpg", + "spec" : "M:/Megascans Library/Downloaded/3dplant/plants_3d_rbtnZ/Textures/Atlas/pjxvi_4K_Roughness.jpg", + "opac" : "M:/Megascans Library/Downloaded/3dplant/plants_3d_rbtnZ/Textures/Atlas/pjxvi_4K_Opacity.jpg", + "nrml" : "M:/Megascans Library/Downloaded/3dplant/plants_3d_rbtnZ/Textures/Atlas/pjxvi_4K_Normal.jpg", + "disp" : "M:/Megascans Library/Downloaded/3dplant/plants_3d_rbtnZ/Textures/Atlas/pjxvi_4K_Displacement.exr" + } + + no_map = { + "alb" : "", + "rough" : "", + "metal" : "", + "spec" : "", + "opac" :"", + "nrml" : "", + "disp" : "", + } + + map1 = { + 'alb': 'M:/Megascans Library/Downloaded/3d/nature_rock_vcljbb1iw/vcljbb1iw_4K_Albedo.jpg', + 'rough': 'M:/Megascans Library/Downloaded/3d/nature_rock_vcljbb1iw/vcljbb1iw_4K_Roughness.jpg', + 'metal': '', + 'spec': '', + 'opac': '', + 'nrml': 'M:/Megascans Library/Downloaded/3d/nature_rock_vcljbb1iw/vcljbb1iw_4K_Normal_LOD0.jpg', + 'disp': 'M:/Megascans Library/Downloaded/3d/nature_rock_vcljbb1iw/vcljbb1iw_4K_Displacement.exr' + } + test_map = maps + MTLX_DEST = hou.node("/obj").createNode("matnet") + Geo_DEST = hou.node("/obj").createNode("geo") + create_MTLX_Subnet(MTLX_DEST, map1) + +# Test() \ No newline at end of file diff --git a/Set_Desktop_Layout_InitiateUSD.py b/Set_Desktop_Layout_InitiateUSD.py new file mode 100644 index 0000000..9cb4452 --- /dev/null +++ b/Set_Desktop_Layout_InitiateUSD.py @@ -0,0 +1,22 @@ +import hou + +desktop = hou.ui.curDesktop() ## Desktop Class +panel_float_tab = desktop.createFloatingPanel(hou.paneTabType.NetworkEditor) # floatingPanel Class +panel_float_tab.setName("USD_IMPORTER") + +panel_float_tab.panes()[0].splitVertically() #Pane + +panel_float_tab.panes()[0].showPaneTabsStow(False) +panel_float_tab.panes()[1].showPaneTabsStow(False) + +pp1 = panel_float_tab.paneTabs()[0].setType(hou.paneTabType.PythonPanel) +pp1.showToolbar(False) + +pp2 = panel_float_tab.paneTabs()[1].setType(hou.paneTabType.PythonPanel) + +pp1.setActiveInterface(hou.pypanel.interfaceByName("MS_USD_Converter")) +pp2.setActiveInterface(hou.pypanel.interfaceByName("layout_asset_gallery")) + +lag = pp2.activeInterface() + + diff --git a/USDConverterUI_2.py b/USDConverterUI_2.py new file mode 100644 index 0000000..351c0ca --- /dev/null +++ b/USDConverterUI_2.py @@ -0,0 +1,166 @@ +import os, sys +from PySide2.QtCore import Qt +from PySide2.QtGui import QFont, QIcon +from PySide2.QtWidgets import (QComboBox, QFrame, QHBoxLayout, QLabel, + QLineEdit, QListWidget, QMainWindow, + QMessageBox, QPushButton, QRadioButton, + QStatusBar, QVBoxLayout, QWidget, QApplication) + +SRC_PATH = "M:\\Notes\\Tools\\USD_Megascan_Importer" + +sys.path.append(SRC_PATH) +from EditListUI import ExportPathVarUI +from Help_UI import HelpUI +import master_conversion_USD + +class USD_UI(QMainWindow): + def __init__(self): + super().__init__() + + self.setWindowFlags(Qt.WindowStaysOnTopHint) + self.setWindowTitle("Megascan USD Asset Converter") + + self.setWindowIcon(QIcon(SRC_PATH + "\\bin\\icons\\main.png")) + self.LightGreyFont = QFont("Courier", 8) + self._UI_ImportSection() + self._createUI() + + #--------- UI MAIN ---------# + def _createUI(self): + self.setStatusBar(QStatusBar(self)) + # Step 1 + PathPrefixLabel = QLabel("Set a Default Path Prefix for Asset Export Path") + PathPrefixLabel.setStyleSheet( "font-size : 10pt; color: lightgrey; font-weight:bold;") + + self.SetPathPrefixCombo = QComboBox() + self.SetPathPrefixCombo.setFixedWidth(200) + self.EditPathWindow = ExportPathVarUI(self) + + self.SetPathPrefixCombo.addItems(self.EditPathWindow._getList()) + + EditPathSet = QPushButton("Edit List") + EditPathSet.clicked.connect(self.EditList_was_clicked) + + PathPrefixLabel2 = QLabel("Default $HIP/usd/assets would be good if you need to move around your Project") + PathPrefixLabel2.setWordWrap(True) + PathPrefixLabel2.setFont(self.LightGreyFont) + + # Step 2 + HLine = QFrame() + HLine.setFrameShape(QFrame.HLine) + Frame1 = QFrame() + Frame1.setFrameShape(QFrame.Box) + + self.convert = QPushButton("Convert into USD") + self.convert.setStyleSheet("color: rgb(0, 255, 155);") + self.help = QPushButton("Help") + self.help.setStyleSheet("color: rgb(255, 80, 80);") + self.help.clicked.connect(self.help_was_clicked) + self.convert.clicked.connect(self.convert_was_clicked) + + ## Path Layout + LayHor1 = QHBoxLayout() + LayHor1.addStretch() + LayHor1.addWidget(self.SetPathPrefixCombo) + LayHor1.addStretch() + LayHor1.addWidget(EditPathSet) + LayHor1.addStretch() + + + ## Final Layout + FinalLayout = QHBoxLayout() + FinalLayout.addWidget(self.help) + FinalLayout.addWidget(self.convert) + FinalLayout.setAlignment(self.help, Qt.AlignHCenter) + FinalLayout.setAlignment(self.convert, Qt.AlignHCenter) + + ## Core Layout + CoreLayout = QVBoxLayout() + CoreLayout.addWidget(PathPrefixLabel) + CoreLayout.addLayout(LayHor1) + CoreLayout.addWidget(PathPrefixLabel2) + CoreLayout.addWidget(HLine) + CoreLayout.addSpacing(20) + CoreLayout.addLayout(self.ImportLayout) + CoreLayout.addSpacing(20) + CoreLayout.addLayout(FinalLayout) + CoreLayout.addStretch() + + Container = QWidget() + Container.setLayout(CoreLayout) + + self.setCentralWidget(Container) + + #--------- UI Import Section ---------# + def _UI_ImportSection(self): + + label1 = QLabel("1. Import Megascan Asset Using Bridge and MSPlugin and select the *Asset Subnet*.") + ImportHeading = QLabel("Import Settings") + ImportHeading.setStyleSheet( "font-size : 10pt; color: lightgrey; font-weight:bold;") + label2 = QLabel("2. Select One of the Import Method.") + + self.Single = QRadioButton ("Single Mesh") + self.Variant = QRadioButton ("Multiple Variant Mesh LOD0 SOPS") + self.Split = QRadioButton ("Sub-Split Variant Meshes inside LOD0") + self.Single.toggled.connect(self._updateImportMethod) + self.Variant.toggled.connect(self._updateImportMethod) + self.Split.toggled.connect(self._updateImportMethod) + self.Single.setStatusTip("Creates Single Asset for Single Mesh") + self.Variant.setStatusTip("Creates Individual Asset for each of the collection Items of Single Meshes.") + self.Split.setStatusTip("Creates Single Asset containing all variant of each collection items.") + + ## Method Radio Buttons + ButtonLayout = QHBoxLayout() + ButtonLayout.addStretch() + ButtonLayout.addWidget(self.Single) + ButtonLayout.addWidget(self.Variant) + ButtonLayout.addWidget(self.Split) + ButtonLayout.addStretch() + + + self.ImportLayout = QVBoxLayout() + self.ImportLayout.addWidget(ImportHeading) + self.ImportLayout.setAlignment(ImportHeading, Qt.AlignHCenter) + self.ImportLayout.addSpacing(10) + self.ImportLayout.addWidget(label1) + self.ImportLayout.addSpacing(10) + self.ImportLayout.addWidget(label2) + self.ImportLayout.addLayout(ButtonLayout) + + + #--------- Choose Import Method ---------# + def _updateImportMethod(self, data): + ... + + #--------- Help ---------# + def convert_was_clicked(self): + if self.Single.isChecked(): + master_conversion_USD.mainSingle() + print("single") + elif self.Variant.isChecked(): + master_conversion_USD.SOPVariants() + print("Variant") + elif self.Split.isChecked(): + master_conversion_USD.subSOPVariants() + print("Split") + + #--------- Help ---------# + def help_was_clicked(self): + print("help") + self.H = HelpUI() + self.H.show() + + def EditList_was_clicked(self): + self.EditPathWindow.show() + + +def main(): + # app = QApplication() + A = USD_UI() + A.show() + # app.exec_() + +# if __name__ == '__main__': +# main() + +main() \ No newline at end of file diff --git a/bin/DEV/Generate_USD.py b/bin/DEV/Generate_USD.py new file mode 100644 index 0000000..21bd032 --- /dev/null +++ b/bin/DEV/Generate_USD.py @@ -0,0 +1,64 @@ + +""" + STATUS: v01_01 Working + Feature/Purpose: Should create texture nodes based on the dict + +""" + +import hou +ASSET_NAME = "Test" +ASSET_PATH = "/obj/geo1" +EXPORT_PATH = "$HIP/usd/assets" + +## Check if the asset Stager Exists and use it if it does +if hou.node("/stage/MS_Asset_USD_Processor") == None: + Asset_Stager = hou.node("/stage").createNode("lopnet", "MS_Asset_USD_Processor") + Asset_Stager.setUserData("nodeinfo_boxPos", "0") + i = int(Asset_Stager.userData("nodeinfo_boxPos")) + print("i = ", i) +else: + print("Asset is being imported in /stage/MS_Asset_USD_Processor") + Asset_Stager = hou.node("/stage/MS_Asset_USD_Processor") + i = int(Asset_Stager.userData("nodeinfo_boxPos")) + print("i = ", i) + +## Create a basic component builder +asset_compGeo = Asset_Stager.createNode("componentgeometry", ASSET_NAME + "componentGeometry") +asset_compMat = Asset_Stager.createNode("componentmaterial", ASSET_NAME + "componentMaterial") +asset_matLib = Asset_Stager.createNode("materiallibrary", ASSET_NAME + "componentLibrary") +asset_compOut = Asset_Stager.createNode("componentoutput", ASSET_NAME + "componentoutput") + +asset_compMat.setFirstInput(asset_compGeo) +asset_compMat.setNextInput(asset_matLib) +asset_compOut.setNextInput(asset_compMat) + +Asset_Stager.layoutChildren() + +box = Asset_Stager.createNetworkBox(ASSET_NAME) +box.setComment(ASSET_NAME) +box.addItem(asset_compGeo) +box.addItem(asset_compMat) +box.addItem(asset_matLib) +box.addItem(asset_compOut) +box.fitAroundContents() + +i+=1 +box.setPosition(hou.Vector2((i%5)*6,-(i//5)*5)) +Asset_Stager.setUserData("nodeinfo_boxPos", str(i)) + +# Component Geometry +asset_compGeo_Inner = hou.node(asset_compGeo.path() + "/sopnet/geo") + +obj_merge = asset_compGeo_Inner.createNode("object_merge") +obj_merge.parm("objpath1").set(ASSET_PATH) +hou.node(asset_compGeo.path() + "/sopnet/geo" + "/default").setNextInput(obj_merge) +polyreduce = obj_merge.createOutputNode("polyreduce::2.0") +polyreduce.parm("percentage").set(10) +hou.node(asset_compGeo.path() + "/sopnet/geo" + "/proxy").setNextInput(polyreduce) +hou.node(asset_compGeo.path() + "/sopnet/geo" + "/simproxy").setNextInput(polyreduce) + +asset_compGeo_Inner.layoutChildren() + +# Setting Component Output Parameters +asset_compOut.parm("rootprim").set("/" + ASSET_NAME) +asset_compOut.parm("lopoutput").set(EXPORT_PATH + "/" + ASSET_NAME + "/" + asset_compOut.parm("filename").eval()) diff --git a/bin/DEV/Generate_USD_02_Single_Asset.py b/bin/DEV/Generate_USD_02_Single_Asset.py new file mode 100644 index 0000000..fec2067 --- /dev/null +++ b/bin/DEV/Generate_USD_02_Single_Asset.py @@ -0,0 +1,130 @@ + +""" + STATUS: v01_01 Working + Feature/Purpose: Should create texture nodes based on the dict + +""" + +import hou, sys +varPath = "M:\\Notes\\Tools\\USD_Megascan_Importer" +sys.path.append(varPath) + +from MaterialXSubnet_v01_02 import create_MTLX_Subnet +from Get_Maps_v01_02 import Texture_Files +#-----------------------------------------------------------# +# Get Bridge Asset +def get_AssetGeo(asset): + for child in asset_name.children(): + if child.name() == "Asset_Geometry": + return child + +def get_AssetMat(asset): + for child in asset_name.children(): + if child.name() == "Asset_Material": + return child + +if len(hou.selectedNodes())==0: + hou.ui.displayMessage("Please Select a MS Subnet") +else: + asset_name = hou.selectedNodes()[0] + ms_geo = get_AssetGeo(asset_name) + ms_shader = get_AssetMat(asset_name).children() + + print(ms_geo, ms_geo.path(), ms_shader[0]) + + ASSET_NAME = str(asset_name) + ASSET_PATH = ms_geo.path() + tx = Texture_Files() + maps = tx.GetMapsFromNode(ms_shader[0]) +#-----------------------------------------------------------# + +# ASSET_NAME = "Test" +# ASSET_PATH = "/obj/pig" +EXPORT_PATH = "$HIP/usd/assets" + +class USD_Asset_Builder(): + def __init__(self): + ## Check if the asset Stager Exists and use it if it does + if hou.node("/stage/MS_Asset_USD_Processor") == None: + Asset_Stager = hou.node("/stage").createNode("lopnet", "MS_Asset_USD_Processor") + Asset_Stager.setUserData("nodeinfo_boxPos", "0") + i = int(Asset_Stager.userData("nodeinfo_boxPos")) + print("i = ", i) + else: + print("Asset is being imported in /stage/MS_Asset_USD_Processor") + Asset_Stager = hou.node("/stage/MS_Asset_USD_Processor") + i = int(Asset_Stager.userData("nodeinfo_boxPos")) + print("i = ", i) + + ## Create a basic component builder + self.asset_compGeo = Asset_Stager.createNode("componentgeometry", ASSET_NAME + "_cGeo") + self.asset_compMat = Asset_Stager.createNode("componentmaterial", ASSET_NAME + "_cMat") + self.asset_matLib = Asset_Stager.createNode("materiallibrary", ASSET_NAME + "_cMLib") + self.asset_compOut = Asset_Stager.createNode("componentoutput", ASSET_NAME + "_cOut") + + self.asset_compMat.setFirstInput(self.asset_compGeo) + self.asset_compMat.setNextInput(self.asset_matLib) + self.asset_compOut.setNextInput(self.asset_compMat) + self.asset_compMat.setGenericFlag(hou.nodeFlag.Display, True) + # time.sleep(3) + self.asset_compOut.setGenericFlag(hou.nodeFlag.Display, True) + + + # Global Component Output Settings + self.asset_matLib.parm("matpathprefix").set("/ASSET/mtl/") + self.asset_compMat.parm("variantname").set("Default_MS_Mat") + self.asset_compMat.parm("primpattern1").set("*") + self.asset_compOut.parm("thumbnailmode").set(2) + self.asset_compOut.parm("res1").set(256) + self.asset_compOut.parm("res2").set(256) + self.asset_compOut.parm("autothumbnail").set(True) + + Asset_Stager.layoutChildren() + + ## Set Network Box + box = Asset_Stager.createNetworkBox(ASSET_NAME) + box.setComment(ASSET_NAME) + box.addItem(self.asset_compGeo) + box.addItem(self.asset_compMat) + box.addItem(self.asset_matLib) + box.addItem(self.asset_compOut) + box.fitAroundContents() + + i+=1 + box.setPosition(hou.Vector2((i%5)*6,-(i//5)*5)) + Asset_Stager.setUserData("nodeinfo_boxPos", str(i)) + + #-----------------------------------------------------------# + # Sets the Object import into the Component Geometry + def singleGeoImport(self): + # Component Geometry + asset_compGeo_Inner = hou.node(self.asset_compGeo.path() + "/sopnet/geo") + + obj_merge = asset_compGeo_Inner.createNode("object_merge") + obj_merge.parm("objpath1").set(ASSET_PATH) + hou.node(self.asset_compGeo.path() + "/sopnet/geo" + "/default").setNextInput(obj_merge) + polyreduce = obj_merge.createOutputNode("polyreduce::2.0") + polyreduce.parm("percentage").set(10) + hou.node(self.asset_compGeo.path() + "/sopnet/geo" + "/proxy").setNextInput(polyreduce) + hou.node(self.asset_compGeo.path() + "/sopnet/geo" + "/simproxy").setNextInput(polyreduce) + + asset_compGeo_Inner.layoutChildren() + + #-----------------------------------------------------------# + # Set Single Mesh Export + def setSingleMeshExport(self): + # Setting Component Output Parameters + self.asset_compOut.parm("rootprim").set("/" + ASSET_NAME) + self.asset_compOut.parm("lopoutput").set(EXPORT_PATH + "/" + ASSET_NAME + "/" + self.asset_compOut.parm("filename").eval()) + # time.sleep(1) + buttonPath = self.asset_compOut.path() + "/execute" + hou.parm(buttonPath).pressButton() + # time.sleep(1) + buttonPath = self.asset_compOut.path() + "/addtogallery" + hou.parm(buttonPath).pressButton() + self.asset_compOut.parm("loadfromdisk").set(True) + +MS = USD_Asset_Builder() +MS.singleGeoImport() +create_MTLX_Subnet(MS.asset_matLib, maps, ASSET_NAME) +MS.setSingleMeshExport() diff --git a/bin/DEV/Get_Bridge_Asset.py b/bin/DEV/Get_Bridge_Asset.py new file mode 100644 index 0000000..210e7d7 --- /dev/null +++ b/bin/DEV/Get_Bridge_Asset.py @@ -0,0 +1,20 @@ +import hou + +def get_AssetGeo(asset): + for child in asset_name.children(): + if child.name() == "Asset_Geometry": + return child + +def get_AssetMat(asset): + for child in asset_name.children(): + if child.name() == "Asset_Material": + return child + +if len(hou.selectedNodes())==0: + hou.ui.displayMessage("Please Select a MS Subnet") +else: + asset_name = hou.selectedNodes()[0] + ms_geo = get_AssetGeo(asset_name) + ms_shader = get_AssetMat(asset_name).children() + + print(ms_geo, ms_geo.path(), ms_shader[0]) diff --git a/bin/DEV/Get_Maps_v01_01.py b/bin/DEV/Get_Maps_v01_01.py new file mode 100644 index 0000000..8a717a4 --- /dev/null +++ b/bin/DEV/Get_Maps_v01_01.py @@ -0,0 +1,84 @@ +""" + STATUS: V01_01 Completed + Feature/Purpose: Should Return Dict object with maps + tex_maps = { + "alb" : "", + "rough" : "", + "metal" : "", + "spec" : "", + "opac" :"", + "nrml" : "", + "disp" : "", + } + """ + +import hou, os + +tex_maps = { + "alb" : "", + "rough" : "", + "metal" : "", + "spec" : "", + "opac" :"", + "nrml" : "", + "disp" : "", + } + +#-----------------------------------------------------------# +# Get Maps From Folder + +def GetMapsFromFolder(folderPath): + """ + :param folderPath: Dest Path for creating materialX subnet + :type folderPath: matnet + + :raise TypeError: if folderPath not str + :rtype: dictionary + """ + MegaScanLib = "M:\\Megascans Library" + path = MegaScanLib + "\\Downloaded\\3d\\3d_other_ufokciifa" + + dir_list = os.listdir(path) + print(dir_list) + + + + + +#-----------------------------------------------------------# +# Get Maps From Node + +def GetMapsFromNode(prinMatShader): + """ + :param prinMatShader: Dest Path for creating materialX subnet + :type prinMatShader: matnet + + :raise TypeError: if folderPath not str + :rtype: dictionary + """ + global tex_maps + + if prinMatShader.type().name() != "principledshader::2.0": + print("Not a principle shader") + return tex_maps + + tex_maps["alb"] = prinMatShader.parm("basecolor_texture").eval() + tex_maps["rough"] = prinMatShader.parm("rough_texture").eval() + tex_maps["metal"] = prinMatShader.parm("metallic_texture").eval() + tex_maps["spec"] = prinMatShader.parm("reflect_texture").eval() + tex_maps["opac"] = prinMatShader.parm("opaccolor_texture").eval() + tex_maps["nrml"] = prinMatShader.parm("baseNormal_texture").eval() + tex_maps["disp"] = prinMatShader.parm("dispTex_texture").eval() + + # safety strip + for tex in tex_maps: + tex_maps[tex] = tex_maps[tex].strip() + print(tex_maps[tex]) + + return tex_maps + +def main(): + + + shader = hou.selectedNodes()[0] + print(GetMapsFromNode(shader)) \ No newline at end of file diff --git a/bin/DEV/MaterialXSubnet_v01_01.py b/bin/DEV/MaterialXSubnet_v01_01.py new file mode 100644 index 0000000..990a218 --- /dev/null +++ b/bin/DEV/MaterialXSubnet_v01_01.py @@ -0,0 +1,108 @@ +""" + STATUS: V01_01 Working + Feature/Purpose: Creates Mtlx Subnet with Basic Texture Connection +""" +import hou +print("----------------------------") +hou.node("/obj").deleteItems(hou.node("/obj").children()) + + + +#-----------------------------------------------------------# +# Create MaterialX Subnet + +def create_MTLX_Subnet(matcontext): + """ + :param matContext: Dest Path for creating materialX subnet + :type matContext: matnet + + :raise TypeError: if not a matnet object + :rtype: Boolean + """ + if matcontext.type().name() != "matnet": + print("create_MTLX_Subnet requires Matnet Object as input") + return False + + mtlxSubnet = matcontext.createNode("subnet", matcontext.type().name() + "_materialX") + print("Material X subnet Created") + + children = mtlxSubnet.allSubChildren() + mtlxSubnet.deleteItems(children) + + # Define Outer Surface + surfaceOutput = mtlxSubnet.createNode("subnetconnector") + surfaceOutput.setName("Surface_Output") + surfaceOutput.parm("connectorkind").set("output") + surfaceOutput.parm("parmname").set("surface") + surfaceOutput.parm("parmlabel").set("surface") + surfaceOutput.parm("parmtype").set("surface") + + + # Discplacement Output + displacementOutput = mtlxSubnet.createNode("subnetconnector") + displacementOutput.setName("Displacement_Output") + displacementOutput.parm("connectorkind").set("output") + displacementOutput.parm("parmname").set("Displacement") + displacementOutput.parm("parmlabel").set("Displacement") + displacementOutput.parm("parmtype").set("displacement") + + # Mtlx_Standard_Surface + mtlxStandard = mtlxSubnet.createNode("mtlxstandard_surface") + surfaceOutput.setInput(0, mtlxStandard) + + IMG_TEX_NODE = "mtlximage" + + # Albedo + albedo = mtlxSubnet.createNode(IMG_TEX_NODE, "Albedo") + mtlxStandard.setNamedInput("base_color", albedo, "out") + + # Roughness + roughness = mtlxSubnet.createNode(IMG_TEX_NODE, "Roughness") + roughness.parm("signature").set("float") + mtlxStandard.setNamedInput("specular_roughness", roughness, "out") + + # Metallic + metallic = mtlxSubnet.createNode(IMG_TEX_NODE, "Metallic") + metallic.parm("signature").set("float") + mtlxStandard.setNamedInput("metalness", metallic, "out") + + # SPECULAR + specular = mtlxSubnet.createNode(IMG_TEX_NODE, "Specular") + specular.parm("signature").set("float") + mtlxStandard.setNamedInput("specular", specular, "out") + + #OPACITY + opacity = mtlxSubnet.createNode(IMG_TEX_NODE, "Opacity") + mtlxStandard.setNamedInput("opacity", opacity, "out") + + # Normals + normal = mtlxSubnet.createNode(IMG_TEX_NODE, "Normals") + normal_map = mtlxSubnet.createNode("mtlxnormalmap") + normal_map.setNamedInput("in", normal, "out") + mtlxStandard.setNamedInput("normal", normal_map, "out") + + # Displacement + displacement_tex = mtlxSubnet.createNode(IMG_TEX_NODE, "Displacement") + displacement_tex.parm("signature").set("float") + displacement_remap = mtlxSubnet.createNode("mtlxremap") + displacement = mtlxSubnet.createNode("mtlxdisplacement") + + displacementOutput.setNamedInput("suboutput", displacement, "out") + displacement.setNamedInput("displacement", displacement_remap, "out") + displacement_remap.setNamedInput("in", displacement_tex, "out") + + displacement_remap.parm("outlow").set(-0.5) + displacement_remap.parm("outhigh").set(0.5) + displacement.parm("scale").set(0.1) + + # LAYOUT + mtlxSubnet.layoutChildren() + return True +#-----------------------------------------------------------# + +def main(): + + MTLX_DEST = hou.node("/obj").createNode("matnet") + create_MTLX_Subnet(MTLX_DEST) + +main() \ No newline at end of file diff --git a/bin/DEV/USDConverterUI.py b/bin/DEV/USDConverterUI.py new file mode 100644 index 0000000..3e14d6a --- /dev/null +++ b/bin/DEV/USDConverterUI.py @@ -0,0 +1,133 @@ +from PySide2.QtWidgets import QMainWindow, QWidget, QStatusBar, QListWidget, QRadioButton, QFrame, QPushButton, QLabel, QHBoxLayout, QVBoxLayout, QLineEdit +from PySide2.QtCore import Qt +from PySide2.QtGui import QFont +import hou + +class USD_UI(QMainWindow): + def __init__(self): + super().__init__() + + self.setWindowFlags(Qt.WindowStaysOnTopHint) + self.setWindowTitle("Megascan USD Asset Converter") + self.LightGreyFont = QFont("Courier", 8) + self._UI_ImportSection() + self._createUI() + + #--------- UI MAIN ---------# + def _createUI(self): + self.setStatusBar(QStatusBar(self)) + # Step 1 + PathPrefixLabel = QLabel("Set a Default Path Prefix for Asset Export Path") + PathPrefixLabel.setStyleSheet( "font-size : 10pt; color: lightgrey; font-weight:bold;") + self.SetPathPrefix = QLineEdit("$HIP/usd") + self.SetPathPrefix.echoMode() + self.SetPathPrefix.setAlignment(Qt.AlignHCenter) + # pathPrefixVarSet = QListWidget("Edit List") + + PathPrefixLabel2 = QLabel("Default $HIP/usd would be good if you need to move around your Project.\n[TIP] You can set a $VAR = /MS_USD_Path and use it as a common USD Library Directory for Export") + PathPrefixLabel2.setWordWrap(True) + PathPrefixLabel2.setFont(self.LightGreyFont) + + # Step 2 + HLine = QFrame() + HLine.setFrameShape(QFrame.HLine) + Frame1 = QFrame() + Frame1.setFrameShape(QFrame.Box) + + self.convert = QPushButton("Convert into USD") + self.convert.setStyleSheet("color: rgb(0, 255, 155);") + self.help = QPushButton("Help") + self.help.setStyleSheet("color: rgb(255, 80, 80);") + self.help.clicked.connect(self.help_was_clicked) + + ## Path Layout + LayHor1 = QHBoxLayout() + LayHor1.addWidget(PathPrefixLabel) + LayHor1.addStretch() + LayHor1.addWidget(self.SetPathPrefix) + # LayHor1.addWidget(pathPrefixVarSet) + + ## Final Layout + FinalLayout = QHBoxLayout() + FinalLayout.addWidget(self.help) + FinalLayout.addWidget(self.convert) + FinalLayout.setAlignment(self.help, Qt.AlignHCenter) + FinalLayout.setAlignment(self.convert, Qt.AlignHCenter) + + ## Core Layout + CoreLayout = QVBoxLayout() + CoreLayout.addLayout(LayHor1) + CoreLayout.addWidget(PathPrefixLabel2) + CoreLayout.addWidget(HLine) + CoreLayout.addSpacing(20) + CoreLayout.addLayout(self.ImportLayout) + CoreLayout.addSpacing(20) + CoreLayout.addLayout(FinalLayout) + CoreLayout.addStretch() + + Container = QWidget() + Container.setLayout(CoreLayout) + + self.setCentralWidget(Container) + + #--------- UI Import Section ---------# + def _UI_ImportSection(self): + + label1 = QLabel("1. Import Megascan Asset Using Bridge and MSPlugin and select the *Asset Subnet*.") + ImportHeading = QLabel("Import Settings") + ImportHeading.setStyleSheet( "font-size : 10pt; color: lightgrey; font-weight:bold;") + label2 = QLabel("2. Select One of the Import Method.") + + self.Single = QRadioButton ("Single Mesh") + self.Variant = QRadioButton ("Variant Mesh") + self.Split = QRadioButton ("Split Variant Mesh") + self.Single.toggled.connect(self._updateImportMethod) + self.Variant.toggled.connect(self._updateImportMethod) + self.Split.toggled.connect(self._updateImportMethod) + self.Single.setStatusTip("Creates Single Asset for Single Mesh") + self.Variant.setStatusTip("Creates Individual Asset for each of the collection Items of Single Meshes.") + self.Split.setStatusTip("Creates Single Asset containing all variant of each collection items.") + + ## Method Radio Buttons + ButtonLayout = QHBoxLayout() + ButtonLayout.addStretch() + ButtonLayout.addWidget(self.Single) + ButtonLayout.addWidget(self.Variant) + ButtonLayout.addWidget(self.Split) + ButtonLayout.addStretch() + + + self.ImportLayout = QVBoxLayout() + self.ImportLayout.addWidget(ImportHeading) + self.ImportLayout.setAlignment(ImportHeading, Qt.AlignHCenter) + self.ImportLayout.addSpacing(10) + self.ImportLayout.addWidget(label1) + self.ImportLayout.addSpacing(10) + self.ImportLayout.addWidget(label2) + self.ImportLayout.addLayout(ButtonLayout) + + + #--------- Choose Import Method ---------# + def _updateImportMethod(self, data): + if self.Single.isChecked(): + print("single") + elif self.Variant.isChecked(): + print("Variant") + elif self.Split.isChecked(): + print("Split") + + #--------- Help ---------# + def help_was_clicked(self): + print("help") + self.H = HelpUI() + self.H.show() + +#--------- Help Widget Class---------# +class HelpUI(QWidget): + def __init__(self): + super().__init__() + self.setWindowFlags(Qt.WindowStaysOnTopHint) + self.setWindowTitle("Help - Megascan USD Asset Converter") + +A = USD_UI() +A.show() \ No newline at end of file diff --git a/bin/icons/USDLogo400x400.png b/bin/icons/USDLogo400x400.png new file mode 100644 index 0000000000000000000000000000000000000000..212465a1bf259ac9294a9b6f058625cf9af63830 GIT binary patch literal 13646 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 Hu0mjfXhkg% literal 0 HcmV?d00001 diff --git a/bin/preset/exportpath.csv b/bin/preset/exportpath.csv new file mode 100644 index 0000000..f4d816d --- /dev/null +++ b/bin/preset/exportpath.csv @@ -0,0 +1 @@ +$HIP/usd/assets, \ No newline at end of file diff --git a/master_conversion_USD.py b/master_conversion_USD.py new file mode 100644 index 0000000..ff9edb2 --- /dev/null +++ b/master_conversion_USD.py @@ -0,0 +1,70 @@ +import hou, sys +varPath = "M:\\Notes\\Tools\\USD_Megascan_Importer" +sys.path.append(varPath) + +from Get_Bridge_Asset_2 import MS_Asset_Data +from Get_Maps_v01_02 import Texture_Files +from MaterialXSubnet_v01_02 import create_MTLX_Subnet +from Generate_USD_02_Variant_Asset import USD_Asset_Builder + + +def mainSingle(): # Working + + if len(hou.selectedNodes()) == 0: + hou.ui.displayMessage("Select a Megascan Imported Asset Subnet") + else: + if not MS_Asset_Data().Check_is_MS_Asset(): + hou.ui.displayMessage("Select a Megascan Imported Asset Subnet") + else: + ASSET_NAME, ASSET_PATH, ASSET_MAT_PATH = MS_Asset_Data().SingleMeshData() + + prinShader = hou.node(ASSET_MAT_PATH) + maps = Texture_Files().GetMapsFromNode(prinShader) + + MS = USD_Asset_Builder(ASSET_NAME, ASSET_PATH) + MS.singleGeoImport() + + create_MTLX_Subnet(MS.asset_matLib, maps, ASSET_NAME) + MS.setMeshExport() + + +def SOPVariants(): # + + print(MS_Asset_Data().SOPvariantsData()) + if len(hou.selectedNodes()) == 0: + hou.ui.displayMessage("Select a Megascan Imported Asset Subnet") + else: + if not MS_Asset_Data().Check_is_MS_Asset(): + hou.ui.displayMessage("Select a Megascan Imported Asset Subnet") + else: + ASSET_NAME, ASSET_PATH, ASSET_MAT_PATH, ASSET_ITER_RANGE = MS_Asset_Data().SOPvariantsData() + # l = MS_Asset_Data().SOPvariantsData() + # print (l) + + prinShader = hou.node(ASSET_MAT_PATH) + maps = Texture_Files().GetMapsFromNode(prinShader) + + MS = USD_Asset_Builder(ASSET_NAME, ASSET_PATH) + MS.variantSOPsGeoImport(ASSET_ITER_RANGE) + + create_MTLX_Subnet(MS.asset_matLib, maps, ASSET_NAME) + MS.setMeshExport() + +def subSOPVariants(): + + if len(hou.selectedNodes()) == 0: + hou.ui.displayMessage("Select a Megascan Imported Asset Subnet") + else: + if not MS_Asset_Data().Check_is_MS_Asset(): + hou.ui.displayMessage("Select a Megascan Imported Asset Subnet") + else: + ASSET_NAME, ASSET_PATH, ASSET_MAT_PATH, ASSET_ITER_RANGE = MS_Asset_Data().SubSOPvariantsData() + print(ASSET_PATH) + prinShader = hou.node(ASSET_MAT_PATH) + maps = Texture_Files().GetMapsFromNode(prinShader) + + MS = USD_Asset_Builder(ASSET_NAME, ASSET_PATH) + MS.variantSub_SOPGeoImport(ASSET_ITER_RANGE - 1) + + create_MTLX_Subnet(MS.asset_matLib, maps, ASSET_NAME) + MS.setMeshExport()