Coding a Python Plugin for fields



  • Hope I'm not doing something wrong. Second post and I got a kind of warning on the first one without really saying what I'd done wrong. If I am, sorry - please gently correct me and I'll abide by the rules.

    Starting in on plugin writing and kind of working my way up. I thought I'd do a field since there is a built in "python field" so I started there and finally got that working. Then I'd try a python plugin and finally I'd turn it into a C++ plugin - a language I'm much more familiar with. I decided to do a field that would be alternate off and on in angular segments around an axis. Okay - next I'd try a python plugin. I have my code from the "python field" I created - how hard can it be? I eventually figured out the menu system and got a plugin with a non-functional but proper menu to appear under plugins. At this point, I'm ready to create a field, give it a somewhat tweaked version of the Sampling method I'd written for the "python field" and return that - somewhere. I'm not sure where (GetVirtualObjects? But that seems to create objects that don't end up on the object list so doesn't seem right) but figured I'd definitely have to create a subclassed field so I made a new class and subclassed it off of c4d.modules.mograph.FieldObject. That should do it - but no:

     type 'c4d.FieldObject' is not an acceptable base type
    

    I had used "c4d.modules.mograph.FieldObject" but the message refers to "c4d.FieldObject" but whatever. I assume this is because I'm not a python guru and I'm missing some sort of aliasing weirdness on classes maybe. Spent the last 30 years writing in C++ and C# but not much Python programming. I looked at the documentation which is very low on semantic content and pretty much just gives barebones functions so I'm not really sure what I should be instantiating here - just guessed that it might be something called FieldObject but I guessed wrong. Saw FieldList and finally kinda guessed that this represents the list of fields in Falloffs, etc.. Saw that you put "FieldLayers" in these so maybe that's what I should be instantiating? Tried it and got the same "not acceptable base type". I've seen a few lists of "objects you can create in R20" and I don't see "Field" on them. I know that I can create an Ofield object but that will be a generic field object that doesn't have my sampling behavior, correct? Do I create one of those and somehow alter it? Is there a pointer to a sampling function that I replace somehow so I don't do subclassing at all? I've included a zipped file of what I've got currently (at least I tried - the forum told me that I didn't allow zip files but then uploaded it anyway so I'm keeping my fingers crossed). At this point it doesn't work since I've got the class in there that subclasses off of FieldObject. Remove that class and you get my nice little non-functional plugin with it's non-functional parameters menu.

    Thanks for any help here.

    Darrell Plank

    P.S. Finger crossing failed. I guess I'll just post the python function code by itself. Won't work without all the supporting stuff, but at least you'll see what I've got.

    P.P.S. Didn't want to load the pyp file either. I'm not sure how to upload a file. I press the "upload file" button and it seems to upload something but then just leaves some stuff in brackets which doesn't link anywhere. Sorry if I'm being dumb and obtuse, but I'm not figuring this out. I'll try again. Oh wait - it only allows image files and c4d files? That seems crazy in a forum dedicated to plugins, but okay. I tried to put a OneDrive link to the zip file up but my OneDrive is busy uploading other stuff at the moment. Argh. I guess I'll just past in my pyp code. Not very satisfactory, but...

    import c4d
    from c4d import gui, plugins
    import os
    
    PLUGIN_ID = 1050334
    
    ANGULAR_AXIS		= 1000
    ANGULAR_AXISX		= 1001
    ANGULAR_AXISY		= 1002
    ANGULAR_AXISZ		= 1003
    ANGULAR_STRCOUNT	= 1004
    ANGULAR_RATIO		= 1005
    ANGULAR_OFFSET		= 1006
    
    Ofield				= 440000200
    
    class AngularField(c4d.plugins.ObjectData):
    
        def GetVirtualObjects(self, op, hierarchyhelp):
            dirty = op.CheckCache(hierarchyhelp) or op.IsDirty(c4d.DIRTY_DATA)
            if dirty is False:
                return op.GetCache(hierarchyhelp)
    
        def __init__(self):
            self.SetOptimizeCache(True)
        
        def Init(self, op):
        	print c4d.Ofield
        	self.InitAttr(op, int, ANGULAR_AXIS)
        	self.InitAttr(op, float, ANGULAR_RATIO)
        	
        	op[ANGULAR_AXIS] = ANGULAR_AXISX
        	op[ANGULAR_RATIO] = 0.5
            return True
    
        def Execute(self, op, doc, bt, priority, flags):
            return True
    
    """
    class AngularFieldObject(c4d.modules.mograph.FieldObject):
    
    	def Sample( op, inputs, outputs, info):
    	    # Determine field strength based on angle around Y axis
    	    localMl = ~op.GetMg()
    	    for i in range(0, inputs._blockCount):
    	        localpos = localMl.Mul(inputs._position[i])
    	        if op[AXIS] == ANGULAR_AXISX:
    	        	xval = localpos.y
    	        	yval = localpos.z
    	        elif op[AXIS] == ANGULAR_AXISY:
    	        	xval = localpos.x
    	        	yval = localpos.z
    	        else:
    	        	xval = localpos.x
    	        	yval = localpos.y
    	        
    	        angle = math.atan2(yval, xval) + math.pi
    	        angleBin = math.floor(op[ANGULAR_STRCOUNT] * angle / math.pi)
    	        val = 1.0 if angleBin % 2 == 0 else 0.0
    	        outputs.SetValue(i, val)
    	    return True	
    """
    
    # Register
    if __name__=='__main__':
        bmp = c4d.bitmaps.BaseBitmap()
        dir, file = os.path.split(__file__)
        fn = os.path.join(dir, "res", "Angular.tif")
        bmp.InitWith(fn)
        result = plugins.RegisterObjectPlugin(
            id=PLUGIN_ID,
            str="AngularField",
            g=AngularField,
            description="AngularField",
            info=c4d.OBJECT_GENERATOR,
            icon=bmp
            )
    


  • This post is deleted!

  • Global Moderator

    Hello,

    in the Cinema 4D APIs, plugins are not created by creating a subclass of the object class. To create a plugin you have to implement a subclass of a special plugin class. To create custom Field objects, you must not create a subclass of FieldObject but of the dedicated class FieldData.

    Currently FieldData is not available in the Python API. The only way to create a Field using Python is to use the Python Field.

    The C++ API contains the FieldData class. You find information about that in the C++ documentation:

    best wishes,
    Sebastian



  • @s_bach I was beginning to wonder if I was beating my head against a brick wall. Apparently so. Thanks so much for alleviating the pain! Well, I learned quite a bit about Python in the process so not really a loss. Guess I'll try moving on directly to the C++ version.