Plugin Cafe Homepage
Forum Home Forum Home > Plugin Cafe > PYTHON Development
  New Posts New Posts
  FAQ FAQ  Forum Search

Selecting All Children, and Dialogs

Author
Message
  Topic Search Topic Search
DSchmidt View Drop Down
Member
Member


Joined: 2012 Jun 19
Online Status: Offline
Posts: 135
Direct Link To This Post Topic: Selecting All Children, and Dialogs
    Posted: 2013 Feb 06 at 1:40pm
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():
              GetObjects(kid)


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. 

Dan

Back to Top
NiklasR View Drop Down
Member
Member


Joined: 2010 Dec 13
Location: Germany
Online Status: Offline
Posts: 2575
Direct Link To This Post Posted: 2013 Feb 06 at 2:08pm
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):
    do_stuff(op)
    op = op.GetDown()
    while op:
        process_hierarchy(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.

-Niklas


Edited by NiklasR - 2013 Feb 06 at 2:08pm
Back to Top
DSchmidt View Drop Down
Member
Member


Joined: 2012 Jun 19
Online Status: Offline
Posts: 135
Direct Link To This Post Posted: 2013 Feb 06 at 3:46pm
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.

Dan
Back to Top
NiklasR View Drop Down
Member
Member


Joined: 2010 Dec 13
Location: Germany
Online Status: Offline
Posts: 2575
Direct Link To This Post Posted: 2013 Feb 06 at 3:56pm
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.

-Niklas
Back to Top
DSchmidt View Drop Down
Member
Member


Joined: 2012 Jun 19
Online Status: Offline
Posts: 135
Direct Link To This Post Posted: 2013 Feb 11 at 2:06pm
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.
Dan
Back to Top
ferdinand View Drop Down
Member
Member


Joined: 2013 Feb 05
Online Status: Offline
Posts: 26
Direct Link To This Post Posted: 2013 Feb 11 at 2:21pm
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.
win, r14, python
Back to Top
DSchmidt View Drop Down
Member
Member


Joined: 2012 Jun 19
Online Status: Offline
Posts: 135
Direct Link To This Post Posted: 2013 Feb 14 at 10:16am
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()
    doc.InsertObject(clone)
    c4d.EventAdd()


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

Dan
Back to Top
ferdinand View Drop Down
Member
Member


Joined: 2013 Feb 05
Online Status: Offline
Posts: 26
Direct Link To This Post Posted: 2013 Feb 14 at 10:28am
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()

win, r14, python
Back to Top
NiklasR View Drop Down
Member
Member


Joined: 2010 Dec 13
Location: Germany
Online Status: Offline
Posts: 2575
Direct Link To This Post Posted: 2013 Feb 14 at 10:28am
Hi Dan,

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

-Niklas
Back to Top

Forum Jump Forum Permissions View Drop Down

Bulletin Board Software by Web Wiz Forums® version 9.61 [Free Express Edition]
Copyright ©2001-2009 Web Wiz

This page was generated in 0.094 seconds.