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

    Adding multiple cameras from a single file to the render queue

    Cinema 4D SDK
    python r23
    4
    22
    17.4k
    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.
    • B
      beezle
      last edited by beezle

      Hey guys, I'm back on R&D, and while I've posted this question before, I've tried some things and have some new questions.

      Basically, where I left off was, I'm trying to add all selected cameras to the render queue at once. I can add as many cameras as I have selected to the render queue, but they're all the same camera - whatever camera was set as the scene camera before the script was run. There are no object properties for then changing the Camera, which we can do manually with each render item via dropdown.

      I've tried a couple things to work around this. First was to loop through all the cameras, and on each iteration, set the current camera I'm adding as the active camera, save, and add the file to the render queue. Then close and reload the file, and continue doing that until I've iterated through all the selected cameras. Unfortunately, no matter what I do (even after adding a time.sleep command to give c4d time to load the file completely before trying to set the camera), it seems c4d ignores all the commands to set the active camera until the very end, after the rest of the script has run. I imagine an event trigger might be a good way to trick the compiler into executing the queued "set active camera" command, but I'm not seeing any events for when a file loads.

      The only other thing I could think of to do was to use pyautogui to automate keyboard commands to traverse the render queue via the gui and change the camera dropdowns "manually". Unfortunately, unless I'm missing something, it seems like pyautogui commands don't work in c4d.

      Does anyone have any suggestions? Because I'm at wit's end trying to automate this frankly basic functionality, which should've been included with the software, let alone it being impossible to automate via python.

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

        Hi @beezle,

        thank you for reaching out to us. I did not have any problems creating batch render jobs for different cameras in a document. You approach is correct, you must have made a minor mistake. Below you will find my solution and a scene file I did ran it on.

        Cheers,
        Ferdinand

        pc13061_scene.c4d

        """Demonstrates how to create batch render jobs for multiple cameras in a
        scene file as discussed in:
        
            https://developers.maxon.net/forum/topic/13059
        
        Note:
            * This script is designed for Cinema's native camera objects, to include
              other camera types, either modify CAMERA_TYPES or adopt 
              get_scene_cameras to accommodate render engines which use tags to mark 
              "their" camera types.
            * This script has been written for R23, i.e., relies on Python 3 syntax.
            * This is not by any means production ready code, but rather a code 
              example. The script for example does not handle preventing overwriting
              existing files, some proper batch render status feedback, etc.
        """
        
        import c4d
        import os
        import time
        
        # The node types which we consider to be a camera.
        CAMERA_TYPES = (c4d.Ocamera,)
        
        def get_scene_cameras(doc):
            """Returns all relevant camera objects in the passed document.
            
            Args:
                doc (c4d.documents.BaseDocument): The document to get the camera 
                 objects for.
            
            Returns:
                list[c4d.BaseObject]: The retrieved camera objects. Can be an empty 
                 list.
            
            Raises:
                RuntimeError: When the document does not contain any objects.
            """
            def iter_scene_graph(node):
                """An iterator which yields nodes in the scene graph.
                """
                while node:
                    yield node
                    for child in iter_scene_graph(node.GetDown()):
                        yield child
                    node = node.GetNext()
        
            # Get the first object and raise if there is none.
            first_object = doc.GetFirstObject()
            if not isinstance(first_object, c4d.BaseObject):
                raise RuntimeError("Could not find any objects.")
        
            # Return all nodes which are of type CAMERA_TYPES
            return [node for node in iter_scene_graph(first_object) 
                    if node.GetType() in CAMERA_TYPES]
        
        def save_camera_variations(doc, cameras):
            """Saves a variant of `doc` for each camera in `cameras`.
            
            Args:
                doc (c4d.documents.BaseDocument): The document to save the variations
                 for.
                cameras (list[c4d.BaseObject]): The list of nodes in `doc` to use as 
                 cameras.
            
            Returns:
                list[str]: The file paths of the generated variations.
            
            Raises:
                IOError: When a file could not be written.
                RuntimeError: When `doc` has no file path, i.e. is an unsaved file.
            """
            # Raise when the master document has not been saved yet.
            if doc.GetDocumentPath() in (None, ""):
                raise RuntimeError("Cannot be run on unsaved documents.")
        
            # The render BaseDraw, the initial render camera and render data.
            bd = doc.GetRenderBaseDraw()
            initial_camera = bd.GetSceneCamera(doc)
            rd = doc.GetActiveRenderData()
            # The render path and the document name.
            render_path = rd[c4d.RDATA_PATH]
            render_path, render_ext = os.path.splitext(render_path)
            document_name = os.path.splitext(doc.GetDocumentName())[0]
        
            # Go over all cameras and store a document for each of them.
            document_paths = []
            cameras = sorted(cameras, key=lambda cam: cam.GetName())
            SaveDocument = c4d.documents.SaveDocument
            for i, camera in enumerate(cameras):
                # Set the next camera as the render camera and modify the render data
                # to set a new render path.
                bd.SetSceneCamera(camera)
                rd[c4d.RDATA_PATH] = f"{render_path}_{i}{render_ext}"
                print (rd[c4d.RDATA_PATH])
                doc.SetActiveRenderData(rd)
                c4d.EventAdd()
                # Save the file and store the save path.
                path = os.path.join(doc.GetDocumentPath(),
                                    f"{document_name}_{i}.c4d")
                result = SaveDocument(doc=doc, name=path, 
                                      saveflags=c4d.SAVEDOCUMENTFLAGS_NONE, 
                                      format=c4d.FORMAT_C4DEXPORT)
                if result is False:
                    raise IOError(f"Could not write file to: {path}")
                print (f"Saved camera variation to: {path}")
                document_paths.append(path)
        
            # Set the render path of the document back to its initial value and set
            # the camera back.
            rd[c4d.RDATA_PATH] = f"{render_path}{render_ext}"
            doc.SetActiveRenderData(rd)
            bd.SetSceneCamera(initial_camera)
            c4d.EventAdd()
            return document_paths
        
        
        def run_batch_jobs(paths):
            """Runs a batch renderer job with the `paths` generated by the rest of the
            script.
            
            Args:
                paths (list[str]): The file paths for the Cinema 4D documents to 
                 render.
            
            Raises:
                IOError: When a file path in `paths` is not accessible.
            """
            batch = c4d.documents.GetBatchRender()
        
            # Populate the batch renderer.
            for i, path in enumerate(paths):
                if not os.path.exists(path):
                    raise IOError(f"Could not access path: {path}")
                batch.AddFile(path, i)
                print (f"Added job for: {path}.")
        
            # Run the renders.
            batch.SetRendering(c4d.BR_START)
        
            
        def main():
            """Entry point.
            """
            # Get all cameras.
            cameras = get_scene_cameras(doc)
            # Generate new documents for each camera.
            paths = save_camera_variations(doc, cameras)
            # Render these new documents.
            run_batch_jobs(paths)
        
        
        if __name__ == "__main__":
            main()
        

        MAXON SDK Specialist
        developers.maxon.net

        B 1 Reply Last reply Reply Quote 1
        • B
          beezle
          last edited by beezle

          This post is deleted!
          1 Reply Last reply Reply Quote 0
          • B
            beezle @ferdinand
            last edited by beezle

            @zipit
            A couple issues:
            This works on your file, but not on my own files. On my files, It simply repeats the same camera for as many cameras are in the project, which is the behavior I was getting with my script. Unfortunately, I'm new to C4D - is there something unique about how you've set up these cameras that allow the script to work?

            The other issue is I see that the way it works is to create a new file for every camera in the original file. We could have hundreds of cameras per file, and we have lots of these files. Creating a new file for every camera isn't really sustainable for us. Is there another way to do this?

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

              Hi @beezle,

              This works on your file, but not on my own files. On my files, It simply repeats the same camera for as many cameras are in the project, which is the behavior I was getting with my script [...]

              That is rather hard to answer without details or having a look at your file. There is not really anything special about how I did setup the cameras in the demo scene and I could not really think of a scenario out of my head which would break with this "standard scheme". Note that I did deliberately design the script as being modular, so you can print out the cameras and the file paths to see where something is going wrong. You can also look into the saved files or the render queue to see if they have different cameras activated as they are supposed to have. You can send files you do not want to post publicly to sdk_support(at)maxon.net.

              The other issue is I see that the way it works is to create a new file for every camera in the original file [...]

              I simply did mimic what you stated in your original posting (using the render queue, a.k.a. BatchRender, and saving files). BatchRender does not allow you to load in a BaseDocument (i.e. something that could reside in volatile memory only) in its public C++ and Python interface, you have to use a file on disk, as there is only BatchRender.AddFile. Also the camera switching functionality of the dialog is not exposed in the public interfaces. You could use c4d.modules.net, i.e. Cinema's full blown distributed render client, which will also allow you load files from memory via NetRenderService.InitRendering. But I somehow doubt, that doing it all in RAM would be beneficial/possible, when already disk space is a problem for you.

              You could of course also just constantly overwrite the same file, then launch a render for each change.

              Cheers,
              zipit

              MAXON SDK Specialist
              developers.maxon.net

              B 1 Reply Last reply Reply Quote 0
              • B
                beezle @ferdinand
                last edited by

                @zipit Damn. I'm testing your script against your file and mine, and when I bring your cameras into my file, I get the repeated camera behavior bug again. There's some difference between the files that's causing the incorrect behavior. My file has a lot of large assets in it - could it be a memory issue? I can send the files to the address you specified. I'm having someone email that address with an NDA. Thanks!

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

                  Hi @beezle,

                  unfortunately, we cannot sign any NDAs for sent in files. We merely do offer the option to reach out to us with more sensitive information in a more private manner. I am sorry if I somehow led you to believe otherwise.

                  However, I just spotted something which might be have been your issue for you, could please try the adjusted code below? Otherwise I would mostly suspect you more having a write permission error than actually something being wrong with render queue. Which is not out of the question, but would be my last guess. I would suggest carefully looking for any console error messages while the script is running. Also check if the render path of the document itself is valid, as otherwise BatchRender will fail.

                  Cheers,
                  Ferdinand

                  """Demonstrates how to create batch render jobs for multiple cameras in a
                  scene file as discussed in:
                  
                      https://developers.maxon.net/forum/topic/13059
                  
                  Note:
                      * This script is designed for Cinema's native camera objects, to include
                        other camera types, either modify CAMERA_TYPES or adopt
                        get_scene_cameras to accommodate render engines which use tags to mark
                        "their" camera types.
                      * This script has been written for R23, i.e., relies on Python 3 syntax.
                      * This is not by any means production ready code, but rather a code
                        example. The script for example does not handle preventing overwriting
                        existing files, some proper batch render status feedback, etc.
                  """
                  
                  import c4d
                  import os
                  import time
                  
                  # The node types which we consider to be a camera.
                  CAMERA_TYPES = (c4d.Ocamera,)
                  
                  def get_scene_cameras(doc):
                      """Returns all relevant camera objects in the passed document.
                  
                      Args:
                          doc (c4d.documents.BaseDocument): The document to get the camera
                           objects for.
                  
                      Returns:
                          list[c4d.BaseObject]: The retrieved camera objects. Can be an empty
                           list.
                  
                      Raises:
                          RuntimeError: When the document does not contain any objects.
                      """
                      def get_next(op):
                          """Returns the "next" node in a graph in a depth-first traversal.
                  
                          Args:
                              op (c4d.GeListNode): The node from which to traverse.
                              stop_node (c4d.GeListNode): A node not to exceed in the horizontal
                               hierarchical traversal.
                  
                          Returns:
                              c4d.GeListNode or None: A child or grandchild of op. Or
                               `None` when the graph has been exhausted.
                          """
                          if op is None:
                              return None
                          elif op.GetDown():
                              return op.GetDown()
                          while op.GetUp() and not op.GetNext():
                              op = op.GetUp()
                          return op.GetNext()
                  
                      # Get the first object and raise if there is none.
                      node = doc.GetFirstObject()
                      if not isinstance(node, c4d.BaseObject):
                          raise RuntimeError("Could not find any objects.")
                  
                      # Return all nodes which are of type CAMERA_TYPES
                      result = []
                      while node:
                          if node.GetType() in CAMERA_TYPES:
                              result.append(node)
                          node = get_next(node)
                      return result
                  
                  def save_camera_variations(doc, cameras):
                      """Saves a variant of `doc` for each camera in `cameras`.
                  
                      Args:
                          doc (c4d.documents.BaseDocument): The document to save the variations
                           for.
                          cameras (list[c4d.BaseObject]): The list of nodes in `doc` to use as
                           cameras.
                  
                      Returns:
                          list[str]: The file paths of the generated variations.
                  
                      Raises:
                          IOError: When a file could not be written.
                          RuntimeError: When `doc` has no file path, i.e. is an unsaved file.
                      """
                      # Raise when the master document has not been saved yet.
                      if doc.GetDocumentPath() in (None, ""):
                          raise RuntimeError("Cannot be run on unsaved documents.")
                  
                      # The render BaseDraw, the initial render camera and render data.
                      bd = doc.GetRenderBaseDraw()
                      initial_camera = bd.GetSceneCamera(doc)
                      rd = doc.GetActiveRenderData()
                      # The render path and the document name.
                      render_path = rd[c4d.RDATA_PATH]
                      render_path, render_ext = os.path.splitext(render_path)
                      document_name = os.path.splitext(doc.GetDocumentName())[0]
                  
                      # Go over all cameras and store a document for each of them.
                      document_paths = []
                      cameras = sorted(cameras, key=lambda cam: cam.GetName())
                      SaveDocument = c4d.documents.SaveDocument
                      for i, camera in enumerate(cameras):
                          # Set the next camera as the render camera and modify the render data
                          # to set a new render path.
                          bd.SetSceneCamera(camera)
                          rd[c4d.RDATA_PATH] = f"{render_path}_{i}{render_ext}"
                          print (rd[c4d.RDATA_PATH])
                          doc.SetActiveRenderData(rd)
                          c4d.EventAdd()
                          # Save the file and store the save path.
                          path = os.path.join(doc.GetDocumentPath(),
                                              f"{document_name}_{i}.c4d")
                          result = SaveDocument(doc=doc, name=path,
                                                saveflags=c4d.SAVEDOCUMENTFLAGS_NONE,
                                                format=c4d.FORMAT_C4DEXPORT)
                          if result is False:
                              raise IOError(f"Could not write file to: {path}")
                          print (f"Saved camera variation to: {path}")
                          document_paths.append(path)
                  
                      # Set the render path of the document back to its initial value and set
                      # the camera back.
                      rd[c4d.RDATA_PATH] = f"{render_path}{render_ext}"
                      doc.SetActiveRenderData(rd)
                      bd.SetSceneCamera(initial_camera)
                      c4d.EventAdd()
                      return document_paths
                  
                  
                  def run_batch_jobs(paths):
                      """Runs a batch renderer job with the `paths` generated by the rest of the
                      script.
                  
                      Args:
                          paths (list[str]): The file paths for the Cinema 4D documents to
                           render.
                  
                      Raises:
                          IOError: When a file path in `paths` is not accessible.
                      """
                      batch = c4d.documents.GetBatchRender()
                  
                      # Populate the batch renderer.
                      for i, path in enumerate(paths):
                          if not os.path.exists(path):
                              raise IOError(f"Could not access path: {path}")
                          batch.AddFile(path, i)
                          print (f"Added job for: {path}.")
                  
                      # Run the renders.
                      batch.SetRendering(c4d.BR_START)
                  
                  
                  def main():
                      """Entry point.
                      """
                      # Get all cameras.
                      cameras = get_scene_cameras(doc)
                      # Generate new documents for each camera.
                      paths = save_camera_variations(doc, cameras)
                      # Render these new documents.
                      run_batch_jobs(paths)
                  
                  
                  if __name__ == "__main__":
                      main()
                  

                  MAXON SDK Specialist
                  developers.maxon.net

                  B 1 Reply Last reply Reply Quote 0
                  • B
                    beezle @ferdinand
                    last edited by ferdinand

                    @zipit said in Adding multiple cameras from a single file to the render queue:

                    """Demonstrates how to create batch render jobs for multiple cameras in a
                    scene file as discussed in:
                    
                        https://developers.maxon.net/forum/topic/13059
                    
                    Note:
                        * This script is designed for Cinema's native camera objects, to include
                          other camera types, either modify CAMERA_TYPES or adopt
                          get_scene_cameras to accommodate render engines which use tags to mark
                          "their" camera types.
                        * This script has been written for R23, i.e., relies on Python 3 syntax.
                        * This is not by any means production ready code, but rather a code
                          example. The script for example does not handle preventing overwriting
                          existing files, some proper batch render status feedback, etc.
                    """
                    
                    import c4d
                    import os
                    import time
                    
                    # The node types which we consider to be a camera.
                    CAMERA_TYPES = (c4d.Ocamera,)
                    
                    def get_scene_cameras(doc):
                        """Returns all relevant camera objects in the passed document.
                    
                        Args:
                            doc (c4d.documents.BaseDocument): The document to get the camera
                             objects for.
                    
                        Returns:
                            list[c4d.BaseObject]: The retrieved camera objects. Can be an empty
                             list.
                    
                        Raises:
                            RuntimeError: When the document does not contain any objects.
                        """
                        def get_next(op):
                            """Returns the "next" node in a graph in a depth-first traversal.
                    
                            Args:
                                op (c4d.GeListNode): The node from which to traverse.
                                stop_node (c4d.GeListNode): A node not to exceed in the horizontal
                                 hierarchical traversal.
                    
                            Returns:
                                c4d.GeListNode or None: A child or grandchild of op. Or
                                 `None` when the graph has been exhausted.
                            """
                            if op is None:
                                return None
                            elif op.GetDown():
                                return op.GetDown()
                            while op.GetUp() and not op.GetNext():
                                op = op.GetUp()
                            return op.GetNext()
                    
                        # Get the first object and raise if there is none.
                        node = doc.GetFirstObject()
                        if not isinstance(node, c4d.BaseObject):
                            raise RuntimeError("Could not find any objects.")
                    
                        # Return all nodes which are of type CAMERA_TYPES
                        result = []
                        while node:
                            if node.GetType() in CAMERA_TYPES:
                                result.append(node)
                            node = get_next(node)
                        return result
                    
                    def save_camera_variations(doc, cameras):
                        """Saves a variant of `doc` for each camera in `cameras`.
                    
                        Args:
                            doc (c4d.documents.BaseDocument): The document to save the variations
                             for.
                            cameras (list[c4d.BaseObject]): The list of nodes in `doc` to use as
                             cameras.
                    
                        Returns:
                            list[str]: The file paths of the generated variations.
                    
                        Raises:
                            IOError: When a file could not be written.
                            RuntimeError: When `doc` has no file path, i.e. is an unsaved file.
                        """
                        # Raise when the master document has not been saved yet.
                        if doc.GetDocumentPath() in (None, ""):
                            raise RuntimeError("Cannot be run on unsaved documents.")
                    
                        # The render BaseDraw, the initial render camera and render data.
                        bd = doc.GetRenderBaseDraw()
                        initial_camera = bd.GetSceneCamera(doc)
                        rd = doc.GetActiveRenderData()
                        # The render path and the document name.
                        render_path = rd[c4d.RDATA_PATH]
                        render_path, render_ext = os.path.splitext(render_path)
                        document_name = os.path.splitext(doc.GetDocumentName())[0]
                    
                        # Go over all cameras and store a document for each of them.
                        document_paths = []
                        cameras = sorted(cameras, key=lambda cam: cam.GetName())
                        SaveDocument = c4d.documents.SaveDocument
                        for i, camera in enumerate(cameras):
                            # Set the next camera as the render camera and modify the render data
                            # to set a new render path.
                            bd.SetSceneCamera(camera)
                            rd[c4d.RDATA_PATH] = f"{render_path}_{i}{render_ext}"
                            print (rd[c4d.RDATA_PATH])
                            doc.SetActiveRenderData(rd)
                            c4d.EventAdd()
                            # Save the file and store the save path.
                            path = os.path.join(doc.GetDocumentPath(),
                                                f"{document_name}_{i}.c4d")
                            result = SaveDocument(doc=doc, name=path,
                                                  saveflags=c4d.SAVEDOCUMENTFLAGS_NONE,
                                                  format=c4d.FORMAT_C4DEXPORT)
                            if result is False:
                                raise IOError(f"Could not write file to: {path}")
                            print (f"Saved camera variation to: {path}")
                            document_paths.append(path)
                    
                        # Set the render path of the document back to its initial value and set
                        # the camera back.
                        rd[c4d.RDATA_PATH] = f"{render_path}{render_ext}"
                        doc.SetActiveRenderData(rd)
                        bd.SetSceneCamera(initial_camera)
                        c4d.EventAdd()
                        return document_paths
                    
                    
                    def run_batch_jobs(paths):
                        """Runs a batch renderer job with the `paths` generated by the rest of the
                        script.
                    
                        Args:
                            paths (list[str]): The file paths for the Cinema 4D documents to
                             render.
                    
                        Raises:
                            IOError: When a file path in `paths` is not accessible.
                        """
                        batch = c4d.documents.GetBatchRender()
                    
                        # Populate the batch renderer.
                        for i, path in enumerate(paths):
                            if not os.path.exists(path):
                                raise IOError(f"Could not access path: {path}")
                            batch.AddFile(path, i)
                            print (f"Added job for: {path}.")
                    
                        # Run the renders.
                        batch.SetRendering(c4d.BR_START)
                    
                    
                    def main():
                        """Entry point.
                        """
                        # Get all cameras.
                        cameras = get_scene_cameras(doc)
                        # Generate new documents for each camera.
                        paths = save_camera_variations(doc, cameras)
                        # Render these new documents.
                        run_batch_jobs(paths)
                    
                    
                    if __name__ == "__main__":
                        main()
                    

                    Oh my god, I figured it out. Both of our scripts were working sporadically, but it wasn't a script issue. Neither was my file, since it now works on my file as well. Apparently, if I have an active camera set before I run the script, instead of updating the active camera each iteration, it makes copies of the camera that was active before the script was run. If I create a new camera, set it to be the active camera, and then delete it before running the script (or in script, set the active camera to None), both our scripts work. Holy crap this was driving me crazy.

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

                      Hi @beezle,

                      Apparently, if I have an active camera set before I run the script, instead of updating the active camera each iteration, it makes copies of the camera that was active before the script was run.

                      That cannot be at least the sole explanation for your problems, because for once I cannot really see a technical explanation for such behavior and I also just tested it on my machine here and my script does not have any problems with dealing with a scene file where the active camera is the editor camera, i.e. has "no active camera".

                      But as long as it does work for you 😉

                      Cheers,
                      Ferdinand

                      MAXON SDK Specialist
                      developers.maxon.net

                      B 1 Reply Last reply Reply Quote 0
                      • B
                        beezle @ferdinand
                        last edited by

                        @zipit Yeah, you're right. It's flaking out on me again. I'll keep messing with it. Thanks.

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

                          Hi @beezle,

                          as said before, please approach the problem systematically, or otherwise we won't be able to help you:

                          1. What are the console error messages in such faulty scenes?
                          2. What is the error status of the render queue manager after you ran the script?
                          3. Are there any noticeable problems when you do print out the camera objects and document paths my script does generate?
                          4. Does each saved file have a different camera selected?
                          5. Does the queue manager properly reflect these camera selection?
                          6. Do you have write access to the path where you want to render the animations to?
                          7. Do you have write access to the path where you want to save the documents to?

                          When you have crossed of all these, I would start removing systematically "features" from the scene. Starting with plugins,
                          then render data (a.k.a. settings) and finally scene objects to pin point the problem.

                          Cheers,
                          Ferdinand

                          MAXON SDK Specialist
                          developers.maxon.net

                          B 1 Reply Last reply Reply Quote 0
                          • B
                            beezle @ferdinand
                            last edited by

                            @zipit

                            1. It's not failing, so there are no error messages.
                            2. It adds one render item for every camera in the scene, but the cameras in these render items, instead of each being a different camera, are all set to whatever camera was the active camera before I ran the script.
                            3. I'm not sure what you mean by this, but other than the issues I've mentioned, I haven't noticed any other issues.
                            4. Yes. So each file is being saved with the proper camera selected, but it's not being queued that way for some reason.
                            5. No
                            6. Yes
                            7. Yes

                            The scene I'm using is the example scene you sent me. The ONLY difference between whether or not the script works is if I have an active camera set before I run the script. I've even added this line of code at the beginning of your script to try to foolproof it, but it doesn't seem to work.

                            docs.GetActiveDocument().GetActiveBaseDraw().SetSceneCamera(None)
                            

                            It seems it's behaving more stable now, and the script consistently works correctly if I make sure to unset the active camera manually before running the script, but obviously if we can get the script to work without that manual condition, all the better. I understand that it makes no sense on your end that the script working would hinge on this, but I can't think of any other difference between the times the script works and when it doesn't.

                            Are you not able to recreate this same issue on your end with your script and your document? Could it be a version issue? I'm on Windows 10, currently testing R23.110 build RB330286.

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

                              Hi @beezle,

                              yes, I am on R23.110. I did test it on Windows and I just reran successfully the script for good measure. Regarding point three in my previous posting, I meant that you should print out the camera objects and file paths the script does generate for you and check if they "add up". So when you say that the files have the correct cameras activated, but the render queue manager does not, that is rather puzzling:

                              1. Just to understand this correctly, the renders go through for you, right? You get the little green traffic light signals in the render queue, not the red ones, indicating an error?
                              2. Have your tried clearing the render queue and then adding the files manually to see if the manger still shows the wrong camera?
                              3. Since you did use my file, the render settings and the scene objects can be eliminated as possible causes, but I still would recommend removing all plugins to test if they are the reason for your problems.

                              Cheers,
                              Ferdinand

                              MAXON SDK Specialist
                              developers.maxon.net

                              B 1 Reply Last reply Reply Quote 0
                              • B
                                beezle @ferdinand
                                last edited by

                                @zipit

                                1. Yeah, the renders all go through. The "R" column is all green.
                                2. Manually adding the cameras from the original file renders the corrects cameras. So does adding the cameras from the documents your script created. But interestingly, when I opened those files, and found the right cameras selected in each one, I added them to the render queue, and it queued up the wrong camera. It wasn't until I changed the active camera to a different one, and then reselected the correct camera that it queued up the right camera when I manually added it with the Render Queue's "Add Current Project" button.
                                3. I haven't installed any plugins in this iteration of c4d.
                                1 Reply Last reply Reply Quote 0
                                • ferdinandF
                                  ferdinand
                                  last edited by

                                  Hi @beezle,

                                  I was able to reproduce your problem with the file you did sent us. The problem seems indeed to be connected to the fact if the document has a user chosen camera or just the editor camera. This behavior is most likely a bug - I am not sure though yet what conditions do make it appear and what not, as I was also now able to reproduce it with my file. I will report back when we have any further news.

                                  Cheers,
                                  Ferdinand

                                  MAXON SDK Specialist
                                  developers.maxon.net

                                  B 1 Reply Last reply Reply Quote 0
                                  • B
                                    beezle @ferdinand
                                    last edited by

                                    @zipit Thanks for looking into it!

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

                                      Hi @beezle,

                                      just as a quick update, this issue has not been forgotten, but is still under inspection.

                                      Cheers,
                                      Ferdinand

                                      MAXON SDK Specialist
                                      developers.maxon.net

                                      B 1 Reply Last reply Reply Quote 0
                                      • B
                                        beezle @ferdinand
                                        last edited by

                                        @zipit Thanks for the update

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

                                          Hi @beezle,

                                          so I heard back from the devs now and:

                                          1. This is a bug unrelated to Python, as I was able to reproduce the faulty behavior just in Cinema 4D.
                                          2. The bug has been fixed and the fix will be published with one of the next service updates of R23 (I cannot guarantee though that it will be the upcoming update).
                                          3. For now there is not much to do for you, since the bug is related to Cinema's take system and there is not much you can reasonably do to prevent it from happening.

                                          So the only thing for you to do at the moment is unfortunately to wait for the update. You could technically try use RenderDocument or the NetRenderService to basically create your own render queue, but that would be of course a lot of work and also outside of the scope of the solutions we can provide here for you; but we will be happy to answer any questions you might have when you need and immediate solution and choose to take that route of implementing your own render queue functionalities.

                                          Cheers,
                                          Ferdinand

                                          MAXON SDK Specialist
                                          developers.maxon.net

                                          B 1 Reply Last reply Reply Quote 0
                                          • B
                                            beezle @ferdinand
                                            last edited by

                                            @zipit
                                            That's quite alright. I still have the workaround of manually unsetting the active camera for now, so I don't have a problem waiting for the update. Thanks very much for looking into it.

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