@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.
Best posts made by darrellp
Latest posts made by darrellp
@m_adam Oh - okay - I see you moved it. I thought that was the mistake at first but then saw it was in "Coding & Development" and assumed I put it there even though I didn't remember it that way. I was a little confused by the two different categories. Got it now.
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.
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 )
@m_adam Yes - thanks. I actually got it working after posting. I'm not sure what kind of rule infraction you seem to be referring to here. I'd really like to comply with regulations but I'm not sure what I did wrong. I read the two articles you referenced and didn't see anything I might have done wrong. Maybe you're just suggesting that after my first post? In any event, if I'm doing something wrong please let me know and I'll try to take care of it. Thanks again!
I've coded in C#/C++ since both those respective languages started but haven't programmed much in Python though I don't think that's a serious problem. I'm trying to find the sample positions local to the field object in the Sample routine for a Python field. The sample code provided when you create a python field varies based on time and is totally agnostic on positions so doesn't really offer any insight. It appears to me that the values in the Sample function's inputs parameter for inputs._position are all global positions. I thought that I'd be able to multiply them by inputs._transform but that seems to always be an identity matrix no matter whether I move the object I'm dealing with or the field so I guess I must really not understand it's purpose. It says in the documentation "The transform matrix for the points in the input block. Use to bring the position and direction lists into world space or the local space of a FieldObject." but I don't see how this happens if it stays as an identity matrix. I'm enclosing a file which has what I'm working on. It has a sphere with a red material applied to a face selection set determined by the Python field. The code in the field just specifies 1 if the input point has a z value < 0 and 0 otherwise. This always colors red based on the world origin showing that the inputs are world coordinates. I have printed out inputs._transform to verify it's the identity matrix. I can't seem to find any examples of a Python Field anywhere on the internet except the default one produced initially which, as noted above, is no help. Can somebody help me out here? Thanks in advance!