Blender Kitsu: Move Render Review into Blender Kitsu #296
@ -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)
|
||||||
|
@ -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,
|
@ -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?")
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,13 +81,12 @@ 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")
|
||||||
|
|
||||||
@ -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,7 +144,6 @@ 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')
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user