Skip to content

Commit

Permalink
Merge pull request #82 from p2or/sequencer
Browse files Browse the repository at this point in the history
Basic sequencer support
  • Loading branch information
p2or authored Mar 20, 2024
2 parents ae1eef1 + 718c4ce commit d6983fa
Showing 1 changed file with 115 additions and 22 deletions.
137 changes: 115 additions & 22 deletions loom.py
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,22 @@ def poll(cls, context):
def check(self, context):
return True

def validate_comp(self, context):
if context.scene.use_nodes:
for n in context.scene.node_tree.nodes:
if n.type == 'R_LAYERS' and not n.scene.camera:
if not n.mute:
return n.scene.name
return None

def validate_sequencer(self, context):
seq = context.scene.sequence_editor
for i in seq.sequences_all:
if i.type == 'SCENE' and not i.mute:
if not seq.channels[i.channel].mute:
return True
return False

def write_permission(self, folder): # Hacky, but ok for now
# https://stackoverflow.com/q/2113427/3091066
try: # os.access(os.path.realpath(bpy.path.abspath(out_folder)), os.W_OK)
Expand All @@ -1191,28 +1207,45 @@ def execute(self, context):

""" Error handling """
user_error = False

if not self.options.is_invoke:
user_error = True

if not bpy.data.is_saved:
self.report({'ERROR'}, "Blend-file not saved.")
bpy.ops.wm.save_as_mainfile('INVOKE_DEFAULT')
user_error = True

if not scn.camera:
self.report({'WARNING'}, "No camera in scene.")
user_error = True
if scn.use_nodes:
user_error = False

if not user_input and not any(char.isdigit() for char in user_input):
self.report({'ERROR'}, "No frames to render.")
user_error = True


""" Scene validation """
if len(scn.sequence_editor.sequences):
if self.validate_sequencer(context):
if not user_input.isdigit():
self.report(
{'INFO'},
"Scene Strip(s) in 'Sequencer' detected: "
"Switched to commandline rendering...")
lum.command_line = True
else:
if scn.use_nodes:
rlyr = self.validate_comp(context)
if rlyr is not None:
self.report(
{'WARNING'},
"No camera assigned in '{}' "
"scene (used in comp).".format(rlyr))
user_error = True
else:
if not scn.camera:
self.report({'WARNING'}, "No active camera.")
user_error = True

if user_error: #bpy.ops.loom.render_dialog('INVOKE_DEFAULT')
return {"CANCELLED"}


""" Tests passed """
if not lum.override_render_settings:
lum.property_unset("custom_render_presets")

Expand All @@ -1223,12 +1256,13 @@ def execute(self, context):
frames = user_input,
threads = lum.threads,
isolate_numbers = filter_individual_numbers,
render_preset=lum.custom_render_presets)
render_preset = lum.custom_render_presets)
else:
bpy.ops.render.image_sequence(
frames = user_input,
isolate_numbers = filter_individual_numbers,
render_silent = False)
render_silent = False,
validate_scene = False)
return {"FINISHED"}

def invoke(self, context, event):
Expand All @@ -1244,7 +1278,7 @@ def invoke(self, context, event):
bpy.ops.loom.verify_terminal()
if not lum.is_property_set("threads") or not lum.threads:
lum.threads = scn.render.threads # *.5

return context.window_manager.invoke_props_dialog(self,
width=(prefs.render_dialog_width))

Expand Down Expand Up @@ -1569,7 +1603,7 @@ def draw(self, context):
layout.prop(prefs, "batch_path_col_width")
else:
layout.prop(prefs, "batch_name_col_width")
layout.operator("loom.batch_dialog_reset_display", icon="ANIM")
layout.operator(LOOM_OT_batch_dialog_reset.bl_idname, icon="ANIM")


class LOOM_UL_batch_list(bpy.types.UIList):
Expand All @@ -1583,18 +1617,27 @@ def draw_item(self, context, layout, data, item, icon, active_data, active_propn
else:
split = layout.split(factor=prefs.batch_name_col_width, align=True)
split_left = split.split(factor=0.1)
split_left.operator("loom.batch_default_frames", text="{:02d}".format(index+1), emboss=False).item_id = index
split_left.operator(
LOOM_OT_batch_default_range.bl_idname,
text="{:02d}".format(index+1),
emboss=False).item_id = index
split_left.label(text=item.name, icon='FILE_BLEND')

split_right = split.split(factor=.99)
row = split_right.row(align=True)
row.operator("loom.batch_default_frames", icon="PREVIEW_RANGE", text="").item_id = index
row.operator(
LOOM_OT_batch_default_range.bl_idname,
icon="PREVIEW_RANGE",
text="").item_id = index
row.prop(item, "frames", text="") #, icon='IMAGEFILE'
#row = split_right.row(align=True) #row.prop(item, "input_filter", text="", icon='FILTER')
row.prop(item, "input_filter", text="", icon='FILTER')

row.prop(item, "encode_flag", text="", icon='FILE_MOVIE')
row.operator("loom.batch_verify_input", text="", icon='GHOST_ENABLED').item_id = index
row.operator(
LOOM_OT_batch_verify_input.bl_idname,
text="",
icon='GHOST_ENABLED').item_id = index
row.separator()
row.operator(LOOM_OT_open_folder.bl_idname,
icon="DISK_DRIVE", text="").folder_path = os.path.dirname(item.path)
Expand Down Expand Up @@ -3681,6 +3724,11 @@ class LOOM_OT_render_image_sequence(bpy.types.Operator):
name="Render Preset",
description="Pass a custom Preset.py")

validate_scene: bpy.props.BoolProperty(
name="Scene Validation",
description="Sequencer Strips, Active Camera etc.",
default=True)

_image_formats = {'BMP': 'bmp', 'IRIS': 'iris', 'PNG': 'png', 'JPEG': 'jpg',
'JPEG2000': 'jp2', 'TARGA': 'tga', 'TARGA_RAW': 'tga', 'CINEON': 'cin',
'DPX': 'dpx', 'OPEN_EXR_MULTILAYER': 'exr', 'OPEN_EXR': 'exr', 'HDR': 'hdr',
Expand All @@ -3694,7 +3742,10 @@ class LOOM_OT_render_image_sequence(bpy.types.Operator):

@classmethod
def poll(cls, context):
return not context.scene.render.is_movie_format
if context.scene.render.is_movie_format:
cls.poll_message_set("Video file formats are not supported by Loom")
return False
return True

def pre_render(self, scene, depsgraph):
self._rendering = True
Expand All @@ -3709,7 +3760,7 @@ def post_render(self, scene, depsgraph):
self._frames.pop(0)
self._rendering = False
scene.loom.is_rendering = False

def file_extension(self, file_format):
return self._image_formats[file_format]

Expand Down Expand Up @@ -3818,6 +3869,22 @@ def start_render(self, scene, frame, silent=False):
if frame not in self._rendered_frames:
self._rendered_frames.append(frame)

def validate_comp(self, context):
if context.scene.use_nodes:
for n in context.scene.node_tree.nodes:
if n.type == 'R_LAYERS' and not n.scene.camera:
if not n.mute:
return n.scene.name
return None

def validate_sequencer(self, context):
seq = context.scene.sequence_editor
for i in seq.sequences_all:
if i.type == 'SCENE' and not i.mute:
if not seq.channels[i.channel].mute:
return True
return False

def log_sequence(self, scene, limit):
from time import ctime #lum.render_collection.clear()
lum = scene.loom
Expand Down Expand Up @@ -3852,21 +3919,47 @@ def final_report(self):
mf=i[0], sf=str(i[1]).split(".")[1]) for i in self._skipped_frames)
else:
skipped = ','.join(map(str, self._skipped_frames))
self.report({'WARNING'}, "Frame(s): {} skipped (would overwrite existing file(s))".format(skipped))

self.report(
{'WARNING'},
"Frame(s): {} skipped (would overwrite existing file(s))".format(skipped))

def execute(self, context):
scn = context.scene
prefs = context.preferences
loom_prefs = prefs.addons[__name__].preferences
glob_vars = loom_prefs.global_variable_coll

""" Filter user input """
self._frames = filter_frames(self.frames, scn.frame_step, self.isolate_numbers)

if not self._frames:
self.report({'INFO'}, "No frames to render")
return {"CANCELLED"}


""" Scene validation in case the operator is called via console """
if self.validate_scene:
if len(scn.sequence_editor.sequences):
if self.validate_sequencer(context):
if len(self._frames) > 1 and not self.render_silent:
self.report(
{'INFO'},
"Scene Strip(s) in 'Sequencer' detected: "
"Automatically switched to silent rendering...")
self.render_silent = True
else:
if scn.use_nodes:
rlyr = self.validate_comp(context)
if rlyr is not None:
self.report(
{'WARNING'},
"No camera assigned in '{}' "
"scene (used in comp).".format(rlyr))
return {"CANCELLED"}
else:
if not scn.camera:
self.report({'WARNING'}, "No camera in scene.")
return {"CANCELLED"}

if not self.render_silent:
self.report({'INFO'}, "Rendering Image Sequence...\n")

Expand Down

0 comments on commit d6983fa

Please sign in to comment.