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 0000000..212465a Binary files /dev/null and b/bin/icons/USDLogo400x400.png differ diff --git a/bin/icons/help.png b/bin/icons/help.png new file mode 100644 index 0000000..03d9523 Binary files /dev/null and b/bin/icons/help.png differ diff --git a/bin/icons/main.png b/bin/icons/main.png new file mode 100644 index 0000000..17f855a Binary files /dev/null and b/bin/icons/main.png differ 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()