Navigation

    • Register
    • Login
    • Search
    1. Home
    2. esan
    esan

    esan

    @esan

    exploring polygonal and polyphonal frequencies

    1
    Reputation
    15
    Posts
    24
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online
    Location redmond washingtong Age 39

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

    Best posts made by esan

    RE: Cant select newly created Instance

    @blastframe Ok was able to retrofit your version to get what I wanted, a bit of guesswork in here, but got the result im after lol

    import c4d
    from c4d import gui
    
    def createInstance():
        obj = op.GetDown()
        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, inst, 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
        inst.SetUserDataContainer(descid, bc)
    
    def main(doc):
        obj = doc.GetActiveObject()
        if (obj == None):
            gui.MessageDialog("Please select the Root of the Assets you wish to Instance.")
            return
    
        doc.StartUndo()
        inst = createInstance()
        doc.InsertObject(inst)
        AddLongDataType(inst)
        data = inst.GetUserDataContainer()
        setQuickTab(obj, inst, data)
        
        doc.AddUndo(c4d.UNDO_NEW, inst)
        doc.EndUndo()
        c4d.EventAdd()
    
    if __name__=='__main__':
        main(doc)
    
    posted in Cinema 4D SDK •

    Latest posts made by esan

    RE: Connect + Delete groups iteratively

    @m_magalhaes This is fantastic, it works and gives me a lot to dissect. I'll be further expanding on it to include Instance objects and cloners [have already had that working as theyre a simple "make editable"]. In my day to day i have to often share assets via FBX, and if my assets are built with instances/clonser/MoText [<-particularly messy], FBXs auto conversion of those assets create quite a messy hierarchy, roots on roots for days lol. This will help clean things up. Thanks!

    I think one issue i need to solve with this method is reapplying/maintaining the original objects applied Material.

    posted in Cinema 4D SDK •
    Connect + Delete groups iteratively

    C4D R20

    I started the "SendModelCommand" path but trying to just get this stood up quickly with CallCommands first. The issue im having is obviously Connect + Delete happens on "All" selected objects, collapsing into one, when I want each to collapse into their own respective objects . My thoughts are to find all "MoText" under op root, store in an array and run the[ select > make editable >] select children of new hierarchy > connect+delete (deselect all?) stepping through the whole sequence per item. before moving onto the next item since connect+delete doesn't care about hierarchy, at least in CallCommand form anyway.

    I've made a couple of attempts at executing that logic, but am fairly new to writing python for C4D so haven't had success yet. Hoping i can be shown how to achieve my logic or be told/shown there's a much better way to go about it altogether.

    Thanks in advance!

    import c4d
    from c4d import gui
    from c4d import utils
    
    def selchildren(obj,next): # Scan obj hierarchy and select children
    
        while obj and obj != next:
    
            doc.AddUndo(c4d.UNDOTYPE_CHANGE_SMALL,obj)
    
            if obj.CheckType(1019268): #find MoText
                obj.SetBit(c4d.BIT_ACTIVE)
    
            selchildren(obj.GetDown(),next)
    
            obj = obj.GetNext()
    
        c4d.EventAdd()
    
        return True
    
    
    
    def main():
    
    
        for obj in doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_CHILDREN):
            if selchildren(obj, obj.GetNext()):
                obj.DelBit(c4d.BIT_ACTIVE)
                c4d.CallCommand(12236) # Make Editable
                c4d.CallCommand(16768, 16768) # Connect + Delte
                
    
    # Execute main()
    if __name__=='__main__':
        main()
    
    posted in Cinema 4D SDK •
    RE: Xpresso Python Node . "Code" field

    @Cairyn

    Ah youre right, the Return was the cause of the errors, not the triple quotes. Got it all working now! (after taking a few tries to get the "indents" with the strings right)

    Thanks a ton!

    posted in Cinema 4D SDK •
    RE: Xpresso Python Node . "Code" field

    @m_adam

    So final question. When i execute node[2][c4d.GV_PYTHON_CODE] = 'test string', all is well. When i try to exectute this as a function, i get errors. This setup gives me error " setitem expected str, not None"

    i wanted to do a multi-line string incapsulation but the triple quotes seem to be reserved for title/headers in this environment. How would i go about conveying that this function is a Str if making it a bucket of strings doesnt do it?

    def pythonNodeCode():
    
        'import c4d'
        
        'def main():'
    
        '    global Output2'
        '    global Input3'
     
        '    Output2 = c4d.BaseList2D.GetName(Input3)'
    
    def main():
    
        #skip a lot of other code
    
        node[2][c4d.GV_PYTHON_CODE] = pythonNodeCode()
    
    
    
    
    

    (i tried node[2][c4d.GV_PYTHON_CODE] = str(pythonNodeCode()) too just to make sure the obvious wasnt sitting in my face)

    edit: I achieved the intent with this, but still interested in the non-atrocious way to write it lol

     node[2][c4d.GV_PYTHON_CODE] = 'import c4d \n\ndef main():\n\n    global Output2\n    global Input3\n\n    Output2 = c4d.BaseList2D.GetName(Input3)'
    
    posted in Cinema 4D SDK •
    RE: Xpresso Python Node . "Code" field

    @m_adam

    ahh, palm securely in face. Ya I had the GV_PYTHON_CODE but since I had spent so much time wrapping my head around this OperatorSetData in the node world prior I overcomplicated it from the start. Hadnt come across that console manual either, thanks a lot!

    posted in Cinema 4D SDK •
    RE: Xpresso Python Node . "Code" field

    @Cairyn

    Sorry, i have a lot of permutations of this and the code snippet isn't from that exact node pictured, just grabbed examples at random since the point of the question was asking how to populate the Python Node Code field with my Python Script. Once that works then yes ill make all the proper ports/names to accommodate, that part i have figured out and got working, just inserting code into the field is what im missing. Thanks

    posted in Cinema 4D SDK •
    Xpresso Python Node . "Code" field

    R20

    I need to add an "Object" port to an object node, but I guess since I have R20 with that particular python bug preventing it, I need to find a workaround. All I need to do is get the currently instanced objects name, fed back into the display name (and appending with another string in here). Ive seen that "UserData" workaround to get a makeshift Object port but that feels heavy handed for my case. Thought a python node with simple script can replace my Object node and Name port like so
    0bbef353-e55e-43bb-a3e9-991674a387d0-image.png

    And this works, but cant seem to figure out how to "set" this Python Code in this Node via my Python Script. Have made this snippet of code a function and was trying everything from OperatorSetData, and even the InsertObjects through In/Exclude method I was just shown for my Link List question. But nothing ive done yet seems to populate the field. Final Stretch! Thanks for all the help thus far, this script has already been an amazing learning experience.

    def main():
    
        global Output2
        global Input3
    
        Output2 = c4d.BaseList2D.GetName(Input3)
    
    posted in Cinema 4D SDK •
    RE: OperatorSetData for "Lists"?

    @r_gigante Another quick question. is there still a bug on c4d.GV_OBJECT_OPERATOR_OBJECT_OUT? I dont get object ports on my nodes when trying to add this and I saw it was a long standing bug.

    ...just saw notes that the bug was fixed in R21. But I (and the people ill be distributing this script to) are all on R20, is there any patch or easy workaround to getting Object ports showing up? This is the last step needed to finish my script!

    thanks

    posted in Cinema 4D SDK •
    RE: OperatorSetData for "Lists"?

    @r_gigante said in OperatorSetData for "Lists"?:

    inexdata.InsertObject(sphere, 1)

    Thanks so much for your reply, I started getting way off track trying other methods lol! I got it working with:

    inexdata = c4d.InExcludeData()
        
        for i, obj in enumerate(children):
            inexdata.InsertObject(children[i], 1)
            
        node[1][c4d.GV_LINK_LIST] = inexdata
    
    posted in Cinema 4D SDK •
    OperatorSetData for "Lists"?

    Am i understanding this correctly? Im trying to populate an Xpresso Link List nodes (node[1])
    "Link List" field with the children of Tiles. Just a partial snippet of code here, i dont get any errors, the objects just dont populate.
    R20

    Ive tried many permutations, tried GeListNode as type, tried enumerating children, putting that in a list()...im guessing my "Children" arent an actual "List" type, and im blindly dancing around the right answer, just cant quite get it? Do i need to first make these children a "list" (and how would i go about that?), or do i need to "insert" into document at any point? Based on the documentation it sounds like OperatorSetData should take care of the insertion. Or maybe im assuming incorrectly that "simulates user dragging onto the node" means it can simulate dragging into attribute manager of the node? Just learning Python for C4D so just trying to wrap my head around it all. Thanks!

    Edit: Have given up on OperatorSetData and trying to follow some examples set by "Inserting" objects to IN/Exclude, though it has its own class to call on so working out those discrepancies, I tried a doc.InsertObject on a single child from the children list and console told me to "add them separately", so also trying to decipher that message since c4d.BaseObjects apparently don't like to be iterated, says console. Maybe a makeshift Python node acting as a Link List node is the way to go?

    obj = doc.SearchObject("Tiles")
        children = obj.GetChildren()
    
    node[1].OperatorSetData(c4d.GV_LINK_LIST, children ,c4d.GV_OP_DROP_IN_BODY)
    
    posted in Cinema 4D SDK •