Python Effectors



  • Hi everyone,

    I've made a simply python effector that allows me to manipulate the color of a effected cloner. That works fine but when I creat an instance of that object and start moving it in 3D space, I get a ton of these errors:

    Traceback (most recent call last):
    File "'<Python>'", line 18, in main
    TypeError: object of type 'NoneType' has no len()

    https://www.dropbox.com/s/4cui1f7t8a1l0n9/PyEffectorTest_v1.c4d?dl=0

    import c4d
    from c4d.modules import mograph as mo
    #Welcome to the world of Python
    
    def main():
        linked = op[c4d.ID_USERDATA,1]
        md = mo.GeGetMoData(op)
        md2 = mo.GeGetMoData(linked)
        EB = op[c4d.ID_USERDATA,2]
    
        if md is None: return False
        
        cnt = md.GetCount()
        clr = md.GetArray(c4d.MODATA_COLOR)
        clr2 = md2.GetArray(c4d.MODATA_COLOR)    
    
        if cnt > 0: 
            print cnt
        
        #for i in xrange(0,cnt):
            #clr[i] = clr2[i] + (clr2[i] * c4d.Vector(EB))
        
        md.SetArray(c4d.MODATA_COLOR, clr, True)
        return True
    
    
        c4d.EventAdd()
        
        
    
    if __name__=='__main__':
        main()
    

    Does anyone have an idea how to get around this?



  • This post is deleted!


  • Took a second look. It seems that you're trying to iterate on a list that doesn't exist. xrange(0,0) returns None not []. This likely happens because the instanced effector can't access the MoData of the other cloner that's been instanced (or something like that). I've taken the liberty of reworking your code to be a bit more error-tolerant:

    import c4d
    from c4d.modules import mograph as mo
    
    def main():
        # Retrieve User Inputs
        EB = op[c4d.ID_USERDATA,2]
        linked = op[c4d.ID_USERDATA,1]
        if linked is None:
            return True
        
        md = mo.GeGetMoData(op)
        if md is None:
            return True
        
        linked_md = mo.GeGetMoData(linked)
        if linked_md is None:
            return True
        
        md_count = md.GetCount()
        if not md_count:
            return True
        
        linked_md_count = linked_md.GetCount()
        if not linked_md_count:
            return True
        
        # If counts don't match between cloners, use the smaller number.
        clone_count = min([md_count, linked_md_count])
        
        colors = md.GetArray(c4d.MODATA_COLOR)
        if colors is None:
            return
        
        linked_colors = linked_md.GetArray(c4d.MODATA_COLOR)
        if linked_colors is None:
            return
    
        for i in xrange(clone_count):
            colors[i] = linked_colors[i] + (linked_colors[i] * c4d.Vector(EB))
        
        md.SetArray(c4d.MODATA_COLOR, colors, True)
        return True
        
    
    if __name__=='__main__':
        main()
    

    But looking at your scene I'm not sure you'll get the result you want trying to colorize one cloner with a cloner object it's cloning.


  • Global Moderator

    I have moved this thread to "Cinema 4D Development" category.



  • Thanks dskeith, that code worked perfectly. Thanks for that!