From 5b818313ce8642744c18a6579e195b0fe8dc08f4 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Tue, 11 Apr 2023 10:55:22 -0400 Subject: [PATCH 01/28] [Blender_Kitsu] Add `upload edit to Kitsu` operator - add a basic poll method - register operator --- blender_kitsu/sqe/ops.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 559b8b1c..299747df 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -308,6 +308,30 @@ class KITSU_OT_sqe_push_new_shot(bpy.types.Operator): ) +class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): + bl_idname = "kitsu.sqe_push_new_edit" + bl_label = "Submit New Kitsu Edit" + bl_description = "Creates a new edit on Kitsu server." + + confirm: bpy.props.BoolProperty(name="confirm") + + @classmethod + def poll(cls, context: bpy.types.Context) -> bool: + return bool( + prefs.session_auth(context) + and cache.project_active_get() + ) + + + def execute(self, context: bpy.types.Context) -> Set[str]: + + self.report( + {"INFO"}, + f"Submitted new edit", #TODO Add name of new edit + ) + return {"FINISHED"} + + class KITSU_OT_sqe_push_new_sequence(bpy.types.Operator): bl_idname = "kitsu.sqe_push_new_sequence" bl_label = "Submit New Sequence" @@ -2405,6 +2429,7 @@ class KITSU_OT_sqe_change_strip_source(bpy.types.Operator): classes = [ KITSU_OT_sqe_push_new_sequence, KITSU_OT_sqe_push_new_shot, + KITSU_OT_sqe_push_new_edit, KITSU_OT_sqe_push_shot_meta, KITSU_OT_sqe_uninit_strip, KITSU_OT_sqe_unlink_shot, -- 2.30.2 From 37c16734a8ad7ab762143385e6c80bf0d95a1907 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Tue, 11 Apr 2023 13:57:18 -0400 Subject: [PATCH 02/28] [Blender_Kitsu] Create gazu.edit sub-module --- blender_kitsu/gazu/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/blender_kitsu/gazu/__init__.py b/blender_kitsu/gazu/__init__.py index 13c2d546..14ce8de4 100644 --- a/blender_kitsu/gazu/__init__.py +++ b/blender_kitsu/gazu/__init__.py @@ -6,6 +6,7 @@ from . import asset from . import casting from . import context from . import entity +from . import edit from . import files from . import project from . import person -- 2.30.2 From 7472ec1cb374c4dd0ea5221d44fb144a0ddfc2a1 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Tue, 11 Apr 2023 13:59:10 -0400 Subject: [PATCH 03/28] [Blender_Kitsu] Add function to publish edit to Kitsu --- blender_kitsu/gazu/edit.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 blender_kitsu/gazu/edit.py diff --git a/blender_kitsu/gazu/edit.py b/blender_kitsu/gazu/edit.py new file mode 100644 index 00000000..b872d706 --- /dev/null +++ b/blender_kitsu/gazu/edit.py @@ -0,0 +1,32 @@ +from . import client as raw + +from .helpers import normalize_model_parameter + +default = raw.default_client + + +def new_edit( + project, + name=None, + description = "", + data={}, + client=default, +): + """ + Create a new edit within project. + + Args: + project (str / dict): The project dict or the project ID. + sequence (str / dict): The sequence dict or the sequence ID. + name (str): The name of the edit to create. + description (str): The name of the edit to create. + data (dict): Free field to set metadata of any kind. + + Returns: + Created edit. + """ + + project = normalize_model_parameter(project) + path = f"data/projects/{project['id']}/edits" + data = {"name": name, "description": description,} + return raw.post(path, data, client=client) \ No newline at end of file -- 2.30.2 From 2f308f0b0d127f2e13135abdff273b3a196180a9 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Tue, 11 Apr 2023 14:02:49 -0400 Subject: [PATCH 04/28] [Bledner_Kitsu] Call new_edit() in 'Submit New Edit to Kitsu' op - pass name and description as a string - Provide feedback to user about submitted file - Add TODO to pass actual render file --- blender_kitsu/sqe/ops.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 299747df..f55a4c9e 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -313,7 +313,8 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): bl_label = "Submit New Kitsu Edit" bl_description = "Creates a new edit on Kitsu server." - confirm: bpy.props.BoolProperty(name="confirm") + name: bpy.props.StringProperty(name="Edit Name") + description: bpy.props.StringProperty(name="Description") @classmethod def poll(cls, context: bpy.types.Context) -> bool: @@ -322,12 +323,25 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): and cache.project_active_get() ) + def invoke(self, context, event): + return context.window_manager.invoke_props_dialog(self) + + def draw(self, context: bpy.types.Context) -> None: + layout = self.layout + layout.prop(self, "name") + layout.prop(self, "description") def execute(self, context: bpy.types.Context) -> Set[str]: - + project_active = cache.project_active_get() + gazu.edit.new_edit( + project_active.id, + self.name, + self.description, + context.scene.frame_start, + ) #TODO Pass actual render file to this function self.report( {"INFO"}, - f"Submitted new edit", #TODO Add name of new edit + f"Submitted new edit '{self.name}'" ) return {"FINISHED"} -- 2.30.2 From f0a6170fedf5509c4b01e75cb46abcd5835d56b6 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Tue, 11 Apr 2023 15:01:00 -0400 Subject: [PATCH 05/28] [Blender_Kitsu] Make override_render_settings a generic function --- blender_kitsu/playblast/core.py | 169 ++++++++++++++++++++++++++++++++ blender_kitsu/playblast/ops.py | 168 +------------------------------ 2 files changed, 171 insertions(+), 166 deletions(-) create mode 100644 blender_kitsu/playblast/core.py diff --git a/blender_kitsu/playblast/core.py b/blender_kitsu/playblast/core.py new file mode 100644 index 00000000..fd16cbc4 --- /dev/null +++ b/blender_kitsu/playblast/core.py @@ -0,0 +1,169 @@ +import contextlib + +from blender_kitsu import ( + prefs, +) + +@contextlib.contextmanager +def override_render_settings(self, context, render_file_path): + """Overrides the render settings for playblast creation""" + addon_prefs = prefs.addon_prefs_get(context) + rd = context.scene.render + sps = context.space_data.shading + sp = context.space_data + # Get first last name for stamp note text. + session = prefs.session_get(context) + first_name = session.data.user["first_name"] + last_name = session.data.user["last_name"] + # Remember current render settings in order to restore them later. + + # Filepath. + filepath = rd.filepath + + # Format render settings. + percentage = rd.resolution_percentage + file_format = rd.image_settings.file_format + ffmpeg_constant_rate = rd.ffmpeg.constant_rate_factor + ffmpeg_codec = rd.ffmpeg.codec + ffmpeg_format = rd.ffmpeg.format + ffmpeg_audio_codec = rd.ffmpeg.audio_codec + + # Stamp metadata settings. + metadata_input = rd.metadata_input + use_stamp_date = rd.use_stamp_date + use_stamp_time = rd.use_stamp_time + use_stamp_render_time = rd.use_stamp_render_time + use_stamp_frame = rd.use_stamp_frame + use_stamp_frame_range = rd.use_stamp_frame_range + use_stamp_memory = rd.use_stamp_memory + use_stamp_hostname = rd.use_stamp_hostname + use_stamp_camera = rd.use_stamp_camera + use_stamp_lens = rd.use_stamp_lens + use_stamp_scene = rd.use_stamp_scene + use_stamp_marker = rd.use_stamp_marker + use_stamp_marker = rd.use_stamp_marker + use_stamp_note = rd.use_stamp_note + stamp_note_text = rd.stamp_note_text + use_stamp = rd.use_stamp + stamp_font_size = rd.stamp_font_size + stamp_foreground = rd.stamp_foreground + stamp_background = rd.stamp_background + use_stamp_labels = rd.use_stamp_labels + + # Space data settings. + shading_type = sps.type + shading_light = sps.light + studio_light = sps.studio_light + color_type = sps.color_type + background_type = sps.background_type + + show_backface_culling = sps.show_backface_culling + show_xray = sps.show_xray + show_shadows = sps.show_shadows + show_cavity = sps.show_cavity + show_object_outline = sps.show_object_outline + show_specular_highlight = sps.show_specular_highlight + + show_gizmo = sp.show_gizmo + + try: + # Filepath. + rd.filepath = render_file_path + + # Format render settings. + rd.resolution_percentage = 100 + rd.image_settings.file_format = "FFMPEG" + rd.ffmpeg.constant_rate_factor = "HIGH" + rd.ffmpeg.codec = "H264" + rd.ffmpeg.format = "MPEG4" + rd.ffmpeg.audio_codec = "AAC" + + # Stamp metadata settings. + rd.metadata_input = "SCENE" + rd.use_stamp_date = False + rd.use_stamp_time = False + rd.use_stamp_render_time = False + rd.use_stamp_frame = True + rd.use_stamp_frame_range = False + rd.use_stamp_memory = False + rd.use_stamp_hostname = False + rd.use_stamp_camera = False + rd.use_stamp_lens = True + rd.use_stamp_scene = False + rd.use_stamp_marker = False + rd.use_stamp_marker = False + rd.use_stamp_note = True + rd.stamp_note_text = f"Animator: {first_name} {last_name}" + rd.use_stamp = True + rd.stamp_font_size = 12 + rd.stamp_foreground = (0.8, 0.8, 0.8, 1) + rd.stamp_background = (0, 0, 0, 0.25) + rd.use_stamp_labels = True + + # Space data settings. + sps.type = "SOLID" + sps.light = "STUDIO" + sps.studio_light = "Default" + sps.color_type = "MATERIAL" + sps.background_type = "THEME" + + sps.show_backface_culling = False + sps.show_xray = False + sps.show_shadows = False + sps.show_cavity = False + sps.show_object_outline = False + sps.show_specular_highlight = True + + sp.show_gizmo = False + + yield + + finally: + # Filepath. + rd.filepath = filepath + + # Return the render settings to normal. + rd.resolution_percentage = percentage + rd.image_settings.file_format = file_format + rd.ffmpeg.codec = ffmpeg_codec + rd.ffmpeg.constant_rate_factor = ffmpeg_constant_rate + rd.ffmpeg.format = ffmpeg_format + rd.ffmpeg.audio_codec = ffmpeg_audio_codec + + # Stamp metadata settings. + rd.metadata_input = metadata_input + rd.use_stamp_date = use_stamp_date + rd.use_stamp_time = use_stamp_time + rd.use_stamp_render_time = use_stamp_render_time + rd.use_stamp_frame = use_stamp_frame + rd.use_stamp_frame_range = use_stamp_frame_range + rd.use_stamp_memory = use_stamp_memory + rd.use_stamp_hostname = use_stamp_hostname + rd.use_stamp_camera = use_stamp_camera + rd.use_stamp_lens = use_stamp_lens + rd.use_stamp_scene = use_stamp_scene + rd.use_stamp_marker = use_stamp_marker + rd.use_stamp_marker = use_stamp_marker + rd.use_stamp_note = use_stamp_note + rd.stamp_note_text = stamp_note_text + rd.use_stamp = use_stamp + rd.stamp_font_size = stamp_font_size + rd.stamp_foreground = stamp_foreground + rd.stamp_background = stamp_background + rd.use_stamp_labels = use_stamp_labels + + # Space data settings. + sps.type = shading_type + sps.light = shading_light + sps.studio_light = studio_light + sps.color_type = color_type + sps.background_type = background_type + + sps.show_backface_culling = show_backface_culling + sps.show_xray = show_xray + sps.show_shadows = show_shadows + sps.show_cavity = show_cavity + sps.show_object_outline = show_object_outline + sps.show_specular_highlight = show_specular_highlight + + sp.show_gizmo = show_gizmo \ No newline at end of file diff --git a/blender_kitsu/playblast/ops.py b/blender_kitsu/playblast/ops.py index 119737a9..387344b9 100644 --- a/blender_kitsu/playblast/ops.py +++ b/blender_kitsu/playblast/ops.py @@ -18,7 +18,6 @@ # # (c) 2023, Blender Foundation -import contextlib import webbrowser from pathlib import Path from typing import Dict, List, Set, Optional, Tuple, Any @@ -39,7 +38,7 @@ from blender_kitsu.types import ( TaskStatus, TaskType, ) - +from blender_kitsu.playblast.core import override_render_settings from blender_kitsu.playblast import opsdata logger = LoggerFactory.getLogger() @@ -92,7 +91,7 @@ class KITSU_OT_playblast_create(bpy.types.Operator): context.window_manager.progress_update(0) # Render and save playblast - with self.override_render_settings(context): + with override_render_settings(self, context, context.scene.kitsu.playblast_file): # Get output path. output_path = Path(context.scene.kitsu.playblast_file) @@ -264,169 +263,6 @@ class KITSU_OT_playblast_create(bpy.types.Operator): url = f"{host_url}/productions/{cache.project_active_get().id}/shots?search={cache.shot_active_get().name}" webbrowser.open(url) - @contextlib.contextmanager - def override_render_settings(self, context): - """Overrides the render settings for playblast creation""" - addon_prefs = prefs.addon_prefs_get(context) - rd = context.scene.render - sps = context.space_data.shading - sp = context.space_data - # Get first last name for stamp note text. - session = prefs.session_get(context) - first_name = session.data.user["first_name"] - last_name = session.data.user["last_name"] - # Remember current render settings in order to restore them later. - - # Filepath. - filepath = rd.filepath - - # Format render settings. - percentage = rd.resolution_percentage - file_format = rd.image_settings.file_format - ffmpeg_constant_rate = rd.ffmpeg.constant_rate_factor - ffmpeg_codec = rd.ffmpeg.codec - ffmpeg_format = rd.ffmpeg.format - ffmpeg_audio_codec = rd.ffmpeg.audio_codec - - # Stamp metadata settings. - metadata_input = rd.metadata_input - use_stamp_date = rd.use_stamp_date - use_stamp_time = rd.use_stamp_time - use_stamp_render_time = rd.use_stamp_render_time - use_stamp_frame = rd.use_stamp_frame - use_stamp_frame_range = rd.use_stamp_frame_range - use_stamp_memory = rd.use_stamp_memory - use_stamp_hostname = rd.use_stamp_hostname - use_stamp_camera = rd.use_stamp_camera - use_stamp_lens = rd.use_stamp_lens - use_stamp_scene = rd.use_stamp_scene - use_stamp_marker = rd.use_stamp_marker - use_stamp_marker = rd.use_stamp_marker - use_stamp_note = rd.use_stamp_note - stamp_note_text = rd.stamp_note_text - use_stamp = rd.use_stamp - stamp_font_size = rd.stamp_font_size - stamp_foreground = rd.stamp_foreground - stamp_background = rd.stamp_background - use_stamp_labels = rd.use_stamp_labels - - # Space data settings. - shading_type = sps.type - shading_light = sps.light - studio_light = sps.studio_light - color_type = sps.color_type - background_type = sps.background_type - - show_backface_culling = sps.show_backface_culling - show_xray = sps.show_xray - show_shadows = sps.show_shadows - show_cavity = sps.show_cavity - show_object_outline = sps.show_object_outline - show_specular_highlight = sps.show_specular_highlight - - show_gizmo = sp.show_gizmo - - try: - # Filepath. - rd.filepath = context.scene.kitsu.playblast_file - - # Format render settings. - rd.resolution_percentage = 100 - rd.image_settings.file_format = "FFMPEG" - rd.ffmpeg.constant_rate_factor = "HIGH" - rd.ffmpeg.codec = "H264" - rd.ffmpeg.format = "MPEG4" - rd.ffmpeg.audio_codec = "AAC" - - # Stamp metadata settings. - rd.metadata_input = "SCENE" - rd.use_stamp_date = False - rd.use_stamp_time = False - rd.use_stamp_render_time = False - rd.use_stamp_frame = True - rd.use_stamp_frame_range = False - rd.use_stamp_memory = False - rd.use_stamp_hostname = False - rd.use_stamp_camera = False - rd.use_stamp_lens = True - rd.use_stamp_scene = False - rd.use_stamp_marker = False - rd.use_stamp_marker = False - rd.use_stamp_note = True - rd.stamp_note_text = f"Animator: {first_name} {last_name}" - rd.use_stamp = True - rd.stamp_font_size = 12 - rd.stamp_foreground = (0.8, 0.8, 0.8, 1) - rd.stamp_background = (0, 0, 0, 0.25) - rd.use_stamp_labels = True - - # Space data settings. - sps.type = "SOLID" - sps.light = "STUDIO" - sps.studio_light = "Default" - sps.color_type = "MATERIAL" - sps.background_type = "THEME" - - sps.show_backface_culling = False - sps.show_xray = False - sps.show_shadows = False - sps.show_cavity = False - sps.show_object_outline = False - sps.show_specular_highlight = True - - sp.show_gizmo = False - - yield - - finally: - # Filepath. - rd.filepath = filepath - - # Return the render settings to normal. - rd.resolution_percentage = percentage - rd.image_settings.file_format = file_format - rd.ffmpeg.codec = ffmpeg_codec - rd.ffmpeg.constant_rate_factor = ffmpeg_constant_rate - rd.ffmpeg.format = ffmpeg_format - rd.ffmpeg.audio_codec = ffmpeg_audio_codec - - # Stamp metadata settings. - rd.metadata_input = metadata_input - rd.use_stamp_date = use_stamp_date - rd.use_stamp_time = use_stamp_time - rd.use_stamp_render_time = use_stamp_render_time - rd.use_stamp_frame = use_stamp_frame - rd.use_stamp_frame_range = use_stamp_frame_range - rd.use_stamp_memory = use_stamp_memory - rd.use_stamp_hostname = use_stamp_hostname - rd.use_stamp_camera = use_stamp_camera - rd.use_stamp_lens = use_stamp_lens - rd.use_stamp_scene = use_stamp_scene - rd.use_stamp_marker = use_stamp_marker - rd.use_stamp_marker = use_stamp_marker - rd.use_stamp_note = use_stamp_note - rd.stamp_note_text = stamp_note_text - rd.use_stamp = use_stamp - rd.stamp_font_size = stamp_font_size - rd.stamp_foreground = stamp_foreground - rd.stamp_background = stamp_background - rd.use_stamp_labels = use_stamp_labels - - # Space data settings. - sps.type = shading_type - sps.light = shading_light - sps.studio_light = studio_light - sps.color_type = color_type - sps.background_type = background_type - - sps.show_backface_culling = show_backface_culling - sps.show_xray = show_xray - sps.show_shadows = show_shadows - sps.show_cavity = show_cavity - sps.show_object_outline = show_object_outline - sps.show_specular_highlight = show_specular_highlight - - sp.show_gizmo = show_gizmo class KITSU_OT_playblast_set_version(bpy.types.Operator): -- 2.30.2 From 63991eaaa4e42212aa93e72c040ffdbb5c3682e2 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Tue, 11 Apr 2023 16:09:26 -0400 Subject: [PATCH 06/28] [Blender_Kitsu] Render File and submit path to Kitsu - Pass Rendered_filepath to new_edit() - Temoprarily construct rebder path path - Add TODO for bad server response - Using upload method similar to`playblast.ops.KITSU_OT_playblast_create` --- blender_kitsu/gazu/edit.py | 8 ++++++-- blender_kitsu/sqe/ops.py | 14 ++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/blender_kitsu/gazu/edit.py b/blender_kitsu/gazu/edit.py index b872d706..3f9053a7 100644 --- a/blender_kitsu/gazu/edit.py +++ b/blender_kitsu/gazu/edit.py @@ -9,6 +9,7 @@ def new_edit( project, name=None, description = "", + rendered_filepath = None, data={}, client=default, ): @@ -25,8 +26,11 @@ def new_edit( Returns: Created edit. """ - + project = normalize_model_parameter(project) path = f"data/projects/{project['id']}/edits" data = {"name": name, "description": description,} - return raw.post(path, data, client=client) \ No newline at end of file + new_edit = raw.post(path, data, client=client) + upload_path = f"{path}/{new_edit['id']}" + raw.upload(upload_path, rendered_filepath, client=client) + return new_edit \ No newline at end of file diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index f55a4c9e..eda55ba3 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -40,6 +40,8 @@ from blender_kitsu.types import ( Task, ) +from blender_kitsu.playblast.core import override_render_settings + logger = LoggerFactory.getLogger() @@ -333,12 +335,16 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): def execute(self, context: bpy.types.Context) -> Set[str]: project_active = cache.project_active_get() + render_path = f"{context.scene.kitsu.playblast_dir}{self.name}.mp4" # TODO FIX SAVES RENDER NEXT TO SHOT FILE + with override_render_settings(self, context, render_path): + bpy.ops.render.opengl(animation=True, sequencer=True) gazu.edit.new_edit( project_active.id, self.name, self.description, + Path(render_path), context.scene.frame_start, - ) #TODO Pass actual render file to this function + ) #TODO This fails to upload returns 500 Code self.report( {"INFO"}, f"Submitted new edit '{self.name}'" @@ -1442,11 +1448,7 @@ class KITSU_OT_sqe_push_render(bpy.types.Operator): logger.info("-END- Pushing Sequence Editor Render") return {"FINISHED"} - def _gen_output_path(self, strip: bpy.types.Sequence, task_type: TaskType) -> Path: - addon_prefs = prefs.addon_prefs_get(bpy.context) - folder_name = addon_prefs.sqe_render_dir - file_name = f"{strip.kitsu.shot_id}_{strip.kitsu.shot_name}.{(task_type.name).lower()}.mp4" - return Path(folder_name).absolute().joinpath(file_name) + @contextlib.contextmanager def override_render_settings(self, context, thumbnail_width=256): -- 2.30.2 From 16fe6f705890913deaa89fd2a8bd12ac5152c4c4 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Wed, 12 Apr 2023 14:55:14 -0400 Subject: [PATCH 07/28] [Blender_Kitsu] Submit Render as Comment to Edit Task - This is a simple implementation of the task but it is working! - rename new_edit() to add_comment_on_edit_task() -pass only render_path, task_id and comment -pass task_id via UI -pass comment via UI - Update TODOs --- blender_kitsu/gazu/edit.py | 37 ++++++++++--------------------------- blender_kitsu/sqe/ops.py | 35 ++++++++++++++++++----------------- 2 files changed, 28 insertions(+), 44 deletions(-) diff --git a/blender_kitsu/gazu/edit.py b/blender_kitsu/gazu/edit.py index 3f9053a7..87c8b485 100644 --- a/blender_kitsu/gazu/edit.py +++ b/blender_kitsu/gazu/edit.py @@ -1,36 +1,19 @@ -from . import client as raw +from blender_kitsu import gazu -from .helpers import normalize_model_parameter - -default = raw.default_client - - -def new_edit( - project, - name=None, - description = "", - rendered_filepath = None, - data={}, - client=default, +def add_comment_on_edit_task(task_id:str, + rendered_filepath = None, comment="" ): """ - Create a new edit within project. + Comment Full Edit Render on Edit Task Args: - project (str / dict): The project dict or the project ID. - sequence (str / dict): The sequence dict or the sequence ID. - name (str): The name of the edit to create. - description (str): The name of the edit to create. - data (dict): Free field to set metadata of any kind. + #TODO Returns: - Created edit. + Comment on Edit Task. """ - project = normalize_model_parameter(project) - path = f"data/projects/{project['id']}/edits" - data = {"name": name, "description": description,} - new_edit = raw.post(path, data, client=client) - upload_path = f"{path}/{new_edit['id']}" - raw.upload(upload_path, rendered_filepath, client=client) - return new_edit \ No newline at end of file + task_entity = gazu.task.get_task(task_id) + new_comment = gazu.task.add_comment(task_entity, task_entity["task_status"], comment) + uploaded_preview = gazu.task.add_preview(task_entity, new_comment, rendered_filepath) + return new_comment \ No newline at end of file diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index eda55ba3..14b8641b 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -311,12 +311,15 @@ class KITSU_OT_sqe_push_new_shot(bpy.types.Operator): class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): - bl_idname = "kitsu.sqe_push_new_edit" - bl_label = "Submit New Kitsu Edit" - bl_description = "Creates a new edit on Kitsu server." + 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." - name: bpy.props.StringProperty(name="Edit Name") - description: bpy.props.StringProperty(name="Description") + comment: bpy.props.StringProperty(name="comment") + task_id: bpy.props.StringProperty( #TODO Make an Enum (allow user to select both [Edit>Task]) + name="Task ID", + default='6dec9e11-34c0-408a-b828-6a3c638e191f' #TODO Remove temporary default for testing + ) @classmethod def poll(cls, context: bpy.types.Context) -> bool: @@ -330,24 +333,22 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): def draw(self, context: bpy.types.Context) -> None: layout = self.layout - layout.prop(self, "name") - layout.prop(self, "description") + layout.prop(self, "task_id") + layout.prop(self, "comment") def execute(self, context: bpy.types.Context) -> Set[str]: - project_active = cache.project_active_get() - render_path = f"{context.scene.kitsu.playblast_dir}{self.name}.mp4" # TODO FIX SAVES RENDER NEXT TO SHOT FILE + render_path = f"{context.scene.kitsu.playblast_dir}{self.name}.mp4" # TODO FIX RENDER PATH/FILENAME with override_render_settings(self, context, render_path): bpy.ops.render.opengl(animation=True, sequencer=True) - gazu.edit.new_edit( - project_active.id, - self.name, - self.description, - Path(render_path), - context.scene.frame_start, - ) #TODO This fails to upload returns 500 Code + + gazu.edit.add_comment_on_edit_task( + self.task_id, + render_path, + self.comment + ) self.report( {"INFO"}, - f"Submitted new edit '{self.name}'" + f"Submitted new comment '{self.name}'" ) return {"FINISHED"} -- 2.30.2 From 4956a2557b0d93ceef2d5afb88ca7c1d5296bd71 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Wed, 12 Apr 2023 16:49:54 -0400 Subject: [PATCH 08/28] [Blender_Kitsu] Gazu add get_all_edits() function --- blender_kitsu/gazu/edit.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/blender_kitsu/gazu/edit.py b/blender_kitsu/gazu/edit.py index 87c8b485..144cdc77 100644 --- a/blender_kitsu/gazu/edit.py +++ b/blender_kitsu/gazu/edit.py @@ -1,4 +1,22 @@ from blender_kitsu import gazu +from . import client as raw +from .sorting import sort_by_name + +from .cache import cache + +default = raw.default_client + +@cache +def get_all_edits(relations=False, client=default): + """ + Retrieve all edit entries. + """ + params = {} + if relations: + params = {"relations": "true"} + path = "edits/all" + edits = raw.fetch_all(path, params, client=client) + return sort_by_name(edits) def add_comment_on_edit_task(task_id:str, rendered_filepath = None, comment="" -- 2.30.2 From c309dd45cd39b6e649a8801b09735bb26a182599 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Wed, 12 Apr 2023 16:51:55 -0400 Subject: [PATCH 09/28] [Blender_Kitsu] Gazu add all_tasks_for_edit() function --- blender_kitsu/gazu/task.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/blender_kitsu/gazu/task.py b/blender_kitsu/gazu/task.py index 98326e64..27121777 100644 --- a/blender_kitsu/gazu/task.py +++ b/blender_kitsu/gazu/task.py @@ -147,6 +147,20 @@ def all_tasks_for_episode(episode, relations=False, client=default): return sort_by_name(tasks) +@cache +def all_tasks_for_edit(edit, relations=False, client=default): + """ + Retrieve all tasks directly linked to given edit. + """ + edit = normalize_model_parameter(edit) + params = {} + if relations: + params = {"relations": "true"} + path = "edits/%s/tasks" % edit["id"] + tasks = raw.fetch_all(path, params, client=client) + return sort_by_name(tasks) + + @cache def all_shot_tasks_for_sequence(sequence, relations=False, client=default): """ -- 2.30.2 From ebcbf296888115163e3c062edc994ccc44524772 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Wed, 12 Apr 2023 17:19:39 -0400 Subject: [PATCH 10/28] [Blender Kitsu] Return Edits & Tasks submit edit comment op - Add Enum for Edit Entry - Add Enum for Tasks - Use Gazu get_all_edits() and get_all_tasks_for_edit() in enum item - Allow User to select Edit and Task --- blender_kitsu/sqe/ops.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 14b8641b..01310bbc 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -40,7 +40,7 @@ from blender_kitsu.types import ( Task, ) -from blender_kitsu.playblast.core import override_render_settings +from blender_kitsu.playblast.core import override_render_path logger = LoggerFactory.getLogger() @@ -315,11 +315,17 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): bl_label = "Submit New Kitsu Edit Comment" bl_description = "Creates a new edit comment on Edit task via ID." + def get_edit_entry_enum(self: Any, context: bpy.types.Context) -> List[Tuple[str, str, str]]: + edits = gazu.edit.get_all_edits() + return [(item.get("id"), item.get("name"), f'Created at: "{item.get("created_at")}" {item.get("description")}') for item in 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") - task_id: bpy.props.StringProperty( #TODO Make an Enum (allow user to select both [Edit>Task]) - name="Task ID", - default='6dec9e11-34c0-408a-b828-6a3c638e191f' #TODO Remove temporary default for testing - ) + edit_entry: bpy.props.EnumProperty(name="Edit Entry", items=get_edit_entry_enum) + task: bpy.props.EnumProperty(name="Edit Tasks", items=get_edit_task_items) @classmethod def poll(cls, context: bpy.types.Context) -> bool: @@ -333,16 +339,16 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): def draw(self, context: bpy.types.Context) -> None: layout = self.layout - layout.prop(self, "task_id") + layout.prop(self, "edit_entry") + layout.prop(self, "task") layout.prop(self, "comment") def execute(self, context: bpy.types.Context) -> Set[str]: render_path = f"{context.scene.kitsu.playblast_dir}{self.name}.mp4" # TODO FIX RENDER PATH/FILENAME - with override_render_settings(self, context, render_path): - bpy.ops.render.opengl(animation=True, sequencer=True) - + with override_render_path(self, context, render_path): + bpy.ops.render.opengl(animation=True, sequencer=True) gazu.edit.add_comment_on_edit_task( - self.task_id, + self.task, render_path, self.comment ) -- 2.30.2 From 44397b63af3b16eee729c07f5bf5396b6f711b84 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Wed, 12 Apr 2023 17:20:36 -0400 Subject: [PATCH 11/28] [Blender_Kitsu] playblast.core add contextmanager for file_path --- blender_kitsu/playblast/core.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/blender_kitsu/playblast/core.py b/blender_kitsu/playblast/core.py index fd16cbc4..f6dd6dd5 100644 --- a/blender_kitsu/playblast/core.py +++ b/blender_kitsu/playblast/core.py @@ -4,6 +4,24 @@ from blender_kitsu import ( prefs, ) +@contextlib.contextmanager +def override_render_path(self, context, render_file_path): + """Overrides the render settings for playblast creation""" + rd = context.scene.render + # Filepath. + filepath = rd.filepath + + try: + # Filepath. + rd.filepath = render_file_path + + yield + + finally: + # Filepath. + rd.filepath = filepath + + @contextlib.contextmanager def override_render_settings(self, context, render_file_path): """Overrides the render settings for playblast creation""" -- 2.30.2 From 5be2785e81e3656a06c47f071ec1e92fd86fa0de Mon Sep 17 00:00:00 2001 From: TinyNick Date: Wed, 12 Apr 2023 17:54:39 -0400 Subject: [PATCH 12/28] [Blender_Kitsu] playblast.core Add override_render_format() --- blender_kitsu/playblast/core.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/blender_kitsu/playblast/core.py b/blender_kitsu/playblast/core.py index f6dd6dd5..739b3a6d 100644 --- a/blender_kitsu/playblast/core.py +++ b/blender_kitsu/playblast/core.py @@ -4,6 +4,37 @@ from blender_kitsu import ( prefs, ) + +@contextlib.contextmanager +def override_render_format(self, context): + """Overrides the render settings for playblast creation""" + rd = context.scene.render + # Format render settings. + percentage = rd.resolution_percentage + file_format = rd.image_settings.file_format + ffmpeg_constant_rate = rd.ffmpeg.constant_rate_factor + ffmpeg_codec = rd.ffmpeg.codec + ffmpeg_format = rd.ffmpeg.format + ffmpeg_audio_codec = rd.ffmpeg.audio_codec + + try: + rd.resolution_percentage = 100 + rd.image_settings.file_format = "FFMPEG" + rd.ffmpeg.constant_rate_factor = "HIGH" + rd.ffmpeg.codec = "H264" + rd.ffmpeg.format = "MPEG4" + rd.ffmpeg.audio_codec = "AAC" + + yield + + finally: + rd.resolution_percentage = percentage + rd.image_settings.file_format = file_format + rd.ffmpeg.codec = ffmpeg_codec + rd.ffmpeg.constant_rate_factor = ffmpeg_constant_rate + rd.ffmpeg.format = ffmpeg_format + rd.ffmpeg.audio_codec = ffmpeg_audio_codec + @contextlib.contextmanager def override_render_path(self, context, render_file_path): """Overrides the render settings for playblast creation""" -- 2.30.2 From 85cac212a2d984673966f5ea6868cb7ca2044e04 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Wed, 12 Apr 2023 18:54:49 -0400 Subject: [PATCH 13/28] [Blender_Kitsu] Improve submit edit comment op - Pass Render Path in UI - Pass Render Path in Directory - Fix Render Path - Use user renderpath in invoke - create meaningful comment message with timestamp and rendered filename --- blender_kitsu/sqe/ops.py | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 01310bbc..0b45cf7f 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -24,7 +24,7 @@ import colorsys import random from pathlib import Path from typing import Dict, List, Set, Optional, Tuple, Any - +import datetime import bpy from blender_kitsu import gazu, cache, util, prefs, bkglobals @@ -40,7 +40,7 @@ from blender_kitsu.types import ( Task, ) -from blender_kitsu.playblast.core import override_render_path +from blender_kitsu.playblast.core import override_render_path, override_render_format logger = LoggerFactory.getLogger() @@ -326,6 +326,14 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): comment: bpy.props.StringProperty(name="comment") edit_entry: bpy.props.EnumProperty(name="Edit Entry", items=get_edit_entry_enum) task: bpy.props.EnumProperty(name="Edit Tasks", items=get_edit_task_items) + render_dir: bpy.props.StringProperty( + name="Render Directory", + subtype="DIR_PATH", + ) + render_name: bpy.props.StringProperty( + name="Render Name", + description="Name of Render file WITHOUT extension", + ) @classmethod def poll(cls, context: bpy.types.Context) -> bool: @@ -335,6 +343,8 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): ) def invoke(self, context, event): + self.render_dir = context.scene.render.filepath.rsplit("\\", 1)[0] + self.render_name = bpy.path.basename(context.blend_data.filepath).replace('.blend','') return context.window_manager.invoke_props_dialog(self) def draw(self, context: bpy.types.Context) -> None: @@ -342,19 +352,33 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): layout.prop(self, "edit_entry") layout.prop(self, "task") layout.prop(self, "comment") + layout.prop(self, "render_dir") + layout.prop(self, "render_name") def execute(self, context: bpy.types.Context) -> Set[str]: - render_path = f"{context.scene.kitsu.playblast_dir}{self.name}.mp4" # TODO FIX RENDER PATH/FILENAME - with override_render_path(self, context, render_path): - bpy.ops.render.opengl(animation=True, sequencer=True) + # Build render_path + render_dir = bpy.path.abspath(self.render_dir) + render_name = f"{self.render_name.replace('.','_')}.mp4" + render_path = Path(render_dir).joinpath(render_name) + + # Build Comment + time = str(datetime.datetime.now()) + message = f"{self.comment}\n\n\nFile: {render_name} \n\nSubmitted on: {time}" + + # 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) + + # Submit to Kitsu Edit Task gazu.edit.add_comment_on_edit_task( self.task, render_path, - self.comment + message ) self.report( {"INFO"}, - f"Submitted new comment '{self.name}'" + f"Submitted new comment for render'{self.render_name}'" ) return {"FINISHED"} -- 2.30.2 From 59785f8437b70987774f1c23c2ea6283cf657967 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Thu, 13 Apr 2023 13:54:49 -0400 Subject: [PATCH 14/28] [Blender_Kitsu] gazu add get_all_edits_with_tasks() --- blender_kitsu/gazu/edit.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/blender_kitsu/gazu/edit.py b/blender_kitsu/gazu/edit.py index 144cdc77..bfff0d26 100644 --- a/blender_kitsu/gazu/edit.py +++ b/blender_kitsu/gazu/edit.py @@ -18,6 +18,18 @@ def get_all_edits(relations=False, client=default): edits = raw.fetch_all(path, params, client=client) return sort_by_name(edits) +@cache +def get_all_edits_with_tasks(relations=False, client=default): + """ + Retrieve all edit entries. + """ + params = {} + if relations: + params = {"relations": "true"} + path = "edits/with-tasks" + edits_with_tasks = raw.fetch_all(path, params, client=client) + return sort_by_name(edits_with_tasks) + def add_comment_on_edit_task(task_id:str, rendered_filepath = None, comment="" ): -- 2.30.2 From 8bba239422769df1e126010afe4f99e31615b2d0 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Thu, 13 Apr 2023 13:55:52 -0400 Subject: [PATCH 15/28] [Blender_Kitsu] Gazu add get_all_previews_for_edit() --- blender_kitsu/gazu/edit.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/blender_kitsu/gazu/edit.py b/blender_kitsu/gazu/edit.py index bfff0d26..6ccca52b 100644 --- a/blender_kitsu/gazu/edit.py +++ b/blender_kitsu/gazu/edit.py @@ -3,6 +3,7 @@ from . import client as raw from .sorting import sort_by_name from .cache import cache +from .helpers import normalize_model_parameter default = raw.default_client @@ -46,4 +47,18 @@ def add_comment_on_edit_task(task_id:str, task_entity = gazu.task.get_task(task_id) new_comment = gazu.task.add_comment(task_entity, task_entity["task_status"], comment) uploaded_preview = gazu.task.add_preview(task_entity, new_comment, rendered_filepath) - return new_comment \ No newline at end of file + return new_comment + +@cache +def get_all_previews_for_edit(edit, client=default): + """ + Args: + episode (str / dict): The episode dict or the episode ID. + + Returns: + list: Shots which are children of given episode. + """ + edit = normalize_model_parameter(edit) + edit_previews = (raw.fetch_all(f"edits/{edit['id']}/preview-files", client=client)) + for key in [key for key in enumerate(edit_previews.keys())]: + return edit_previews[key[1]] \ No newline at end of file -- 2.30.2 From 774a25689065d9aa35ee2227bc8d5df52e0e07b3 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Thu, 13 Apr 2023 13:57:28 -0400 Subject: [PATCH 16/28] [Blender_Kitsu] submit edit comment early return if no task is found --- blender_kitsu/sqe/ops.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 0b45cf7f..0c9933b8 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -356,6 +356,10 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): layout.prop(self, "render_name") 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"} + # Build render_path render_dir = bpy.path.abspath(self.render_dir) render_name = f"{self.render_name.replace('.','_')}.mp4" -- 2.30.2 From 8377fce1ad8aaef6ec72b5ad5a2e481cf3ee9010 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Thu, 13 Apr 2023 14:01:00 -0400 Subject: [PATCH 17/28] [Blender Kitsu] Edit_Comment only show task if >2 are found --- blender_kitsu/sqe/ops.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 0c9933b8..200a9567 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -350,7 +350,8 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): def draw(self, context: bpy.types.Context) -> None: layout = self.layout layout.prop(self, "edit_entry") - layout.prop(self, "task") + if len(self.get_edit_task_items(context)) >= 2: + layout.prop(self, "task") layout.prop(self, "comment") layout.prop(self, "render_dir") layout.prop(self, "render_name") -- 2.30.2 From d3d703c5aedb97d2481ef1643981217082c0a5d1 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Thu, 13 Apr 2023 14:02:36 -0400 Subject: [PATCH 18/28] [Blender_Kitsu] Edit_Comment remove self.render_name --- blender_kitsu/sqe/ops.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 200a9567..0bff70b5 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -330,10 +330,6 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): name="Render Directory", subtype="DIR_PATH", ) - render_name: bpy.props.StringProperty( - name="Render Name", - description="Name of Render file WITHOUT extension", - ) @classmethod def poll(cls, context: bpy.types.Context) -> bool: @@ -354,7 +350,6 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): layout.prop(self, "task") layout.prop(self, "comment") layout.prop(self, "render_dir") - layout.prop(self, "render_name") def execute(self, context: bpy.types.Context) -> Set[str]: if self.task == "": -- 2.30.2 From 87e0066618c72fb7dce1805d0d1339f699c27e41 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Thu, 13 Apr 2023 14:05:09 -0400 Subject: [PATCH 19/28] [Blender_Kistu] Edit_Comment use user's render dir - Use scene.render.filepath in invoke - remove filename if path is not dictory - allow user to change path, early return if it's not a directory during exec --- blender_kitsu/sqe/ops.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 0bff70b5..278753bb 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -324,7 +324,7 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): 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_enum) + edit_entry: bpy.props.EnumProperty(name="Edit Entry", items=get_edit_entry_enum_key) task: bpy.props.EnumProperty(name="Edit Tasks", items=get_edit_task_items) render_dir: bpy.props.StringProperty( name="Render Directory", @@ -339,8 +339,11 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): ) def invoke(self, context, event): - self.render_dir = context.scene.render.filepath.rsplit("\\", 1)[0] - self.render_name = bpy.path.basename(context.blend_data.filepath).replace('.blend','') + # 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: @@ -358,6 +361,12 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): # 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"} render_name = f"{self.render_name.replace('.','_')}.mp4" render_path = Path(render_dir).joinpath(render_name) -- 2.30.2 From fd5851c4f8a68678f32ce9c32889a7920897fdde Mon Sep 17 00:00:00 2001 From: TinyNick Date: Thu, 13 Apr 2023 14:09:12 -0400 Subject: [PATCH 20/28] [Blender_Kitsu] Edit_Comment only return relevant edit_entry_items - skip if edit is has no task via gazu function - skip if not in current active project - skip if 'canceled' --- blender_kitsu/sqe/ops.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 278753bb..958e00e9 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -314,10 +314,16 @@ 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() - def get_edit_entry_enum(self: Any, context: bpy.types.Context) -> List[Tuple[str, str, str]]: - edits = gazu.edit.get_all_edits() - return [(item.get("id"), item.get("name"), f'Created at: "{item.get("created_at")}" {item.get("description")}') for item in edits] + 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) -- 2.30.2 From 3af7d7b0a081a156a1bc8446927087fecdc2e6de Mon Sep 17 00:00:00 2001 From: TinyNick Date: Thu, 13 Apr 2023 14:18:46 -0400 Subject: [PATCH 21/28] [Blender_Kitsu] Edit_Comment give render relevant filename - Use project name in render_filename - add function to find name of enum entry - Use edit entry name in render_filename - add revision number to filename from previews length - create revision int safely in function - remove add_comment_on_edit_task() move into main op instead (wasn't relevant in gazu.edit module) --- blender_kitsu/gazu/edit.py | 18 --------------- blender_kitsu/sqe/ops.py | 47 +++++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/blender_kitsu/gazu/edit.py b/blender_kitsu/gazu/edit.py index 6ccca52b..8d8e2873 100644 --- a/blender_kitsu/gazu/edit.py +++ b/blender_kitsu/gazu/edit.py @@ -31,24 +31,6 @@ def get_all_edits_with_tasks(relations=False, client=default): edits_with_tasks = raw.fetch_all(path, params, client=client) return sort_by_name(edits_with_tasks) -def add_comment_on_edit_task(task_id:str, - rendered_filepath = None, comment="" -): - """ - Comment Full Edit Render on Edit Task - - Args: - #TODO - - Returns: - Comment on Edit Task. - """ - - task_entity = gazu.task.get_task(task_id) - new_comment = gazu.task.add_comment(task_entity, task_entity["task_status"], comment) - uploaded_preview = gazu.task.add_preview(task_entity, new_comment, rendered_filepath) - return new_comment - @cache def get_all_previews_for_edit(edit, client=default): """ diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 958e00e9..bd8fcc42 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -309,7 +309,21 @@ class KITSU_OT_sqe_push_new_shot(bpy.types.Operator): % (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" @@ -330,7 +344,7 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): 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_enum_key) + 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", @@ -365,6 +379,12 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): 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)): @@ -373,31 +393,26 @@ class KITSU_OT_sqe_push_new_edit(bpy.types.Operator): f"Render path is not set to a directory. '{self.render_dir}'" ) return {"CANCELLED"} - render_name = f"{self.render_name.replace('.','_')}.mp4" + 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) - - # Build Comment - time = str(datetime.datetime.now()) - message = f"{self.comment}\n\n\nFile: {render_name} \n\nSubmitted on: {time}" - + # 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) - # Submit to Kitsu Edit Task - gazu.edit.add_comment_on_edit_task( - self.task, - render_path, - message - ) + # 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 for render'{self.render_name}'" + f"Submitted new comment 'Revision {revision}'" ) return {"FINISHED"} - - class KITSU_OT_sqe_push_new_sequence(bpy.types.Operator): bl_idname = "kitsu.sqe_push_new_sequence" bl_label = "Submit New Sequence" -- 2.30.2 From b8b550c35459be125d2bccfd605efb749ac7d061 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Thu, 13 Apr 2023 15:39:54 -0400 Subject: [PATCH 22/28] [Blender_Kitsu] Edit_Comment rename to Publish_Edit_Revision - Rename BL_Info to `vse_publish_edit_revision` - Rename operator class - Move class to bottom of file --- blender_kitsu/sqe/ops.py | 212 ++++++++++++++++++++------------------- 1 file changed, 107 insertions(+), 105 deletions(-) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index bd8fcc42..0966d5bb 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -309,110 +309,6 @@ class KITSU_OT_sqe_push_new_shot(bpy.types.Operator): % (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): bl_idname = "kitsu.sqe_push_new_sequence" bl_label = "Submit New Sequence" @@ -2501,12 +2397,116 @@ class KITSU_OT_sqe_change_strip_source(bpy.types.Operator): 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 ----------. classes = [ KITSU_OT_sqe_push_new_sequence, KITSU_OT_sqe_push_new_shot, - KITSU_OT_sqe_push_new_edit, KITSU_OT_sqe_push_shot_meta, KITSU_OT_sqe_uninit_strip, KITSU_OT_sqe_unlink_shot, @@ -2531,6 +2531,8 @@ classes = [ KITSU_OT_sqe_scan_for_media_updates, KITSU_OT_sqe_change_strip_source, KITSU_OT_sqe_clear_update_indicators, + KITSU_OT_vse_publish_edit_revision, + ] -- 2.30.2 From 5b573c04766deadf0e66710409127d32a6c8c1d2 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Thu, 13 Apr 2023 15:40:28 -0400 Subject: [PATCH 23/28] [Blender_Kitsu] Add 'Publish Edit Revision' to VSE UI --- blender_kitsu/sqe/ui.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/blender_kitsu/sqe/ui.py b/blender_kitsu/sqe/ui.py index 681a6eee..25584414 100644 --- a/blender_kitsu/sqe/ui.py +++ b/blender_kitsu/sqe/ui.py @@ -735,6 +735,14 @@ class KITSU_PT_sqe_general_tools(bpy.types.Panel): KITSU_OT_sqe_change_strip_source.bl_idname, text="", icon="FILE_PARENT" ).go_latest = True + # Create box. + layout = self.layout + box = layout.box() + box.label(text="Edit Tasks", icon="SEQ_SEQUENCER") + + # Scan for outdated media and reset operator. + row = box.row(align=True) + row.operator("kitsu.vse_publish_edit_revision") # ---------REGISTER ----------. -- 2.30.2 From 0fe7fb56f6e4ff080f555c93364af286800c14b4 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Fri, 14 Apr 2023 11:34:59 -0400 Subject: [PATCH 24/28] [Blender_Kitsu] gazu.edit add get_edit() function --- blender_kitsu/gazu/edit.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/blender_kitsu/gazu/edit.py b/blender_kitsu/gazu/edit.py index 8d8e2873..178f5464 100644 --- a/blender_kitsu/gazu/edit.py +++ b/blender_kitsu/gazu/edit.py @@ -19,6 +19,19 @@ def get_all_edits(relations=False, client=default): edits = raw.fetch_all(path, params, client=client) return sort_by_name(edits) +@cache +def get_edit(edit_id, relations=False, client=default): + """ + Retrieve all edit entries. + """ + edit_entry = normalize_model_parameter(edit_id) + params = {} + if relations: + params = {"relations": "true"} + path = f"edits/{edit_entry['id']}" + edit_entry = raw.fetch_all(path, params, client=client) + return edit_entry + @cache def get_all_edits_with_tasks(relations=False, client=default): """ -- 2.30.2 From 1cdc515034bc4c5fb5e85a318f766bd2c5ba5720 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Fri, 14 Apr 2023 11:36:36 -0400 Subject: [PATCH 25/28] [Blender_Kitsu] Publush_Edit_Rev use get_edit() --- blender_kitsu/sqe/ops.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index 0966d5bb..e4ac4098 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -2407,11 +2407,6 @@ 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'" @@ -2481,9 +2476,8 @@ class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator): 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" + edit_entry = gazu.edit.get_edit(self.edit_entry) + render_name = f"{active_project.name}_{edit_entry.get('name')}_v{revision}.mp4" render_path = Path(render_dir).joinpath(render_name) # Render Sequence to .mp4 -- 2.30.2 From dfaec5f3e7e5ad674eec8eb2bd1af74db99d97d0 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Fri, 14 Apr 2023 12:26:31 -0400 Subject: [PATCH 26/28] [Blender_Kitsu] gazu.entity add update_entity() function --- blender_kitsu/gazu/entity.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/blender_kitsu/gazu/entity.py b/blender_kitsu/gazu/entity.py index 8ac2cef1..32dcfcf1 100644 --- a/blender_kitsu/gazu/entity.py +++ b/blender_kitsu/gazu/entity.py @@ -104,3 +104,16 @@ def remove_entity(entity, force=False, client=default): if force: params = {"force": "true"} return raw.delete(path, params, client=client) + +def update_entity(entity, client=default): + """ + Save given shot data into the API. Metadata are fully replaced by the ones + set on given shot. + + Args: + Entity (dict): The shot dict to update. + + Returns: + dict: Updated entity. + """ + return raw.put(f"data/entities/{entity['id']}", entity, client=client) \ No newline at end of file -- 2.30.2 From 208524146e62ec8e90c0a25a92a355535282a4ff Mon Sep 17 00:00:00 2001 From: TinyNick Date: Fri, 14 Apr 2023 13:02:18 -0400 Subject: [PATCH 27/28] [Blender_Kits] Publish_Edit_Rev add `frame_start` feature - add 'frame_start' and 'use_frame_start' props - check for 'frame_start' in invoke function (incase only some projects contain frame_start) - not all projects contain 'frame_start' - fix missing comment --- blender_kitsu/sqe/ops.py | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/blender_kitsu/sqe/ops.py b/blender_kitsu/sqe/ops.py index e4ac4098..4bd29efc 100644 --- a/blender_kitsu/sqe/ops.py +++ b/blender_kitsu/sqe/ops.py @@ -2395,7 +2395,15 @@ class KITSU_OT_sqe_change_strip_source(bpy.types.Operator): util.ui_redraw() return {"FINISHED"} + +def set_entity_data(entity, key: str, value: int): + if get_entity_data(entity, key) is not None: + entity['data'][key] = value + return entity +def get_entity_data(entity, key: str): + if entity.get("data").get(key) is not None: + return entity.get("data").get(key) def get_dict_len(items:dict): try: @@ -2426,13 +2434,15 @@ class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator): 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) + comment: bpy.props.StringProperty(name="Comment") + edit_entry: bpy.props.EnumProperty(name="Edit", items=get_edit_entry_items) + task: bpy.props.EnumProperty(name="Edit", items=get_edit_task_items) render_dir: bpy.props.StringProperty( - name="Render Directory", + name="Folder", subtype="DIR_PATH", ) + use_frame_start: bpy.props.BoolProperty(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 def poll(cls, context: bpy.types.Context) -> bool: @@ -2447,6 +2457,11 @@ class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator): if not os.path.isdir(Path(dir_path)): dir_path = Path(dir_path).parent self.render_dir = str(dir_path) + + #'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') + self.frame_start = server_frame_start + self.use_frame_start = bool(server_frame_start is not None) return context.window_manager.invoke_props_dialog(self) def draw(self, context: bpy.types.Context) -> None: @@ -2457,6 +2472,11 @@ class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator): layout.prop(self, "comment") layout.prop(self, "render_dir") + # Only set `frame_start` if exists on current project + if self.use_frame_start: + layout.prop(self, "frame_start") + + 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 .") @@ -2486,9 +2506,15 @@ class KITSU_OT_vse_publish_edit_revision(bpy.types.Operator): 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) + task_entity = gazu.task.get_task(self.task) + 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) + + # Update edit_entry's frame_start if 'frame_start' is found on server + if self.use_frame_start: + edit_entity_update = set_entity_data(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"}, -- 2.30.2 From 65c173e54583cffe3607e9f0ad94abe4e946b784 Mon Sep 17 00:00:00 2001 From: TinyNick Date: Mon, 17 Apr 2023 09:37:55 -0400 Subject: [PATCH 28/28] [Blender_Kitsu] playblast add TODO for refactor --- blender_kitsu/playblast/core.py | 1 + 1 file changed, 1 insertion(+) diff --git a/blender_kitsu/playblast/core.py b/blender_kitsu/playblast/core.py index 739b3a6d..d7c48594 100644 --- a/blender_kitsu/playblast/core.py +++ b/blender_kitsu/playblast/core.py @@ -4,6 +4,7 @@ from blender_kitsu import ( prefs, ) +# TODO refactor so these are nest-able and re-use code @contextlib.contextmanager def override_render_format(self, context): -- 2.30.2