2
$\begingroup$

is there a way to automate render file names and avoid accidental overwrites?

E.G. add timestamp to filename?

I find my workflow involves many fast test renders, and it drives me nuts that for each time I launch F12 if I have not renamed previous render and overwrite is enabled I lose it, if overwrite is not enabled it does not save the file automatically.

I am using the compositor file output node to at least automate file saving for images

I do not understand why there is no simple way to press F12 and have a file with a unique name (eg. timestamp added at end) be saved automatically as soon as the render is complete, it seems ridiculous that you can wait maybe hours for a render to be done and risk losing it entirely because it is accidentally overwritten or you forget that you have not saved it.

After a day passed fruitlessly googling and reading forums I humbly ask for help here!

$\endgroup$
1
4
$\begingroup$

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, 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()

The add-on can also be downloaded from GitHub Gist.

$\endgroup$
8
  • $\begingroup$ Wow this is almost exactly what I need, thank you so much! If I may ask, is there a way to adapt the code so the renaming occurs just to the file name itself rather than creating a sub-folder for each render? In any case thank you so much for your help, this is already a big problem solved! $\endgroup$ Mar 22 '20 at 21:39
  • $\begingroup$ Yes, that's possible. How should the names be formatted? It would still be necessary to have unique names among multiple file output nodes. Should the node name be included in the filename? $\endgroup$
    – Robert Gützkow
    Mar 22 '20 at 21:55
  • $\begingroup$ Ideally I would like the file naming to work in this way: render image: filename is timestamp, file is in output folder. render animation: filename is timestamp + #### framenumber, in output folder or subfolder, it makes little difference. I currently only ever use one output node, and name does not need to be included, as compositing or separate render layers are not a big part of my workflow. Thanks! $\endgroup$ Mar 23 '20 at 7:53
  • 1
    $\begingroup$ @ddd That look like an error to me, but it's currently 3am. Let me take another look tomorrow. $\endgroup$
    – Robert Gützkow
    Oct 8 '20 at 0:42
  • 1
    $\begingroup$ @ddd Yes, that was an error. It's fixed now. $\endgroup$
    – Robert Gützkow
    Oct 8 '20 at 9:27
1
$\begingroup$

Press F2 and click "+" next to the file name input field. This indexes .blend files. The same goes for rendered images (F3). To my knowledge your problem involves scripting or code alteration as this is not yet automatic by default.

$\endgroup$
1
  • $\begingroup$ FYI, you can also use Numpad+, Shift Numpad+ and Ctrl Numpad+. $\endgroup$
    – lemon
    Mar 22 '20 at 6:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.