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).
I am currently using this approach to iterate the objects in a document
doc = c4d.documents.GetActiveDocument() obj = doc.GetFirstObject() next_obj = obj.GetNext() while next_obj: # Do stuff next_obj = obj.GetNext()
Is there some equivalent of doing this via e.g. indexing in a for-loop ?
Cheers
Hi @nicholas_yue,
thank you for reaching out to us. And thanks at @Cairyn for jumping in. @Cairyn answer is perfectly fine, but I would like to point out of some stuff.
list
iterator
yield
Below you will find an example for such iterator, which intentionally does something slightly different than @Cairyn example, as it only will only return children and grand-children and no siblings, i.e. it will only traverse a partial graph marked by an input node as the root of that partial graph. As said in 2. it really depends on what you want to do and you should design your own on an as-needed basis.
Cheers, Ferdinand
import c4d def get_next(op, stop_node): """Returns the "next" node in a graph in a depth-first traversal. Args: op (c4d.GeListNode): The node from which to traverse. stop_node (c4d.GeListNode): A node not to exceed in the horizontal hierarchical traversal. Returns: c4d.GeListNode or None: A child or grandchild of op. Or `None` when the graph has been exhausted. """ if op is None: return None elif op.GetDown(): return op.GetDown() while (op.GetUp() and op.GetUp() != stop_node and not op.GetNext()): op = op.GetUp() return op.GetNext() def iter_partial_graph(node): """Yields all children and grand-children of the passed node. """ stop_node = node while node is not None: yield node node = get_next(node, stop_node) if __name__=='__main__': # Go over all children and grand-children of the currently selected node. for node in iter_partial_graph(op): print (node)
I hope that's not really your code because it will hang. In the last line, you retrieve next_obj always from obj.GetNext() so you get the same object forever. Also, you're skipping the first object before you Do Stuff. And next_obj is not needed anyway:
doc = c4d.documents.GetActiveDocument() obj = doc.GetFirstObject() while obj: # Do stuff obj = obj.GetNext()
Also, doc is a predefined variable that is already set to the current document. And you are not traversing into the child objects, but I guess you know that.
As per your question, you can use GeListNode.GetChildren() to retrieve a list of child objects which you can address by index, but there is no GetSiblings() built in to achieve the same on the top level. Nevertheless, you can create your own function easily which assembles all siblings into a Python list, or alternatively a function that yields the next sibling, depending on how you want to use it.
GeListNode.GetChildren()
GetSiblings()
The following script shows all siblings on top level (still not traversing the children) by assembling them into a list:
import c4d from c4d import gui def GetSiblings(obj): while obj.GetPred(): obj = obj.GetPred() # go to first sibling retlist = [] while obj: retlist.append(obj) obj = obj.GetNext() return retlist def main(): obj = doc.GetFirstObject() print GetSiblings(obj) if __name__=='__main__': main()
Learn more about Python for C4D scripting: https://www.patreon.com/cairyn
Hi,
without further feedback, we will consider this thread as solved by Monday and flag it accordingly.