The layer material ID is the same as the node material ID.



  • Hi:
    I'm a beginner in Python, and I've had a problem for a long time, because the material ID is the same, and some of the functionality doesn't work. When can the ID be updated?



  • Hi,

    I am not quite sure what you are talking about. I never dabbled with the new node based materials in Python, but I somehow doubt that they have the same ID as Cinema's standard material (which would be c4d.Mmaterial), as Cinema otherwise would not be able to distinguish between these two. What are you referring to with "(material) ID"?

    Also noteworthy is that the node based materials require a special interface to do anything useful. Afaik, this interface has not been exposed to Python yet, so you won't really be able to do anything meaningful, unless you find an unofficial way to modify such a material.

    Cheers,
    zipit



  • Thank you for your reply. I know that the third party renderer has opened the Python interface. Sorry to interrupt. Thanks again for your reply.The screenshot is as follows:

    Material_picture.jpg



  • Hm,

    that is weird, 5703 is the ID Mmaterial. As you can see here, while both Material and NodeMaterial inherit from BaseMaterial, NodeMaterial does not inherit from Material. So this is either some sort of dummy Mmaterial node for the old material editor, or this has to do with the fact, that NodeMaterial has not been exposed to Python yet.

    If you are really hellbent on determining if a Mmaterial node is actually a node material or not, you could look at their description, as they are obviously not the same. But be aware that materials can have dynamically generated elements in their description. So just comparing the lengths or looking for a specific length is probably a very unreliable method. You probably want to look for the presence of a certain parameter/attribute.

    import c4d
    
    def main():
        """
        """
        # Get the first material.
        material = doc.GetFirstMaterial()
        if not isinstance(material, c4d.BaseMaterial):
            raise ValueError("No material found.")
    
        # Loop over all materials.
        while material:
            # Get the description of the current material.
            description = material.GetDescription(0)
            # The number of elements in that description.
            parameter_count = len(list(description))
            print material, parameter_count
            material = material.GetNext()
    
    if __name__ == "__main__":
        main()
    

    Which will print for some node and some true Mmaterial materials something like this:

    <c4d.Material object called 'Mat/Mat' with ID 5703 at 0x00000178FA08FEF0> 267
    <c4d.Material object called 'Mat/Mat' with ID 5703 at 0x00000178FA08F690> 267
    <c4d.Material object called 'Node/Mat' with ID 5703 at 0x00000178FA08F0B0> 278
    <c4d.Material object called 'Node/Mat' with ID 5703 at 0x00000178FA08FEF0> 278
    <c4d.Material object called 'Mat/Mat' with ID 5703 at 0x00000178FA08F690> 267
    

    Cheers,
    zipit



  • Thank you for your patience, but I really want to implement the following function: automatically create the material ball and sky objects to reduce the workload.But the standard material and node material have the same ID, which is difficult to implement in a normal way.Thank you again for your patient reply.

    Here is the Arnold renderer script code:

    import c4d
    
    def main():
        #Select active objects.
        objects = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
        if not objects :
           raise ValueError("No objects selected.")
    
        doc.StartUndo()
        
        for obj in objects:
            
            #Collect texture tags.
            Tags = obj.GetTags()
            TextureTag = [TagList for TagList in Tags if TagList.GetRealType() == 5616]
    
            #Delet blank texture tag.
            if TextureTag != 0:
                for Blank in TextureTag:
                    if Blank[c4d.TEXTURETAG_MATERIAL] == None:
                        doc.AddUndo(c4d.UNDOTYPE_CHANGE,Blank)
                        Blank.Remove()
    
            #Add an arnold texture ball and texture tag to each active object.
            arnold = c4d.BaseMaterial(1033991)
            Tag = c4d.BaseTag(5616)
            Tag[c4d.TEXTURETAG_MATERIAL] = arnold
            doc.InsertMaterial(arnold)
            obj.InsertTag(Tag)
    
        #Create the arnold sky object.
        Sky = c4d.BaseObject(1034624)
        doc.InsertObject(Sky)
        
        doc.EndUndo()
        c4d.EventAdd()
    
    if __name__ == "__main__":
        main()
    


  • Hi,

    as I said: The node space has not been exposed to Python yet. You cannot create, modify or even just access NodeMaterial materials in Python. So would either have to use C++ or just another material system.

    Cheers,
    zipit



  • Hi in C++ there is the BaseList2D.IsNodeBased method to check if a BaseList2D contains nodes and more interesting there is the NodeMaterial class that represents a Nodal Material, unfortunately, both are not available in Python.
    Note also that any type of material can be evaluated to a NodeMaterial and this will add the MaterialData the ability to use NodeGraph.

    So I confirm the only reliable way in Python to know if a material is a NodeBased one is to check the description.

    If you want to explicitly create a NodeBaseMaterial the only way for you do to do so is via CallCommand with

    c4d.CallCommand(202541) # New Node Material
    

    Cheers,
    Maxime.


Log in to reply