Blender Kitsu: Move Render Review into Blender Kitsu #296

Merged
5 changed files with 45 additions and 71 deletions
Showing only changes of commit 24f22fd89a - Show all commits

View File

@ -23,7 +23,7 @@ import bpy
from . import ( from . import (
util, util,
props, props,
kitsu, core,
opsdata, opsdata,
checksqe, checksqe,
ops, ops,
@ -40,7 +40,7 @@ if _need_reload:
util = importlib.reload(util) util = importlib.reload(util)
props = importlib.reload(props) props = importlib.reload(props)
kitsu = importlib.reload(kitsu) core = importlib.reload(core)
opsdata = importlib.reload(opsdata) opsdata = importlib.reload(opsdata)
checksqe = importlib.reload(checksqe) checksqe = importlib.reload(checksqe)
ops = importlib.reload(ops) ops = importlib.reload(ops)

View File

@ -18,7 +18,6 @@
# #
# (c) 2021, Blender Foundation - Paul Golter # (c) 2021, Blender Foundation - Paul Golter
# TODO Remove duplicate code between this page and the main Blender Kitsu functions
from typing import List, Dict, Union, Any, Set, Optional from typing import List, Dict, Union, Any, Set, Optional
import bpy import bpy
@ -31,26 +30,11 @@ from ..logger import LoggerFactory
logger = LoggerFactory.getLogger() logger = LoggerFactory.getLogger()
def is_auth() -> bool:
return prefs.addon_prefs_get(bpy.context).session.is_auth()
def get_project() -> Optional[types.Project]:
return cache.project_active_get()
def is_active_project() -> bool: def is_active_project() -> bool:
return bool(cache.project_active_get()) return bool(cache.project_active_get())
def is_auth_and_project() -> bool: # TODO De-duplicate code from sqe create metastrip
return bool(is_auth() and is_active_project())
def addon_prefs() -> bpy.types.AddonPreferences:
return prefs.addon_prefs_get(bpy.context)
def create_metadata_strip( def create_metadata_strip(
context: bpy.types.Context, strip: bpy.types.Sequence context: bpy.types.Context, strip: bpy.types.Sequence
) -> bpy.types.MovieSequence: ) -> bpy.types.MovieSequence:
@ -87,6 +71,7 @@ def create_metadata_strip(
return metadata_strip return metadata_strip
# TODO De-duplicate code from sqe code
def link_strip_by_name( def link_strip_by_name(
context: bpy.types.Context, context: bpy.types.Context,
strip: bpy.types.Sequence, strip: bpy.types.Sequence,

View File

@ -28,7 +28,7 @@ from collections import OrderedDict
import bpy import bpy
from . import vars, opsdata, util, kitsu from . import vars, opsdata, util, core
from .. import prefs, cache from .. import prefs, cache
from .. import types as kitsu_types from .. import types as kitsu_types
@ -145,19 +145,15 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
prev_frame_end = strip_longest.frame_final_end prev_frame_end = strip_longest.frame_final_end
# Perform kitsu operations if enabled. # Perform kitsu operations if enabled.
if ( if prefs.session_auth(context) and imported_strips:
addon_prefs.enable_blender_kitsu if core.is_active_project():
and prefs.is_blender_kitsu_enabled()
and imported_strips
):
if kitsu.is_auth_and_project():
sequence_name = shot_version_folders[0].parent.parent.parent.name sequence_name = shot_version_folders[0].parent.parent.parent.name
# Create metadata strip. # Create metadata strip.
metadata_strip = kitsu.create_metadata_strip(context, strip_longest) metadata_strip = core.create_metadata_strip(context, strip_longest)
# Link metadata strip. # Link metadata strip.
kitsu.link_strip_by_name(context, metadata_strip, shot_name, sequence_name) core.link_strip_by_name(context, metadata_strip, shot_name, sequence_name)
else: else:
logger.error( logger.error(
@ -167,13 +163,11 @@ class RR_OT_sqe_create_review_session(bpy.types.Operator):
# Set default scene resolution to resolution of loaded image. # Set default scene resolution to resolution of loaded image.
render_resolution_x = vars.RESOLUTION[0] render_resolution_x = vars.RESOLUTION[0]
render_resolution_y = vars.RESOLUTION[1] render_resolution_y = vars.RESOLUTION[1]
project = cache.project_active_get()
# If Kitsu add-on is enabled, fetch the resolution from the online project # If Kitsu add-on is enabled, fetch the resolution from the online project
if ( if project:
addon_prefs.enable_blender_kitsu and prefs.is_blender_kitsu_enabled()
) and kitsu.is_active_project():
# TODO: make the resolution fetching a bit more robust # TODO: make the resolution fetching a bit more robust
# Assume resolution is a string '<str:width>x<str:height>' # Assume resolution is a string '<str:width>x<str:height>'
project = kitsu.get_project()
resolution = project.resolution.split('x') resolution = project.resolution.split('x')
render_resolution_x = int(resolution[0]) render_resolution_x = int(resolution[0])
render_resolution_y = int(resolution[1]) render_resolution_y = int(resolution[1])
@ -371,11 +365,8 @@ class RR_OT_setup_review_workspace(bpy.types.Operator):
area.spaces.active.show_overlays = False area.spaces.active.show_overlays = False
def invoke(self, context, _event): def invoke(self, context, _event):
if (
not prefs.is_blender_kitsu_enabled() if not cache.project_active_get():
or not prefs.addon_prefs_get(context).enable_blender_kitsu
or not kitsu.is_auth_and_project()
):
return self.execute(context) return self.execute(context)
return context.window_manager.invoke_props_dialog(self) return context.window_manager.invoke_props_dialog(self)
@ -544,34 +535,34 @@ class RR_OT_sqe_approve_render(bpy.types.Operator):
bpy.ops.rr.sqe_push_to_edit() bpy.ops.rr.sqe_push_to_edit()
strip_dir = opsdata.get_strip_folder(active_strip) strip_dir = opsdata.get_strip_folder(active_strip)
shot_frames_dir = opsdata.get_shot_frames_dir(active_strip) frames_root_dir = opsdata.get_frames_root_dir(active_strip)
shot_frames_backup_path = opsdata.get_shot_frames_backup_path(active_strip) shot_frames_backup_path = opsdata.get_shot_frames_backup_path(active_strip)
metadata_path = opsdata.get_shot_frames_metadata_path(active_strip) metadata_path = opsdata.get_shot_frames_metadata_path(active_strip)
# Create Shot Frames path if not exists yet. # Create Shot Frames path if not exists yet.
if shot_frames_dir.exists(): if frames_root_dir.exists():
# Delete backup if exists. # Delete backup if exists.
if shot_frames_backup_path.exists(): if shot_frames_backup_path.exists():
shutil.rmtree(shot_frames_backup_path) shutil.rmtree(shot_frames_backup_path)
# Rename current to backup. # Rename current to backup.
shot_frames_dir.rename(shot_frames_backup_path) frames_root_dir.rename(shot_frames_backup_path)
logger.info( logger.info(
"Created backup: %s > %s", "Created backup: %s > %s",
shot_frames_dir.name, frames_root_dir.name,
shot_frames_backup_path.name, shot_frames_backup_path.name,
) )
else: else:
shot_frames_dir.mkdir(parents=True) frames_root_dir.mkdir(parents=True)
logger.info("Created dir in Shot Frames: %s", shot_frames_dir.as_posix()) logger.info("Created dir in Shot Frames: %s", frames_root_dir.as_posix())
# Copy dir. # Copy dir.
opsdata.copytree_verbose( opsdata.copytree_verbose(
strip_dir, strip_dir,
shot_frames_dir, frames_root_dir,
dirs_exist_ok=True, dirs_exist_ok=True,
) )
logger.info("Copied: %s \nTo: %s", strip_dir.as_posix(), shot_frames_dir.as_posix()) logger.info("Copied: %s \nTo: %s", strip_dir.as_posix(), frames_root_dir.as_posix())
# Update metadata json. # Update metadata json.
if not metadata_path.exists(): if not metadata_path.exists():
@ -595,22 +586,22 @@ class RR_OT_sqe_approve_render(bpy.types.Operator):
util.redraw_ui() util.redraw_ui()
# Log. # Log.
self.report({"INFO"}, f"Updated {shot_frames_dir.name} in Shot Frames") self.report({"INFO"}, f"Updated {frames_root_dir.name} in Shot Frames")
logger.info("Updated metadata in: %s", metadata_path.as_posix()) logger.info("Updated metadata in: %s", metadata_path.as_posix())
return {"FINISHED"} return {"FINISHED"}
def invoke(self, context, event): def invoke(self, context, event):
active_strip = context.scene.sequence_editor.active_strip active_strip = context.scene.sequence_editor.active_strip
shot_frames_dir = opsdata.get_shot_frames_dir(active_strip) frames_root_dir = opsdata.get_frames_root_dir(active_strip)
width = 200 + len(shot_frames_dir.as_posix()) * 5 width = 200 + len(frames_root_dir.as_posix()) * 5
return context.window_manager.invoke_props_dialog(self, width=width) return context.window_manager.invoke_props_dialog(self, width=width)
def draw(self, context: bpy.types.Context) -> None: def draw(self, context: bpy.types.Context) -> None:
layout = self.layout layout = self.layout
active_strip = context.scene.sequence_editor.active_strip active_strip = context.scene.sequence_editor.active_strip
strip_dir = opsdata.get_strip_folder(active_strip) strip_dir = opsdata.get_strip_folder(active_strip)
shot_frames_dir = opsdata.get_shot_frames_dir(active_strip) frames_root_dir = opsdata.get_frames_root_dir(active_strip)
layout.separator() layout.separator()
layout.row(align=True).label(text="From Farm Output:", icon="RENDER_ANIMATION") layout.row(align=True).label(text="From Farm Output:", icon="RENDER_ANIMATION")
@ -618,7 +609,7 @@ class RR_OT_sqe_approve_render(bpy.types.Operator):
layout.separator() layout.separator()
layout.row(align=True).label(text="To Shot Frames:", icon="FILE_TICK") layout.row(align=True).label(text="To Shot Frames:", icon="FILE_TICK")
layout.row(align=True).label(text=shot_frames_dir.as_posix()) layout.row(align=True).label(text=frames_root_dir.as_posix())
layout.separator() layout.separator()
layout.row(align=True).label(text="Update Shot Frames?") layout.row(align=True).label(text="Update Shot Frames?")

View File

@ -26,7 +26,7 @@ from typing import Set, Union, Optional, List, Dict, Any, Tuple
import bpy import bpy
from . import vars, checksqe from . import vars, checksqe
from .. import prefs from .. import prefs, cache
from .exception import NoImageSequenceAvailableException from .exception import NoImageSequenceAvailableException
from ..logger import LoggerFactory from ..logger import LoggerFactory
@ -83,7 +83,7 @@ def get_valid_cs_sequences(
else: else:
sequences = context.selected_sequences or context.scene.sequence_editor.sequences_all sequences = context.selected_sequences or context.scene.sequence_editor.sequences_all
if prefs.is_blender_kitsu_enabled(): if cache.project_active_get():
valid_sequences = [ valid_sequences = [
s s
@ -96,11 +96,11 @@ def get_valid_cs_sequences(
return valid_sequences return valid_sequences
def get_shot_frames_dir(strip: bpy.types.Sequence) -> Path: def get_frames_root_dir(strip: bpy.types.Sequence) -> Path:
# sf = shot_frames | fo = farm_output. # sf = shot_frames | fo = farm_output.
addon_prefs = prefs.addon_prefs_get(bpy.context) addon_prefs = prefs.addon_prefs_get(bpy.context)
fo_dir = get_strip_folder(strip) fo_dir = get_strip_folder(strip)
sf_dir = addon_prefs.shot_frames_dir / fo_dir.parent.relative_to(fo_dir.parents[3]) sf_dir = addon_prefs.frames_root_dir / fo_dir.parent.relative_to(fo_dir.parents[3])
return sf_dir return sf_dir
@ -116,7 +116,7 @@ def get_shot_previews_path(strip: bpy.types.Sequence) -> Path:
# Fo > farm_output. # Fo > farm_output.
addon_prefs = prefs.addon_prefs_get(bpy.context) addon_prefs = prefs.addon_prefs_get(bpy.context)
fo_dir = get_strip_folder(strip) fo_dir = get_strip_folder(strip)
shot_previews_dir = addon_prefs.shot_previews_path / fo_dir.parent.relative_to( shot_previews_dir = addon_prefs.shot_playblast_root_dir / fo_dir.parent.relative_to(
fo_dir.parents[3] fo_dir.parents[3]
) )
@ -172,12 +172,12 @@ def get_best_preview_sequence(dir: Path) -> List[Path]:
def get_shot_frames_backup_path(strip: bpy.types.Sequence) -> Path: def get_shot_frames_backup_path(strip: bpy.types.Sequence) -> Path:
fs_dir = get_shot_frames_dir(strip) fs_dir = get_frames_root_dir(strip)
return fs_dir.parent / f"_backup.{fs_dir.name}" return fs_dir.parent / f"_backup.{fs_dir.name}"
def get_shot_frames_metadata_path(strip: bpy.types.Sequence) -> Path: def get_shot_frames_metadata_path(strip: bpy.types.Sequence) -> Path:
fs_dir = get_shot_frames_dir(strip) fs_dir = get_frames_root_dir(strip)
return fs_dir.parent / "metadata.json" return fs_dir.parent / "metadata.json"

View File

@ -34,8 +34,8 @@ from .ops import (
RR_OT_open_path, RR_OT_open_path,
RR_OT_sqe_push_to_edit, RR_OT_sqe_push_to_edit,
) )
from . import opsdata, kitsu from . import opsdata, core
from .. import prefs from .. import prefs, cache
class RR_PT_render_review(bpy.types.Panel): class RR_PT_render_review(bpy.types.Panel):
@ -81,15 +81,14 @@ class RR_PT_render_review(bpy.types.Panel):
row.prop(addon_prefs, 'use_video_latest_only') row.prop(addon_prefs, 'use_video_latest_only')
# Warning if kitsu on but not logged in. # Warning if kitsu on but not logged in.
if addon_prefs.enable_blender_kitsu and prefs.is_blender_kitsu_enabled(): if not prefs.session_auth(context):
if not kitsu.is_auth(): row = box.split(align=True, factor=0.7)
row = box.split(align=True, factor=0.7) row.label(text="Kitsu enabled but not logged in", icon="ERROR")
row.label(text="Kitsu enabled but not logged in", icon="ERROR") row.operator("kitsu.session_start", text="Login")
row.operator("kitsu.session_start", text="Login")
elif not kitsu.is_active_project(): elif not core.is_active_project():
row = box.row(align=True) row = box.row(align=True)
row.label(text="Kitsu enabled but no active project", icon="ERROR") row.label(text="Kitsu enabled but no active project", icon="ERROR")
sqe = context.scene.sequence_editor sqe = context.scene.sequence_editor
if not sqe: if not sqe:
@ -134,7 +133,7 @@ class RR_PT_render_review(bpy.types.Panel):
row.operator(RR_OT_sqe_update_sequence_statuses.bl_idname, text="", icon="FILE_REFRESH") row.operator(RR_OT_sqe_update_sequence_statuses.bl_idname, text="", icon="FILE_REFRESH")
# Push to edit. # Push to edit.
if not addon_prefs.shot_previews_path: if not addon_prefs.shot_playblast_root_dir:
shot_previews_dir = "" # ops handle invalid path shot_previews_dir = "" # ops handle invalid path
else: else:
shot_previews_dir = Path(opsdata.get_shot_previews_path(active_strip)).as_posix() shot_previews_dir = Path(opsdata.get_shot_previews_path(active_strip)).as_posix()
@ -145,9 +144,8 @@ class RR_PT_render_review(bpy.types.Panel):
shot_previews_dir shot_previews_dir
) )
if prefs.is_blender_kitsu_enabled(): # Push strip to Kitsu.
# Push strip to Kitsu. box.row().operator('kitsu.sqe_push_shot', icon='URL')
box.row().operator('kitsu.sqe_push_shot', icon='URL')
def RR_topbar_file_new_draw_handler(self: Any, context: bpy.types.Context) -> None: def RR_topbar_file_new_draw_handler(self: Any, context: bpy.types.Context) -> None: