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 can I get a Layer's objects with Python?

    Cinema 4D SDK
    2
    4
    906
    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.
    • delizadeD
      delizade
      last edited by

      Hello,
      I have 450 takes. Every take activates only one layer (make editor and render visibility true) of the document. (Other layers are disabled by default)

      I want to modify objects that belongs to that layer which is activated by a take.

      After getting Layer, I need to get list of objects of that Layer by Python.

      Simply I want to make:
      after I activated a take I will execute a script. That script will make some modifications about objects and their materials. After that it will updates take overrides. To make those actions I need to find Active Take > Layer > Objects

      how can I make this? could anyone help me about this please?

      thank you

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

        Hello @delizade,

        thank you for reaching out to us. Please remember to tag your topics also with the version(s) of Cinema 4D and OS you are targeting.

        About your question: The answer to that is unfortunately not trivial. The take system of Cinema 4D is powerful, but that makes it sometimes hard to find general solutions for working with it programmatically. There is no general solution for "find all classic nodes that are somehow part of the active take". The reason for that is that classic nodes can be manipulated in many ways by takes. In your example it is the layers which are being manipulated and not the objects themselves you are after. So, you will need to find the layer(s) which are part of the active take and then the objects that are part of that layer.

        We cannot provide full solutions, but I wrote a little example which goes into the direction you want to go. Please note that this is an example and that we can only answer specific follow up questions. We cannot improve the script so that it will fit your requirements, you will have to do that yourself.

        I hope this helps and cheers,
        Ferdinand

        The result:
        1.gif

        The code:

        """Example for iterating over all objects that are attached to a layer.
        
        The script retrieves the layer to be tested for via the take system, looking
        for a layer which is part of the overrides of the currently active take.
        
        As discussed in:
            plugincafe.maxon.net/topic/13640
        """
        
        import c4d
        
        def Iterate(document, callback, **kwargs):
            """The iteration function, walking a document object graph depth first.
            
            Args:
                document (c4d.documents.BaseDocument): The document to iterate over.
                callback (callable): A callback to evaluate if a certain node should
                 be yielded or not.
                **kwargs: The additional kw arguments for the callback.
            
            Yields:
                c4d.BaseObject: An object node within the document graph that did
                 satisfy the callback.
            """
            node = document.GetFirstObject()
            visisted = []
            terminal = node.GetUp() if isinstance(node, c4d.GeListNode) else None
        
            while node:
                if node not in visisted:
                    if callback(node, document, **kwargs):
                        yield node
                    visisted.append(node)
        
                if node.GetDown() and node.GetDown() not in visisted:
                    node = node.GetDown()
                elif node.GetNext():
                    node = node.GetNext()
                else:
                    node = node.GetUp()
        
                if node == terminal:
                    break
        
        def MyCallback(node, document, **kwargs):
            """A little callback function which does test if a node should be yielded
            or not.
        
            We are testing here if the node is attached to the same layer as passed
            down via activeLayer to `Iterate`.
            """
            if not isinstance(node, c4d.BaseList2D):
                return False
            if "activeLayer" not in kwargs:
                return False
            return kwargs["activeLayer"] == node.GetLayerObject(document)
        
        def main():
            """Entry point.
            """
            # Get the active take 
            takeData = doc.GetTakeData()
            baseTake = takeData.GetCurrentTake()
        
            # Iterate over all overrides to find the first override for a layer 
            # object. Bail the script when we cannot find any overrides for a layer.
            layer = None
            for item in baseTake.GetOverrides():
                if isinstance(item.GetSceneNode(), c4d.documents.LayerObject):
                    layer = item.GetSceneNode()
                    break
            if layer is None:
                raise RuntimeError("Could not find any layer object overrides.")
        
            # Iterate over all objects in the scene which are attached to that layer.
            for node in Iterate(doc, MyCallback, activeLayer=layer):
                print (node)
        
        
        if __name__ == '__main__':
            main()
        

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 1
        • delizadeD
          delizade
          last edited by

          Thank you so much for your time and help.

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

            Hello @delizade,

            we will set this topic to 'Solved' when there are no further questions or replies until Monday, November the 22th.

            Thank you for your understanding,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

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