Skip to content

Instantly share code, notes, and snippets.

@robertguetzkow
Last active March 27, 2024 01:25
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save robertguetzkow/8dacd4b565538d657b72efcaf0afe07e to your computer and use it in GitHub Desktop.
Save robertguetzkow/8dacd4b565538d657b72efcaf0afe07e to your computer and use it in GitHub Desktop.
Blender add-on for automatic unique output path generation based on the current timestamp
bl_info = {
"name": "Auto-Filepath",
"author": "Robert Guetzkow",
"version": (1, 0, 2),
"blender": (2, 80, 0),
"location": "Output Properties > Auto-filepath",
"description": "Automatically sets 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_pre.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_pre.remove(update_filepath)
if __name__ == "__main__":
register()
@mhe500
Copy link

mhe500 commented Oct 16, 2022

Thank you for sharing this. It is very helpful.

I might suggest applying bpy.path.abspath before creating a Path object to handle cases using the Blender "//" convention.

@robertguetzkow
Copy link
Author

@mhe500 I've updated the script.

@mhe500
Copy link

mhe500 commented Oct 17, 2022

@robertguetzkow I think it also needs to be added to set_directory (I should have been clearer). Else, the addon will not allow you to save a path using the "//" notation. After installing, the first thing I did was try to set the output path to "//render/" and noticed the setting wouldn't stick because Path.is_dir returns false at L37. Thanks again.

@robertguetzkow
Copy link
Author

robertguetzkow commented Oct 17, 2022

Right, I missed that. I will take a look when I have time. Until then I've reverted it back to the original version.

@QuietNoise
Copy link

QuietNoise commented Dec 17, 2023

Here is my take on this. Rather than generating new folder for each image I just save images with timestamps in filename.
https://gist.github.com/QuietNoise/c56c5f4bf1e42238928bf2cef481cde0

@robertguetzkow
Copy link
Author

@QuietNoise I think I originally wrote this for animations, hence the separate folder. Thanks for leaving a link to the adapted version, might be useful for someone looking at the old question on Stack Exchange.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment