Creating a material and applying to BaseObject within Python Generator



  • Hello, I did a search and couldn't find much to do with materials.

    My c4d version is R19

    I am creating a bunch of BaseObjects inside a Python Generator and trying to shade them in various ways- which requires me to create a new material for each BaseObject.

    I am successfully creating the Material instance (I think) by storing a new c4d.Material() into a new variable. However, when I run MakeTag(c4d.Ttexture) on the BaseObject and set the c4d.TEXTURETAG_MATERIAL parameter to my newly created material, it does not appear to take.

    Here is my code. It uses some modata from a linked matrix object to generate a series of discs / rings.

    import c4d
    from c4d.modules import mograph as mo
    #Welcome to the world of Python
    
    def main():
        link = op[c4d.ID_USERDATA,1]
        size = op[c4d.ID_USERDATA,2]
        roff = op[c4d.ID_USERDATA,3]
        
        md = mo.GeGetMoData(link)
        if md is None: return False
        
        null = c4d.BaseObject(c4d.Onull)
        
        cnt = md.GetCount()
        marr = md.GetArray(c4d.MODATA_MATRIX)
        carr = md.GetArray(c4d.MODATA_COLOR)
        for i in reversed(xrange(0, cnt)):
            
            mat = c4d.Material()
            mat.SetChannelState(c4d.CHANNEL_COLOR, True)
            mat[c4d.MATERIAL_COLOR_COLOR] = carr[i]
            
            disc1 = c4d.BaseObject(c4d.Odisc)
            disc1[c4d.PRIM_DISC_ORAD] = carr[i][0] * size
            disc1[c4d.PRIM_AXIS] = 4
            disc1.SetMg(marr[i])
            disc1.InsertUnder(null)
            
            disc2 = c4d.BaseObject(c4d.Odisc)
            disc2[c4d.PRIM_DISC_IRAD] = carr[i][0] * size
            disc2[c4d.PRIM_DISC_ORAD] = carr[i][0] * size * 1.2
            disc2[c4d.PRIM_AXIS] = 4
            moff = marr[i]
            moff.off = moff.off + (roff * carr[i][0])
            disc2.SetMg(marr[i])
            ttag =  disc2.MakeTag(c4d.Ttexture)
            ttag[c4d.TEXTURETAG_MATERIAL] = mat
            disc2.InsertUnder(null)
        
        return null
    

    Any ideas or suggestions are greatly appreciated! Thank you!



  • Hello,

    you cannot create a Material in the main() function of a Python Generator object.

    The main() function of the Python Generator object defines a cache of "virtual" BaseObjects which will appear in the scene.

    Materials cannot be created this way. A material must be inserted into the BaseDocument. This must only happen from the main thread, typically in reaction to some user interaction.

    One way of doing this would be to add a user data button to your Generator. Then your user could simply press that button to create the needed materials. Pressing the button can be detected by implementing the message() function.

    This could look like this:

    def main():
    
        # search for material
        mat = doc.SearchMaterial("Generator Material")
    
        if mat is None:
            return None
    
        # create object
        cube = c4d.BaseObject(c4d.Ocube)
        
        # apply material
        ttag =  cube.MakeTag(c4d.Ttexture)
        ttag[c4d.TEXTURETAG_MATERIAL] = mat
    
        return cube
    
    def message(id, data):
        if id == c4d.MSG_DESCRIPTION_COMMAND:
            buttonId = data['id']
    
            # check button ID
            if buttonId[1].id == 1:
                
                # create material and insert it into the host document
                c4d.StopAllThreads()
    
                material = c4d.Material()
                material.SetName("Generator Material")
                material[c4d.MATERIAL_COLOR_COLOR] = c4d.Vector(1,0,0)
    
                doc.InsertMaterial(material, None)
    
                c4d.EventAdd()
    

    Also, please use the Q&A system.

    best wishes,
    Sebastian


Log in to reply