Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    how to get all subobject(children) of active object?

    Cinema 4D SDK
    python r21
    3
    6
    1.6k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • gheyretG
      gheyret
      last edited by

      Hi everyone~~
      I want to get all subobject(children) of active object.

      Snipaste_2019-11-07_23-20-42.png

      This is my idea :

      import c4d
      from c4d import gui
      # Welcome to the world of Python
      
      def all_child(obj):
          if not obj: return
          elif obj.GetDown():
              return obj.GetDown()
          elif obj.GetNext():
              return obj.GetNext()
          while obj.GetUp() and not obj.GetNext():
              obj = obj.GetUp()
          return obj.GetNext()
      
      def main():
          obj = doc.GetActiveObject()
          if not obj: return
          objs = []
          if obj.GetDown():
              while obj:
                  objs.append(obj)
      
                  obj = all_child(obj)
          else:
              objs.append(obj)
          
          print len(objs),objs
      
      # Execute main()
      if __name__=='__main__':
          main()
      

      but something is wrong, i don't know how to fix it.
      somebody can help me?

      www.boghma.com

      1 Reply Last reply Reply Quote 0
      • gheyretG
        gheyret
        last edited by

        Is anyone here?

        www.boghma.com

        1 Reply Last reply Reply Quote 0
        • ferdinandF
          ferdinand
          last edited by ferdinand

          Hi,

          there are basically two approaches how you can do this: iteratively and recursively. The recursive approach is somewhat easier to implement / more readable, but has the disadvantage that you actually might hit Python's recursion limit when dealing with a graph with 100's of objects. It might look something like this:

          import c4d
          
          def get_descendants(op):
              """ Returns all descendants of op.
              """
              if not isinstance(op, c4d.GeListNode):
                  return []
              
              res = []
              
              for child in op.GetChildren():
                  res.append(child)
                  res += get_descendants(child) # recursion happens here
              return res
          
          # Main function
          def main():
              for node in get_descendants(op):
                  print node
          
          # Execute main()
          if __name__=='__main__':
              main()
          

          The iterative approach is a bit more complex in implementation but does not have this disadvantage. If you need an iterative approach - as your code does go into that direction -, just ask.

          Cheers
          zipit

          MAXON SDK Specialist
          developers.maxon.net

          gheyretG 1 Reply Last reply Reply Quote 0
          • gheyretG
            gheyret @ferdinand
            last edited by

            @zipit
            Thank you zipit.
            I find your methods convenient, but I still need an iterative approach
            Can you give me some simple example?

            Cheers

            www.boghma.com

            1 Reply Last reply Reply Quote 0
            • ferdinandF
              ferdinand
              last edited by ferdinand

              Hi,

              I am not sure what you would consider a simple example. I have once written this here. It does a bit more than (then?, argh, the English language ;)) you are asking for, but should show the principle. Its actually not that hard, you only have to find "your" algorithm to navigate the graph. There is no one way to do it (you can do it for example depth first or breadth first). Building a simple example graph and doing it on paper by hand might help. That is also why it is not easy to debug your example for you.

              def iter_node(node, include_node=False, include_siblings=False):
                  """Provides a non-recursive iterator for all descendants of a node.
              
                  Args:
                      node (c4d.GeListNode): The node to iterate over.
                      include_node (bool, optional): If node itself should be included in
                       the generator. Defaults to False. 
                      include_siblings (bool, optional): If the siblings (and their
                       descendants) of node should be included. Will implicitly include
                       node (i.e. set include_node to True). Defaults to False. 
              
                  Yields:
                      c4d.GeListNode: A descendant of node.
              
                  Example:
                      For the following graph with object.2 as the input node.
              
                      object.0
                          object.1
                          object.2
                              object.3
                              object.4
                                  object.5
                          object.6
                              object.7
                              object.8
              
                      >> for node in iter_node(object_2, False, False):
                      >>     print node.GetName()
                      object.3
                      object.4
                      object.5
                      >> for node in iter_node(object_2, True, False):
                      >>     print node.GetName()
                      object.2
                      object.3
                      object.4
                      object.5
                      >> for node in iter_node(object_2, True, True):
                      >>     print node.GetName()
                      object.1
                      object.2
                      object.3
                      object.4
                      object.5
                      object.6
                      object.7
                      object.8
                  """
                  if not isinstance(node, c4d.GeListNode):
                      msg = "The argument node has to be a c4d.GeListNode. Received: {}."
                      raise TypeError(msg.format(type(node)))
              
                  # Lookup lists
                  input_node = node
                  yielded_nodes = []
                  top_nodes = []
              
                  # Set top nodes (and set node to first sibling if siblings are included)
                  if include_siblings:
                      while node.GetNext():
                          node = node.GetNext()
                      top_nodes = [node]
                      while node.GetPred():
                          node = node.GetPred()
                          top_nodes.append(node)
                  else:
                      top_nodes = [node]
              
                  # Start of iterator
                  while node:
                      # Yield the current node if it has not been yielded yet
                      if node not in yielded_nodes:
                          yielded_nodes.append(node)
                          if node is input_node and include_node:
                              yield node
                          elif node is not input_node:
                              yield node
              
                      # Get adjacent nodes
                      is_top_node = node in top_nodes
                      node_down = node.GetDown()
                      node_next = node.GetNext()
                      node_up = node.GetUp()
              
                      if is_top_node:
                          node_up = None
                      if is_top_node and not include_siblings:
                          node_next = None
              
                      # Get the next node in the graph in a depth first fashion
                      if node_down and node_down not in yielded_nodes:
                          node = node_down
                      elif node_next and node_next not in yielded_nodes:
                          node = node_next
                      elif node_up:
                          node = node_up
                      else:
                          node = None
              

              Cheers
              zipit

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 0
              • r_giganteR
                r_gigante
                last edited by

                Hi @gheyret, thanks for reaching out us.

                Although @zipit has already provide an exhaustive answer to the topic (thanks man!) , I warmly suggest to look also to this blog post[URL-REMOVED] from @fwilleke80 and also to have a look at Navigation in Lists and Trees section on the GeListNode Manual.

                Best, Riccardo


                [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post