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.


Log in to reply