Blender Kitsu: Set Custom Thumbnail during Playblast #77

Merged
Nick Alberelli merged 12 commits from feature/custom-playblast-thumbnails into main 2023-06-15 21:26:54 +02:00
4 changed files with 72 additions and 39 deletions
Showing only changes of commit 99197cfb97 - Show all commits

View File

@ -411,7 +411,6 @@ def get_user_all_tasks() -> List[Task]:
def _init_cache_entity( def _init_cache_entity(
entity_id: str, entity_type: Any, cache_variable_name: Any, cache_name: str entity_id: str, entity_type: Any, cache_variable_name: Any, cache_name: str
) -> None: ) -> None:
if entity_id: if entity_id:
try: try:
globals()[cache_variable_name] = entity_type.by_id(entity_id) globals()[cache_variable_name] = entity_type.by_id(entity_id)

View File

@ -7,7 +7,7 @@ import requests
import tempfile import tempfile
import mimetypes import mimetypes
from blender_kitsu.gazu.exception import DownloadFileException from .exception import DownloadFileException
if sys.version_info[0] == 3: if sys.version_info[0] == 3:
import urllib.parse as urlparse import urllib.parse as urlparse

View File

@ -1,5 +1,5 @@
import datetime import datetime
from blender_kitsu.gazu.exception import NotAuthenticatedException from .exception import NotAuthenticatedException
from . import client as raw from . import client as raw
from .sorting import sort_by_name from .sorting import sort_by_name

View File

@ -43,16 +43,19 @@ class KitsuPreferences(bpy.types.PropertyGroup):
backend: bpy.props.StringProperty( # type: ignore backend: bpy.props.StringProperty( # type: ignore
name="Server URL", name="Server URL",
description="Kitsu server address", description="Kitsu server address",
default="https://kitsu.blender.cloud/api") default="https://kitsu.blender.cloud/api",
)
username: bpy.props.StringProperty( # type: ignore username: bpy.props.StringProperty( # type: ignore
name="Username", name="Username",
description="Username to connect to Kitsu",) description="Username to connect to Kitsu",
)
password: bpy.props.StringProperty( # type: ignore password: bpy.props.StringProperty( # type: ignore
name="Password", name="Password",
description="Password to connect to Kitsu", description="Password to connect to Kitsu",
subtype='PASSWORD',) subtype='PASSWORD',
)
def draw(self, layout: bpy.types.UILayout, context: bpy.types.Context) -> None: def draw(self, layout: bpy.types.UILayout, context: bpy.types.Context) -> None:
layout.label(text="Kitsu") layout.label(text="Kitsu")
@ -63,10 +66,11 @@ class KitsuPreferences(bpy.types.PropertyGroup):
def _validate(self): def _validate(self):
if not (self.backend and self.username and self.password): if not (self.backend and self.username and self.password):
raise KitsuException( raise KitsuException(
"Kitsu connector has not been configured in the add-on preferences") "Kitsu connector has not been configured in the add-on preferences"
)
class KitsuDataContainer(): class KitsuDataContainer:
def __init__(self, data: typing.Dict[str, typing.Optional[str]]): def __init__(self, data: typing.Dict[str, typing.Optional[str]]):
self._data = data self._data = data
@ -109,7 +113,17 @@ class KitsuSequenceRef(ShotRef):
class KitsuShotRef(ShotRef): class KitsuShotRef(ShotRef):
def __init__(self, kitsu_id: str, name: str, code: str, frame_start: int, frames: int, frame_end: int, frames_per_second: float, sequence: KitsuSequenceRef): def __init__(
self,
kitsu_id: str,
name: str,
code: str,
frame_start: int,
frames: int,
frame_end: int,
frames_per_second: float,
sequence: KitsuSequenceRef,
):
super().__init__(name=name, code=code) super().__init__(name=name, code=code)
self.kitsu_id = kitsu_id self.kitsu_id = kitsu_id
self.frame_start = frame_start self.frame_start = frame_start
@ -137,8 +151,7 @@ class KitsuConnector(Connector):
def __get_production_data(self) -> KitsuProject: def __get_production_data(self) -> KitsuProject:
production = cache.project_active_get() production = cache.project_active_get()
project = KitsuProject(typing.cast( project = KitsuProject(typing.cast(typing.Dict[str, typing.Any], production))
typing.Dict[str, typing.Any], production))
return project return project
def get_name(self) -> str: def get_name(self) -> str:
@ -149,6 +162,7 @@ class KitsuConnector(Connector):
project = cache.project_active_get() project = cache.project_active_get()
task_types = project.task_types task_types = project.task_types
import pprint import pprint
pprint.pprint(task_types) pprint.pprint(task_types)
return [] return []
@ -156,56 +170,76 @@ class KitsuConnector(Connector):
project = cache.project_active_get() project = cache.project_active_get()
kitsu_sequences = all_sequences_for_project(project.id) kitsu_sequences = all_sequences_for_project(project.id)
sequence_lookup = {sequence_data['id']: KitsuSequenceRef( sequence_lookup = {
sequence_data['id']: KitsuSequenceRef(
kitsu_id=sequence_data['id'], kitsu_id=sequence_data['id'],
name=sequence_data['name'], name=sequence_data['name'],
code=sequence_data['code'], code=sequence_data['code'],
) for sequence_data in kitsu_sequences} )
for sequence_data in kitsu_sequences
}
kitsu_shots = all_shots_for_project(project.id) kitsu_shots = all_shots_for_project(project.id)
shots: typing.List[ShotRef] = [] shots: typing.List[ShotRef] = []
for shot_data in kitsu_shots: for shot_data in kitsu_shots:
# Initialize default values
#Initialize default values
frame_start = vars.DEFAULT_FRAME_START frame_start = vars.DEFAULT_FRAME_START
frame_end = 0 frame_end = 0
# shot_data['data'] can be None # shot_data['data'] can be None
if shot_data['data']: if shot_data['data']:
# If 3d_in key not found use default start frame. # If 3d_in key not found use default start frame.
frame_start = int(shot_data['data'].get('3d_in', vars.DEFAULT_FRAME_START)) frame_start = int(
shot_data['data'].get('3d_in', vars.DEFAULT_FRAME_START)
)
frame_end = int(shot_data['data'].get('3d_out', 0)) frame_end = int(shot_data['data'].get('3d_out', 0))
# If 3d_in and 3d_out available use that to calculate frames. # If 3d_in and 3d_out available use that to calculate frames.
# If not try shot_data['nb_frames'] or 0 -> invalid. # If not try shot_data['nb_frames'] or 0 -> invalid.
frames = int((frame_end - frame_start + 1) if frame_end else shot_data['nb_frames'] or 0) frames = int(
(frame_end - frame_start + 1)
if frame_end
else shot_data['nb_frames'] or 0
)
if frames < 0: if frames < 0:
logger.error("%s duration is negative: %i. Check frame range information on Kitsu", shot_data['name'], frames) logger.error(
"%s duration is negative: %i. Check frame range information on Kitsu",
shot_data['name'],
frames,
)
frames = 0 frames = 0
shots.append(KitsuShotRef( shots.append(
KitsuShotRef(
kitsu_id=shot_data['id'], kitsu_id=shot_data['id'],
name=shot_data['name'], name=shot_data['name'],
code=shot_data['code'], code=shot_data['code'],
frame_start=frame_start, frame_start=frame_start,
frames=frames, frames=frames,
frame_end = frame_end, frame_end=frame_end,
frames_per_second=24.0, frames_per_second=24.0,
sequence=sequence_lookup[shot_data['parent_id']], sequence=sequence_lookup[shot_data['parent_id']],
)) )
)
return shots return shots
def get_assets_for_shot(self, shot: Shot) -> typing.List[AssetRef]: def get_assets_for_shot(self, shot: Shot) -> typing.List[AssetRef]:
kitsu_assets = all_assets_for_shot(shot.kitsu_id) kitsu_assets = all_assets_for_shot(shot.kitsu_id)
return [AssetRef(name=asset_data['name'], code=asset_data['code']) return [
for asset_data in kitsu_assets] AssetRef(name=asset_data['name'], code=asset_data['code'])
for asset_data in kitsu_assets
]
def get_render_settings(self, shot: Shot) -> RenderSettings: def get_render_settings(self, shot: Shot) -> RenderSettings:
""" """
Retrieve the render settings for the given shot. Retrieve the render settings for the given shot.
""" """
project = cache.project_active_get() project = cache.project_active_get()
return RenderSettings(width=int(project.resolution.split('x')[0]), height=int(project.resolution.split('x')[1]), frames_per_second=project.fps) return RenderSettings(
width=int(project.resolution.split('x')[0]),
height=int(project.resolution.split('x')[1]),
frames_per_second=project.fps,
)