Monday, January 02, 2023

ChatGPT Modifies a Python Script for a Blender Add-On to Remove Unintended Consequences

 https://github.com/blaisefaint/blender_render_cameras_ver0

Revising a Python Script to create an add-on for Blender 3.4.1: Yesterday, you revised a Python script to create an add-on for Blender 3.4.1 to render multiple cameras. Here is the code:

bl_info = {
    "name": "Render Cameras ver 1",
    "blender": (3, 4, 1),
    "category": "Render",
}

import bpy

class RenderCamerasOperator(bpy.types.Operator):
    """Renders the animation for each camera in the scene"""
    bl_idname = "render.render_cameras"
    bl_label = "Render Cameras"

    def execute(self, context):
        # Get the current settings
        frame_start = bpy.context.scene.frame_start
        frame_end = bpy.context.scene.frame_end
        file_format = bpy.context.scene.render.image_settings.file_format
        encoding_container = bpy.context.scene.render.ffmpeg.format
        video_codec = bpy.context.scene.render.ffmpeg.codec
        color_depth = bpy.context.scene.render.image_settings.color_mode
        output_dir = bpy.context.scene.render.filepath

        # Get the file name
        file_name = bpy.path.basename(bpy.context.blend_data.filepath)
               
        # Find the first object with an action
        first_object = None
        for obj in bpy.data.objects:
            if obj.animation_data is not None and obj.animation_data.action is not None:
                first_object = obj
                break  # No need to keep searching, so we can exit the loop

        # Get the action name
        action_name = first_object.animation_data.action.name if first_object else ""
 
        # Save the first camera to use later
        first_camera = None

        # Render each camera in the scene
        for camera_obj in bpy.data.objects:
            if camera_obj.type == 'CAMERA':
                # Save the first camera
                if first_camera is None:
                    first_camera = camera_obj
                # Set the active camera
                bpy.context.scene.camera = camera_obj
                # Set the output file name
                bpy.context.scene.render.filepath = f"{output_dir}{action_name} {file_name} {camera_obj.name} "
                # Set the frame range
                bpy.context.scene.frame_start = frame_start
                bpy.context.scene.frame_end = frame_end
                # Set the other rendering options
                bpy.context.scene.render.image_settings.file_format = file_format
                bpy.context.scene.render.ffmpeg.format = encoding_container
                bpy.context.scene.render.ffmpeg.codec = video_codec
                bpy.context.scene.render.image_settings.color_mode = color_depth
                # Render the scene and save the output
                bpy.ops.render.render(animation=True, write_still=True)

        # Set the active camera to the first camera
        bpy.context.scene.camera = first_camera

        return {'FINISHED'}

class RenderCamerasPanel(bpy.types.Panel):
    """Creates a panel with a button to render the animation for each camera in the scene"""
    bl_label = "Render Cameras"
    bl_idname = "RENDER_PT_render_cameras"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "render"

    def draw(self, context):
        layout = self.layout
        layout.operator(RenderCamerasOperator.bl_idname)

def register():
    bpy.utils.register_class(RenderCamerasOperator)
    bpy.utils.register_class(RenderCamerasPanel)
    bpy.types.RENDER_PT_output.append(RenderCamerasPanel)

def unregister():
    bpy.types.RENDER_PT_render.remove(RenderCamerasPanel)
    bpy.utils.unregister_class(RenderCamerasPanel)
    bpy.utils.unregister_class(RenderCamerasOperator)

if __name__ == "__main__":
    register()
To use this script as an add-on in Blender 3.4.1, you will need to save it in a file with a .py extension and then install it as an add-on in Blender.

To install the add-on in Blender, follow these steps:

Open Blender.
Go to Edit > Preferences.
In the Preferences window, go to the Add-ons tab.
Click the Install... button.
In the file browser, navigate to the location where you saved the script and select it.
Click the Install Add-on from File... button.
The add-on should now be installed. You can check if it was installed correctly by going to the Add-ons tab in the Preferences window and searching for "Render Cameras" in the search box.
To use the add-on, go to the Render tab in the Properties window and look for the "Render Cameras" panel. Click the "Render Cameras" button to render the animation for each camera in the scene.




 
Thank you. I have already installed the add-on. Unfortunately, it has an unintended consequence. It modifies the Output Path to include the name of the file, so that if I run it twice, the output has  information from the previous output. To avoid this, please add a block of code near the end after the output has been generated to remove the file information from the Output path, leaving the directory information as it was at the start.
You can modify the script to reset the output file path after the rendering is finished. Here is how you can do that:

Copy code
    # Reset the output file path
    bpy.context.scene.render.filepath = output_dir
You can add this line of code after the for loop that iterates over the cameras and renders the scene. This will reset the output file path to the original value that was saved at the beginning of the script.

Here is the modified script:

Copy code
bl_info = {
    "name": "Render Cameras ver 1",
    "blender": (3, 4, 1),
    "category": "Render",
}

import bpy

class RenderCamerasOperator(bpy.types.Operator):
    """Renders the animation for each camera in the scene"""
    bl_idname = "render.render_cameras"
    bl_label = "Render Cameras"

    def execute(self, context):
        # Get the current settings
        frame_start = bpy.context.scene.frame_start
        frame_end = bpy.context.scene.frame_end
        file_format = bpy.context.scene.render.image_settings.file_format
        encoding_container = bpy.context.scene.render.ffmpeg.format
        video_codec = bpy.context.scene.render.ffmpeg.codec
        color_depth = bpy.context.scene.render.image_settings.color_mode
        output_dir = bpy.context.scene.render.filepath

        # Get the file name
        file_name = bpy.path.basename(bpy.context.blend_data.filepath)
               
        # Find the first object with an action
        first_object = None
        for obj in bpy.data.objects:
            if obj.animation_data is not None and obj.animation_data.action is not None:
                first_object = obj
                break  # No need to keep searching, so we can exit the loop

        # Get the action name
        action_name = first_object.animation_data.action.name if first_object else ""
 
        # Save the first camera to use later
        first_camera = None

        # Render each camera in the scene
        for camera_obj in bpy.data.objects:
            if camera_obj.type == 'CAMERA':
                # Save the first camera
                if first_camera is None:
                    first_camera = camera_obj
                # Set the active camera
                bpy.context.scene.camera = camera_obj
                # Set the output file name
                bpy.context.scene.render.filepath = f"{output_dir}{action_name} {file_name} {camera_obj.name} "
                # Set the frame range
                bpy.context.scene.frame_start = frame_start
                bpy.context.scene.frame_end = frame_end
                # Set the other rendering options
                bpy.context.scene.render.image_settings.file_format = file_format
                bpy.context.scene.render.ffmpeg.format = encoding_container
                bpy.context.scene.render.ffmpeg.codec



 
Unfortunately, your response was truncated. Please continue after "                bpy.context.scene.render.ffmpeg.codec":
I apologize for the truncation. Here is the rest of the script:

Copy code
                = video_codec
                bpy.context.scene.render.image_settings.color_mode = color_depth
                # Render the scene and save the output
                bpy.ops.render.render(animation=True, write_still=True)

        # Set the active camera to the first camera
        bpy.context.scene.camera = first_camera

        # Reset the output file path
        bpy.context.scene.render.filepath = output_dir

        return {'FINISHED'}

class RenderCamerasPanel(bpy.types.Panel):
    """Creates a panel with a button to render the animation for each camera in the scene"""
    bl_label = "Render Cameras"
    bl_idname = "RENDER_PT_render_cameras"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "render"

    def draw(self, context):
        layout = self.layout
        layout.operator(RenderCamerasOperator.bl_idname)

def register():
    bpy.utils.register_class(RenderCamerasOperator)
    bpy.utils.register_class(RenderCamerasPanel)
    bpy.types.RENDER_PT_output.append(RenderCamerasPanel)

def unregister():
    bpy.types.RENDER_PT_render.remove(RenderCamerasPanel)
    bpy.utils.unregister_class(RenderCamerasPanel)
    bpy.utils.unregister_class(RenderCamerasOperator)
This modified script should reset the output file path after the rendering is finished, so that the output path is not modified when the add-on is run multiple times.

 
This works as expected. Thank you.

You're welcome! I'm glad that I could help. If you have any other questions or need further assistance, please don't hesitate to ask.