Render Review: Fix Import Errors #122

Merged
Nick Alberelli merged 4 commits from :fix/render-review-import-errors into main 2023-07-13 19:44:15 +02:00
Showing only changes of commit 5be5e75d39 - Show all commits

View File

@ -29,6 +29,7 @@ from collections import OrderedDict
import bpy import bpy
from render_review import vars, prefs, opsdata, util, kitsu from render_review import vars, prefs, opsdata, util, kitsu
if prefs.is_blender_kitsu_enabled(): if prefs.is_blender_kitsu_enabled():
from blender_kitsu import types as kitsu_types from blender_kitsu import types as kitsu_types
from blender_kitsu import cache from blender_kitsu import cache
@ -68,7 +69,9 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
or opsdata.is_sequence_dir(render_dir) or opsdata.is_sequence_dir(render_dir)
) )
def load_strip_from_img_seq(self, context, directory, idx: int, frame_start: int = 0): def load_strip_from_img_seq(
self, context, directory, idx: int, frame_start: int = 0
):
try: try:
# Get best preview files sequence. # Get best preview files sequence.
image_sequence = opsdata.get_best_preview_sequence(directory) image_sequence = opsdata.get_best_preview_sequence(directory)
@ -99,11 +102,11 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
# Create new image strip. # Create new image strip.
strip = context.scene.sequence_editor.sequences.new_image( strip = context.scene.sequence_editor.sequences.new_image(
name = directory.name, name=directory.name,
filepath = image_sequence[0].as_posix(), filepath=image_sequence[0].as_posix(),
channel = idx + 1, channel=idx + 1,
frame_start = frame_start, frame_start=frame_start,
fit_method = 'ORIGINAL' fit_method='ORIGINAL',
) )
# Extend strip elements with all the available frames. # Extend strip elements with all the available frames.
@ -115,7 +118,6 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
return strip return strip
def execute(self, context: bpy.types.Context) -> Set[str]: def execute(self, context: bpy.types.Context) -> Set[str]:
# Clear existing strips and markers # Clear existing strips and markers
context.scene.sequence_editor_clear() context.scene.sequence_editor_clear()
@ -124,19 +126,18 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
render_dir = Path(context.scene.rr.render_dir_path) render_dir = Path(context.scene.rr.render_dir_path)
shot_version_folders_dict = self.get_shot_folder_dict( shot_version_folders_dict = self.get_shot_folder_dict(
render_dir = render_dir, render_dir=render_dir,
max_versions_per_shot = addon_prefs.versions_max_count, max_versions_per_shot=addon_prefs.versions_max_count,
) )
prev_frame_end: int = 1 prev_frame_end: int = 1
for shot_name, shot_version_folders in shot_version_folders_dict.items(): for shot_name, shot_version_folders in shot_version_folders_dict.items():
logger.info("Loading versions of shot %s", shot_name) logger.info("Loading versions of shot %s", shot_name)
imported_strips = self.import_shot_versions_as_strips( imported_strips = self.import_shot_versions_as_strips(
context, context,
shot_version_folders, shot_version_folders,
frame_start = prev_frame_end, frame_start=prev_frame_end,
shot_name = shot_name, shot_name=shot_name,
) )
if not imported_strips: if not imported_strips:
@ -174,8 +175,7 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
render_resolution_y = vars.RESOLUTION[1] render_resolution_y = vars.RESOLUTION[1]
# If Kitsu add-on is enabled, fetch the resolution from the online project # If Kitsu add-on is enabled, fetch the resolution from the online project
if ( if (
addon_prefs.enable_blender_kitsu addon_prefs.enable_blender_kitsu and prefs.is_blender_kitsu_enabled()
and prefs.is_blender_kitsu_enabled()
) and kitsu.is_active_project(): ) and kitsu.is_active_project():
# TODO: make the resolution fetching a bit more robust # TODO: make the resolution fetching a bit more robust
# Assume resolution is a string '<str:width>x<str:height>' # Assume resolution is a string '<str:width>x<str:height>'
@ -209,12 +209,11 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
def get_shot_folder_dict( def get_shot_folder_dict(
self, self,
render_dir: str, render_dir: str,
max_versions_per_shot = 32, max_versions_per_shot=32,
) -> OrderedDict[str, List[Path]]: ) -> OrderedDict[str, List[Path]]:
shot_version_folders: List[Path] = [] shot_version_folders: List[Path] = []
# If render is sequence folder user wants to review whole sequence. # If render is sequence folder user wants to review whole sequence.
@ -248,13 +247,12 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
return sorted_dict return sorted_dict
def import_shot_versions_as_strips( def import_shot_versions_as_strips(
self, self,
context: bpy.types.Context, context: bpy.types.Context,
shot_version_folders: List[Path], shot_version_folders: List[Path],
frame_start: int, frame_start: int,
shot_name: str shot_name: str,
) -> List[bpy.types.Sequence]: ) -> List[bpy.types.Sequence]:
addon_prefs = prefs.addon_prefs_get(context) addon_prefs = prefs.addon_prefs_get(context)
imported_strips: bpy.types.Sequence = [] imported_strips: bpy.types.Sequence = []
@ -267,22 +265,22 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
for idx, shot_folder in enumerate(shot_version_folders): for idx, shot_folder in enumerate(shot_version_folders):
logger.info("Processing %s", shot_folder.name) logger.info("Processing %s", shot_folder.name)
use_video = addon_prefs.use_video and \ use_video = addon_prefs.use_video and not (
not (shot_folder != shot_version_folders[-1] and addon_prefs.use_video_latest_only) shot_folder != shot_version_folders[-1]
and addon_prefs.use_video_latest_only
)
shot_strip = self.import_shot_as_strip( shot_strip = self.import_shot_as_strip(
context, context,
frame_start = frame_start, frame_start=frame_start,
channel_idx = idx, channel_idx=idx,
shot_folder = shot_folder, shot_folder=shot_folder,
shot_name = shot_name, shot_name=shot_name,
use_video = use_video use_video=use_video,
) )
imported_strips.append(shot_strip) imported_strips.append(shot_strip)
return imported_strips return imported_strips
def import_shot_as_strip( def import_shot_as_strip(
self, self,
context: bpy.types.Context, context: bpy.types.Context,
@ -290,7 +288,7 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
channel_idx: int, channel_idx: int,
shot_folder: Path, shot_folder: Path,
shot_name: str, shot_name: str,
use_video = False, use_video=False,
) -> bpy.types.Sequence: ) -> bpy.types.Sequence:
context.scene.timeline_markers.new(shot_name, frame=frame_start) context.scene.timeline_markers.new(shot_name, frame=frame_start)
@ -309,14 +307,16 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
logger.warning("%s found no .mp4 preview sequence", shot_folder.name) logger.warning("%s found no .mp4 preview sequence", shot_folder.name)
video_path = shot_folder video_path = shot_folder
strip = context.scene.sequence_editor.sequences.new_movie( strip = context.scene.sequence_editor.sequences.new_movie(
name = shot_folder.name, name=shot_folder.name,
filepath = video_path.as_posix(), filepath=video_path.as_posix(),
channel = channel_idx + 1, channel=channel_idx + 1,
frame_start = frame_start, frame_start=frame_start,
fit_method = 'ORIGINAL' fit_method='ORIGINAL',
) )
else: else:
strip = self.load_strip_from_img_seq(context, shot_folder, channel_idx, frame_start) strip = self.load_strip_from_img_seq(
context, shot_folder, channel_idx, frame_start
)
shot_datetime = datetime.fromtimestamp(shot_folder.stat().st_mtime) shot_datetime = datetime.fromtimestamp(shot_folder.stat().st_mtime)
time_str = shot_datetime.strftime("%B %d, %I:%M") time_str = shot_datetime.strftime("%B %d, %I:%M")
@ -346,15 +346,15 @@ class RR_OT_setup_review_workspace(bpy.types.Operator):
return [("None", "None", "None")] + cache.get_sequences_enum_list(self, context) return [("None", "None", "None")] + cache.get_sequences_enum_list(self, context)
sequence: bpy.props.EnumProperty( sequence: bpy.props.EnumProperty(
name = "Sequence", name="Sequence",
description = "Select which sequence to review", description="Select which sequence to review",
items = sequences_enum_items if prefs.is_blender_kitsu_enabled() else [] items=sequences_enum_items if prefs.is_blender_kitsu_enabled() else [],
) )
@staticmethod @staticmethod
def delayed_setup_review_workspace(): def delayed_setup_review_workspace():
"""This function can be used as a bpy.app.timer. """This function can be used as a bpy.app.timer.
It is necessary to delay certain UI changing operations that rely It is necessary to delay certain UI changing operations that rely
on previous UI changing operations, because Blender.""" on previous UI changing operations, because Blender."""
context = bpy.context context = bpy.context
@ -371,16 +371,18 @@ class RR_OT_setup_review_workspace(bpy.types.Operator):
if area.spaces.active.type == 'SEQUENCE_EDITOR': if area.spaces.active.type == 'SEQUENCE_EDITOR':
area.spaces.active.timeline_overlay.show_strip_source = False area.spaces.active.timeline_overlay.show_strip_source = False
area.spaces.active.timeline_overlay.show_strip_duration = False area.spaces.active.timeline_overlay.show_strip_duration = False
if area.spaces.active.view_type == 'PREVIEW': if area.spaces.active.view_type == 'PREVIEW':
area.spaces.active.show_overlays = False area.spaces.active.show_overlays = False
def invoke(self, context, _event): def invoke(self, context, _event):
if not prefs.is_blender_kitsu_enabled() or \ if (
not prefs.addon_prefs_get(context).enable_blender_kitsu or \ not prefs.is_blender_kitsu_enabled()
not kitsu.is_auth_and_project(): or not prefs.addon_prefs_get(context).enable_blender_kitsu
or not kitsu.is_auth_and_project()
):
return self.execute(context) return self.execute(context)
return context.window_manager.invoke_props_dialog(self) return context.window_manager.invoke_props_dialog(self)
def draw(self, context): def draw(self, context):
@ -397,7 +399,6 @@ class RR_OT_setup_review_workspace(bpy.types.Operator):
if addon_prefs.use_video: if addon_prefs.use_video:
row.prop(addon_prefs, 'use_video_latest_only') row.prop(addon_prefs, 'use_video_latest_only')
def execute(self, context: bpy.types.Context) -> Set[str]: def execute(self, context: bpy.types.Context) -> Set[str]:
scripts_path = bpy.utils.script_paths(use_user=False)[0] scripts_path = bpy.utils.script_paths(use_user=False)[0]
template_path = "/startup/bl_app_templates_system/Video_Editing/startup.blend" template_path = "/startup/bl_app_templates_system/Video_Editing/startup.blend"
@ -407,7 +408,6 @@ class RR_OT_setup_review_workspace(bpy.types.Operator):
filepath=ws_filepath.as_posix(), filepath=ws_filepath.as_posix(),
) )
# Pre-fill render directory with farm output shots directory. # Pre-fill render directory with farm output shots directory.
addon_prefs = prefs.addon_prefs_get(bpy.context) addon_prefs = prefs.addon_prefs_get(bpy.context)
context.scene.rr.render_dir = addon_prefs.farm_output_dir + "/shots" context.scene.rr.render_dir = addon_prefs.farm_output_dir + "/shots"
@ -444,10 +444,8 @@ class RR_OT_sqe_inspect_exr_sequence(bpy.types.Operator):
def poll(cls, context: bpy.types.Context) -> bool: def poll(cls, context: bpy.types.Context) -> bool:
active_strip = context.scene.sequence_editor.active_strip active_strip = context.scene.sequence_editor.active_strip
image_editor = opsdata.get_image_editor(context) image_editor = opsdata.get_image_editor(context)
if not (active_strip if not (active_strip and active_strip.rr.is_render and image_editor):
and active_strip.rr.is_render
and image_editor):
return False return False
output_dir = opsdata.get_strip_folder(active_strip) output_dir = opsdata.get_strip_folder(active_strip)
@ -511,7 +509,6 @@ class RR_OT_sqe_clear_exr_inspect(bpy.types.Operator):
@classmethod @classmethod
def _get_image_editor(self, context: bpy.types.Context) -> Optional[bpy.types.Area]: def _get_image_editor(self, context: bpy.types.Context) -> Optional[bpy.types.Area]:
image_editor = None image_editor = None
for area in bpy.context.screen.areas: for area in bpy.context.screen.areas:
@ -555,7 +552,6 @@ class RR_OT_sqe_approve_render(bpy.types.Operator):
# Create Shot Frames path if not exists yet. # Create Shot Frames path if not exists yet.
if shot_frames_dir.exists(): if shot_frames_dir.exists():
# Delete backup if exists. # Delete backup if exists.
if shot_frames_backup_path.exists(): if shot_frames_backup_path.exists():
shutil.rmtree(shot_frames_backup_path) shutil.rmtree(shot_frames_backup_path)
@ -675,7 +671,6 @@ class RR_OT_open_path(bpy.types.Operator):
) )
def execute(self, context: bpy.types.Context) -> Set[str]: def execute(self, context: bpy.types.Context) -> Set[str]:
if not self.filepath: if not self.filepath:
self.report({"ERROR"}, "Can't open empty path in explorer") self.report({"ERROR"}, "Can't open empty path in explorer")
return {"CANCELLED"} return {"CANCELLED"}
@ -718,7 +713,6 @@ class RR_OT_sqe_isolate_strip_exit(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
def execute(self, context: bpy.types.Context) -> Set[str]: def execute(self, context: bpy.types.Context) -> Set[str]:
for i in context.scene.rr.isolate_view: for i in context.scene.rr.isolate_view:
try: try:
strip = context.scene.sequence_editor.sequences[i.name] strip = context.scene.sequence_editor.sequences[i.name]
@ -746,7 +740,6 @@ class RR_OT_sqe_isolate_strip_enter(bpy.types.Operator):
return bool(active_strip) return bool(active_strip)
def execute(self, context: bpy.types.Context) -> Set[str]: def execute(self, context: bpy.types.Context) -> Set[str]:
sequences = list(context.scene.sequence_editor.sequences_all) sequences = list(context.scene.sequence_editor.sequences_all)
if context.scene.rr.isolate_view.items(): if context.scene.rr.isolate_view.items():
@ -968,7 +961,6 @@ addon_keymap_items = []
def register(): def register():
for cls in classes: for cls in classes:
bpy.utils.register_class(cls) bpy.utils.register_class(cls)