Blender_Kitsu & Render Review: Remove Metastrip Filepath #80
@ -154,10 +154,6 @@ class KITSU_addon_preferences(bpy.types.AddonPreferences):
|
|||||||
return ""
|
return ""
|
||||||
return self.project_root_path.joinpath("pipeline/blender_kitsu").as_posix()
|
return self.project_root_path.joinpath("pipeline/blender_kitsu").as_posix()
|
||||||
|
|
||||||
def get_metastrip_file(self) -> str:
|
|
||||||
res_dir = bkglobals.RES_DIR_PATH
|
|
||||||
return res_dir.joinpath("metastrip.mp4").as_posix()
|
|
||||||
|
|
||||||
def init_playblast_file_model(self, context: bpy.types.Context) -> None:
|
def init_playblast_file_model(self, context: bpy.types.Context) -> None:
|
||||||
ops_playblast_data.init_playblast_file_model(context)
|
ops_playblast_data.init_playblast_file_model(context)
|
||||||
|
|
||||||
@ -228,16 +224,6 @@ class KITSU_addon_preferences(bpy.types.AddonPreferences):
|
|||||||
get=get_config_dir,
|
get=get_config_dir,
|
||||||
)
|
)
|
||||||
|
|
||||||
metastrip_file: bpy.props.StringProperty( # type: ignore
|
|
||||||
name="Meta Strip File",
|
|
||||||
description=(
|
|
||||||
"Filepath to black .mp4 file that will be used as metastrip for shots in the sequence editor"
|
|
||||||
),
|
|
||||||
default="",
|
|
||||||
subtype="FILE_PATH",
|
|
||||||
get=get_metastrip_file,
|
|
||||||
)
|
|
||||||
|
|
||||||
project_active_id: bpy.props.StringProperty( # type: ignore
|
project_active_id: bpy.props.StringProperty( # type: ignore
|
||||||
name="Project Active ID",
|
name="Project Active ID",
|
||||||
description="Server Id that refers to the last active project",
|
description="Server Id that refers to the last active project",
|
||||||
@ -252,7 +238,7 @@ class KITSU_addon_preferences(bpy.types.AddonPreferences):
|
|||||||
name="Show Advanced Settings",
|
name="Show Advanced Settings",
|
||||||
description="Show advanced settings that should already have good defaults",
|
description="Show advanced settings that should already have good defaults",
|
||||||
)
|
)
|
||||||
shot_builder_show_advanced : bpy.props.BoolProperty( # type: ignore
|
shot_builder_show_advanced: bpy.props.BoolProperty( # type: ignore
|
||||||
name="Show Advanced Settings",
|
name="Show Advanced Settings",
|
||||||
description="Show advanced settings that should already have good defaults",
|
description="Show advanced settings that should already have good defaults",
|
||||||
)
|
)
|
||||||
@ -313,13 +299,12 @@ class KITSU_addon_preferences(bpy.types.AddonPreferences):
|
|||||||
options={"HIDDEN", "SKIP_SAVE"},
|
options={"HIDDEN", "SKIP_SAVE"},
|
||||||
description="File pattern to search for latest editorial export. Typically '{proj_name}_v\d\d\d.mp4'",
|
description="File pattern to search for latest editorial export. Typically '{proj_name}_v\d\d\d.mp4'",
|
||||||
default="petprojects_v\d\d\d.mp4",
|
default="petprojects_v\d\d\d.mp4",
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
edit_export_frame_offset: bpy.props.IntProperty( # type: ignore
|
edit_export_frame_offset: bpy.props.IntProperty( # type: ignore
|
||||||
name="Editorial Export Offset",
|
name="Editorial Export Offset",
|
||||||
description="Shift Editorial Export by this frame-range after set-up.",
|
description="Shift Editorial Export by this frame-range after set-up.",
|
||||||
default=-102, #HARD CODED FOR PET PROJECTS BLENDER FILM
|
default=-102, # HARD CODED FOR PET PROJECTS BLENDER FILM
|
||||||
)
|
)
|
||||||
|
|
||||||
shot_builder_frame_offset: bpy.props.IntProperty( # type: ignore
|
shot_builder_frame_offset: bpy.props.IntProperty( # type: ignore
|
||||||
@ -340,7 +325,7 @@ class KITSU_addon_preferences(bpy.types.AddonPreferences):
|
|||||||
default="ANI-",
|
default="ANI-",
|
||||||
)
|
)
|
||||||
|
|
||||||
user_exec_code: bpy.props.StringProperty(# type: ignore
|
user_exec_code: bpy.props.StringProperty( # type: ignore
|
||||||
name="Post Execution Command",
|
name="Post Execution Command",
|
||||||
description="Run this command after shot_builder is complete, but before the file is saved.",
|
description="Run this command after shot_builder is complete, but before the file is saved.",
|
||||||
default="",
|
default="",
|
||||||
@ -424,7 +409,7 @@ class KITSU_addon_preferences(bpy.types.AddonPreferences):
|
|||||||
icon="ADD",
|
icon="ADD",
|
||||||
emboss=False,
|
emboss=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Shot_Builder settings.
|
# Shot_Builder settings.
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
box.label(text="Shot Builder", icon="MOD_BUILD")
|
box.label(text="Shot Builder", icon="MOD_BUILD")
|
||||||
@ -437,7 +422,7 @@ class KITSU_addon_preferences(bpy.types.AddonPreferences):
|
|||||||
start_frame_row.label(text="Start Frame Offset")
|
start_frame_row.label(text="Start Frame Offset")
|
||||||
start_frame_row.prop(self, "shot_builder_frame_offset", text="")
|
start_frame_row.prop(self, "shot_builder_frame_offset", text="")
|
||||||
box.row().prop(self, "shot_builder_armature_prefix")
|
box.row().prop(self, "shot_builder_armature_prefix")
|
||||||
box.row().prop(self, "shot_builder_action_prefix")
|
box.row().prop(self, "shot_builder_action_prefix")
|
||||||
box.row().prop(self, "user_exec_code")
|
box.row().prop(self, "user_exec_code")
|
||||||
|
|
||||||
# Misc settings.
|
# Misc settings.
|
||||||
@ -453,7 +438,6 @@ class KITSU_addon_preferences(bpy.types.AddonPreferences):
|
|||||||
box.row().prop(self, "shot_counter_digits")
|
box.row().prop(self, "shot_counter_digits")
|
||||||
box.row().prop(self, "shot_counter_increment")
|
box.row().prop(self, "shot_counter_increment")
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def playblast_root_path(self) -> Optional[Path]:
|
def playblast_root_path(self) -> Optional[Path]:
|
||||||
if not self.is_playblast_root_valid:
|
if not self.is_playblast_root_valid:
|
||||||
@ -495,16 +479,17 @@ class KITSU_addon_preferences(bpy.types.AddonPreferences):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_editorial_dir_valid(self) -> bool:
|
def is_editorial_dir_valid(self) -> bool:
|
||||||
if editorial_export_check_latest(bpy.context) is None:
|
if editorial_export_check_latest(bpy.context) is None:
|
||||||
logger.error(
|
logger.error(
|
||||||
"Failed to initialize editorial export file model. Invalid path/pattern. Check addon preferences"
|
"Failed to initialize editorial export file model. Invalid path/pattern. Check addon preferences"
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def session_get(context: bpy.types.Context) -> Session:
|
def session_get(context: bpy.types.Context) -> Session:
|
||||||
"""
|
"""
|
||||||
Shortcut to get session from blender_kitsu addon preferences
|
Shortcut to get session from blender_kitsu addon preferences
|
||||||
@ -544,7 +529,6 @@ def register():
|
|||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
|
|
||||||
# Log user out.
|
# Log user out.
|
||||||
addon_prefs = bpy.context.preferences.addons["blender_kitsu"].preferences
|
addon_prefs = bpy.context.preferences.addons["blender_kitsu"].preferences
|
||||||
if addon_prefs.session.is_auth():
|
if addon_prefs.session.is_auth():
|
||||||
|
@ -172,7 +172,6 @@ class KITSU_OT_sqe_push_new_shot(bpy.types.Operator):
|
|||||||
return bool(prefs.session_auth(context) and cache.project_active_get())
|
return bool(prefs.session_auth(context) and cache.project_active_get())
|
||||||
|
|
||||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||||
|
|
||||||
if not self.confirm:
|
if not self.confirm:
|
||||||
self.report({"WARNING"}, "Submit new shots aborted")
|
self.report({"WARNING"}, "Submit new shots aborted")
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
@ -309,6 +308,7 @@ class KITSU_OT_sqe_push_new_shot(bpy.types.Operator):
|
|||||||
% (noun.lower()),
|
% (noun.lower()),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class KITSU_OT_sqe_push_new_sequence(bpy.types.Operator):
|
class KITSU_OT_sqe_push_new_sequence(bpy.types.Operator):
|
||||||
bl_idname = "kitsu.sqe_push_new_sequence"
|
bl_idname = "kitsu.sqe_push_new_sequence"
|
||||||
bl_label = "Submit New Sequence"
|
bl_label = "Submit New Sequence"
|
||||||
@ -327,7 +327,6 @@ class KITSU_OT_sqe_push_new_sequence(bpy.types.Operator):
|
|||||||
return bool(prefs.session_auth(context) and cache.project_active_get())
|
return bool(prefs.session_auth(context) and cache.project_active_get())
|
||||||
|
|
||||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||||
|
|
||||||
if not self.confirm:
|
if not self.confirm:
|
||||||
self.report({"WARNING"}, "Submit new sequence aborted")
|
self.report({"WARNING"}, "Submit new sequence aborted")
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
@ -420,7 +419,6 @@ class KITSU_OT_sqe_init_strip(bpy.types.Operator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for strip in selected_sequences:
|
for strip in selected_sequences:
|
||||||
|
|
||||||
if not checkstrip.is_valid_type(strip):
|
if not checkstrip.is_valid_type(strip):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -621,7 +619,6 @@ class KITSU_OT_sqe_link_shot(bpy.types.Operator):
|
|||||||
|
|
||||||
|
|
||||||
class KITSU_OT_sqe_multi_edit_strip(bpy.types.Operator):
|
class KITSU_OT_sqe_multi_edit_strip(bpy.types.Operator):
|
||||||
|
|
||||||
bl_idname = "kitsu.sqe_multi_edit_strip"
|
bl_idname = "kitsu.sqe_multi_edit_strip"
|
||||||
bl_label = "Multi Edit Strip"
|
bl_label = "Multi Edit Strip"
|
||||||
bl_options = {"INTERNAL"}
|
bl_options = {"INTERNAL"}
|
||||||
@ -685,7 +682,6 @@ class KITSU_OT_sqe_multi_edit_strip(bpy.types.Operator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for idx, strip in enumerate(selected_sequences):
|
for idx, strip in enumerate(selected_sequences):
|
||||||
|
|
||||||
# Gen data for resolver.
|
# Gen data for resolver.
|
||||||
counter_number = shot_counter_start + (shot_counter_increment * idx)
|
counter_number = shot_counter_start + (shot_counter_increment * idx)
|
||||||
counter = str(counter_number).rjust(shot_counter_digits, "0")
|
counter = str(counter_number).rjust(shot_counter_digits, "0")
|
||||||
@ -852,7 +848,6 @@ class KITSU_OT_sqe_uninit_strip(bpy.types.Operator):
|
|||||||
logger.info("-START- Uninitializing strips")
|
logger.info("-START- Uninitializing strips")
|
||||||
|
|
||||||
for strip in context.selected_sequences:
|
for strip in context.selected_sequences:
|
||||||
|
|
||||||
if not checkstrip.is_valid_type(strip):
|
if not checkstrip.is_valid_type(strip):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -905,7 +900,6 @@ class KITSU_OT_sqe_unlink_shot(bpy.types.Operator):
|
|||||||
logger.info("-START- Unlinking shots")
|
logger.info("-START- Unlinking shots")
|
||||||
|
|
||||||
for strip in context.selected_sequences:
|
for strip in context.selected_sequences:
|
||||||
|
|
||||||
if not checkstrip.is_valid_type(strip):
|
if not checkstrip.is_valid_type(strip):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -1047,7 +1041,6 @@ class KITSU_OT_sqe_set_thumbnail_task_type(bpy.types.Operator):
|
|||||||
return bool(prefs.session_auth(context) and cache.project_active_get())
|
return bool(prefs.session_auth(context) and cache.project_active_get())
|
||||||
|
|
||||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||||
|
|
||||||
# Task type selected by user.
|
# Task type selected by user.
|
||||||
task_type_id = self.enum_prop
|
task_type_id = self.enum_prop
|
||||||
|
|
||||||
@ -1084,7 +1077,6 @@ class KITSU_OT_sqe_set_sqe_render_task_type(bpy.types.Operator):
|
|||||||
return bool(prefs.session_auth(context) and cache.project_active_get())
|
return bool(prefs.session_auth(context) and cache.project_active_get())
|
||||||
|
|
||||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||||
|
|
||||||
# Task type selected by user.
|
# Task type selected by user.
|
||||||
task_type_id = self.enum_prop
|
task_type_id = self.enum_prop
|
||||||
|
|
||||||
@ -1135,7 +1127,6 @@ class KITSU_OT_sqe_push_thumbnail(bpy.types.Operator):
|
|||||||
|
|
||||||
with self.override_render_settings(context):
|
with self.override_render_settings(context):
|
||||||
with self.temporary_current_frame(context) as original_curframe:
|
with self.temporary_current_frame(context) as original_curframe:
|
||||||
|
|
||||||
# ----RENDER AND SAVE THUMBNAILS ------.
|
# ----RENDER AND SAVE THUMBNAILS ------.
|
||||||
|
|
||||||
# Begin first progress update.
|
# Begin first progress update.
|
||||||
@ -1320,7 +1311,6 @@ class KITSU_OT_sqe_push_render(bpy.types.Operator):
|
|||||||
Cache.clear_all()
|
Cache.clear_all()
|
||||||
|
|
||||||
with self.override_render_settings(context):
|
with self.override_render_settings(context):
|
||||||
|
|
||||||
# ----RENDER AND SAVE SQE ------.
|
# ----RENDER AND SAVE SQE ------.
|
||||||
|
|
||||||
# Get strips.
|
# Get strips.
|
||||||
@ -1404,13 +1394,12 @@ class KITSU_OT_sqe_push_render(bpy.types.Operator):
|
|||||||
# Log.
|
# Log.
|
||||||
logger.info("-END- Pushing Sequence Editor Render")
|
logger.info("-END- Pushing Sequence Editor Render")
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
def _gen_output_path(self, strip: bpy.types.Sequence, task_type: TaskType) -> Path:
|
def _gen_output_path(self, strip: bpy.types.Sequence, task_type: TaskType) -> Path:
|
||||||
addon_prefs = prefs.addon_prefs_get(bpy.context)
|
addon_prefs = prefs.addon_prefs_get(bpy.context)
|
||||||
folder_name = addon_prefs.sqe_render_dir
|
folder_name = addon_prefs.sqe_render_dir
|
||||||
file_name = f"{strip.kitsu.shot_id}_{strip.kitsu.shot_name}.{(task_type.name).lower()}.mp4"
|
file_name = f"{strip.kitsu.shot_id}_{strip.kitsu.shot_name}.{(task_type.name).lower()}.mp4"
|
||||||
return Path(folder_name).absolute().joinpath(file_name)
|
return Path(folder_name).absolute().joinpath(file_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def override_render_settings(self, context, thumbnail_width=256):
|
def override_render_settings(self, context, thumbnail_width=256):
|
||||||
@ -1473,9 +1462,7 @@ class KITSU_OT_sqe_push_render(bpy.types.Operator):
|
|||||||
class KITSU_OT_sqe_push_shot(bpy.types.Operator):
|
class KITSU_OT_sqe_push_shot(bpy.types.Operator):
|
||||||
bl_idname = "kitsu.sqe_push_shot"
|
bl_idname = "kitsu.sqe_push_shot"
|
||||||
bl_label = "Push Shot to Kitsu"
|
bl_label = "Push Shot to Kitsu"
|
||||||
bl_description = (
|
bl_description = "Pushes the active strip to Kitsu"
|
||||||
"Pushes the active strip to Kitsu"
|
|
||||||
)
|
|
||||||
|
|
||||||
comment: bpy.props.StringProperty(
|
comment: bpy.props.StringProperty(
|
||||||
name="Comment",
|
name="Comment",
|
||||||
@ -1483,14 +1470,14 @@ class KITSU_OT_sqe_push_shot(bpy.types.Operator):
|
|||||||
default="",
|
default="",
|
||||||
)
|
)
|
||||||
task_type: bpy.props.EnumProperty(
|
task_type: bpy.props.EnumProperty(
|
||||||
name = "Task Type",
|
name="Task Type",
|
||||||
description = "Which task this video should be added to",
|
description="Which task this video should be added to",
|
||||||
items = cache.get_task_types_enum_for_current_context
|
items=cache.get_task_types_enum_for_current_context,
|
||||||
)
|
)
|
||||||
task_status: bpy.props.EnumProperty(
|
task_status: bpy.props.EnumProperty(
|
||||||
name = "Task Status",
|
name="Task Status",
|
||||||
description = "What to set the task's status to",
|
description="What to set the task's status to",
|
||||||
items = cache.get_all_task_statuses_enum
|
items=cache.get_all_task_statuses_enum,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -1499,9 +1486,7 @@ class KITSU_OT_sqe_push_shot(bpy.types.Operator):
|
|||||||
if not hasattr(active_strip, 'filepath'):
|
if not hasattr(active_strip, 'filepath'):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return bool(
|
return bool(prefs.session_auth(context))
|
||||||
prefs.session_auth(context)
|
|
||||||
)
|
|
||||||
|
|
||||||
def invoke(self, context, _event):
|
def invoke(self, context, _event):
|
||||||
return context.window_manager.invoke_props_dialog(self)
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
@ -1523,8 +1508,8 @@ class KITSU_OT_sqe_push_shot(bpy.types.Operator):
|
|||||||
shot_name = active_strip.name.split(".")[0]
|
shot_name = active_strip.name.split(".")[0]
|
||||||
metastrip = context.scene.sequence_editor.sequences.get(shot_name)
|
metastrip = context.scene.sequence_editor.sequences.get(shot_name)
|
||||||
if not metastrip:
|
if not metastrip:
|
||||||
# The metastrip should've been created by sqe_create_review_session,
|
# The metastrip should've been created by sqe_create_review_session,
|
||||||
# if the Kitsu integration is enabled in the add-on preferences,
|
# if the Kitsu integration is enabled in the add-on preferences,
|
||||||
# the Kitsu add-on is enabled, and valid Kitsu credentials were entered.
|
# the Kitsu add-on is enabled, and valid Kitsu credentials were entered.
|
||||||
self.report({"ERROR"}, f"Could not find Kitsu metastrip: {shot_name}.")
|
self.report({"ERROR"}, f"Could not find Kitsu metastrip: {shot_name}.")
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
@ -1707,11 +1692,7 @@ class KITSU_OT_sqe_pull_edit(bpy.types.Operator):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context: bpy.types.Context) -> bool:
|
def poll(cls, context: bpy.types.Context) -> bool:
|
||||||
addon_prefs = prefs.addon_prefs_get(context)
|
addon_prefs = prefs.addon_prefs_get(context)
|
||||||
return bool(
|
return bool(prefs.session_auth(context) and cache.project_active_get())
|
||||||
prefs.session_auth(context)
|
|
||||||
and cache.project_active_get()
|
|
||||||
and addon_prefs.metastrip_file
|
|
||||||
)
|
|
||||||
|
|
||||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||||
addon_prefs = prefs.addon_prefs_get(context)
|
addon_prefs = prefs.addon_prefs_get(context)
|
||||||
@ -1791,12 +1772,12 @@ class KITSU_OT_sqe_pull_edit(bpy.types.Operator):
|
|||||||
frame_end,
|
frame_end,
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
# TODO Refactor as this reuses code from KITSU_OT_sqe_create_meta_strip
|
||||||
if not strip:
|
if not strip:
|
||||||
# Create new strip.
|
# Create new strip.
|
||||||
strip = context.scene.sequence_editor.sequences.new_movie(
|
strip = context.scene.sequence_editor.sequences.new_movie(
|
||||||
shot.name,
|
shot.name,
|
||||||
addon_prefs.metastrip_file,
|
"",
|
||||||
channel,
|
channel,
|
||||||
frame_start,
|
frame_start,
|
||||||
)
|
)
|
||||||
@ -1912,7 +1893,6 @@ class KITSU_OT_sqe_pull_edit(bpy.types.Operator):
|
|||||||
|
|
||||||
|
|
||||||
class KITSU_OT_sqe_init_strip_start_frame(bpy.types.Operator):
|
class KITSU_OT_sqe_init_strip_start_frame(bpy.types.Operator):
|
||||||
|
|
||||||
bl_idname = "kitsu.sqe_init_strip_start_frame"
|
bl_idname = "kitsu.sqe_init_strip_start_frame"
|
||||||
bl_label = "Initialize Shot Start Frame"
|
bl_label = "Initialize Shot Start Frame"
|
||||||
bl_description = "Calculates offset so the current shot starts at 101"
|
bl_description = "Calculates offset so the current shot starts at 101"
|
||||||
@ -1932,7 +1912,6 @@ class KITSU_OT_sqe_init_strip_start_frame(bpy.types.Operator):
|
|||||||
selected_sequences = context.scene.sequence_editor.sequences_all
|
selected_sequences = context.scene.sequence_editor.sequences_all
|
||||||
|
|
||||||
for strip in selected_sequences:
|
for strip in selected_sequences:
|
||||||
|
|
||||||
if not checkstrip.is_valid_type(strip):
|
if not checkstrip.is_valid_type(strip):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -1981,7 +1960,7 @@ class KITSU_OT_sqe_create_meta_strip(bpy.types.Operator):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context: bpy.types.Context) -> bool:
|
def poll(cls, context: bpy.types.Context) -> bool:
|
||||||
addon_prefs = prefs.addon_prefs_get(context)
|
addon_prefs = prefs.addon_prefs_get(context)
|
||||||
return bool(context.selected_sequences and addon_prefs.metastrip_file)
|
return bool(context.selected_sequences)
|
||||||
|
|
||||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||||
addon_prefs = prefs.addon_prefs_get(context)
|
addon_prefs = prefs.addon_prefs_get(context)
|
||||||
@ -1993,15 +1972,7 @@ class KITSU_OT_sqe_create_meta_strip(bpy.types.Operator):
|
|||||||
selected_sequences = context.selected_sequences
|
selected_sequences = context.selected_sequences
|
||||||
|
|
||||||
# Check if metastrip file actually exists.
|
# Check if metastrip file actually exists.
|
||||||
if not Path(addon_prefs.metastrip_file).exists():
|
|
||||||
self.report(
|
|
||||||
{"ERROR"},
|
|
||||||
f"Failed to load metastrip file: {addon_prefs.metastrip_file}. Path does not exist",
|
|
||||||
)
|
|
||||||
return {"CANCELLED"}
|
|
||||||
|
|
||||||
for strip in selected_sequences:
|
for strip in selected_sequences:
|
||||||
|
|
||||||
# Get frame range information from current strip.
|
# Get frame range information from current strip.
|
||||||
strip_range = range(strip.frame_final_start, strip.frame_final_end)
|
strip_range = range(strip.frame_final_start, strip.frame_final_end)
|
||||||
channel = strip.channel + 1
|
channel = strip.channel + 1
|
||||||
@ -2026,7 +1997,7 @@ class KITSU_OT_sqe_create_meta_strip(bpy.types.Operator):
|
|||||||
# on the first try, EDIT: seems to work maybe per python overlaps of sequences possible?
|
# on the first try, EDIT: seems to work maybe per python overlaps of sequences possible?
|
||||||
meta_strip = context.scene.sequence_editor.sequences.new_movie(
|
meta_strip = context.scene.sequence_editor.sequences.new_movie(
|
||||||
f"{strip.name}_metastrip",
|
f"{strip.name}_metastrip",
|
||||||
addon_prefs.metastrip_file,
|
"",
|
||||||
strip.channel + 1,
|
strip.channel + 1,
|
||||||
strip.frame_final_start,
|
strip.frame_final_start,
|
||||||
)
|
)
|
||||||
@ -2117,7 +2088,8 @@ class KITSU_OT_sqe_scan_for_media_updates(bpy.types.Operator):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context: bpy.types.Context) -> bool:
|
def poll(cls, context: bpy.types.Context) -> bool:
|
||||||
sqe = context.scene.sequence_editor
|
sqe = context.scene.sequence_editor
|
||||||
if not sqe: return False
|
if not sqe:
|
||||||
|
return False
|
||||||
return bool(sqe.sequences_all)
|
return bool(sqe.sequences_all)
|
||||||
|
|
||||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||||
@ -2136,7 +2108,6 @@ class KITSU_OT_sqe_scan_for_media_updates(bpy.types.Operator):
|
|||||||
logger.info("-START- Scanning for media updates")
|
logger.info("-START- Scanning for media updates")
|
||||||
|
|
||||||
for strip in sequences:
|
for strip in sequences:
|
||||||
|
|
||||||
if not strip.type == "MOVIE":
|
if not strip.type == "MOVIE":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -2253,7 +2224,6 @@ class KITSU_OT_sqe_clear_update_indicators(bpy.types.Operator):
|
|||||||
sequences = context.scene.sequence_editor.sequences_all
|
sequences = context.scene.sequence_editor.sequences_all
|
||||||
|
|
||||||
for strip in sequences:
|
for strip in sequences:
|
||||||
|
|
||||||
if strip.kitsu.media_outdated:
|
if strip.kitsu.media_outdated:
|
||||||
strip.kitsu.media_outdated = False
|
strip.kitsu.media_outdated = False
|
||||||
reset.append(strip)
|
reset.append(strip)
|
||||||
@ -2400,32 +2370,40 @@ class KITSU_OT_sqe_change_strip_source(bpy.types.Operator):
|
|||||||
|
|
||||||
util.ui_redraw()
|
util.ui_redraw()
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
def set_entity_data(entity, key: str, value: int):
|
def set_entity_data(entity, key: str, value: int):
|
||||||
if get_entity_data(entity, key) is not None:
|
if get_entity_data(entity, key) is not None:
|
||||||
entity['data'][key] = value
|
entity['data'][key] = value
|
||||||
return entity
|
return entity
|
||||||
|
|
||||||
|
|
||||||
def get_entity_data(entity, key: str):
|
def get_entity_data(entity, key: str):
|
||||||
if entity.get("data").get(key) is not None:
|
if entity.get("data").get(key) is not None:
|
||||||
return entity.get("data").get(key)
|
return entity.get("data").get(key)
|
||||||
|
|
||||||
def get_dict_len(items:dict):
|
|
||||||
|
def get_dict_len(items: dict):
|
||||||
try:
|
try:
|
||||||
return len(items)
|
return len(items)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def set_revision_int(prev_rev=None):
|
def set_revision_int(prev_rev=None):
|
||||||
if prev_rev is None:
|
if prev_rev is None:
|
||||||
return 1
|
return 1
|
||||||
return prev_rev+1
|
return prev_rev + 1
|
||||||
|
|
||||||
|
|
||||||
class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator):
|
class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator):
|
||||||
bl_idname = "kitsu.vse_publish_edit_revision"
|
bl_idname = "kitsu.vse_publish_edit_revision"
|
||||||
bl_label = "Render and 'Publish as Revision'"
|
bl_label = "Render and 'Publish as Revision'"
|
||||||
bl_description = "Renders current VSE Edit as .mp4 and publishes as revision on 'Edit Task'.\nWill not overwrite existing files"
|
bl_description = "Renders current VSE Edit as .mp4 and publishes as revision on 'Edit Task'.\nWill not overwrite existing files"
|
||||||
|
|
||||||
def get_edit_entry_items(self: Any, context: bpy.types.Context) -> List[Tuple[str, str, str]]:
|
def get_edit_entry_items(
|
||||||
|
self: Any, context: bpy.types.Context
|
||||||
|
) -> List[Tuple[str, str, str]]:
|
||||||
sorted_edits = []
|
sorted_edits = []
|
||||||
active_project = cache.project_active_get()
|
active_project = cache.project_active_get()
|
||||||
|
|
||||||
@ -2433,45 +2411,68 @@ class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator):
|
|||||||
if (edit["project_id"] == active_project.id) and not edit['canceled']:
|
if (edit["project_id"] == active_project.id) and not edit['canceled']:
|
||||||
sorted_edits.append(edit)
|
sorted_edits.append(edit)
|
||||||
|
|
||||||
return [(item.get("id"), item.get("name"), f'Created at: "{item.get("created_at")}" {item.get("description")}') for item in sorted_edits]
|
return [
|
||||||
|
(
|
||||||
|
item.get("id"),
|
||||||
|
item.get("name"),
|
||||||
|
f'Created at: "{item.get("created_at")}" {item.get("description")}',
|
||||||
|
)
|
||||||
|
for item in sorted_edits
|
||||||
|
]
|
||||||
|
|
||||||
def get_edit_task_items(self: Any, context: bpy.types.Context) -> List[Tuple[str, str, str]]:
|
def get_edit_task_items(
|
||||||
|
self: Any, context: bpy.types.Context
|
||||||
|
) -> List[Tuple[str, str, str]]:
|
||||||
tasks = gazu.task.all_tasks_for_edit(self.edit_entry)
|
tasks = gazu.task.all_tasks_for_edit(self.edit_entry)
|
||||||
return [(item.get("id"), item.get("name"), f'Created at: "{item.get("created_at")}" {item.get("description")}') for item in tasks]
|
return [
|
||||||
|
(
|
||||||
|
item.get("id"),
|
||||||
|
item.get("name"),
|
||||||
|
f'Created at: "{item.get("created_at")}" {item.get("description")}',
|
||||||
|
)
|
||||||
|
for item in tasks
|
||||||
|
]
|
||||||
|
|
||||||
comment: bpy.props.StringProperty(name="Comment")
|
comment: bpy.props.StringProperty(name="Comment")
|
||||||
edit_entry: bpy.props.EnumProperty(name="Edit", items=get_edit_entry_items)
|
edit_entry: bpy.props.EnumProperty(name="Edit", items=get_edit_entry_items)
|
||||||
task: bpy.props.EnumProperty(name="Edit", items=get_edit_task_items)
|
task: bpy.props.EnumProperty(name="Edit", items=get_edit_task_items)
|
||||||
render_dir: bpy.props.StringProperty(
|
render_dir: bpy.props.StringProperty(
|
||||||
name="Folder",
|
name="Folder",
|
||||||
subtype="DIR_PATH",
|
subtype="DIR_PATH",
|
||||||
)
|
)
|
||||||
use_frame_start: bpy.props.BoolProperty(name="Submit update to 'frame_start'.", default=False)
|
use_frame_start: bpy.props.BoolProperty(
|
||||||
frame_start: bpy.props.IntProperty(name="Frame Start", description="Send an integerfor the 'frame_start' value of the current Kitsu Edit. \nThis is used by Watchtower to pad the edit in the timeline.", default=0)
|
name="Submit update to 'frame_start'.", default=False
|
||||||
|
)
|
||||||
|
frame_start: bpy.props.IntProperty(
|
||||||
|
name="Frame Start",
|
||||||
|
description="Send an integerfor the 'frame_start' value of the current Kitsu Edit. \nThis is used by Watchtower to pad the edit in the timeline.",
|
||||||
|
default=0,
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context: bpy.types.Context) -> bool:
|
def poll(cls, context: bpy.types.Context) -> bool:
|
||||||
return bool(
|
return bool(prefs.session_auth(context) and cache.project_active_get())
|
||||||
prefs.session_auth(context)
|
|
||||||
and cache.project_active_get()
|
|
||||||
)
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
# Ensure user has permissions to access edit data
|
# Ensure user has permissions to access edit data
|
||||||
try:
|
try:
|
||||||
edits = gazu.edit.get_all_edits_with_tasks()
|
edits = gazu.edit.get_all_edits_with_tasks()
|
||||||
except gazu.exception.NotAllowedException:
|
except gazu.exception.NotAllowedException:
|
||||||
self.report({"ERROR"}, "Kitsu User doesn't have permissions to access edit data.")
|
self.report(
|
||||||
return {"CANCELLED"}
|
{"ERROR"}, "Kitsu User doesn't have permissions to access edit data."
|
||||||
|
)
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
# Remove file name if set in render.filepath
|
# Remove file name if set in render.filepath
|
||||||
dir_path = bpy.path.abspath(context.scene.render.filepath)
|
dir_path = bpy.path.abspath(context.scene.render.filepath)
|
||||||
if not os.path.isdir(Path(dir_path)):
|
if not os.path.isdir(Path(dir_path)):
|
||||||
dir_path = Path(dir_path).parent
|
dir_path = Path(dir_path).parent
|
||||||
self.render_dir = str(dir_path)
|
self.render_dir = str(dir_path)
|
||||||
|
|
||||||
#'frame_start' is optionally property appearring on all edit_entries for a project if it exists
|
#'frame_start' is optionally property appearring on all edit_entries for a project if it exists
|
||||||
server_frame_start = get_entity_data(gazu.edit.get_edit(self.edit_entry), 'frame_start')
|
server_frame_start = get_entity_data(
|
||||||
|
gazu.edit.get_edit(self.edit_entry), 'frame_start'
|
||||||
|
)
|
||||||
if server_frame_start is int:
|
if server_frame_start is int:
|
||||||
self.frame_start = server_frame_start
|
self.frame_start = server_frame_start
|
||||||
self.use_frame_start = bool(server_frame_start is not None)
|
self.use_frame_start = bool(server_frame_start is not None)
|
||||||
@ -2488,11 +2489,12 @@ class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator):
|
|||||||
# Only set `frame_start` if exists on current project
|
# Only set `frame_start` if exists on current project
|
||||||
if self.use_frame_start:
|
if self.use_frame_start:
|
||||||
layout.prop(self, "frame_start")
|
layout.prop(self, "frame_start")
|
||||||
|
|
||||||
|
|
||||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||||
if self.task == "":
|
if self.task == "":
|
||||||
self.report({"ERROR"}, "Selected edit doesn't have any task associated with it .")
|
self.report(
|
||||||
|
{"ERROR"}, "Selected edit doesn't have any task associated with it ."
|
||||||
|
)
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
active_project = cache.project_active_get()
|
active_project = cache.project_active_get()
|
||||||
@ -2505,9 +2507,8 @@ class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator):
|
|||||||
render_dir = bpy.path.abspath(self.render_dir)
|
render_dir = bpy.path.abspath(self.render_dir)
|
||||||
if not os.path.isdir(Path(render_dir)):
|
if not os.path.isdir(Path(render_dir)):
|
||||||
self.report(
|
self.report(
|
||||||
{"ERROR"},
|
{"ERROR"}, f"Render path is not set to a directory. '{self.render_dir}'"
|
||||||
f"Render path is not set to a directory. '{self.render_dir}'"
|
)
|
||||||
)
|
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
edit_entry = gazu.edit.get_edit(self.edit_entry)
|
edit_entry = gazu.edit.get_edit(self.edit_entry)
|
||||||
prod_name = active_project.name.lower().replace(' ', '')
|
prod_name = active_project.name.lower().replace(' ', '')
|
||||||
@ -2516,33 +2517,35 @@ class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator):
|
|||||||
# check path exists
|
# check path exists
|
||||||
if render_path.is_file():
|
if render_path.is_file():
|
||||||
self.report(
|
self.report(
|
||||||
{"ERROR"},
|
{"ERROR"}, f"File '{render_name}' already exists at '{self.render_dir}'"
|
||||||
f"File '{render_name}' already exists at '{self.render_dir}'"
|
)
|
||||||
)
|
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
# Render Sequence to .mp4
|
# Render Sequence to .mp4
|
||||||
with override_render_path(self, context, render_path.as_posix()):
|
with override_render_path(self, context, render_path.as_posix()):
|
||||||
with override_render_format(self, context):
|
with override_render_format(self, context):
|
||||||
bpy.ops.render.opengl(animation=True, sequencer=True)
|
bpy.ops.render.opengl(animation=True, sequencer=True)
|
||||||
|
|
||||||
# Create comment with video
|
# Create comment with video
|
||||||
task_entity = gazu.task.get_task(self.task)
|
task_entity = gazu.task.get_task(self.task)
|
||||||
new_comment = gazu.task.add_comment(task_entity, task_entity["task_status"], self.comment)
|
new_comment = gazu.task.add_comment(
|
||||||
|
task_entity, task_entity["task_status"], self.comment
|
||||||
|
)
|
||||||
new_preview = gazu.task.add_preview(task_entity, new_comment, render_path)
|
new_preview = gazu.task.add_preview(task_entity, new_comment, render_path)
|
||||||
|
|
||||||
# Update edit_entry's frame_start if 'frame_start' is found on server
|
# Update edit_entry's frame_start if 'frame_start' is found on server
|
||||||
if self.use_frame_start:
|
if self.use_frame_start:
|
||||||
edit_entity_update = set_entity_data(edit_entry, 'frame_start', self.frame_start)
|
edit_entity_update = set_entity_data(
|
||||||
updated_edit_entity = gazu.entity.update_entity(edit_entity_update) #TODO add a generic function to update entites
|
edit_entry, 'frame_start', self.frame_start
|
||||||
|
)
|
||||||
|
updated_edit_entity = gazu.entity.update_entity(
|
||||||
|
edit_entity_update
|
||||||
|
) # TODO add a generic function to update entites
|
||||||
|
|
||||||
|
self.report({"INFO"}, f"Submitted new comment 'Revision {revision}'")
|
||||||
self.report(
|
|
||||||
{"INFO"},
|
|
||||||
f"Submitted new comment 'Revision {revision}'"
|
|
||||||
)
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
# ---------REGISTER ----------.
|
# ---------REGISTER ----------.
|
||||||
|
|
||||||
classes = [
|
classes = [
|
||||||
@ -2573,7 +2576,6 @@ classes = [
|
|||||||
KITSU_OT_sqe_change_strip_source,
|
KITSU_OT_sqe_change_strip_source,
|
||||||
KITSU_OT_sqe_clear_update_indicators,
|
KITSU_OT_sqe_clear_update_indicators,
|
||||||
KITSU_OT_vse_publish_edit_revision,
|
KITSU_OT_vse_publish_edit_revision,
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ def addon_prefs() -> bpy.types.AddonPreferences:
|
|||||||
def create_meta_strip(
|
def create_meta_strip(
|
||||||
context: bpy.types.Context, strip: bpy.types.Sequence
|
context: bpy.types.Context, strip: bpy.types.Sequence
|
||||||
) -> bpy.types.MovieSequence:
|
) -> bpy.types.MovieSequence:
|
||||||
|
|
||||||
# Get frame range information from current strip.
|
# Get frame range information from current strip.
|
||||||
strip_range = range(strip.frame_final_start, strip.frame_final_end)
|
strip_range = range(strip.frame_final_start, strip.frame_final_end)
|
||||||
channel = strip.channel + 1
|
channel = strip.channel + 1
|
||||||
@ -63,7 +62,7 @@ def create_meta_strip(
|
|||||||
# Create new meta strip.
|
# Create new meta strip.
|
||||||
meta_strip = context.scene.sequence_editor.sequences.new_movie(
|
meta_strip = context.scene.sequence_editor.sequences.new_movie(
|
||||||
f"{strip.name}_metastrip",
|
f"{strip.name}_metastrip",
|
||||||
addon_prefs().metastrip_file,
|
"",
|
||||||
strip.channel + 1,
|
strip.channel + 1,
|
||||||
strip.frame_final_start,
|
strip.frame_final_start,
|
||||||
)
|
)
|
||||||
@ -94,7 +93,6 @@ def link_strip_by_name(
|
|||||||
shot_name: str,
|
shot_name: str,
|
||||||
sequence_name: str,
|
sequence_name: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
# Get seq and shot.
|
# Get seq and shot.
|
||||||
active_project = cache.project_active_get()
|
active_project = cache.project_active_get()
|
||||||
seq = active_project.get_sequence_by_name(sequence_name)
|
seq = active_project.get_sequence_by_name(sequence_name)
|
||||||
|
Loading…
Reference in New Issue
Block a user