Navigation

    • Register
    • Login
        No matches found
    • Search
    1. Home
    2. blastframe
    blastframe

    blastframe

    @blastframe

    18
    Reputation
    321
    Posts
    228
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online
    Website www.blastframe.com Location Burbank, CA

    • Profile
    • More
      • Following
      • Followers
      • Topics
      • Posts
      • Best
      • Groups
    blastframe Follow

    Best posts made by blastframe

    COLOR Constants Guide & Documentation Error

    Hello,
    I made this graphic of default R21 COLOR Constants as a guide for me to find the right colors and wanted to share it with the community:
    Cinema4D_ColorIDs.png
    https://imgur.com/a/H11thSt

    The spaces where there is no text means that the attribute is the same as c4d.COLOR_BG and is blending in with the background.

    Also, while making this, I found that the documentation lists one attribute that throws an error: c4d.COLOR_TIMELINE

    AttributeError: 'module' object has no attribute 'COLOR_TIMELINE'
    
    posted in Cinema 4D SDK •
    RE: Pycharm - Invalid Python SDK

    @m_adam said in Pycharm - Invalid Python SDK:

    Hi, @blastframe thanks for contact us.

    So far we never encounter this issue and we are not able to reproduce it so few ideas to try:

    1. Make sure you have permission to write in the Cinema 4D folder and subfolder.
    2. Flush the cache, https://stackoverflow.com/a/45099651.
    3. Send us your PyCharm log, see https://intellij-support.jetbrains.com/hc/en-us/articles/207241085-Locating-IDE-log-files

    Cheers,
    Maxime.

    Hi @m_adam,
    Thank you for the reply. I ran PyCharm as an Administrator and flushed the cache. I still received the same error. When I looked at the log, I found a lot of missing file errors, which made me think I had the python.exe (c4dpy.exe) file in the wrong location. When I moved the file to the same folder as the R20 .exe, PyCharm started working. I was confused about the file location because, while in the Install instructions from the C4D Python SDK Documentation has the c4dpy in the C4D folder, this image made it seem like it could exist in a separate folder:
    c4dpy_pycharm_win2.png

    I would have expected a file location similar to the default Windows location:
    C:\Program Files\MAXON\Cinema 4D R20\python.exe

    Thank you again. I have one follow-up question that I'll ask as a new topic.

    posted in Cinema 4D SDK •
    RE: how to get object's position and material color on all time line?

    Hi @jhpark!
    I don't work for the SDK team, but I believe the script below will do what you want.

    Some quick notes about posting:

    1. When entering your code into a post on this forum, make sure you hit this button first
      code.png
      It creates code tags in your post. Put your code in between those and then it will format your code automatically.

    2. Also, after submitting, hit the button Topic Tools at the bottom right of your post to Ask as Question.
      code3.png

    3. When someone has answered your question correctly, click this button at the bottom of their post.
      code2.png
      This makes it clear to the moderators when the question has been correctly answered.

    Here's the code. Because you were using ID_BASEOBJECT_COLOR, I was unsure if you wanted the object's display color or the material color (they are two different things), but I wrote this for the sphere's texture tags' material's color. Also, the code is for the spheres' relative position. More work would need to be done to get the animating position track values into global space.

    import c4d
    from c4d import gui
    
    def GetNextObject(op):
        #function for navigating the hierarchy
        if op==None: return None
        if op.GetDown(): return op.GetDown()
        while not op.GetNext() and op.GetUp():
            op = op.GetUp()
        return op.GetNext()
        c4d.EventAdd()
    
    def getPreviewRange(doc,fps):
        #returns the active preview range
        fps = doc.GetFps()
        fromTime = doc.GetLoopMinTime().GetFrame(fps)
        toTime = doc.GetLoopMaxTime().GetFrame(fps)+1
        return [fromTime,toTime]
    
    def convertVecToRgb(vector):
        #converts vector to rgb list
        return [vector[0]*255,vector[1]*255,vector[2]*255]
    
    def main(doc):
        fps = doc.GetFps()
        previewRange = getPreviewRange(doc,fps) #rather than needing to set frames manually, you can simply resize your preview range.
        frame_count = previewRange[1]-previewRange[0]
    
        # this section navigates the hierarchy and saves all of the spheres to a list called 'output'
        # it's better to do this than to use doc.SearchObject in the case you have multiple spheres with the same name
        obj = doc.GetFirstObject()
        if obj==None:
            gui.MessageDialog('There are no objects in the scene.')
            return
    
        output = []
        while obj and obj!=None:
            if obj.GetType() == c4d.Osphere:
                output.append(obj)
            obj = GetNextObject(obj)
    
        if len(output) == 0:
            gui.MessageDialog('There are no spheres in the scene.')
    
        # loops through spheres in the scene
        for sphere in output:
            #prints a separating line to the console
            print '#' * 80
            for f in range(previewRange[0], previewRange[1]):
                doc.SetTime(c4d.BaseTime(0, doc[c4d.DOCUMENT_FPS]))
                keyTime = c4d.BaseTime(f,fps) #get the current frame
    
                # POSITION
                pTracks = sphere.GetCTracks() #get the sphere's animating tracks
                
                pos = [sphere.GetMl().off.x,sphere.GetMl().off.y,sphere.GetMl().off.z] #get the sphere's default relative position
    
                #replace those values with the animating ones.
                for t in pTracks:
                    descid = t.GetDescriptionID() #get the track's id
                    if descid[0].id == c4d.ID_BASEOBJECT_REL_POSITION: #see if it matches the object's position track
                        curve = t.GetCurve() #get the track's animation curve
                        keyvalue = curve.GetValue(keyTime, fps) #get the animation curve's value at the current frame
                        if descid[1].id == c4d.VECTOR_X:
                            pos[0] = keyvalue #add to x
                        elif descid[1].id == c4d.VECTOR_Y:
                            pos[1] = keyvalue #add to x
                        elif descid[1].id == c4d.VECTOR_Z:
                            pos[2] = keyvalue #add to z
    
                # MATERIAL COLOR
                tags = sphere.GetTags() #get sphere's tags
    
                matColor = [] #create material color list
    
                for tag in tags: #loop through sphere's tags
                    if tag.GetType() == c4d.Ttexture: #check if tag is a texture tag
                        mat = tag.GetMaterial() #if yes, get the tag's material
    
                        tracks = mat.GetCTracks() #get the material's animating tracks
                        
                        for t in tracks:
                            descid = t.GetDescriptionID() #get the track's id
                            if descid[0].id == c4d.MATERIAL_COLOR_COLOR: #see if it matches the material color track
                                curve = t.GetCurve() #get the track's animation curve
                                keyvalue = curve.GetValue(keyTime, fps) #get the animation curve's value at the current frame
                                matColor.append(keyvalue*255) #add r,g,b to matColor
                        
                        if len(tracks) == 0: #in case it's not animating, use general Color
                            matColor = convertVecToRgb(mat[c4d.MATERIAL_COLOR_COLOR])
    
                # I prefer using string formatting with the placeholder %s for strings, %d for numbers,
                # and the % as the replacement operator
                print("Name: %s, Frame: %d, Position (x,y,z): %d,%d,%d, Material Color (r,g,b): %d,%d,%d"%(
                                                                                sphere.GetName(),f,pos[0],pos[1],pos[2],
                                                                                matColor[0],matColor[1],matColor[2]))
    
    if __name__=='__main__':
        # rather than using documents.GetActiveDocument, I found that you can pass a reference to the document using this method
        main(doc)
    

    Here's a scene file where the object's display colors and material colors are different. The display colors are visible in the viewport, but you will see the material color if you render.
    Spheres.c4d

    posted in Cinema 4D SDK •
    RE: Rebuild a scene with Python

    Hi @woodstar
    There's definitely a way! What did you want to connect in Xpresso with Python? I wrote a script that does some of what you described: it prompts the user for a camera name, then creates an Xpresso rig based on that. The rig connects a user data checkbox 'Follow Target' to a couple of properties in the rig (Target tag's 'Enable' and the camera's 'Use Target Object''s checkbox for setting the Focus Distance). That would allow you to follow an object for some of the camera move and then keyframe it off.

    Camera_Controls.png

    """
    Name-US:Xpresso Camera Rig
    Description-US:Creates an Xpresso Camera Rig
    author:blastframe
    
    credits:
    Creating User Data - https://www.cineversity.com/wiki/Python%3A_User_Data/
    Python Xpresso - https://www.cineversity.com/vidplaytut/xpresso_maker_overview
    """
    
    import c4d
    from c4d import gui
    
    def create_user_data_group(obj, name, parentGroup=None, columns=None, shortname=None):
        # see Creating User Data url above
        if obj is None: return False
        if shortname is None: shortname = name
        bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_GROUP)
        bc[c4d.DESC_NAME] = name
        bc[c4d.DESC_SHORT_NAME] = shortname
        bc[c4d.DESC_TITLEBAR] = 1
        if parentGroup is not None:
            bc[c4d.DESC_PARENTGROUP] = parentGroup
        if columns is not None:
            bc[22] = columns
        return obj.AddUserData(bc)
    
    def create_user_data_bool(obj, name, val=True, parentGroup=None):
        # see Creating User Data url above
        if obj is None: return False
        bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_BOOL)
        bc[c4d.DESC_NAME] = name
        bc[c4d.DESC_SHORT_NAME] = name
        bc[c4d.DESC_DEFAULT] = val
        bc[c4d.DESC_ANIMATE] = c4d.DESC_ANIMATE_ON
    
        if parentGroup is not None:
            bc[c4d.DESC_PARENTGROUP] = parentGroup
    
        element = obj.AddUserData(bc)
        obj[element] = val
        return element
    
    def connect_xpresso(camera,camera_truck_ctrl,targetTag):
        # Xpresso documentation:
        # https://developers.maxon.net/docs/Cinema4DPythonSDK/html/modules/c4d.modules/graphview/index.html
        xtag = camera_truck_ctrl.MakeTag(c4d.Texpresso) # create Xpresso tag
        doc.AddUndo(c4d.UNDOTYPE_NEW, xtag)
    
        # A Graph View Node Master stores a collection of Graph View Nodes.
        gv = xtag.GetNodeMaster()
    
        # create node for the camera truck control
        camera_truck_ctrlNode = gv.CreateNode(parent=gv.GetRoot(), id=c4d.ID_OPERATOR_OBJECT, insert=None, x=100, y=0)
        doc.AddUndo(c4d.UNDOTYPE_NEW, camera_truck_ctrlNode)
    
        doc.AddUndo(c4d.UNDOTYPE_CHANGE, camera_truck_ctrlNode)
        udPort = None
        # create output port for the user data boolean (from Rick Barrett script)
        for id, bc in camera_truck_ctrl.GetUserDataContainer():
            if bc[c4d.DESC_CUSTOMGUI] is not None and \
            bc[c4d.DESC_CUSTOMGUI] is not c4d.CUSTOMGUI_SEPARATOR:
                doc.AddUndo(c4d.UNDOTYPE_CHANGE,camera_truck_ctrlNode)
                udPort = camera_truck_ctrlNode.AddPort(c4d.GV_PORT_OUTPUT, id)
    
        # create node for the camera Target tag
        targetNode = gv.CreateNode(gv.GetRoot(), c4d.ID_OPERATOR_OBJECT, insert=None, x=300, y=0)
        # get DescID for Target tag's Enable property
        targetEnabled = c4d.DescID(c4d.DescLevel(c4d.EXPRESSION_ENABLE));
    
        doc.AddUndo(c4d.UNDOTYPE_NEW, targetNode)
        # after creating node we need to give it an object
        targetNode[c4d.GV_OBJECT_OBJECT_ID] = targetTag
        # add Target node Enabled input port
        enablePort = targetNode.AddPort(c4d.GV_PORT_INPUT, targetEnabled)
    
        # create node for the camera
        cameraNode = gv.CreateNode(parent=gv.GetRoot(), id=c4d.ID_OPERATOR_OBJECT, insert=None, x=300, y=100)
        # after creating node we need to give it an object
        cameraNode[c4d.GV_OBJECT_OBJECT_ID] = camera
        # add camera input port for using the Target tag's object as the Focus Object
        useTargetObjectPort = cameraNode.AddPort(c4d.GV_PORT_INPUT, c4d.CAMERAOBJECT_USETARGETOBJECT)
    
        # connect the ports
        udPort.Connect(enablePort)
        udPort.Connect(useTargetObjectPort)
    
        # refresh the Graph View
        c4d.modules.graphview.RedrawMaster(gv)
    
    def main(doc):
        doc.StartUndo()
        camera_truck_ctrl = c4d.BaseObject(c4d.Osplinenside) # Create camera_truck_ctrl control
        camera_truck_ctrl[c4d.ID_BASEOBJECT_USECOLOR] = 2 # turn on display color
        camera_truck_ctrl[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(0,1,1) # set display color
        doc.InsertObject(camera_truck_ctrl)
        doc.AddUndo(c4d.UNDOTYPE_NEW, camera_truck_ctrl)
        cameraControls = create_user_data_group(camera_truck_ctrl,"Camera Controls",c4d.DescID(0)) # create user data group
        followTargetBool = create_user_data_bool(camera_truck_ctrl,"Follow Target",True,cameraControls) # Follow Target boolean checkbox
        camera = c4d.BaseObject(c4d.Ocamera) # Create camera
        name = gui.InputDialog("What would you like to name your camera?", "Camera") # prompt user for name
        camera.SetName(name)
        camera_truck_ctrl.SetName("%s_con+"%name) # use camera name to name control
    
        targetTag = camera.MakeTag(c4d.Ttargetexpression) # create Target tag
        doc.AddUndo(c4d.UNDOTYPE_NEW, targetTag)
    
        focusObject = c4d.BaseObject(c4d.Onull) # Create focus object
        focusObject.SetName("%s Target"%name)
    
        focusObject[c4d.ID_BASEOBJECT_USECOLOR] = 2 # turn on display color
        focusObject[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1,0,0) # set display color
        focusObject[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Z]  = 500 # set focus object's position Z to 500
        focusObject[c4d.NULLOBJECT_DISPLAY] = 13  # set null target to display as sphere
        focusObject[c4d.NULLOBJECT_RADIUS] = 30 # set sphere radius to 30
        focusObject[c4d.NULLOBJECT_ORIENTATION] = 1 # set sphere plane to XY
        targetTag[c4d.TARGETEXPRESSIONTAG_LINK] = focusObject # assign focus object to Target tag object link
    
        # insert objects to document
        doc.InsertObject(focusObject)
        doc.AddUndo(c4d.UNDOTYPE_NEW, focusObject)
        doc.InsertObject(camera_truck_ctrl)
        doc.AddUndo(c4d.UNDOTYPE_NEW, camera_truck_ctrl)
        camera.InsertUnder(camera_truck_ctrl) # parent to camera_truck_ctrl
        doc.AddUndo(c4d.UNDOTYPE_NEW, camera)
    
        connect_xpresso(camera,camera_truck_ctrl,targetTag) # create Xpresso connections
        doc.SetActiveObject(camera_truck_ctrl,c4d.SELECTION_NEW) # select camera truck control
    
        c4d.EventAdd()
        doc.EndUndo()
    
    if __name__=='__main__':
        main(doc)
    
    posted in Cinema 4D SDK •
    RE: Cant select newly created Instance

    Hello @esan !
    I'm not entirely sure what the purpose of your script is, so I made changes to what you provided. You're probably already aware, but this script will only work with children of your selected object, not grandchildren.

    children.pnggrandchildren.png

    The biggest changes were:

    • createInstance: passing the selected object and returning the Instance created using BaseObject & the Instance Object type
    • Your loop for populating the Integer Cycle was reduced by several lines of code by using Python's enumerate function. It gives you an index and instance variable so you don't have to do it all manually. Here's an article about it.
    • To allow for a one-step Undo, you need to add Undos along the way in your functions. Here's more info about the types of Undos in the C4D SDK documentation.
    • This doesn't impact your script too much, but for future scripts it's better to use your main function to get references to your document and active object(s) and then pass them to the functions you write. That will allow you to call those GetActiveDocument and GetActiveObject methods less frequently and reuse your code in the case you want to pass other objects to the functions (e.g. the 'parent' variable in your setQuickTab function).
    import c4d
    from c4d import gui
    
    def createInstance(obj):
        inst = c4d.BaseObject(c4d.Oinstance) # created Instance with Base Object
        inst[c4d.INSTANCEOBJECT_LINK] = obj # set Instance's reference link
        # set the name using the object passed to the function
        inst[c4d.ID_BASELIST_NAME] = "%s Instance"%obj[c4d.ID_BASELIST_NAME]
        return inst # return the Instance instance
    
    def AddLongDataType(obj): # create User Data Container named Picker
        if obj is None: return
    
        bc = c4d.GetCustomDataTypeDefault(c4d.DTYPE_LONG)
        bc[c4d.DESC_NAME] = "Picker"
    
        doc.AddUndo(c4d.UNDO_CHANGE, obj)
        obj.AddUserData(bc)
    
        c4d.EventAdd()
    
    def setQuickTab(obj, data): # change User Date container to type Cycle, populate with Children Names
        descid = data[0][0]
        bc = data[0][1]
    
        children = obj.GetChildren()
    
        # Build new cycle options container dynamically
        cycle = c4d.BaseContainer()
    
        for i,child in enumerate(children):
          cycle.SetData(i, child.GetName())
    
        bc[c4d.DESC_CYCLE] = cycle
    
        doc.AddUndo(c4d.UNDO_CHANGE, obj)
        # Set modified description data container
        obj.SetUserDataContainer(descid, bc)
    
    def main(doc):
        obj = doc.GetActiveObject()
        if (obj == None):
            gui.MessageDialog("Please select an object.")
            return
    
        doc.StartUndo()
        AddLongDataType(obj)
        data = obj.GetUserDataContainer()
        setQuickTab(obj, data)
        inst = createInstance(obj)
        doc.InsertObject(inst)
        doc.AddUndo(c4d.UNDO_NEW, inst)
        doc.EndUndo()
        c4d.EventAdd()
    
    if __name__=='__main__':
        main(doc)
    
    posted in Cinema 4D SDK •
    RE: Undo for GeDialog (GUI)?

    Hi @bentraje!
    I found this documentation in the C++ manual that says:

    "To start and end an undo based on some interaction in a GeDialog the messages BFM_INTERACTSTART and BFM_INTERACTEND can be used."

    I tried this in the GeDialog and got a TypeError:

        def Message(self, msg, result):
            if msg.GetId()==c4d.BFM_INTERACTSTART:
                print("Interact Start")
                doc.AddUndo(c4d.UNDOTYPE_CHANGE,self)
            elif msg.GetId()==c4d.BFM_INTERACTEND:
                print("Interact End")
            return gui.GeDialog.Message(self, msg, result)
    

    TypeError: argument 2 must be c4d.GeListNode

    I don't think I'm setting up the Undo correctly because what can be passed to doc.AddUndo from the GeDialog that is GeListNode? Without the doc.AddUndo line, those message conditionals do work.

    posted in Cinema 4D SDK •
    BaseBitmap.ScaleIt Documentation

    Hello,
    I think I've found a small error in the documentation:

    In BaseBitmap.ScaleIt it lists the final argument as inprop. While using this:

    orig.ScaleIt(newBitmap, intens=256, sample=True, inprop=False)
    

    I got the following error:
    TypeError: Required argument 'nprop' (pos 4) not found

    When I changed the argument to nprop, it worked.

    Thanks.

    posted in Cinema 4D SDK •
    RE: Drag & Drop to Reorder in GUI

    @m_adam This is nice work, Maxime, thank you! I have to check out weakref 🔍

    I'm getting a couple of errors when clicking in a part of the GeUserArea without a square or hitting a key on the keyboard. How can I handle these?

    No square:

    line 331, in InputEvent
            currentIndex = self.draggedObj.GetParentedIndex()   
        AttributeError: 'NoneType' object has no attribute 'GetParentedIndex'`
    

    Keyboard input:

    line 278, in InputEvent
        self.MouseDragStart(c4d.KEY_MLEFT, mouseX, mouseY, c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE | c4d.MOUSEDRAGFLAGS_NOMOVE)
    TypeError: a float is required
    
    posted in Cinema 4D SDK •
    RE: GeUserArea Tool Tips

    @m_adam & @PluginStudent Thank you both! This was exactly what I needed. This forum is so so helpful.

    posted in Cinema 4D SDK •
    RE: How to Communicate between SubDialog and main GeDialog

    @m_adam Hi Maxime, I did try your example and I saw it working as a gadget but, you're right, I want to communicate between two GeDialogs. I followed your advice on using CoreMessage and found success with SpecialEventAdd. Thank you!

    posted in Cinema 4D SDK •

    Latest posts made by blastframe

    Why are there no Sketch and Toon shaders?

    Hello,
    I noticed that there are no Sketch and Toon shader symbols in the Python API. Why is that?

    Here are the IDs for anyone needing them:

    Art = 1012161
    Cel = 1012158
    Hatch = 1012166
    Spots = 1012160
    

    They are in the C++ shader symbols as xartshader, xcelshader, xhatchingshader, and xspotshader.

    Here are the Python Shader Symbols:

    c4d.Xambientocclusion = 1001191
    c4d.Xbase = 5707
    c4d.Xbitmap = 5833
    c4d.Xbrick = 5804
    c4d.Xchanlum = 1007539
    c4d.Xcheckerboard = 5800
    c4d.Xcloud = 5802
    c4d.Xcolor = 5832
    c4d.Xcolorizer = 1011112
    c4d.Xcolorstripes = 5822
    c4d.Xcyclone = 5821
    c4d.Xdistorter = 1011114
    c4d.Xearth = 5825
    c4d.Xfalloff = 1011101
    c4d.Xfilter = 1011128
    c4d.Xfire = 5803
    c4d.Xflame = 5817
    c4d.Xformula = 1031433
    c4d.Xfresnel = 1011103
    c4d.Xfusion = 1011109
    c4d.Xgalaxy = 5813
    c4d.Xgradient = 1011100
    c4d.Xlayer = 1011123
    c4d.Xlumas = 1011105
    c4d.Xmarble = 5830
    c4d.Xmetal = 5827
    c4d.Xmosaic = 1022119
    c4d.Xnoise = 1011116
    c4d.Xnormaldirection = 1011107
    c4d.Xnormalizer = 1026588
    c4d.Xobjectcolor = 1033961
    c4d.Xplanet = 5829
    c4d.Xposterizer = 1011111
    c4d.Xprojector = 1011115
    c4d.Xproximal = 1011106
    c4d.Xrainsampler = 1026576
    c4d.Xripple = 1011199
    c4d.Xrust = 5828
    c4d.Xsimplenoise = 5807
    c4d.Xsimpleturbulence = 5806
    c4d.Xskyshader = 1000
    c4d.Xspectral = 5831
    c4d.Xspline = 1011124
    c4d.Xsss = 1001197
    c4d.Xstar = 5816
    c4d.Xstarfield = 5808
    c4d.Xsubstance = 1032171
    c4d.Xsunburst = 5820
    c4d.Xterrainmask = 1026277
    c4d.Xthinfilm = 1035731
    c4d.Xtiles = 1011102
    c4d.Xtranslucency = 1011108
    c4d.Xvariation = 1033825
    c4d.Xvenus = 5826
    c4d.Xvertexmap = 1011137
    c4d.Xwater = 5818
    c4d.Xwood = 5823
    c4d.Xxmbsubsurface = 1025614
    

    Thank you.

    posted in Cinema 4D SDK •
    RE: Changing VideoPost leads to TypeError

    @m_magalhaes Yes, I think the error was because Octane was the result of rdata.GetFirstVideoPost() and those symbols don't exist in it. If I check for the Viewport Renderer, it seems to work fine. Thanks for the reply and symbol tip!

    posted in Cinema 4D SDK •
    RE: Changing VideoPost leads to TypeError

    I think I have discovered the issue: I believe rdata.GetFirstVideoPost() was getting a renderer other than the Viewport Renderer, so those symbols weren't available. I am now using the following (I found it here) to check that the video post is the Viewport Renderer.

                post = rdata.GetFirstVideoPost()
                while post is not None:
                  if post.CheckType(300001061):
                    break
                  post = post.GetNext()
                if post is None:
                  rd.InsertVideoPost(c4d.BaseList2D(300001061))
    

    Unless the API devs have any corrections, I'll mark this as solved.

    posted in Cinema 4D SDK •
    Changing VideoPost leads to TypeError

    Hello,
    I am trying to change the Viewport Renderer parameters. I was able to use the method illustrated in the code sample below, but something changed (I believe in the API) and this now leads to TypeError: __setitem__ expected str, not bool. If I'm not to assign these values as a boolean, can someone please advise on how these are to be set? Thank you.

    import c4d
    from c4d import documents
    
    def main():
        doc = documents.GetActiveDocument()
        rdata = doc.GetActiveRenderData()
        rd = rdata.GetData()
        post = rdata.GetFirstVideoPost()
        post[c4d.VP_PREVIEWHARDWARE_DISPLAYFILTER_NGONLINES] = False
        post[c4d.VP_PREVIEWHARDWARE_DISPLAYFILTER_OTHER] = False
        post[c4d.VP_PREVIEWHARDWARE_DISPLAYFILTER_SDSCAGE] = False
        post[c4d.VP_PREVIEWHARDWARE_DISPLAYFILTER_ONION] = False
    
    if __name__=='__main__':
        main()
    
    posted in Cinema 4D SDK •
    GeDialog Button Highlighted By Default

    Hello,
    When I create a GeDialog with buttons, the first button is highlighted by default for some reason:

    import c4d
    from c4d import gui
    
    MY_PLUGIN_ID = 1234567
    GROUP1_ID = 1000
    GROUP2_ID = 1001
    BUTTON1_ID = 1002
    BUTTON2_ID = 1003
    BUTTON3_ID = 1004
    
    class Example_Dialog(gui.GeDialog):
        def CreateLayout(self):
            self.SetTitle("BUTTON_HIGHLIGHTED")
            self.GroupBorderSpace(10,10,10,10)
            if self.GroupBegin(GROUP1_ID, c4d.BFH_SCALEFIT | c4d.BFV_SCALE | c4d.BFV_CENTER):
                if self.GroupBegin(GROUP2_ID, c4d.BFH_SCALEFIT, 1):
                    self.GroupBorderSpace(5,5,5,5)
                    self.AddButton(BUTTON1_ID, c4d.BFH_SCALEFIT | c4d.BFV_SCALE | c4d.BFV_CENTER, name='Button1')
                    self.AddButton(BUTTON2_ID, c4d.BFH_SCALEFIT | c4d.BFV_SCALE | c4d.BFV_CENTER, name='Button2')
                    self.AddButton(BUTTON3_ID, c4d.BFH_SCALEFIT | c4d.BFV_SCALE | c4d.BFV_CENTER, name='Button3')
                self.GroupEnd()
            self.GroupEnd()
            return True
    
    # Main function
    def main():
        global example_dialog
        example_dialog = Example_Dialog()
        example_dialog.Open(c4d.DLG_TYPE_ASYNC, pluginid=MY_PLUGIN_ID, defaultw=300, defaulth=150)
    
    # Execute main()
    if __name__=='__main__':
        main()
    

    32aa2c03-38d6-4b72-a3c8-a064dca61328-image.png

    posted in Cinema 4D SDK •
    RE: Detecting a Change in Position/Rotation Keyframes from Tag

    @ferdinand Thank you. I'll try to cache myself.

    posted in Cinema 4D SDK •
    RE: Get a Deformed Point Position Over Time

    @ferdinand Hi, thank you for the reply. I won't need particles. This is a polygon object with a deformer whose point positions I need to get over the Preview Range.

    Isn't the crawl you're describing the same as the range loop in the basedocument_read_animated_mesh.py? My question is: is there a more performant way if this needs to be calculated on each frame?

    If this is the only way, since the animation keyframes would be on another object (the deformer, joints, or a controller) and not a point level animation, I believe the position will depend upon all of the ExecutePasses (animation, expressions, and caches) as in the example. Unless the deformed cache stores these points between playback?

    Thank you.

    posted in Cinema 4D SDK •
    RE: Get a Deformed Point Position Over Time

    @ferdinand Thank you for the prompt reply.

    In my project I need to get the entire timeline and be able to scrub it. Can you please explain the "crawl" method more?

    I was able to remove the EventAdd from my expression tag. I tried removing ExecutePasses() and it the deformation animation froze.

    posted in Cinema 4D SDK •
    RE: Detecting a Change in Position/Rotation Keyframes from Tag

    @ferdinand Thank you for the reply. I mentioned in the title, but (my apologies), I didn't specify in the body of my topic or code example: Is it possible to detect when there a new keyframe has been added for transformation from a tag plugin?

    posted in Cinema 4D SDK •
    RE: Get a Deformed Point Position Over Time

    I found this post on CGSociety where @m_adam shares a link to this file: basedocument_read_animated_mesh.py. Awesome stuff!

    I've got it working, but I'm curious: do I need to use doc.SetTime() to get all the values over time at once?

    This seems like a resource-expensive process for my project because I'm using it in a tag.

    posted in Cinema 4D SDK •