Selecting All Children, and Dialogs

On 06/02/2013 at 13:40, xxxxxxxx wrote:

Hello all.  I have a couple Python question.  Is there a none function way to get all of the objects that are children, grandchildren, great grand children, etc?   I know how to get them all with a function such as:

def GetObjects(obj) :  
    for kid in obj.GetChildren() :  

Or something similar to that.  But if I have a thousand objects in a hierarchy  I don't want to call a function that many times.   Is there a more efficient to do it?  Or at least get the count of all the children and grand children, etc?

And is there any way to get if the cancel button was hit one a c4d.gui.InputDialog() dialog? It seems to just return the string regardless.

Thanks for any help you can give.


On 06/02/2013 at 14:08, xxxxxxxx wrote:

Hi Dan,

1. You always have to call a function. Technically everything you do in Python ends up with a
function-call. Anyway, you can iterate manually over all objects in the hierarchy. It depends on
the actual use-case which version is faster. If you have to process the objects multiple times,
you might want to use the GetChildren() function. If you process them once, you might want to
iterate manually. You need to perform tests to check what runs faster in your certain case. See
the example code below for the alternative manual iteration.

def process_hierarchy(op) :
    op = op.GetDown()
    while op:
        op = op.GetNext()

For time-measurement, I suggest to use the c4dtools.util.Watch class or the standart time module.

2. The c4d.gui.InputDialog() function returns an empty string when either the user entered no
text or the dialog was cancelled. Both cases indicate abort by the user.


On 06/02/2013 at 15:46, xxxxxxxx wrote:

Hi Niklas,

1. I misspoke about the this part.  I understand about the functions, what I meant was if there was away to do it without recursion.  I know you can raise limit on the number of recursions that can occur but I wanted to avoid the function calling itself if possible

2.  I feel really stupid about this part.  When I used c4d.gui.InputDialog() I had it like:

c4d.gui.InputDialog("Enter a number.","25")  

And when cancel is hit it returns the default value and I never caught on, doh.  I thought it was crazy that there wouldn't be a way to get if cancel was hit.

Thanks for the help Niklas.


On 06/02/2013 at 15:56, xxxxxxxx wrote:

1. I understand. Yes there is, but it's much slower. The only thing is that you will not hit the
recursion limit. When you try to get the next object from the current object, you try to get its children.
If there is no children, go to the next object. If there is no next object: get up.

def get_next(op) :
    if not op:
        return None
    if op.GetDown() :
        return op.GetDown()
    while not op.GetNext() and op.GetUp() :
        op = op.GetUp()
    return op.GetNext()

This can be optimized to avoid unnecessary double function calls:

def get_next(op) :
    if not op:
        return None
    down = op.GetDown()
    if down:
        return down
    up = op.GetUp()
    next = op.GetNext()
    while not next and up:
        op = up
        up = op.GetUp()
        next = op.GetNext()
    return next

2. You're right, it returns the default-value. Didn't know that, sorry. Sounds like a bug to me. My
proposed solution would be to create either your custom input dialog or omitt the default value.


On 11/02/2013 at 14:06, xxxxxxxx wrote:

Thanks again for responding Niklas.

1.  I switched up the function I was going and decided just to do a recursive function using GetChildren().  And I haven't been getting any crashes or anything so far.

2.Yes, that's what I plan on doing now.

3.  Is there a way aside from CallCommand() and SendModelingCommand() to make a object editable?  Isn't it a bad idea to use either of those functions? So  I was hoping that there was another way.

Thanks again.

On 11/02/2013 at 14:21, xxxxxxxx wrote:

Making an object editable does not have so much performance impact, but current state to
object should be avoided if possible.

you can also always read the (deform)cache of a baseobject to get hold of a pointobject
representation of your baseobject. in basedocument is also polygonize, which will try to 
convert the whole document.

On 14/02/2013 at 10:16, xxxxxxxx wrote:

Hi there.

Thanks for the advice Ferdinand.

I'm trying to avoid using any modeling commands or call commands because they mess with the undos.  My current code is:

  cache= op.GetCache()  
  clone = cache.GetClone()  

Which seemed to work so far.  Is that a bad idea though?


On 14/02/2013 at 10:28, xxxxxxxx wrote:

you can do this and there is nothing wrong about it, but copying atoms can sometimes 
lead to unexpected results with missing children and so on. and i think getclone also 
invokes the cache to be rebuild.

the alternative would b to read the existing caches.

BaseObjectCache = myBaseObject.GetCache()
BaseObjectDeformCache = myBaseObject.GetDeformCache()

On 14/02/2013 at 10:28, xxxxxxxx wrote:

Hi Dan,

it's fine, nothing bad in there. Maybe just checking if cache is not None. ;-)