Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
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()
hello,
if i understood correctly, you want to make editable the motext, collapse the result (connect) and delete the original one.
I did create an example for that.
I've build the logic slowly. It was pretty straight forward.
The first thing is to have a function that can return the next object in the hierarchy but that only act on the child and not the whole document.
import c4d from c4d import gui def GetNextObject(ori, op): """ Retrieves the next object in the hierarchy. :param ori: the original object to sompare with the next so we never get upper this level. :type: BaseObject :param op: the actual object in the hierarchy :type: BaseObject :Return: the next object in the hierarchy or None :rtype: BaseObject """ if op==None: return None if op.GetDown(): return op.GetDown() while not op.GetNext() and op.GetUp(): # CHecks if the next object up in the hierarchy is not the original one. if op.GetUp() != ori: op = op.GetUp() else: return None return op.GetNext() def CSTO(op ): """ Current State To Object :param op: the object to apply current state to object to. :type: BaseObject :return: the result of the command or raise an error if command failed :rtype: BaseObject """ # Retrieves the document that the object belong to doc = op.GetDocument() # send the modeling command res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_CURRENTSTATETOOBJECT, list = [op], mode = c4d.MODELINGCOMMANDMODE_ALL, bc = c4d.BaseContainer(), doc = doc) # Cheks if the command didn't failed if res is False: raise TypeError("return value of CSTO is not valie") # Returns the first object of the list. return res[0] def JoinCommand(op): """ Apply a join command to the object passe as argument :param op: the object to apply current state to object to. :type: BaseObject :return: the result of the command or raise an error if command failed :rtype: BaseObject """ # Retrieves the document that the object belong to doc = op.GetDocument() # send the modeling command res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_JOIN, list = [op], doc= doc) # Cheks if the command didn't failed if res is False: raise TypeError("return value of Join command is not valie") # Returns the first object of the list. return res[0] # Main function def main(): doc.StartUndo() # Retrieves the active objects objs = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_NONE) if len(objs) <1: raise ValueError("select one objectr please") # prepare a list of object that need to be removed at the end. removeObjectList = [] # Iterates trough the selected objects. for obj in objs: # Use another variable so we can keep one with the original object to compare in the 'GetNextObject' function currentObject = obj while currentObject: # Checks if the current object is a MoText Object. if currentObject.IsInstanceOf(1019268): myNewObject = CSTO(currentObject) myNewObject = JoinCommand(myNewObject) # Inserts the new object after the motext doc.InsertObject(myNewObject, None, currentObject) doc.AddUndo(c4d.UNDOTYPE_NEW, myNewObject) # Adds the motext object to the remove list removeObjectList.append(currentObject) currentObject = GetNextObject(obj, currentObject) # Retrieves the keyboard states for the shift key bc = c4d.BaseContainer() shift = None if c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD,c4d.BFM_INPUT_CHANNEL,bc): shift = bc[c4d.BFM_INPUT_QUALIFIER] & c4d.QSHIFT == c4d.QSHIFT # if shift key is not pressed, remove the objects. if not shift: # Removes all object in the remove list. for obj in removeObjectList: doc.AddUndo(c4d.UNDOTYPE_DELETE, obj) obj.Remove() doc.EndUndo() c4d.EventAdd() # Execute main() if __name__=='__main__': main()
If you have any question just ask
Cheers, Manuel
@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.
The code is using the same command that the user should use using the UI. Could you be a bit more specific about what's not working with material ?
Cheers, Manuel.
I'will consider this thread as solved tomorrow if you have nothing to add