Skip to main content
2 of 4
Fixed handler registration and default value for the directory
Robert Gützkow
  • 26k
  • 3
  • 48
  • 82

The following add-on generates a unique file path from a given directory and the current timestamp. It modifies both the output path (Output Properties > Output) and every base path of File Output nodes.

UI screenshot

For instance, if the directory (Output Properties > Auto-Filename > Directory) is set to C:\tmp\ and the current timestamp is 2020-03-22_01_10_43_857754 then the output path is C:\tmp\2020-03-22_01_10_43_857754\#### and the base path of the File Output nodes are C:\tmp\2020-03-22_01_10_43_857754\[name of the file output node].

bl_info = {
    "name": "Auto-Filepath",
    "author": "Robert Guetzkow",
    "version": (1, 0, 1),
    "blender": (2, 80, 0),
    "location": "Output Properties > Auto-filepath",
    "description": "Automatically sets the a unique filepath for each frame based on the current timestamp.",
    "warning": "",
    "wiki_url": "",
    "category": "Render"}

import bpy
import datetime
from pathlib import Path
from bpy.app.handlers import persistent


@persistent
def update_filepath(self):
    if not bpy.context.scene.auto_filepath_settings.use_auto_filepath:
        return
    now = datetime.datetime.now()
    path = Path(bpy.context.scene.auto_filepath_settings.directory)
    base_path = path / now.strftime('%Y-%m-%d_%H_%M_%S_%f')
    bpy.context.scene.render.filepath = str(base_path / "####")
    bpy.context.scene.render.use_file_extension = True
    bpy.context.scene.render.use_overwrite = False
    if bpy.context.scene.use_nodes:
        for node in bpy.context.scene.node_tree.nodes:
            if node.type == "OUTPUT_FILE":
                node.base_path = str(base_path / node.name)


def set_directory(self, value):
    path = Path(value)
    if path.is_dir():
        self["directory"] = value


def get_directory(self):
    return self.get("directory", bpy.context.scene.auto_filepath_settings.bl_rna.properties["directory"].default)


class AutoFilepathSettings(bpy.types.PropertyGroup):
    use_auto_filepath: bpy.props.BoolProperty(name="Automatic filepath generation.",
                                              description="Enable/disable automatic filepath generation. When enabled, "
                                                          "this will overwrite the output path and the base path of "
                                                          "all File Output nodes.",
                                              default=False)

    directory: bpy.props.StringProperty(name="Directory",
                                        description="Directory where files shall be stored.",
                                        default="/",
                                        maxlen=4096,
                                        subtype="DIR_PATH",
                                        set=set_directory,
                                        get=get_directory)


class AUTOFILEPATH_PT_panel(bpy.types.Panel):
    bl_label = "Auto-Filepath"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "output"
    bl_options = {"DEFAULT_CLOSED"}

    def draw_header(self, context):
        self.layout.prop(context.scene.auto_filepath_settings, "use_auto_filepath", text="")

    def draw(self, context):
        layout = self.layout
        layout.prop(context.scene.auto_filepath_settings, "directory")


classes = (AutoFilepathSettings, AUTOFILEPATH_PT_panel)


def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    bpy.types.Scene.auto_filepath_settings = bpy.props.PointerProperty(type=AutoFilepathSettings)
    if update_filepath not in bpy.app.handlers.render_pre:
        bpy.app.handlers.render_init.append(update_filepath)


def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
    del bpy.types.Scene.auto_filepath_settings
    if update_filepath in bpy.app.handlers.render_pre:
        bpy.app.handlers.render_init.remove(update_filepath)


if __name__ == "__main__":
    register()
Robert Gützkow
  • 26k
  • 3
  • 48
  • 82