Poser Python and Material Nodes



  • @kobaltkween Chapter 16 of the reference manual . Page 465. Expanding compound nodes.



  • @eclark1849 Sorry, I wasn't clear. I know how to do it in the interface. I specifically meant through the Python API. You see, there's no ShaderTree() method for nodes. So my guess would be that you do it through one of the methods described in the explanation of the CompoundData() node method (Page 181 of the Poser Python Manual):
    "Get a data object providing access to compound-node-specific methods. If this is not a compound node, the return value will be None."

    The problem is that I can find absolutely no record of those "compound-node-specific methods." I can get the object, but without knowing how to access it's methods, I'd have to write some sort of script to just get the object to explain/describe its interface to me. Which is a PITA I'd like to avoid if I can.



  • Just in case someone else searches for this, these are the methods I'm finding so far:
    AttachTreeNodes
    ContainedNodes
    CreateNode
    DeleteNode
    DetachTreeNode
    ExposeInput
    ExposeOutput
    ExposedInputs
    ExposedInputsLocation
    ExposedOutputs
    ExposedOutputsLocation
    SetExposedInputsLocation
    SetExposedOutputsLocation

    I'm still not sure how one would use these methods to duplicate a compound node, but it seems I'm going to have to work on it.



  • Some more undocumented methods, for the NodeOutput object
    ConnectToInput
    InternalName
    ItsNode
    Name
    SetName



  • @kobaltkween I know this is resurrection, but did you ever tie all this down so you could create a compound node from code?



  • I have created compound nodes with a script, it is possible. I don't have the script here right now, but I will search for it and post it here in a couple of days.



  • @bantha Did you manage to find anything?


  • Poser Ambassadors

    I have not only created compound nodes before, but also dynamically created all the internal nodes by type, and then dynamically created all the connections between them, so I know it can be done. Each node has an ID that identifies them by type. The manual has a list of all the IDs.

    I also remember the manual being really vague and useless about this, so I had to ask around for the details. Nobody new about this specifically, so I went trial and error until it worked. This was a year ago, so I don't remember the details, but I do remember nodes are identified by IDs, and we loop across all nodes until we find the ID. We can also assign names for the nodes, which help identifying them across others of the same type. This is the name that shows on the title bar of each node. With a combination of ID + name, we can uniquely locate and identify a specific node in that jungle.

    However, if you want to locate a specific node created in other people's shaders, with random node names, that can be difficult.



  • @ken1171 Hi, yes I know it can be done, and I have also done this with materials that don't have compound nodes, both on my own and using EZSkin3, it is the total lack of documentation around compound nodes that stopped me. Yes I'm sure I can figure it out I was just wondering if anyone had a snippet that showed the basics it would be easier :)



  • It works like this:

    scn = poser.Scene()
    mat = scn.CurrentMaterial()
    tree = mat.ShaderTree()
    nodelist = tree.Nodes()
    t1 = tree.Node(0)
    n2=tree.CreateNode("compound")
    n2.SetName("MHSkin2")
    root=n2.CompoundData()

    #Now create a sample node inside "root":.

    n = self.createNode(root,'image_map','Image_Map_9',655,282)
    n.SetName('Image_Map_9')
    n.SetInputsCollapsed(1)
    n.SetPreviewCollapsed(1)
    n.InputByInternalName('Image_Source').SetString(r'C:\Render\Poser\VickyV4\Runtime\Textures\RMMandira\RMMndraT1.jpg')
    n.InputByInternalName('Auto_Fit').SetFloat(0.0)
    n.InputByInternalName('U_Scale').SetFloat(1.0)
    n.InputByInternalName('V_Scale').SetFloat(1.0)
    n.InputByInternalName('U_Offset').SetFloat(0.0)
    n.InputByInternalName('V_Offset').SetFloat(0.0)
    n.InputByInternalName('Texture_Coords').SetFloat(1.0)
    n.InputByInternalName('Image_Mapped').SetFloat(4.0)
    n.InputByInternalName('Background').SetColor(1.0,1.0,1.0)
    n.InputByInternalName('Global_Coordinates').SetFloat(0.0)
    n.InputByInternalName('Mirror_U').SetFloat(0.0)
    n.InputByInternalName('Mirror_V').SetFloat(0.0)
    n.InputByInternalName('Texture_Strength').SetFloat(1.0)
    n.InputByInternalName('Filtering').SetFloat(3.0)
    # Next node

    #Connect multiple nodes like this:

    cmpNodes=root.ContainedNodes()
    cmpO=root.ExposeOutput(cmpNodes[m+19].Output(0))
    cmpO.SetName("BSDF")
    cmpNodes[m+17].ConnectToInput(cmpNodes[m+5].InputByInternalName('Normal'))
    cmpNodes[m+1].ConnectToInput(cmpNodes[m+7].InputByInternalName('Color'))
    cmpNodes[m+17].ConnectToInput(cmpNodes[m+7].InputByInternalName('Normal'))
    cmpNodes[m+38].ConnectToInput(cmpNodes[m+8].InputByInternalName('Closure1'))

    #Create inputs like this:

    expIn=root.ExposeInput(cmpNodes[m+7].Input(0))
    expIn.SetName("Diffuse")
    expIn=root.ExposeInput(cmpNodes[m+8].Input(0))
    expIn.SetName("Diffuse Weight")
    expIn=root.ExposeInput(cmpNodes[m+21].Input(0))
    expIn.SetName("Base")
    expIn=root.ExposeInput(cmpNodes[m+20].Input(0))
    expIn.SetName("SSS Scale")
    expIn=root.ExposeInput(cmpNodes[m+5].Input(0))
    expIn.SetName("Specular Color")
    expIn=root.ExposeInput(cmpNodes[m+14].Input(0))
    expIn.SetName("Specular Weight")
    expIn=root.ExposeInput(cmpNodes[m+5].Input(2))
    expIn.SetName("Specular Roughness")
    expIn=root.ExposeInput(cmpNodes[m+11].Input(0))

    Is this example enough?



  • Hi @bantha yep that gives me what I need, thank you