Blender Kitsu: Add Frame Range Pop-up #128

Merged
Nick Alberelli merged 18 commits from :fix/frame-range-popup into main 2023-07-19 17:32:39 +02:00
3 changed files with 120 additions and 54 deletions

View File

@ -3,9 +3,10 @@ from pathlib import Path
import contextlib import contextlib
from blender_kitsu import ( from blender_kitsu import prefs, cache
prefs, from blender_kitsu.logger import LoggerFactory
)
logger = LoggerFactory.getLogger()
@contextlib.contextmanager @contextlib.contextmanager
@ -255,3 +256,49 @@ def playblast_user_shading_settings(self, context, file_path):
# Make opengl render. # Make opengl render.
bpy.ops.render.opengl(animation=True) bpy.ops.render.opengl(animation=True)
return output_path return output_path
def set_frame_range_in(frame_in: int) -> dict:
shot = cache.shot_active_pull_update()
shot.data["3d_start"] = frame_in
shot.update()
return shot
def get_frame_range(): # TODO return type
active_shot = cache.shot_active_get()
if not active_shot:
return
# Pull update for shot.
cache.shot_active_pull_update()
if "3d_start" not in active_shot.data:
logger.warning(
"Failed to check frame range. Shot %s missing '3d_start' attribute on server",
active_shot.name,
)
return
frame_in = int(active_shot.data["3d_start"])
frame_out = int(active_shot.data["3d_start"]) + int(active_shot.nb_frames) - 1
return frame_in, frame_out
def check_frame_range(context) -> bool:
"""
Compare the current scene's frame range with that of the active shot on kitsu.
If there's a mismatch, set kitsu_error.frame_range -> True. This will enable
a warning in the Animation Tools Tab UI.
"""
try:
frame_in, frame_out = get_frame_range()
except TypeError:
return
scene = context.scene
if frame_in == scene.frame_start and frame_out == scene.frame_end:
scene.kitsu_error.frame_range = False
return True
scene.kitsu_error.frame_range = True
logger.warning("Current frame range is outdated!")
return False

View File

@ -44,7 +44,7 @@ from blender_kitsu.playblast.core import (
playblast_with_shading_settings, playblast_with_shading_settings,
playblast_user_shading_settings, playblast_user_shading_settings,
) )
from blender_kitsu.playblast import opsdata from blender_kitsu.playblast import opsdata, core
logger = LoggerFactory.getLogger() logger = LoggerFactory.getLogger()
@ -348,6 +348,8 @@ class KITSU_OT_push_frame_range(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
bl_description = "Adjusts the start frame of animation file." bl_description = "Adjusts the start frame of animation file."
frame_start = None
@classmethod @classmethod
def poll(cls, context: bpy.types.Context) -> bool: def poll(cls, context: bpy.types.Context) -> bool:
return bool(prefs.session_auth(context) and cache.shot_active_get()) return bool(prefs.session_auth(context) and cache.shot_active_get())
@ -356,16 +358,22 @@ class KITSU_OT_push_frame_range(bpy.types.Operator):
layout = self.layout layout = self.layout
col = layout.column(align=True) col = layout.column(align=True)
col.label(text="Set 3d_start using current scene frame start.") col.label(text="Set 3d_start using current scene frame start.")
col.label(text=f"New Frame Start: {context.scene.frame_start}", icon="ERROR") col.label(text=f"New Frame Start: {self.frame_start}", icon="ERROR")
def execute(self, context: bpy.types.Context) -> Set[str]: def execute(self, context: bpy.types.Context) -> Set[str]:
shot = cache.shot_active_pull_update() core.set_frame_range_in(self.frame_start)
shot.data["3d_start"] = context.scene.frame_start self.report({"INFO"}, f"Updated frame range offset {self.frame_start}")
shot.update()
self.report({"INFO"}, f"Updated frame range offset {context.scene.frame_start}")
return {"FINISHED"} return {"FINISHED"}
def invoke(self, context: bpy.types.Context, event: bpy.types.Event) -> Set[str]: def invoke(self, context: bpy.types.Context, event: bpy.types.Event) -> Set[str]:
self.frame_start = context.scene.frame_start
frame_in, _ = core.get_frame_range()
if frame_in == self.frame_start:
self.report(
{"INFO"},
f"Sever's 'Frame In' already matches current Scene's 'Frame Start' {self.frame_start}",
)
return {"FINISHED"}
return context.window_manager.invoke_props_dialog(self, width=500) return context.window_manager.invoke_props_dialog(self, width=500)
@ -383,23 +391,10 @@ class KITSU_OT_pull_frame_range(bpy.types.Operator):
return bool(prefs.session_auth(context) and cache.shot_active_get()) return bool(prefs.session_auth(context) and cache.shot_active_get())
def execute(self, context: bpy.types.Context) -> Set[str]: def execute(self, context: bpy.types.Context) -> Set[str]:
active_shot = cache.shot_active_pull_update() frame_in, frame_out = core.get_frame_range()
if "3d_start" not in active_shot.data:
self.report(
{"ERROR"},
f"Failed to pull frame range. Shot {active_shot.name} missing '3d_start'.",
)
return {"CANCELLED"}
frame_in = int(active_shot.data["3d_start"])
frame_out = int(active_shot.data["3d_start"]) + int(active_shot.nb_frames) - 1
# Check if current frame range matches the one for active shot. # Check if current frame range matches the one for active shot.
if ( if core.check_frame_range(context):
frame_in == context.scene.frame_start
and frame_out == context.scene.frame_end
):
self.report({"INFO"}, f"Frame range already up to date") self.report({"INFO"}, f"Frame range already up to date")
return {"FINISHED"} return {"FINISHED"}
@ -407,14 +402,36 @@ class KITSU_OT_pull_frame_range(bpy.types.Operator):
context.scene.frame_start = frame_in context.scene.frame_start = frame_in
context.scene.frame_end = frame_out context.scene.frame_end = frame_out
# Update error prop. if not core.check_frame_range(context):
context.scene.kitsu_error.frame_range = False self.report(
{"ERROR"}, f"Failed to update frame range to {frame_in} - {frame_out}"
)
return {"CANCELLED"}
# Log. # Log.
self.report({"INFO"}, f"Updated frame range {frame_in} - {frame_out}") self.report({"INFO"}, f"Updated frame range {frame_in} - {frame_out}")
return {"FINISHED"} return {"FINISHED"}
class KITSU_OT_check_frame_range(bpy.types.Operator):
bl_idname = "kitsu.check_frame_range"
bl_label = "Check Frame Range"
bl_options = {"REGISTER", "UNDO"}
bl_description = (
"Checks frame range of active shot from the server matches current file"
)
@classmethod
def poll(cls, context: bpy.types.Context) -> bool:
return bool(prefs.session_auth(context) and cache.shot_active_get())
def execute(self, context: bpy.types.Context) -> Set[str]:
if core.check_frame_range(context):
self.report({"INFO"}, f"Frame Range is accurate")
return {"FINISHED"}
self.report({"ERROR"}, f"Failed: Frame Range Check")
return {"CANCELLED"}
class KITSU_OT_playblast_increment_playblast_version(bpy.types.Operator): class KITSU_OT_playblast_increment_playblast_version(bpy.types.Operator):
bl_idname = "kitsu.anim_increment_playblast_version" bl_idname = "kitsu.anim_increment_playblast_version"
bl_label = "Add Version Increment" bl_label = "Add Version Increment"
@ -443,37 +460,38 @@ def load_post_handler_init_version_model(dummy: Any) -> None:
opsdata.init_playblast_file_model(bpy.context) opsdata.init_playblast_file_model(bpy.context)
def draw_frame_range_warning(self, context):
active_shot = cache.shot_active_get()
layout = self.layout
layout.alert = True
layout.label(
text="Frame Range on server does not match the active shot. Please 'pull' the correct frame range from the server"
)
layout.label(
text=f" File Frame Range: {context.scene.frame_start}-{context.scene.frame_end}"
)
if active_shot:
layout.label(
text=f' Server Frame Range: {int(active_shot.data["3d_start"])}-{int(active_shot.data["3d_start"]) + int(active_shot.nb_frames) - 1}'
)
else:
layout.label(text=f' Server Frame Range: not found')
layout.operator("kitsu.pull_frame_range", icon='TRIA_DOWN')
@persistent @persistent
def load_post_handler_check_frame_range(dummy: Any) -> None: def load_post_handler_check_frame_range(dummy: Any) -> None:
""" # Only show if kitsu context is detected
Compare the current scene's frame range with that of the active shot on kitsu.
If there's a mismatch, set kitsu_error.frame_range -> True. This will enable
a warning in the Animation Tools Tab UI.
"""
active_shot = cache.shot_active_get() active_shot = cache.shot_active_get()
if not active_shot: if not active_shot:
return return
if not core.check_frame_range(bpy.context):
# Pull update for shot. bpy.context.window_manager.popup_menu(
cache.shot_active_pull_update() draw_frame_range_warning,
title="Warning: Frame Range Error.",
if "3d_start" not in active_shot.data: icon='ERROR',
logger.warning(
"Failed to check frame range. Shot %s missing '3d_start' attribute on server",
active_shot.name,
) )
return
frame_in = int(active_shot.data["3d_start"])
frame_out = int(active_shot.data["3d_start"]) + int(active_shot.nb_frames) - 1
if (
frame_in == bpy.context.scene.frame_start
and frame_out == bpy.context.scene.frame_end
):
bpy.context.scene.kitsu_error.frame_range = False
return
bpy.context.scene.kitsu_error.frame_range = True
logger.warning("Current frame range is outdated!")
@persistent @persistent
@ -506,6 +524,7 @@ classes = [
KITSU_OT_playblast_increment_playblast_version, KITSU_OT_playblast_increment_playblast_version,
KITSU_OT_pull_frame_range, KITSU_OT_pull_frame_range,
KITSU_OT_push_frame_range, KITSU_OT_push_frame_range,
KITSU_OT_check_frame_range,
] ]

View File

@ -50,10 +50,10 @@ def draw_error_invalid_playblast_root_dir(
def draw_error_frame_range_outdated( def draw_error_frame_range_outdated(
box: bpy.types.UILayout, box: bpy.types.UILayout,
) -> bpy.types.UILayout: ) -> bpy.types.UILayout:
row = box.row(align=True) row = box.row(align=True)
row.alert = True
row.label(text="Frame Range Outdated") row.label(text="Frame Range Outdated")
row.operator("kitsu.pull_frame_range", icon="FILE_REFRESH") row.operator("kitsu.pull_frame_range", icon="TRIA_DOWN")
def draw_error_invalid_render_preset_dir( def draw_error_invalid_render_preset_dir(