Render Review: Fix Import Errors #122
@ -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.
|
||||||
@ -237,48 +236,55 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
|
|||||||
|
|
||||||
# Sort versions by date
|
# Sort versions by date
|
||||||
for shot_name, shot_folder in shot_version_folders_dict.items():
|
for shot_name, shot_folder in shot_version_folders_dict.items():
|
||||||
shot_version_folders_dict[shot_name] = sorted(shot_folder, key=lambda dir: dir.stat().st_mtime)
|
shot_version_folders_dict[shot_name] = sorted(shot_folder, reverse=False)
|
||||||
# Limit list to max number of versions
|
# Limit list to max number of versions
|
||||||
shot_version_folders_dict[shot_name] = shot_version_folders_dict[shot_name][:max_versions_per_shot]
|
shot_version_folders_dict[shot_name] = shot_version_folders_dict[shot_name][
|
||||||
|
-max_versions_per_shot:
|
||||||
|
]
|
||||||
|
|
||||||
# Sort shots by name
|
# Sort shots by name
|
||||||
sorted_dict = OrderedDict(sorted(shot_version_folders_dict.items()))
|
sorted_dict = OrderedDict(sorted(shot_version_folders_dict.items()))
|
||||||
|
|
||||||
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 = []
|
||||||
|
|
||||||
for idx, shot_folder in enumerate(shot_version_folders):
|
shots_folder_to_add = []
|
||||||
if addon_prefs.shot_name_filter and addon_prefs.shot_name_filter not in shot_folder.parent.name:
|
|
||||||
# If there is a filter specified, and the shot doesn't match, skip it.
|
if addon_prefs.shot_name_filter == "":
|
||||||
continue
|
shots_folder_to_add = shot_version_folders
|
||||||
|
else:
|
||||||
|
for shot_folder in shot_version_folders:
|
||||||
|
if addon_prefs.shot_name_filter in shot_folder.parent.name:
|
||||||
|
shots_folder_to_add.append(shot_folder)
|
||||||
|
|
||||||
|
for idx, shot_folder in enumerate(shots_folder_to_add):
|
||||||
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,
|
||||||
@ -286,7 +292,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)
|
||||||
|
|
||||||
@ -305,14 +311,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")
|
||||||
@ -342,9 +350,9 @@ 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
|
||||||
@ -372,9 +380,11 @@ class RR_OT_setup_review_workspace(bpy.types.Operator):
|
|||||||
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)
|
||||||
@ -393,7 +403,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"
|
||||||
@ -403,7 +412,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"
|
||||||
@ -441,9 +449,7 @@ class RR_OT_sqe_inspect_exr_sequence(bpy.types.Operator):
|
|||||||
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)
|
||||||
@ -507,7 +513,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:
|
||||||
@ -551,7 +556,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)
|
||||||
@ -671,7 +675,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"}
|
||||||
@ -714,7 +717,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]
|
||||||
@ -742,7 +744,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():
|
||||||
@ -964,7 +965,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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user