# Render Function - rename filename

So close yet so far (I think)

A function within an addon am creating is suppose to rename the file ouput using tokens. This is based on the Oscurart tools.

The projects consists of markers on every frame with different binded cameras. The rendered image name needs to consist of a Marker and Camera.

def replaceMarker (dummy):
global renderpath
#Set Tokens variables
cameraCURRENT = bpy.context.scene.camera.name
markerTIMELINE = []
for marker in bpy.context.scene.timeline_markers:
name = marker.name
markerTIMELINE.extend([name])
markerCURRENT = markerTIMELINE[bpy.context.scene.frame_current-1]

tokens = {
"$$Marker":markerCURRENT, "$$Camera":cameraCURRENT
}
#Replace filename output
renderpath = bpy.context.scene.render.filepath

bpy.context.scene.render.filepath = renderpath.replace("$$Marker",tokens["$$Marker"]).replace("$$Camera",tokens["$$Camera"])
print(bpy.context.scene.render.filepath)
#Clear list to repeat sequence
markerTIMELINE.clear()


The function does not replace the marker and only uses one camera name.

Am I suppose to more this to the init.py? How can I call the function between every frame?

Thanks

EDIT Question to circumvent the issue, it is possible to access the Metadata in fileoutput and use it to rename the file?

• Have you checked that the file path actually contains the markers? If it doesn't, then it can't replace them. Dec 3 '19 at 11:59
• Yes, I can using a dummy file to test the addon. The output is set to /tmp\AAA - $Marker -$Camera Dec 3 '19 at 12:11
• I think we are missing some context information in how this function is used that would explain the problem. Dec 3 '19 at 12:43
• Basically, I am creating a proof of concept to develop an addon which will integrate Blender in the Company's future 3D pipeline. All functions are outside the init.py file, called upon with the import function. As I progress, I can keep adding functions and tools to assist none 3D personal. The file output rename function is in its own file. Dec 3 '19 at 13:18
• I would very much like to see a solution for this. My current project has several cameras bound to the timeline, and I want my output frames named according to the cameras they were rendered from. Apr 29 '20 at 3:53

So sorry for the very late reply. I found the answer in another thread and with some help.

But below is the Render Function I am currently using.

    bl_idname = "render.colorways"
bl_label = "Render list"
bl_description = "Render colorways with marker in filename"

# Define some variables to register
_timer = None
shots = None
stop = None
rendering = None
path = "/tmp/"

# Set up the handler methods
def pre(self, scene, depsgraph):
self.rendering = True

def post(self, scene, depsgraph):
self.rendering = False

def cancelled(self, scene, depsgraph):
self.stop = True

def execute(self, context):
# Define the variables during execution. This allows
# to define when called from a button
self.stop = False
self.rendering = False

# Get all markers in a list and assign them to shots variable
itemmarkers = bpy.context.scene.timeline_markers.items()
self.shots = []
self.shots.clear
for m in itemmarkers:
self.shots.append(m[0])

#don't know why but I need to begin 1 frame before the start
bpy.context.scene.frame_set(bpy.context.scene.frame_start - 1)

self.path = context.scene.render.filepath

bpy.app.handlers.render_pre.append(self.pre)
bpy.app.handlers.render_post.append(self.post)
bpy.app.handlers.render_cancel.append(self.cancelled)

# The timer gets created and the modal handler
# is added to the window manager

return {"RUNNING_MODAL"}

def modal(self, context, event):
if event.type == 'TIMER':
scn = context.scene

# filename prefix ans suffix
firstpart = bpy.context.scene.TextInputProps.nameprefix
lastpart = bpy.context.scene.TextInputProps.namesuffix

# No frames in the list or user hits ESC
if True in (scn.frame_current >= scn.frame_end, self.stop is True):

# We remove the handlers and the modal timer to clean everything
bpy.app.handlers.render_pre.remove(self.pre)
bpy.app.handlers.render_post.remove(self.post)
bpy.app.handlers.render_cancel.remove(self.cancelled)
context.window_manager.event_timer_remove(self._timer)

# Reset the output path
scn.render.filepath = self.path
return {"FINISHED"}

elif self.rendering is False: # Nothing is currently rendering.
# Proceed to render.
# Get the marker from the list
marker_name  = self.shots[scn.frame_current]

#Create filename variable
if firstpart == "" and lastpart == "":
finalfilename = marker_name
elif firstpart == "" and lastpart != "":
finalfilename = marker_name +"_"+ lastpart
elif firstpart != "" and lastpart == "":
finalfilename = firstpart +"_"+ marker_name
else:
finalfilename = firstpart +"_"+ marker_name +"_"+ lastpart

# Assemble the file path and filename
scn.render.filepath = os.path.join(self.path, finalfilename + "." + scn.render.image_settings.file_format)

# Call the render operator
bpy.ops.render.render("INVOKE_DEFAULT", write_still=True)

# Set the next frame
scn.frame_set(scn.frame_current + 1)

return {"PASS_THROUGH"}


There is one issue, in the render process certain frames don't save. Perhaps optimizing the loop the statement in the def modal would help.

I hope this helps.