[Blender_Kitsu] Publish VSE Edit as Revision on Kitsu #7
@ -309,110 +309,6 @@ class KITSU_OT_sqe_push_new_shot(bpy.types.Operator):
|
|||||||
% (noun.lower()),
|
% (noun.lower()),
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_dict_len(items:dict):
|
|
||||||
try:
|
|
||||||
return len(items)
|
|
||||||
except TypeError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def set_revision_int(prev_rev=None):
|
|
||||||
if prev_rev is None:
|
|
||||||
return 1
|
|
||||||
return prev_rev+1
|
|
||||||
|
|
||||||
def get_enum_item_name(items, key):
|
|
||||||
for item in items:
|
|
||||||
if item[0] == key:
|
|
||||||
return item[1]
|
|
||||||
class KITSU_OT_sqe_push_new_edit(bpy.types.Operator):
|
|
||||||
bl_idname = "kitsu.sqe_push_new_edit_comment"
|
|
||||||
bl_label = "Submit New Kitsu Edit Comment"
|
|
||||||
bl_description = "Creates a new edit comment on Edit task via ID."
|
|
||||||
|
|
||||||
def get_edit_entry_items(self: Any, context: bpy.types.Context) -> List[Tuple[str, str, str]]:
|
|
||||||
sorted_edits = []
|
|
||||||
active_project = cache.project_active_get()
|
|
||||||
|
|
||||||
for edit in gazu.edit.get_all_edits_with_tasks():
|
|
||||||
if (edit["project_id"] == active_project.id) and not edit['canceled']:
|
|
||||||
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]
|
|
||||||
|
|
||||||
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)
|
|
||||||
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")
|
|
||||||
edit_entry: bpy.props.EnumProperty(name="Edit Entry", items=get_edit_entry_items)
|
|
||||||
task: bpy.props.EnumProperty(name="Edit Tasks", items=get_edit_task_items)
|
|
||||||
render_dir: bpy.props.StringProperty(
|
|
||||||
name="Render Directory",
|
|
||||||
subtype="DIR_PATH",
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context: bpy.types.Context) -> bool:
|
|
||||||
return bool(
|
|
||||||
prefs.session_auth(context)
|
|
||||||
and cache.project_active_get()
|
|
||||||
)
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
|
||||||
# Remove file name if set in render.filepath
|
|
||||||
dir_path = bpy.path.abspath(context.scene.render.filepath)
|
|
||||||
if not os.path.isdir(Path(dir_path)):
|
|
||||||
dir_path = Path(dir_path).parent
|
|
||||||
self.render_dir = str(dir_path)
|
|
||||||
return context.window_manager.invoke_props_dialog(self)
|
|
||||||
|
|
||||||
def draw(self, context: bpy.types.Context) -> None:
|
|
||||||
layout = self.layout
|
|
||||||
layout.prop(self, "edit_entry")
|
|
||||||
if len(self.get_edit_task_items(context)) >= 2:
|
|
||||||
layout.prop(self, "task")
|
|
||||||
layout.prop(self, "comment")
|
|
||||||
layout.prop(self, "render_dir")
|
|
||||||
|
|
||||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
|
||||||
if self.task == "":
|
|
||||||
self.report({"ERROR"}, "Selected edit doesn't have any task associated with it .")
|
|
||||||
return {"CANCELLED"}
|
|
||||||
|
|
||||||
active_project = cache.project_active_get()
|
|
||||||
|
|
||||||
existing_previews = gazu.edit.get_all_previews_for_edit(self.edit_entry)
|
|
||||||
len_previews = get_dict_len(existing_previews)
|
|
||||||
revision = set_revision_int(len_previews)
|
|
||||||
|
|
||||||
# Build render_path
|
|
||||||
render_dir = bpy.path.abspath(self.render_dir)
|
|
||||||
if not os.path.isdir(Path(render_dir)):
|
|
||||||
self.report(
|
|
||||||
{"ERROR"},
|
|
||||||
f"Render path is not set to a directory. '{self.render_dir}'"
|
|
||||||
)
|
|
||||||
return {"CANCELLED"}
|
|
||||||
edits = self.get_edit_entry_items(context)
|
|
||||||
edit_name = get_enum_item_name(edits, self.edit_entry)
|
|
||||||
render_name = f"{active_project.name}_{edit_name}_v{revision}.mp4"
|
|
||||||
render_path = Path(render_dir).joinpath(render_name)
|
|
||||||
|
|
||||||
# Render Sequence to .mp4
|
|
||||||
with override_render_path(self, context, render_path.as_posix()):
|
|
||||||
with override_render_format(self, context):
|
|
||||||
bpy.ops.render.opengl(animation=True, sequencer=True)
|
|
||||||
|
|
||||||
# Create comment with video
|
|
||||||
task_entity = gazu.task.get_task(self.task,)
|
|
||||||
new_comment = gazu.task.add_comment(task_entity, task_entity["task_status"])
|
|
||||||
uploaded_preview = gazu.task.add_preview(task_entity, new_comment, render_path)
|
|
||||||
|
|
||||||
self.report(
|
|
||||||
{"INFO"},
|
|
||||||
f"Submitted new comment 'Revision {revision}'"
|
|
||||||
)
|
|
||||||
return {"FINISHED"}
|
|
||||||
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"
|
||||||
@ -2501,12 +2397,116 @@ class KITSU_OT_sqe_change_strip_source(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
def get_dict_len(items:dict):
|
||||||
|
try:
|
||||||
|
return len(items)
|
||||||
|
except TypeError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def set_revision_int(prev_rev=None):
|
||||||
|
if prev_rev is None:
|
||||||
|
return 1
|
||||||
|
return prev_rev+1
|
||||||
|
|
||||||
|
def get_enum_item_name(items, key):
|
||||||
|
for item in items:
|
||||||
|
if item[0] == key:
|
||||||
|
return item[1]
|
||||||
|
class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator):
|
||||||
|
bl_idname = "kitsu.vse_publish_edit_revision"
|
||||||
|
bl_label = "Render and 'Publish as Revision'"
|
||||||
|
bl_description = "Renders current VSE Edit as .mp4 and publishes as revision on 'Edit Task'"
|
||||||
|
|
||||||
|
def get_edit_entry_items(self: Any, context: bpy.types.Context) -> List[Tuple[str, str, str]]:
|
||||||
|
sorted_edits = []
|
||||||
|
active_project = cache.project_active_get()
|
||||||
|
|
||||||
|
for edit in gazu.edit.get_all_edits_with_tasks():
|
||||||
|
if (edit["project_id"] == active_project.id) and not edit['canceled']:
|
||||||
|
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]
|
||||||
|
|
||||||
|
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)
|
||||||
|
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")
|
||||||
|
edit_entry: bpy.props.EnumProperty(name="Edit Entry", items=get_edit_entry_items)
|
||||||
|
task: bpy.props.EnumProperty(name="Edit Tasks", items=get_edit_task_items)
|
||||||
|
render_dir: bpy.props.StringProperty(
|
||||||
|
name="Render Directory",
|
||||||
|
subtype="DIR_PATH",
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context: bpy.types.Context) -> bool:
|
||||||
|
return bool(
|
||||||
|
prefs.session_auth(context)
|
||||||
|
and cache.project_active_get()
|
||||||
|
)
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
# Remove file name if set in render.filepath
|
||||||
|
dir_path = bpy.path.abspath(context.scene.render.filepath)
|
||||||
|
if not os.path.isdir(Path(dir_path)):
|
||||||
|
dir_path = Path(dir_path).parent
|
||||||
|
self.render_dir = str(dir_path)
|
||||||
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
|
|
||||||
|
def draw(self, context: bpy.types.Context) -> None:
|
||||||
|
layout = self.layout
|
||||||
|
layout.prop(self, "edit_entry")
|
||||||
|
if len(self.get_edit_task_items(context)) >= 2:
|
||||||
|
layout.prop(self, "task")
|
||||||
|
layout.prop(self, "comment")
|
||||||
|
layout.prop(self, "render_dir")
|
||||||
|
|
||||||
|
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||||
|
if self.task == "":
|
||||||
|
self.report({"ERROR"}, "Selected edit doesn't have any task associated with it .")
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
active_project = cache.project_active_get()
|
||||||
|
|
||||||
|
existing_previews = gazu.edit.get_all_previews_for_edit(self.edit_entry)
|
||||||
|
len_previews = get_dict_len(existing_previews)
|
||||||
|
revision = set_revision_int(len_previews)
|
||||||
|
|
||||||
|
# Build render_path
|
||||||
|
render_dir = bpy.path.abspath(self.render_dir)
|
||||||
|
if not os.path.isdir(Path(render_dir)):
|
||||||
|
self.report(
|
||||||
|
{"ERROR"},
|
||||||
|
f"Render path is not set to a directory. '{self.render_dir}'"
|
||||||
|
)
|
||||||
|
return {"CANCELLED"}
|
||||||
|
edits = self.get_edit_entry_items(context)
|
||||||
|
edit_name = get_enum_item_name(edits, self.edit_entry)
|
||||||
|
render_name = f"{active_project.name}_{edit_name}_v{revision}.mp4"
|
||||||
|
render_path = Path(render_dir).joinpath(render_name)
|
||||||
|
|
||||||
|
# Render Sequence to .mp4
|
||||||
|
with override_render_path(self, context, render_path.as_posix()):
|
||||||
|
with override_render_format(self, context):
|
||||||
|
bpy.ops.render.opengl(animation=True, sequencer=True)
|
||||||
|
|
||||||
|
# Create comment with video
|
||||||
|
task_entity = gazu.task.get_task(self.task,)
|
||||||
|
new_comment = gazu.task.add_comment(task_entity, task_entity["task_status"])
|
||||||
|
uploaded_preview = gazu.task.add_preview(task_entity, new_comment, render_path)
|
||||||
|
|
||||||
|
self.report(
|
||||||
|
{"INFO"},
|
||||||
|
f"Submitted new comment 'Revision {revision}'"
|
||||||
|
)
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
# ---------REGISTER ----------.
|
# ---------REGISTER ----------.
|
||||||
|
|
||||||
classes = [
|
classes = [
|
||||||
KITSU_OT_sqe_push_new_sequence,
|
KITSU_OT_sqe_push_new_sequence,
|
||||||
KITSU_OT_sqe_push_new_shot,
|
KITSU_OT_sqe_push_new_shot,
|
||||||
KITSU_OT_sqe_push_new_edit,
|
|
||||||
KITSU_OT_sqe_push_shot_meta,
|
KITSU_OT_sqe_push_shot_meta,
|
||||||
KITSU_OT_sqe_uninit_strip,
|
KITSU_OT_sqe_uninit_strip,
|
||||||
KITSU_OT_sqe_unlink_shot,
|
KITSU_OT_sqe_unlink_shot,
|
||||||
@ -2531,6 +2531,8 @@ classes = [
|
|||||||
KITSU_OT_sqe_scan_for_media_updates,
|
KITSU_OT_sqe_scan_for_media_updates,
|
||||||
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,
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user