'''
    Daz to Houdini Helper Tool.
    Created by Bilal Malik. (Ver 0.65)
    Contact:echopraxiavfx@gmail.com
    
    This tool aims to provide easier starts for using FBX Exports from Daz to Houdini workflows.
    Currently in development with more features to come.
    
    Code Partially Generated by PYQT-UI Generator Also on my Github.
'''
import os, sys, hou

#Location of Assets
app_location = os.path.join("PATH_HERE")

#Add Path to Qt Module
qt_module = os.path.join(app_location+"\Assets\Qt.pyc")
sys.path.insert(0, qt_module)

#Qt Import Block 
from Qt import QtCore, QtWidgets, QtCompat , QtGui
from Qt.QtWidgets import QFileDialog

#Class Creation
class H2Dz(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
                super(H2Dz, self).__init__(parent, QtCore.Qt.WindowStaysOnTopHint)
                #File Interface File goes here
                file_interface = os.path.join(app_location+"\Assets\Hou2Daz.ui")
                self.mw = QtCompat.loadUi(file_interface)
                self.setCentralWidget(self.mw)
                #Set Window Title Here
                self.setWindowTitle("Daz Helper Script (Houdini)")
                stylesheet = hou.qt.styleSheet()
                self.setStyleSheet(stylesheet)
                #Set Windows Flags
                self.setWindowFlag(QtCore.Qt.WindowMaximizeButtonHint, False)
                self.setWindowFlag(QtCore.Qt.MSWindowsFixedSizeDialogHint, True)
                self.setWindowFlag(QtCore.Qt.WindowMinimizeButtonHint, False)
                
                #Pixmap
                header = os.path.join(app_location+"\Assets\header_daz2hou.png")
                pixmap = QtGui.QPixmap(header)
                self.mw.lbl_Header.setPixmap(pixmap)
                
                helper = os.path.join(app_location+"\Assets\help_daz2hou.png")
                pixmap2 = QtGui.QPixmap(helper)
                self.mw.lbl_help.setPixmap(pixmap2)
                
                #Button Assignment
                self.mw.bttn_ImportFBX.clicked.connect(self.importFbx)
                self.mw.bttn_SelectSubnet.clicked.connect(self.selectSubnet)
                self.mw.bttn_PreviewSubnet.clicked.connect(self.previewSubnet)
                self.mw.bttn_conTex.clicked.connect(self.manualArnold)
                
                self.mw.bttn_scale_1.clicked.connect(lambda: self.setScale(1))
                self.mw.bttn_scale_01.clicked.connect(lambda: self.setScale(0.1))
                self.mw.bttn_scale_001.clicked.connect(lambda: self.setScale(0.01))
                
                self.mw.bttn_lockObjMerges.clicked.connect(self.lockObjMergeNodes)
                self.mw.bttn_clearList.clicked.connect(self.clearList)
                
                self.mw.bttn_createHairGeo.clicked.connect(self.hairGroomGeo)
                
        def clearList(self):
            self.mw.lst_preview.clear()
        
        def importFbx(self):
                #Opens File Dialog
            options = QFileDialog.Options()
            #options |= QFileDialog.DontUseNativeDialog
            fbx_fileName, _ = QFileDialog.getOpenFileName(self,"Select FBX File.", "","Filmbox FBX (*fbx);;All Files (*)", options=options)
            
            if fbx_fileName:
                #Debug Line
                print(fbx_fileName)
                #Try importing FBX
                try:
                    print("Importing FBX...")
                    fbx = hou.hipFile.importFBX(fbx_fileName)
                    print("Imported Complete.")
                    #Call Fill Routine
                    
                except:
                    print("ERROR_IMPORTING_FBX 001")
                    

        def previewSubnet(self):
            self.mw.lst_preview.clear()
            FBX = hou.selectedNodes()[0]
            if FBX.type().name() == "subnet":
                geometry_FBX = [node for node in FBX.children() if node.type().name() == 'geo']
                for geo in geometry_FBX:
                    self.mw.lst_preview.addItem(geo.name())
            else:
                print("ERROR, No Subnet Selected.")
        def selectSubnet(self):
            FBX = hou.selectedNodes()[0]
            #Root Location
            OBJ = hou.node('/obj/')  
            
            if not FBX:
                #Error no fbx sub detected.
                print("Error: No objects selected.")
            elif FBX:
                if FBX.type().name() == "subnet":
                # Create Geometry node to store FBX parts
                    geometry = OBJ.createNode('geo', run_init_scripts = False)
                    geometry.setName('GEO_{}'.format(FBX.name()))
                    geometry.moveToGoodPosition()
                    # Get all parts inside FBX container
                    geometry_FBX = [node for node in FBX.children() if node.type().name() == 'geo']
                    
                    # Create merge node for parts
                    merge = geometry.createNode('merge')
                    merge.setName('master_merge')
                    
                    #Create Null Object at the end
                    oNull = geometry.createNode('null')
                    oNull.setName('OUT_DAZ')
                    
                    #Link MergeOut to NullIn
                    oNull.setInput(0, merge)
                    
                    # Replicate FBX structure in Geometry node
                    for geo in geometry_FBX: 
                        # Create Object Merge node
                        objectMerge = geometry.createNode('object_merge')
                        objectMerge.setName(geo.name())
                        
                        # Set path to FBX part object
                        objectMerge.parm('objpath1').set(geo.path())
                        objectMerge.parm('xformtype').set(1)
                        
                        # MATERIAL HANDLING
                        
                        # Copy Material from Geo
                        matName = hou.node("obj/" + FBX.name() + "/" + geo.name() + "/" + geo.name() + "_material")
                        if matName is not None:
                            parentH = hou.node("obj/" + geometry.name())
                            hou.copyNodesTo([matName], parentH)
                            material = hou.node("obj/" + geometry.name() + "/" + geo.name() + "_material")
                            #Call process to convert materials.
                            if self.mw.rdo_Arnold.isChecked() == True:
                                print("Converting to Arnold Materials.")
                                self.convertArnold(material)
                        else:
                            # Create Material node if none exist. No materials are added if none are detected.
                            material = geometry.createNode('material')
                            material.setName('MAT_{}'.format(geo.name()))
                        
                        # LINK NODES
                        
                        # Link Material to Object MergeName
                        material.setNextInput(objectMerge)
                        # Link part to Merge
                        merge.setNextInput(material)
                    
                    # Set Null Node flags to Render
                    oNull.setDisplayFlag(1)
                    oNull.setRenderFlag(1)
                    
                    # Layout geometry content in Network View 
                    geometry.layoutChildren()
                else:
                    print("NON-SUBNET Node Selected. Hint:You may only select one node at a time.")
                    

        def convertArnold(self,node):
            #Root Shop
            SHOP = hou.node('/shop/')  
            #Get Number of materials to create
            nMats = node.parm('num_materials').eval()
            #Loop for each material creating a new arnold one.
            for i in range(1,nMats+1):
                #Get Group Name of current loop.
                grp = "Ai_"+(node.parm('group'+str(i)).eval())
                #Check If Shader Exists
                if hou.node("/"+SHOP.name()+"/"+grp) is None:
                    #Create Arnold VOP in Root location
                    arnoldNode = SHOP.createNode('arnold_vopnet', run_init_scripts = True)
                    arnoldNode.setName(grp)
                    arnoldNode.moveToGoodPosition()
                    #Create Shader Inside
                    #Create 'smart' type indicator
                    type = 'Surface'
                    if type == 'Surface':
                        surfNode = arnoldNode.createNode('arnold::standard_surface')
                    elif type == 'Hair':
                        surfNode = arnoldNode.createNode('arnold::standard_hair')
                    surfNode.moveToGoodPosition()
                    outNode = hou.node(SHOP.name()+ "/" + arnoldNode.name()+"/"+"OUT_material")
                    outNode.setInput(0,surfNode)
                #Assign Material to Material Group.
                node.parm("shop_materialpath"+str(i)).set("/"+SHOP.name()+"/"+grp)
                
        def manualArnold(self):
            nodeToSend = hou.selectedNodes()[0]
            print(nodeToSend.type())
            if nodeToSend.type().name() == 'material':
                self.convertArnold(nodeToSend)
            else:
                print("ERROR Please Select a Material Node.")
                
                
        def setScale(self,value):
            node = hou.selectedNodes()[0]
            if node.type().name() == 'subnet':
                node.parm('scale').set(value)
            elif node.type().name() == 'geo':
                node.parm('scale').set(value)                
            else:
                print("ERROR Please select a subnet or geo node.")
                
                
        def lockObjMergeNodes(self):
            nodeS = hou.selectedNodes()[0]
            obj_merges = [node for node in nodeS.children() if node.type().name() == 'object_merge']
            for each in obj_merges:
                each.setHardLocked(1)
            
        def hairGroomGeo(self):
            node = hou.selectedNodes()[0]
            OBJ = hou.node('/obj/')  
            if node.type().name() == 'geo':
            
                #Create Geo in OBJ level.
                geometry = OBJ.createNode('geo', run_init_scripts = False)
                geometry.setName('Hair_GEO_{}'.format(node.name()))
                geometry.moveToGoodPosition()
                
                #Obj Merge
                objectMerge = geometry.createNode('object_merge')
                objectMerge.setName(node.name())
                objectMerge.parm('objpath1').set(node.path())
                
                
                #Transform
                xform = geometry.createNode('xform')
                xform.setInput(0,objectMerge)
                
                #Delete
                delnode = geometry.createNode('delete')
                delnode.setInput(0,xform)
                
                #Null Out_Char
                nullChar = geometry.createNode('null')
                nullChar.setName('OUT_CHAR')
                nullChar.setInput(0,delnode)
                
                #AttrbPaint
                attribpaint = geometry.createNode('attribpaint')
                attribpaint.setInput(0,nullChar)
                #Set AttrbPaint Density paramter
                attribpaint.parm('attribname1').set('density')
                
                #Null Out_Density
                nullDen = geometry.createNode('null')
                nullDen.setName('OUT_DENSITY')
                nullDen.setInput(0,attribpaint)
                
                #VDB from Polygons
                vdbN = geometry.createNode('vdbfrompolygons')
                vdbN.setInput(0,attribpaint)
                
                #Null Out_VDB
                nullVDB = geometry.createNode('null')
                nullVDB.setInput(0,vdbN)
                nullVDB.setName('OUT_VDB')
                
                #Set Render Flags
                nullChar.setDisplayFlag(1)
                nullChar.setRenderFlag(1)
                
                #Layout Geo
                geometry.layoutChildren()
       
isPanel = False
#Create the UI Block
if isPanel == True:
    #Create Interface Python Panel
    def onCreateInterface():
        my_window = H2Dz()
        my_window.show()
        return my_window
elif isPanel == False:
    #Create Interface Shelf.
    try:
        my_window.close()
    except:
        pass
    my_window = H2Dz()
    my_window.resize(270,625)
    my_window.show() 

