First addon. Render output file path list.
render_path_list.py
bl_info = {
"name": "Render Path List",
"author": "Boolnori",
"version": (0, 0, 1),
"blender": (2, 78, 0),
"location": "Render Settings > Render Path List",
"description": "Render Path List (file path, frame start, frame end)",
"warning": "",
"wiki_url": "",
"category": "Render",
}
import bpy
from bpy.types import (
Operator,
Panel,
UIList,
PropertyGroup,
)
from bpy.props import (
StringProperty,
IntProperty,
CollectionProperty,
PointerProperty,
)
#Property
class PathListSet(bpy.types.PropertyGroup):
name = StringProperty(name = "Path Name", description="render filepath")
render_file_format = StringProperty(name = "render file format", description="render file format")
path_frame_start = IntProperty(name = "Start Number")
path_frame_end = IntProperty(name = "End Number")
class ActivePathSet(bpy.types.PropertyGroup):
active_path_idx = IntProperty(
name="Index",
description="Index of the currently active path list",
default=0
)
active_path_frame_start = IntProperty(
name="Start",
description="Start frame of the active path playback/rendering range",
default = 1
)
active_path_frame_end = IntProperty(
name="End",
description="End frame of the active path playback/rendering range",
default= 1
)
prev_path_idx = IntProperty(
name="Previous Index",
description="Index of the Previous active path list",
default=0
)
#Panel
class RenderPathList(bpy.types.UIList):
def draw_item(self, context, layout, data, set, icon, active_data, active_propname, index):
layout.prop(set, "name", text="", icon='FILE_FOLDER', emboss=False)
class RenderPathListPanel(bpy.types.Panel):
"""Creates a Panel in the Render properties window"""
bl_label = "Render Path List"
bl_idname = "Scene_Render_File_Path_list"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "render"
def draw(self, context):
scene = context.scene
apSetData = scene.actpath_set
layout = self.layout
row = layout.row()
rows=2
row.template_list("RenderPathList", "", scene, "path_list", apSetData, "active_path_idx",rows=rows)
row = layout.row()
sub = row.row(align=True)
sub.operator("render.path_add", icon='ZOOMIN', text="")
sub.operator("render.path_remove", icon='ZOOMOUT', text="")
sub.operator("render.output_filepath_set", text="Set")
sub.operator("render.play_rendered_animation", text="Play")
sub.operator("render.path_list_delete_all", icon='X', text="")
row = layout.row()
sub2 = row.row(align=True)
sub2.prop(apSetData, "active_path_frame_start", expand=True)
sub2.prop(apSetData, "active_path_frame_end", expand=True)
if scene.path_list.items() != []:
frameRagneLimit(self, context)
apSetData.prev_path_idx = apSetData.active_path_idx
else:
sub2.enabled = False
# Operators
class RENDER_OT_path_list_delete_all(Operator):
bl_idname = "render.path_list_delete_all"
bl_label = "Delete All List"
bl_description = "Deletes All Render Path List"
bl_options = {'UNDO', 'REGISTER'}
def execute(self, context):
scene = context.scene
apSetData = scene.actpath_set
scene.path_list.clear()
apSetData.active_path_idx = 0
apSetData.active_path_frame_start = 1
apSetData.active_path_frame_end = 1
apSetData.prev_path_idx = 0
return {'FINISHED'}
class RENDER_OT_path_add(Operator):
bl_idname = "render.path_add"
bl_label = "Add Render Output Filepath"
bl_description = "Current Output Filepath Add(The Same Path Overwirte)"
bl_options = {'UNDO', 'REGISTER'}
def execute(self, context):
scene = context.scene
apSetData = scene.actpath_set
curRenderFilePath = scene.render.filepath
curPathFrameStart = scene.frame_start
curPathFrameEnd = scene.frame_end
new_path = scene.path_list.add()
new_path.name = curRenderFilePath
new_path.path_frame_start = curPathFrameStart
new_path.path_frame_end = curPathFrameEnd
next_idx =len(scene.path_list.items())
apSetData.active_path_idx = next_idx - 1
apSetData.active_path_frame_start = scene.path_list[apSetData.active_path_idx].path_frame_start
apSetData.active_path_frame_end = scene.path_list[apSetData.active_path_idx].path_frame_end
return {'FINISHED'}
class RENDER_OT_path_remove(Operator):
bl_idname = "render.path_remove"
bl_label = "Delete Render Output Filepath"
bl_description = "Delete Render Output Filepath"
bl_options = {'UNDO', 'REGISTER'}
def execute(self, context):
scene = context.scene
apSetData = scene.actpath_set
scene.path_list.remove(apSetData.active_path_idx)
pathListNums = len(scene.path_list)
if scene.path_list.items()!=[]:
if apSetData.active_path_idx >= pathListNums:
apSetData.active_path_idx = apSetData.active_path_idx - 1
apSetData.active_path_frame_start = scene.path_list[apSetData.active_path_idx].path_frame_start
apSetData.active_path_frame_end = scene.path_list[apSetData.active_path_idx].path_frame_end
return {'FINISHED'}
class RENDER_OT_output_filepath_set(Operator):
bl_idname = "render.output_filepath_set"
bl_label = "Render Output Filepath Set"
bl_description = "Render Output Filepath Set"
bl_options = {'UNDO', 'REGISTER'}
def execute(self, context):
scene = context.scene
apSetData = scene.actpath_set
if scene.path_list.items()!=[]:
selPath = scene.path_list[apSetData.active_path_idx]
scene.render.filepath = selPath.name
scene.frame_start = selPath.path_frame_start
scene.frame_end = selPath.path_frame_end
else:
print("Path List Empty")
return {'FINISHED'}
class RENDER_OT_play_rendered_animation(Operator):
bl_idname = "render.play_rendered_animation"
bl_label = "Play Rendered Animation"
bl_description = "Play Rendered Animation"
bl_options = {'UNDO', 'REGISTER'}
def execute(self, context):
scene = context.scene
apSetData = scene.actpath_set
if scene.path_list.items()!=[]:
selPath = scene.path_list[apSetData.active_path_idx]
curRenderPath = scene.render.filepath
curPathFrameStart = scene.frame_start
curPathFrameEnd = scene.frame_end
scene.render.filepath = selPath.name
scene.frame_start = selPath.path_frame_start
scene.frame_end = selPath.path_frame_end
bpy.ops.render.play_rendered_anim()
scene.render.filepath = curRenderPath
scene.frame_start = curPathFrameStart
scene.frame_end = curPathFrameEnd
print("play")
else:
print("Path List Empty")
return {'FINISHED'}
def frameRagneLimit(self, context):
scene = context.scene
apSetData = scene.actpath_set
if apSetData.prev_path_idx != apSetData.active_path_idx:
apSetData.active_path_frame_start = scene.path_list[apSetData.active_path_idx].path_frame_start
apSetData.active_path_frame_end = scene.path_list[apSetData.active_path_idx].path_frame_end
else:
curpath_frame_start = scene.path_list[apSetData.active_path_idx].path_frame_start
curpath_frame_end = scene.path_list[apSetData.active_path_idx].path_frame_end
if curpath_frame_start != apSetData.active_path_frame_start:
if apSetData.active_path_frame_start < 0:
apSetData.active_path_frame_start = 0
elif apSetData.active_path_frame_start > apSetData.active_path_frame_end:
apSetData.active_path_frame_end = apSetData.active_path_frame_start
elif curpath_frame_end != apSetData.active_path_frame_end:
if apSetData.active_path_frame_end < 0:
apSetData.active_path_frame_end = 0
if apSetData.active_path_frame_end < apSetData.active_path_frame_start:
apSetData.active_path_frame_start = apSetData.active_path_frame_end
scene.path_list[apSetData.active_path_idx].path_frame_start = apSetData.active_path_frame_start
scene.path_list[apSetData.active_path_idx].path_frame_end = apSetData.active_path_frame_end
# Registry
classes = (
PathListSet,
ActivePathSet,
RenderPathList,
RenderPathListPanel,
RENDER_OT_path_list_delete_all,
RENDER_OT_path_add,
RENDER_OT_path_remove,
RENDER_OT_output_filepath_set,
RENDER_OT_play_rendered_animation,
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.Scene.path_list = CollectionProperty(
type=PathListSet,
name="Path List",
description="Render File Path List",
)
bpy.types.Scene.actpath_set = PointerProperty(
type=ActivePathSet,
name = "Active Path Info",
description="Current Selected Path infomation",
)
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)
del bpy.types.Scene.path_list
del bpy.types.Scene.actpath_set
if __name__ == "__main__":
register()
Thank you!