From 87a68fef4b47c6c735fc55aa3b218df7075aae5e Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Fri, 5 Jan 2024 13:38:06 -0500 Subject: [PATCH 1/6] Blender Kitsu: Rename Methods in Shot Class & Enforce Black --- .../addons/blender_kitsu/shot_builder/core.py | 18 +++++------------ .../addons/blender_kitsu/shot_builder/ops.py | 20 ++++++------------- scripts-blender/addons/blender_kitsu/types.py | 12 +++++------ 3 files changed, 17 insertions(+), 33 deletions(-) diff --git a/scripts-blender/addons/blender_kitsu/shot_builder/core.py b/scripts-blender/addons/blender_kitsu/shot_builder/core.py index bd979c4c..49f50dec 100644 --- a/scripts-blender/addons/blender_kitsu/shot_builder/core.py +++ b/scripts-blender/addons/blender_kitsu/shot_builder/core.py @@ -55,9 +55,7 @@ def remove_all_data(): for obj in bpy.data.objects: bpy.data.objects.remove(obj) - bpy.ops.outliner.orphans_purge( - do_local_ids=True, do_linked_ids=True, do_recursive=True - ) + bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True) def set_shot_scene(context: bpy.types.Context, scene_name: str) -> bpy.types.Scene: @@ -151,9 +149,7 @@ def link_camera_rig( output_collection.objects.link(camera_object) return - collection_name = ( - "CA-camera_rig" # TODO Rename the asset itself, this breaks convention - ) + collection_name = "CA-camera_rig" # TODO Rename the asset itself, this breaks convention override_camera_col = link_and_override_collection( file_path=path, collection_name=collection_name, scene=scene @@ -180,9 +176,7 @@ def create_task_type_output_collection( scene.collection.children.link(output_collection) for view_layer in scene.view_layers: - view_layer_output_collection = view_layer.layer_collection.children.get( - output_col_name - ) + view_layer_output_collection = view_layer.layer_collection.children.get(output_col_name) view_layer_output_collection.exclude = True return output_collection @@ -192,11 +186,9 @@ def link_task_type_output_collections(shot: Shot, task_type: TaskType): if bkglobals.OUTPUT_COL_LINK_MAPPING.get(task_type_short_name) == None: return for short_name in bkglobals.OUTPUT_COL_LINK_MAPPING.get(task_type_short_name): - external_filepath = shot.get_shot_filepath(bpy.context, short_name) + external_filepath = shot.get_filepath(bpy.context, short_name) if not Path(external_filepath).exists(): - print( - f"Unable to link output collection for {Path(external_filepath).name}" - ) + print(f"Unable to link output collection for {Path(external_filepath).name}") file_path = external_filepath.__str__() colection_name = shot.get_output_collection_name(short_name) link_data_block(file_path, colection_name, 'Collection') diff --git a/scripts-blender/addons/blender_kitsu/shot_builder/ops.py b/scripts-blender/addons/blender_kitsu/shot_builder/ops.py index dd5a778b..cef13b19 100644 --- a/scripts-blender/addons/blender_kitsu/shot_builder/ops.py +++ b/scripts-blender/addons/blender_kitsu/shot_builder/ops.py @@ -23,9 +23,7 @@ from .hooks import Hooks active_project = None -def get_shots_for_seq( - self: Any, context: bpy.types.Context -) -> List[Tuple[str, str, str]]: +def get_shots_for_seq(self: Any, context: bpy.types.Context) -> List[Tuple[str, str, str]]: if self.seq_id != '': seq = active_project.get_sequence(self.seq_id) shot_enum = cache.get_shots_enum_for_seq(self, context, seq) @@ -34,9 +32,7 @@ def get_shots_for_seq( return [('NONE', "No Shots Found", '')] -def get_tasks_for_shot( - self: Any, context: bpy.types.Context -) -> List[Tuple[str, str, str]]: +def get_tasks_for_shot(self: Any, context: bpy.types.Context) -> List[Tuple[str, str, str]]: global active_project if not (self.shot_id == '' or self.shot_id == 'NONE'): shot = active_project.get_shot(self.shot_id) @@ -186,9 +182,7 @@ class KITSU_OT_build_new_shot(bpy.types.Operator): self.production_name = project.name - return cast( - Set[str], context.window_manager.invoke_props_dialog(self, width=400) - ) + return cast(Set[str], context.window_manager.invoke_props_dialog(self, width=400)) def _get_task_type_for_shot(self, context, shot): for task_type in shot.get_all_task_types(): @@ -202,13 +196,13 @@ class KITSU_OT_build_new_shot(bpy.types.Operator): shot = active_project.get_shot(self.shot_id) task_type = self._get_task_type_for_shot(context, shot) task_type_short_name = task_type.get_short_name() - shot_file_path_str = shot.get_shot_filepath(context, task_type_short_name) + shot_file_path_str = shot.get_filepath(context, task_type_short_name) # Open Template File replace_workspace_with_template(context, task_type_short_name) # Set Up Scene + Naming - shot_task_name = shot.get_shot_task_name(task_type.get_short_name()) + shot_task_name = shot.get_task_name(task_type.get_short_name()) scene = set_shot_scene(context, shot_task_name) remove_all_data() set_resolution_and_fps(active_project, scene) @@ -250,9 +244,7 @@ class KITSU_OT_build_new_shot(bpy.types.Operator): if self.save_file: save_shot_builder_file(file_path=shot_file_path_str) - self.report( - {"INFO"}, f"Successfully Built Shot:`{shot.name}` Task: `{task_type.name}`" - ) + self.report({"INFO"}, f"Successfully Built Shot:`{shot.name}` Task: `{task_type.name}`") return {"FINISHED"} diff --git a/scripts-blender/addons/blender_kitsu/types.py b/scripts-blender/addons/blender_kitsu/types.py index a382851b..2bf042e3 100644 --- a/scripts-blender/addons/blender_kitsu/types.py +++ b/scripts-blender/addons/blender_kitsu/types.py @@ -596,22 +596,22 @@ class Shot(Entity): gazu.shot.update_shot(asdict(self)) return self - def get_shot_task_name(self, task_type_short_name: str) -> str: # + def get_task_name(self, task_type_short_name: str) -> str: # return f"{self.name}{bkglobals.FILE_DELIMITER}{task_type_short_name}" def get_output_collection_name(self, task_type_short_name: str) -> str: - return f"{self.get_shot_task_name(task_type_short_name)}{bkglobals.FILE_DELIMITER}output" + return f"{self.get_task_name(task_type_short_name)}{bkglobals.FILE_DELIMITER}output" - def get_shot_dir(self, context) -> str: + def get_dir(self, context) -> str: project_root_dir = prefs.project_root_dir_get(context) all_shots_dir = project_root_dir.joinpath('pro').joinpath('shots') seq = self.get_sequence() shot_dir = all_shots_dir.joinpath(seq.name).joinpath(self.name) return shot_dir.__str__() - def get_shot_filepath(self, context, task_type_short_name: str) -> str: - file_name = self.get_shot_task_name(task_type_short_name) + '.blend' - return Path(self.get_shot_dir(context)).joinpath(file_name).__str__() + def get_filepath(self, context, task_type_short_name: str) -> str: + file_name = self.get_task_name(task_type_short_name) + '.blend' + return Path(self.get_dir(context)).joinpath(file_name).__str__() def update_data(self, data: Dict[str, Any]) -> Shot: gazu.shot.update_shot_data(asdict(self), data=data) -- 2.30.2 From c34e344216063dacc1982bbd7af4414ce3a10757 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Fri, 5 Jan 2024 13:38:06 -0500 Subject: [PATCH 2/6] Blender Kitsu: Include Episode in Shot Builder Path --- scripts-blender/addons/blender_kitsu/types.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts-blender/addons/blender_kitsu/types.py b/scripts-blender/addons/blender_kitsu/types.py index 2bf042e3..52718f0d 100644 --- a/scripts-blender/addons/blender_kitsu/types.py +++ b/scripts-blender/addons/blender_kitsu/types.py @@ -605,8 +605,15 @@ class Shot(Entity): def get_dir(self, context) -> str: project_root_dir = prefs.project_root_dir_get(context) all_shots_dir = project_root_dir.joinpath('pro').joinpath('shots') + + # Add Episode to Path if avaliable + if self.episode_id: + base_dir = all_shots_dir.joinpath(self.episode_name) + else: + base_dir = all_shots_dir + seq = self.get_sequence() - shot_dir = all_shots_dir.joinpath(seq.name).joinpath(self.name) + shot_dir = base_dir.joinpath(seq.name).joinpath(self.name) return shot_dir.__str__() def get_filepath(self, context, task_type_short_name: str) -> str: -- 2.30.2 From 85045b928f64774115f0907d2f8aa677f546593a Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Fri, 5 Jan 2024 13:38:06 -0500 Subject: [PATCH 3/6] Docs: Add TV Show Path to Naming Conventions --- docs/naming-conventions/file-types.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/naming-conventions/file-types.md b/docs/naming-conventions/file-types.md index 7d60271f..558d56c2 100644 --- a/docs/naming-conventions/file-types.md +++ b/docs/naming-conventions/file-types.md @@ -34,7 +34,9 @@ Sets are more tricky to define, since they can differ even on a shot level. In p ## Shots -**Location:** `{project root}/pro/shots/{sequence number}/{shot identifier}/{shot identifier}-{task identifier}.blend` +**Standard Location:** `{project root}/pro/shots/{sequence number}/{shot identifier}/{shot identifier}-{task identifier}.blend` + +**TV Show Location:** `{project root}/pro/shots/{episode identifier}/{sequence number}/{shot identifier}/{shot identifier}-{task identifier}.blend` ## Example: `prop-dresser_wood.faded-modeling.png` -- 2.30.2 From fec9c6b1a82ffc89d19744ce0c90c5ba92d43b34 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Fri, 5 Jan 2024 13:54:26 -0500 Subject: [PATCH 4/6] Blender Kitsu: Add Episode Support to Context --- scripts-blender/addons/blender_kitsu/context/ops.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts-blender/addons/blender_kitsu/context/ops.py b/scripts-blender/addons/blender_kitsu/context/ops.py index 8685fff7..cb9158d0 100644 --- a/scripts-blender/addons/blender_kitsu/context/ops.py +++ b/scripts-blender/addons/blender_kitsu/context/ops.py @@ -87,7 +87,6 @@ class KITSU_OT_con_episodes_load(bpy.types.Operator): return bool(prefs.session_auth(context) and cache.project_active_get()) def execute(self, context: bpy.types.Context) -> Set[str]: - # Store vars to check if project / seq / shot changed. zep_prev_id = cache.episode_active_get().id @@ -303,7 +302,17 @@ class KITSU_OT_con_detect_context(bpy.types.Operator): # Update kitsu metadata. filepath = Path(bpy.data.filepath) active_project = cache.project_active_get() - category = filepath.parents[2].name + + # TODO REFACTOR THIS WHOLE THING, BAD HACK + # Path is different for tvshow + if ( + active_project.production_type == 'tvshow' + and filepath.parents[3].name == bkglobals.SHOT_DIR_NAME + ): + category = filepath.parents[3].name + else: + category = filepath.parents[2].name + item_group = filepath.parents[1].name item = filepath.parents[0].name item_task_type = filepath.stem.split(bkglobals.FILE_DELIMITER)[-1] -- 2.30.2 From 6adf7cdd30b7d3d1de1d619c652977333c5b34b1 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Fri, 5 Jan 2024 14:49:42 -0500 Subject: [PATCH 5/6] Blender Kitsu: Show Animatin Tools in Layout Files --- scripts-blender/addons/blender_kitsu/anim/ui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts-blender/addons/blender_kitsu/anim/ui.py b/scripts-blender/addons/blender_kitsu/anim/ui.py index 78bce19a..7e906bb7 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ui.py +++ b/scripts-blender/addons/blender_kitsu/anim/ui.py @@ -49,7 +49,7 @@ class KITSU_PT_vi3d_anim_tools(bpy.types.Panel): def poll(cls, context: bpy.types.Context) -> bool: return bool( prefs.session_auth(context) - and cache.task_type_active_get().name == 'Animation' + and cache.task_type_active_get().name in ['Animation', 'Layout'] ) def draw(self, context: bpy.types.Context) -> None: -- 2.30.2 From eac1c9e5bfec22428d9a33acafc192db7f18f12f Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Fri, 5 Jan 2024 15:02:08 -0500 Subject: [PATCH 6/6] Blender Kitsu: Move `get_3d_start` to Shot Class --- .../addons/blender_kitsu/playblast/core.py | 11 +++-------- .../addons/blender_kitsu/playblast/ops.py | 7 +++---- .../addons/blender_kitsu/shot_builder/core.py | 13 +++---------- .../blender_kitsu/shot_builder/editorial.py | 3 +-- scripts-blender/addons/blender_kitsu/sqe/ops.py | 16 +--------------- scripts-blender/addons/blender_kitsu/sqe/push.py | 6 +----- scripts-blender/addons/blender_kitsu/types.py | 7 +++++++ 7 files changed, 19 insertions(+), 44 deletions(-) diff --git a/scripts-blender/addons/blender_kitsu/playblast/core.py b/scripts-blender/addons/blender_kitsu/playblast/core.py index 7394e75c..4b663867 100644 --- a/scripts-blender/addons/blender_kitsu/playblast/core.py +++ b/scripts-blender/addons/blender_kitsu/playblast/core.py @@ -288,14 +288,9 @@ def get_frame_range(): # TODO return type # Pull update for shot. cache.shot_active_pull_update() - if "3d_start" not in active_shot.data: - logger.warning( - "Failed to check frame range. Shot %s missing '3d_start' attribute on server", - active_shot.name, - ) - return - frame_in = int(active_shot.data["3d_start"]) - frame_out = int(active_shot.data["3d_start"]) + int(active_shot.nb_frames) - 1 + kitsu_3d_start = active_shot.get_3d_start() + frame_in = kitsu_3d_start + frame_out = kitsu_3d_start + int(active_shot.nb_frames) - 1 return frame_in, frame_out diff --git a/scripts-blender/addons/blender_kitsu/playblast/ops.py b/scripts-blender/addons/blender_kitsu/playblast/ops.py index f584c19c..4afbdf3d 100644 --- a/scripts-blender/addons/blender_kitsu/playblast/ops.py +++ b/scripts-blender/addons/blender_kitsu/playblast/ops.py @@ -493,12 +493,11 @@ def draw_frame_range_warning(self, context): layout.label( text="Frame Range on server does not match the active shot. Please 'pull' the correct frame range from the server" ) - layout.label( - text=f" File Frame Range: {context.scene.frame_start}-{context.scene.frame_end}" - ) + layout.label(text=f" File Frame Range: {context.scene.frame_start}-{context.scene.frame_end}") if active_shot: + kitsu_3d_start = active_shot.get_3d_start() layout.label( - text=f' Server Frame Range: {int(active_shot.data["3d_start"])}-{int(active_shot.data["3d_start"]) + int(active_shot.nb_frames) - 1}' + text=f'Server Frame Range: {kitsu_3d_start}-{kitsu_3d_start + int(active_shot.nb_frames) - 1}' ) else: layout.label(text=f' Server Frame Range: not found') diff --git a/scripts-blender/addons/blender_kitsu/shot_builder/core.py b/scripts-blender/addons/blender_kitsu/shot_builder/core.py index 49f50dec..463671c4 100644 --- a/scripts-blender/addons/blender_kitsu/shot_builder/core.py +++ b/scripts-blender/addons/blender_kitsu/shot_builder/core.py @@ -82,19 +82,12 @@ def set_resolution_and_fps(project: Project, scene: bpy.types.Scene): scene.render.resolution_percentage = 100 -def get_3d_start(shot: Shot): - if shot.data and shot.data.get("3d_start"): # shot.data and - return int(shot.data.get("3d_start")) - else: - return bkglobals.FRAME_START - - def set_frame_range(shot: Shot, scene: bpy.types.Scene): - start_3d = get_3d_start(shot) - scene.frame_start = start_3d + kitsu_start_3d = shot.get_3d_start() + scene.frame_start = kitsu_start_3d if not shot.nb_frames: raise Exception(f"{shot.name} has missing frame duration information") - scene.frame_end = start_3d + shot.nb_frames - 1 + scene.frame_end = kitsu_start_3d + shot.nb_frames - 1 def link_data_block(file_path: str, data_block_name: str, data_block_type: str): diff --git a/scripts-blender/addons/blender_kitsu/shot_builder/editorial.py b/scripts-blender/addons/blender_kitsu/shot_builder/editorial.py index 5c445df7..606a1351 100644 --- a/scripts-blender/addons/blender_kitsu/shot_builder/editorial.py +++ b/scripts-blender/addons/blender_kitsu/shot_builder/editorial.py @@ -2,7 +2,6 @@ import bpy from .. import prefs from pathlib import Path import re -from .core import get_3d_start def editorial_export_get_latest( @@ -41,7 +40,7 @@ def editorial_export_get_latest( # Update shift frame range prop. frame_in = shot.data.get("frame_in") - frame_3d_start = get_3d_start(shot) + frame_3d_start = shot.get_3d_start() frame_3d_offset = frame_3d_start - addon_prefs.shot_builder_frame_offset edit_export_offset = addon_prefs.edit_export_frame_offset diff --git a/scripts-blender/addons/blender_kitsu/sqe/ops.py b/scripts-blender/addons/blender_kitsu/sqe/ops.py index 59ff102d..77008306 100644 --- a/scripts-blender/addons/blender_kitsu/sqe/ops.py +++ b/scripts-blender/addons/blender_kitsu/sqe/ops.py @@ -1868,22 +1868,8 @@ class KITSU_OT_sqe_pull_edit(bpy.types.Operator): def _apply_strip_slip_from_shot( self, context: bpy.types.Context, strip: bpy.types.Sequence, shot: Shot ) -> None: - if "3d_start" not in shot.data: - logger.warning( - "%s no update to frame_start_offset. '3d_start' key not in shot.data", - shot.name, - ) - return - - if not shot.data["3d_start"]: - logger.warning( - "%s no update to frame_start_offset. '3d_start' key invalid value: %i", - shot.name, - shot.data["3d_start"], - ) - return # get offset - offset = strip.kitsu_frame_start - int(shot.data["3d_start"]) + offset = strip.kitsu_frame_start - int(shot.get_3d_start()) # Deselect everything. if context.selected_sequences: diff --git a/scripts-blender/addons/blender_kitsu/sqe/push.py b/scripts-blender/addons/blender_kitsu/sqe/push.py index def73104..66a60eb1 100644 --- a/scripts-blender/addons/blender_kitsu/sqe/push.py +++ b/scripts-blender/addons/blender_kitsu/sqe/push.py @@ -33,11 +33,7 @@ logger = LoggerFactory.getLogger() def shot_meta(strip: bpy.types.Sequence, shot: Shot) -> None: # Update shot info. - # Only set 3d_start if none is found - try: - kitsu_3d_start = shot.data["3d_start"] - except: - kitsu_3d_start = bkglobals.FRAME_START + kitsu_3d_start = shot.get_3d_start() shot.name = strip.kitsu.shot_name shot.description = strip.kitsu.shot_description shot.data["frame_in"] = strip.frame_final_start diff --git a/scripts-blender/addons/blender_kitsu/types.py b/scripts-blender/addons/blender_kitsu/types.py index 52718f0d..c17f85de 100644 --- a/scripts-blender/addons/blender_kitsu/types.py +++ b/scripts-blender/addons/blender_kitsu/types.py @@ -596,6 +596,13 @@ class Shot(Entity): gazu.shot.update_shot(asdict(self)) return self + def get_3d_start(self) -> int: + try: + logger.info(f"3d_start not found on server, defaulting to '{bkglobals.FRAME_START}'") + return int(self.data["3d_start"]) + except: + return bkglobals.FRAME_START + def get_task_name(self, task_type_short_name: str) -> str: # return f"{self.name}{bkglobals.FILE_DELIMITER}{task_type_short_name}" -- 2.30.2