In this article we’ll take a look at how to crawl through a hierarchy of objects in CINEMA 4D, without using a recursion.
Why not use a recursion?
With very deeply nested hierarchies, a recursion can actually hit the stack limit and cause a crash. Normally, it’s not very likely but it may happen in some cases.
Iterating and counting objects
C++
The functions
BaseObject* GetNextObject(BaseObject* op) { if (!op) return NULL; if (op->GetDown()) return op->GetDown(); while (!op->GetNext() && op->GetUp()) op = op->GetUp(); return op->GetNext(); } LONG IterateHierarchy(BaseObject* op) { LONG count = 0; while (op) { count++; GePrint(op->GetName()); op = GetNextObject(op); } return count; }
Usage
void main() { BaseDocument* doc = GetActiveDocument(); if (doc) { BaseObject* start_object = doc->GetFirstObject(); LONG count = IterateHierarchy(start_object); GePrint("Iterated " + LongToString(count) + " objects."); } }
Python
The functions
def GetNextObject(op): if op==None: return None if op.GetDown(): return op.GetDown() while not op.GetNext() and op.GetUp(): op = op.GetUp() return op.GetNext() def IterateHierarchy(op): if op is None: return count = 0 while op: count += 1 print op.GetName() op = GetNextObject(op) return count
Usage
def main(): start_object = doc.GetFirstObject() count = IterateHierarchy(start_object) print "Iterated " + str(count) + " objects."
Further notes
Also read the article about recursive hierarchy iteration.
Thanks to
Per-Anders Edwards for the original article at:
http://peranders.com/wiki/Python_Object_Iteration
Using Yield
import c4d
def IterateHierarchy(op):
while op:
yield op
if op.GetDown():
op = op.GetDown()
continue
while not op.GetNext() and op.GetUp():
op = op.GetUp()
op = op.GetNext()
def main():
for x in IterateHierarchy(op):
print x.GetName()
if __name__==’__main__’:
main()
Hi Mike, thanks a lot for the insight.
In order to make it more “readable” I’ve reformatted to include space: hope you don’t mind about it.
def IterateHierarchy(op):
while op:
yield op
if op.GetDown():
op = op.GetDown()
continue
while not op.GetNext() and op.GetUp():
op = op.GetUp()
op = op.GetNext()
def main():
for x in IterateHierarchy(op):
print x.GetName()
Best, Riccardo