Render to PictureViewer without breaking plugin
-
On 17/07/2015 at 09:00, xxxxxxxx wrote:
Now that I've finally figured out how to create radio buttons in a res file (why was this info not available before in the forums?) and bitmap icons, there are just a few remaining roadblocks that I have become accustomed to. If anyone is feeling magical and want to try to answer another longstanding question that I haven't been able to figure out, here you go (Thank you in advance!) :
I have to break my plugins before Cinema will allow me to render to the picture viewer. This hasn't been much of a problem because I need to break the plugins anyways to hand my projects over to my co-workers who are too inept to follow my repeated instructions on how to install my plugins (Anyone else have this problem?). What code do I need to allow me to let Cinema render when I have an object plugin in the scene? Let me know if I need to post any example code.
P.S.: Yeah, I know that these seem to simple questions, but as it turns out, the basics are the hardest things to find answers for in programming.
-David
-
On 20/07/2015 at 08:30, xxxxxxxx wrote:
Hi David,
can you please elaborate a bit more? What do you mean by "break my plugins"?`
Also not sure about the "special code" to let Cinema render. I guess, you already know the Py-RoundedTube example from the Python SDK. This renders just fine. -
On 21/07/2015 at 10:42, xxxxxxxx wrote:
Hi Andreas,
By "break" I meant Make Editable. Most of my object plugins don't render unless they are Made Editable, but some do. I'll go ahead and post an entire plugin if it helps. It doesn't have all of it's problems worked out, but the basic functionality works fine:
import c4d, math, string, random from c4d import gui, plugins, utils, bitmaps import os # GoldenFlower 0.9 # Author: David Cox # 07/01/2015 PLUGIN_ID = 9329937 #GROUP_FLOWER = 1000, PEDAL_LINK = 1001, # Pedal Link PEDAL_COUNT = 1002, # Number of pedals FLOWER_SPREAD = 1003, # Pedal Spread PEDAL_OPEN_AMOUNT = 1004, # Amount of open flower GROUP_BEND = 1005, BIAS_BEND = 1006, # Bend Bias BEND_AMOUNT = 1007, # Bend Amount RAND_BEND_AMOUNT = 1008, # Random Bend Amount BEND_HEIGHT = 1009, # Bend Height RAND_BEND_HEIGHT = 1010, # Random Bend Height RANDOM_SEED = 1011, # Random Bend Seed GROUP_TRANSFORMS = 1012, BIAS_POS = 1013, # Position Bias POS_X = 1014, # Pos-X RAND_POS_X = 1015, # Rand_Pos-X POS_Y = 1016, # Pos-Y RAND_POS_Y = 1017, # Rand_Pos-Y POS_Z = 1018, # Pos-Z RAND_POS_Z = 1019, # Rand_Pos-Z BIAS_SCALE = 1021, # Scale Bias SCALE_X = 1022, # Scale-X RAND_SCALE_X = 1023, # Rand_Scale-X SCALE_Y = 1024, # Scale-Y RAND_SCALE_Y = 1025, # Rand_Scale-Y SCALE_Z = 1026, # Scale-Z RAND_SCALE_Z = 1027, # Rand_Scale-Z BIAS_ROT = 1029, # Rotation Bias ROT_X = 1030, # Rot-X RAND_ROT_X = 1031, # Rand_Rot-X ROT_Y = 1032, # Rot-Y RAND_ROT_Y = 1033, # Rand_Rot-Y ROT_Z = 1034, # Rot-Z RAND_ROT_Z = 1035, # Rand_Rot-Z FLOWER_RADIUS = 1036, # Flower Radius MULTI_1 = 1037, MULTI_2 = 1038, MULTI_3 = 1039, MULTIBUTTON = 1040, RADIOBUTTONS = 1041, ABITMAPBUTTON_A = 1042, ABITMAPBUTTON_B = 1043, ABITMAPBUTTON_C = 1044, class GoldenFlower(c4d.plugins.ObjectData) : """GOLDEN FLOWER""" def __init__(self) : self.SetOptimizeCache(True) def Init(self, op) : self.InitAttr(op, float, [1002]) # Number of pedals self.InitAttr(op, float, [1003]) # Pedal Spread self.InitAttr(op, float, [1004]) # Amount of open flower self.InitAttr(op, float, [1006]) # Bend Bias self.InitAttr(op, float, [1007]) # Bend Amount self.InitAttr(op, int, [1008]) # Random Bend Amount self.InitAttr(op, float, [1009]) # Bend Height self.InitAttr(op, int, [1010]) # Random Bend Height self.InitAttr(op, int, [1011]) # Random Seed self.InitAttr(op, float, [1013]) # Position Bias self.InitAttr(op, float, [1014]) # Pos-X self.InitAttr(op, int, [1015]) # Rand_Pos-X self.InitAttr(op, float, [1016]) # Pos-Y self.InitAttr(op, int, [1017]) # Rand_Pos-Y self.InitAttr(op, float, [1018]) # Pos-Z self.InitAttr(op, int, [1019]) # Rand_Pos-Z self.InitAttr(op, float, [1021]) # Scale Bias self.InitAttr(op, float, [1022]) # Scale-X self.InitAttr(op, int, [1023]) # Rand_Scale-X self.InitAttr(op, float, [1024]) # Scale-Y self.InitAttr(op, int, [1025]) # Rand_Scale-Y self.InitAttr(op, float, [1026]) # Scale-Z self.InitAttr(op, int, [1027]) # Rand_Scale-Z self.InitAttr(op, float, [1029]) # Rotation Bias self.InitAttr(op, float, [1030]) # Rotation-X self.InitAttr(op, int, [1031]) # Rand_Rotation-X self.InitAttr(op, float, [1032]) # Rotation-Y self.InitAttr(op, int, [1033]) # Rand_Rotation-Y self.InitAttr(op, float, [1034]) # Rotation-Z self.InitAttr(op, int, [1035]) # Rand_Rotation-Z self.InitAttr(op, float, [1036]) # Flower Radius op[1002] = 100.0 # Number of pedals op[1003] = 0.8 # Pedal Spread op[1004] = 10 # Amount of open flower op[1006] = 0 # Bend Bias op[1007] = 0 # Bend Amount op[1008] = 0 # Random Bend Amount op[1009] = 0 # Bend Height op[1010] = 0 # Random Bend Height op[1011] = 1 # Random Seed op[1013] = 0 # Position Bias op[1014] = 0 # Pos-X op[1015] = 0 # Rand_Pos-X op[1016] = 0 # Pos-Y op[1017] = 0 # Rand_Pos-Y op[1018] = 0 # Pos-Z op[1019] = 0 # Rand_Pos-Z op[1021] = 0 # Scale Bias op[1022] = 0 # Scale-X op[1023] = 0 # Rand_Scale-X op[1024] = 0 # Scale-Y op[1025] = 0 # Rand_Scale-Y op[1026] = 0 # Scale-Z op[1027] = 0 # Rand_Scale-Z op[1029] = 0 # Rotation Bias op[1030] = 0 # Rotation-X op[1031] = 0 # Rand_Rotation-X op[1032] = 0 # Rotation-Y op[1033] = 0 # Rand_Rotation-Y op[1034] = 0 # Rotation-Z op[1035] = 0 # Rand_Rotation-Z op[1036] = 3.0 # Flower Radius return True def Message(self, node, type, data) : if type==c4d.MSG_DESCRIPTION_COMMAND: if data['id'][0].id==1042: self.thePedalA = True self.thePedalB = False self.thePedalC = False if data['id'][0].id==1043: self.thePedalB = True self.thePedalA = False self.thePedalC = False if data['id'][0].id==1044: self.thePedalC = True self.thePedalA = False self.thePedalB = False node.Message(c4d.MSG_CHANGE) return True def GetVirtualObjects(self, op, hierarchyhelp) : # ******************** Set variables ************************************* v = c4d.Vector rad = c4d.utils.Rad doc = op.GetDocument() baseNull = c4d.BaseObject(c4d.Onull) pedal_MyData = op.GetDataInstance() pedalLink = pedal_MyData.GetObjectLink(1001) if pedalLink != None: pedalLink[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 1 pedalLink[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 1 pedalNum = op[1002] pedalSpread = op[1003] openAmount = op[1004]/1000 bendBias = op[1006] bendAmount = rad(op[1007]) randBendAmount = op[1008] bendHeight = op[1009]*4 randBendHeight = op[1010] randSeed = random.seed(op[1011]) posBias = op[1013] posX = op[1014] randPosX = op[1015] posY = op[1016] randPosY = op[1017] posZ = op[1018] randPosZ = op[1019] scaleBias = op[1021] scaleX = op[1022]/100 randScaleX = op[1023] scaleY = op[1024]/100 randScaleY = op[1025] scaleZ = op[1026]/100 randScaleZ = op[1027] rotBias = op[1029] rotX = rad(op[1030]) randRotX = op[1031] rotY = rad(op[1032]) randRotY = op[1033] rotZ = rad(op[1034]) randRotZ = op[1035] flowerRad = op[1036] bitmapButtonA = op[1042] bitmapButtonB = op[1043] bitmapButtonC = op[1044] # ******************** End Variable Assignment Area ****************** bound = flowerRad rotVal = 0.0 tau = 6.28318530718 # pi * 2 phi = (1 + math.sqrt(5)) / 2 #1.618... #calculate the golden angle in radians golden_angle = tau * (2 - phi) theta = 0.0 doc = c4d.documents.GetActiveDocument() pedalTest_A = doc.SearchMaterial("Pedal_A") pedalTest_B = doc.SearchMaterial("Pedal_B") pedalTest_C = doc.SearchMaterial("Pedal_C") path, fn = os.path.split(__file__) fn = os.path.join(path, "pedals", "Pedal_A.c4d") if pedalTest_A == None: c4d.documents.MergeDocument(doc, fn, c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS, None) if pedalTest_A != None: c4d.documents.MergeDocument(doc, fn, c4d.SCENEFILTER_OBJECTS, None) pedal_A = doc.GetActiveObjects(0) tags = pedal_A[0].GetTags() for p in tags: if p.GetTypeName() == "Texture": p.SetMaterial(pedalTest_A) pedal_A = doc.GetActiveObjects(0) pedal_A = pedal_A[0] pedal_A.InsertUnder(baseNull) fn = os.path.join(path, "pedals", "Pedal_B.c4d") if pedalTest_B == None: c4d.documents.MergeDocument(doc, fn, c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS, None) if pedalTest_B != None: c4d.documents.MergeDocument(doc, fn, c4d.SCENEFILTER_OBJECTS, None) pedal_B = doc.GetActiveObjects(0) tags = pedal_B[0].GetTags() for p in tags: if p.GetTypeName() == "Texture": p.SetMaterial(pedalTest_B) pedal_B = doc.GetActiveObjects(0) pedal_B = pedal_B[0] pedal_B.InsertUnder(baseNull) fn = os.path.join(path, "pedals", "Pedal_C.c4d") if pedalTest_C == None: c4d.documents.MergeDocument(doc, fn, c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS, None) if pedalTest_C != None: c4d.documents.MergeDocument(doc, fn, c4d.SCENEFILTER_OBJECTS, None) pedal_C = doc.GetActiveObjects(0) tags = pedal_C[0].GetTags() for p in tags: if p.GetTypeName() == "Texture": p.SetMaterial(pedalTest_C) pedal_C = doc.GetActiveObjects(0) pedal_C = pedal_C[0] pedal_C.InsertUnder(baseNull) doc.SetSelection(op) pedal_A[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 1 pedal_A[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 1 pedal_B[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 1 pedal_B[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 1 pedal_C[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 1 pedal_C[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 1 if self.thePedalA == True: thePedal = pedal_A if self.thePedalB == True: thePedal = pedal_B if self.thePedalC == True: thePedal = pedal_C for n in range(int(pedalNum)) : if pedalLink == None: pedalClone = thePedal.GetClone() pedalClone = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[pedalClone], bc=c4d.BaseContainer(), mode=c4d.MODELINGCOMMANDMODE_ALL, doc = doc, flags = 0) pedalClone = pedalClone[0] pedalBound = pedalClone.GetRad() # Get the bounding box pedalBound += pedalBound radius = (bound * pow(n/pedalNum, pedalSpread)) * 10 theta += golden_angle pos = self.polar_to_cartesian(theta, radius) #Call def self.makeThing(n, pos, radius, rotVal, baseNull, pedalNum, pedalClone, pedalBound, bendAmount, bendHeight, randBendAmount, randBendHeight, bendBias, posBias, scaleBias, rotBias, randPosX, randPosY, randPosZ, randScaleX, randScaleY, randScaleZ, randRotX, randRotY, randRotZ, posX, posY, posZ, scaleX, scaleY, scaleZ, rotX, rotY, rotZ) rotVal += openAmount if n > 0: pedalClone[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 2 pedalClone[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 2 if pedalLink != None: pedalType = pedalLink.GetTypeName() if pedalLink != None and pedalType != "Legacy XRef": pedalClone = pedalLink.GetClone() pedalClone = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[pedalClone], bc=c4d.BaseContainer(), mode=c4d.MODELINGCOMMANDMODE_ALL, doc = doc, flags = 0) pedalClone = pedalClone[0] pedalBound = pedalClone.GetRad() # Get the bounding box pedalBound += pedalBound radius = (bound * pow(n/pedalNum, pedalSpread)) * 10 theta += golden_angle pos = self.polar_to_cartesian(theta, radius) #Call def self.makeThing(n, pos, radius, rotVal, baseNull, pedalNum, pedalClone, pedalBound, bendAmount, bendHeight, randBendAmount, randBendHeight, bendBias, posBias, scaleBias, rotBias, randPosX, randPosY, randPosZ, randScaleX, randScaleY, randScaleZ, randRotX, randRotY, randRotZ, posX, posY, posZ, scaleX, scaleY, scaleZ, rotX, rotY, rotZ) rotVal += openAmount if n > 0: pedalClone[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 2 pedalClone[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 2 c4d.EventAdd() return baseNull def makeThing(self, n, pos, radius, rotVal, baseNull, pedalNum, pedalClone, pedalBound, bendAmount, bendHeight, randBendAmount, randBendHeight, bendBias, posBias, scaleBias, rotBias, randPosX, randPosY, randPosZ, randScaleX, randScaleY, randScaleZ, randRotX, randRotY, randRotZ, posX, posY, posZ, scaleX, scaleY, scaleZ, rotX, rotY, rotZ) : rad = c4d.utils.Rad theThing = pedalClone theThing.SetRelPos(pos) theScale = pow(radius,0.5)*0.265 pos = -pos N = pos.GetNormalized() upVec = c4d.Vector(0,1,0) dist = pos.GetLength() nn = c4d.utils.VectorToHPB(N) norm = c4d.Vector(0,0,0) if N != None: norm = nn.Cross(upVec).GetNormalized() #norm = c4d.Vector(nn.x + rotVal, N.y + rotVal*0.3, nn.z) norm = c4d.Vector(nn.x, N.y + rotVal*0.3, nn.z) theThing.SetRelRot(norm) rot = theThing.GetRelRot() scale = theThing.GetRelScale() pos = theThing.GetRelPos() rand = float(random.randrange(-100, 100))/100 randBendAmount *= rand randBendAmount = randBendAmount/100 randBendHeight *= rand randPosX *= rand randPosY *= rand randPosZ *= rand randScaleX *= rand randScaleX = randScaleX/100 randScaleY *= rand randScaleY = randScaleY/100 randScaleZ *= rand randScaleZ = randScaleZ/100 randRotX *= rand randRotX = randRotX/100 randRotY *= rand randRotY = randRotY/100 randRotZ *= rand randRotZ = randRotZ/100 theThing.SetRelPos(c4d.Vector(posX+pos.x+randPosX, posY+pos.y+randPosY, posZ+pos.z+randPosZ)) theThing.SetRelScale(c4d.Vector(scaleX+scale.x+randScaleX, scaleY+scale.y+randScaleY, scaleZ+scale.z+randScaleZ)) theThing.SetRelRot(c4d.Vector(rotX+rot.x+randRotX, rotY+rot.y+randRotY, rotZ+rot.z+randRotZ)) pedalBend = c4d.BaseObject(c4d.Obend) pedalBend.InsertUnder(theThing) pedalBend[c4d.DEFORMOBJECT_SIZE] = pedalBound pedalBend[c4d.DEFORMOBJECT_STRENGTH] = bendAmount+randBendAmount pedalBend[c4d.BENDOBJECT_KEEPYAXIS] = True pedalBend[c4d.DEFORMOBJECT_ANGLE] = rad(-90) pedalBend[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 1 #print "n: ",n #print "pedalNum: ", pedalNum pedalBend[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y] = pedalBound.y/2 + bendHeight+randBendHeight #pedalBend[c4d.DEFORMOBJECT_STRENGTH] = (bendAmount+randBendAmount) + 10*(pow(bendBias, n/pedalNum)) theThing.InsertUnder(baseNull) def polar_to_cartesian(self, theta, radius) : sn, cs = c4d.utils.SinCos(theta) return c4d.Vector(cs*radius, 0, sn*radius) def SetGlobalPosition(self, obj, pos) : m = obj.GetMg() m.off = pos obj.SetMg(m) def SetGlobalRotation(self, obj, rot) : m = obj.GetMg() pos = m.off scale = c4d.Vector( m.v1.GetLength(), m.v2.GetLength(), m.v3.GetLength()) m = utils.HPBToMatrix(rot) m.off = pos m.v1 = m.v1.GetNormalized() * scale.x m.v2 = m.v2.GetNormalized() * scale.y m.v3 = m.v3.GetNormalized() * scale.z obj.SetMg(m) BITMAP_ID1 = 103721 BITMAP_ID2 = 103722 BITMAP_ID3 = 103723 if __name__ == '__main__': #main() bmp = c4d.bitmaps.BaseBitmap() dir, file = os.path.split(__file__) path, fn = os.path.split(__file__) fn = os.path.join(dir, "res", "Icon.tif") bmp.InitWith(fn) buttonimageA = bitmaps.BaseBitmap() #We need an instance of BaseBitmap class to use an image buttonimageA.InitWith(os.path.join(path, "res", "pedal_A.tif"))#The location where the button image exists buttonimageB = bitmaps.BaseBitmap() #We need an instance of BaseBitmap class to use an image buttonimageB.InitWith(os.path.join(path, "res", "pedal_B.tif"))#The location where the button image exists buttonimageC = bitmaps.BaseBitmap() #We need an instance of BaseBitmap class to use an image buttonimageC.InitWith(os.path.join(path, "res", "pedal_C.tif"))#The location where the button image exists gui.RegisterIcon(BITMAP_ID1, buttonimageA) #We need to register custom images & icons gui.RegisterIcon(BITMAP_ID2, buttonimageB) #We need to register custom images & icons gui.RegisterIcon(BITMAP_ID3, buttonimageC) #We need to register custom images & icons result = plugins.RegisterObjectPlugin( id=PLUGIN_ID, str="GoldenFlower", g=GoldenFlower, description="Ogolden_flower", info=c4d.OBJECT_GENERATOR, icon=bmp )
-
On 22/07/2015 at 03:49, xxxxxxxx wrote:
Hi,
I'm sorry, we are not supposed to debug code. And it would be a good idea to give at least an overview, what your code is supposed to do.
I briefly looked over your code and I think you have several problems in there.Most important:
You are not allowed to modify the active scene with GetVirtualObjects(). Please have look at documentation on ObjectData, GetVirtualObjects() and important threading information.
I noticed for example MergeDocument().Objects can only be inserted once into a scene, while you try to get the active object and insert it under your generated object. That won't work for several reasons:
- The active object is already in the scene and you can't remove it, because you are not allowed to in GVO. Instead you should have a look at the OBJECT_INPUT flag on RegisterObjectPlugin().
- Getting the active object makes no sense during rendering. The scene gets copied for rendering and there simply won't be any active object in there.You are loading several scene files with MergeDocument(), which (as mentioned before) already is a bad idea, but think of situations like for example TeamRender. How is TeamRender supposed to find these files on a different machine?
I think, you will have to rework and restructure your plugin to properly work in all situations, especially for rendering. Sorry, to say this.