Blender Kitsu: Update Kitsu Context UI #187
|
@ -74,6 +74,7 @@ _episode_cache_proj_id: str = ""
|
|||
_all_shot_tasks_cache_proj_id: str = ""
|
||||
_all_task_type_cache_proj_id: str = ""
|
||||
_seq_cache_proj_id: str = ""
|
||||
_seq_cache_episode_id: str = ""
|
||||
_shot_cache_seq_id: str = ""
|
||||
_task_type_cache_shot_id: str = ""
|
||||
_asset_cache_asset_type_id: str = ''
|
||||
|
@ -127,11 +128,15 @@ def episode_active_set_by_id(context: bpy.types.Context, entity_id: str) -> None
|
|||
logger.debug("Set active episode to %s", _episode_active.name)
|
||||
|
||||
|
||||
def episode_active_reset(context: bpy.types.Context) -> None:
|
||||
def episode_active_reset_entity():
|
||||
global _episode_active
|
||||
|
||||
_episode_active = Episode()
|
||||
|
||||
|
||||
def episode_active_reset(context: bpy.types.Context) -> None:
|
||||
episode_active_reset_entity()
|
||||
context.scene.kitsu.episode_active_id = ""
|
||||
context.scene.kitsu.episode_active_name = ""
|
||||
logger.debug("Reset active episode")
|
||||
|
||||
|
||||
|
@ -147,11 +152,15 @@ def sequence_active_set_by_id(context: bpy.types.Context, entity_id: str) -> Non
|
|||
logger.debug("Set active sequence to %s", _sequence_active.name)
|
||||
|
||||
|
||||
def sequence_active_reset(context: bpy.types.Context) -> None:
|
||||
def sequence_active_reset_entity() -> None:
|
||||
global _sequence_active
|
||||
|
||||
_sequence_active = Sequence()
|
||||
|
||||
|
||||
def sequence_active_reset(context: bpy.types.Context) -> None:
|
||||
sequence_active_reset_entity()
|
||||
context.scene.kitsu.sequence_active_id = ""
|
||||
context.scene.kitsu.sequence_active_name = ""
|
||||
logger.debug("Reset active sequence")
|
||||
|
||||
|
||||
|
@ -177,11 +186,15 @@ def shot_active_set_by_id(context: bpy.types.Context, entity_id: str) -> None:
|
|||
logger.debug("Set active shot to %s", _shot_active.name)
|
||||
|
||||
|
||||
def shot_active_reset(context: bpy.types.Context) -> None:
|
||||
def shot_active_reset_entity() -> None:
|
||||
global _shot_active
|
||||
|
||||
_shot_active = Shot()
|
||||
|
||||
|
||||
def shot_active_reset(context: bpy.types.Context) -> None:
|
||||
shot_active_reset_entity()
|
||||
context.scene.kitsu.shot_active_id = ""
|
||||
context.scene.kitsu.shot_active_name = ""
|
||||
logger.debug("Reset active shot")
|
||||
|
||||
|
||||
|
@ -199,11 +212,15 @@ def asset_active_set_by_id(context: bpy.types.Context, entity_id: str) -> None:
|
|||
logger.debug("Set active asset to %s", _asset_active.name)
|
||||
|
||||
|
||||
def asset_active_reset(context: bpy.types.Context) -> None:
|
||||
def asset_active_reset_entity() -> None:
|
||||
global _asset_active
|
||||
|
||||
_asset_active = Asset()
|
||||
|
||||
|
||||
def asset_active_reset(context: bpy.types.Context) -> None:
|
||||
asset_active_reset_entity()
|
||||
context.scene.kitsu.asset_active_id = ""
|
||||
context.scene.kitsu.asset_active_name = ""
|
||||
logger.debug("Reset active asset")
|
||||
|
||||
|
||||
|
@ -221,11 +238,15 @@ def asset_type_active_set_by_id(context: bpy.types.Context, entity_id: str) -> N
|
|||
logger.debug("Set active asset type to %s", _asset_type_active.name)
|
||||
|
||||
|
||||
def asset_type_active_reset(context: bpy.types.Context) -> None:
|
||||
def asset_type_active_reset_entity() -> None:
|
||||
global _asset_type_active
|
||||
|
||||
_asset_type_active = AssetType()
|
||||
|
||||
|
||||
def asset_type_active_reset(context: bpy.types.Context) -> None:
|
||||
asset_type_active_reset_entity()
|
||||
context.scene.kitsu.asset_type_active_id = ""
|
||||
context.scene.kitsu.asset_type_active_name = ""
|
||||
logger.debug("Reset active asset type")
|
||||
|
||||
|
||||
|
@ -243,11 +264,15 @@ def task_type_active_set_by_id(context: bpy.types.Context, entity_id: str) -> No
|
|||
logger.debug("Set active task type to %s", _task_type_active.name)
|
||||
|
||||
|
||||
def task_type_active_reset(context: bpy.types.Context) -> None:
|
||||
def task_type_active_reset_entity() -> None:
|
||||
global _task_type_active
|
||||
|
||||
_task_type_active = TaskType()
|
||||
|
||||
|
||||
def task_type_active_reset(context: bpy.types.Context) -> None:
|
||||
task_type_active_reset_entity()
|
||||
context.scene.kitsu.task_type_active_id = ""
|
||||
context.scene.kitsu.task_type_active_name = ""
|
||||
logger.debug("Reset active task type")
|
||||
|
||||
|
||||
|
@ -297,6 +322,7 @@ def get_sequences_enum_list(
|
|||
) -> List[Tuple[str, str, str]]:
|
||||
global _sequence_enum_list
|
||||
global _seq_cache_proj_id
|
||||
global _seq_cache_episode_id
|
||||
|
||||
project_active = project_active_get()
|
||||
episode_active = episode_active_get()
|
||||
|
@ -304,7 +330,7 @@ def get_sequences_enum_list(
|
|||
return []
|
||||
|
||||
# Return Cached list if project hasn't changed
|
||||
if _seq_cache_proj_id == project_active.id:
|
||||
if _seq_cache_proj_id == project_active.id and _seq_cache_episode_id == episode_active.id:
|
||||
return _sequence_enum_list
|
||||
|
||||
# Update Cache Sequence ID
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import bpy
|
||||
from .. import cache
|
||||
|
||||
|
||||
# Category values are defined in enum props.py KITSU_property_group_scene under category
|
||||
|
@ -16,3 +17,50 @@ def is_asset_context():
|
|||
|
||||
def is_shot_context():
|
||||
return bpy.context.scene.kitsu.category == "SHOT"
|
||||
|
||||
|
||||
def active_project_row(layout: bpy.types.UILayout) -> bpy.types.UILayout:
|
||||
project_active = cache.project_active_get()
|
||||
row = layout.row(align=True)
|
||||
|
||||
if not project_active:
|
||||
row.enabled = False
|
||||
return row
|
||||
|
||||
|
||||
def active_episode_row(layout: bpy.types.UILayout) -> None:
|
||||
episode_active = cache.episode_active_get()
|
||||
project_active = cache.project_active_get()
|
||||
row = active_project_row(layout)
|
||||
if project_active.nb_episodes > 0 and not episode_active:
|
||||
row.enabled = False
|
||||
return row
|
||||
|
||||
|
||||
def draw_episode_selector(context: bpy.types.Context, layout: bpy.types.UILayout) -> None:
|
||||
row = active_project_row(layout)
|
||||
row.prop(context.scene.kitsu, "episode_active_name")
|
||||
|
||||
|
||||
def draw_sequence_selector(context: bpy.types.Context, layout: bpy.types.UILayout) -> None:
|
||||
row = active_episode_row(layout)
|
||||
row.prop(context.scene.kitsu, "sequence_active_name")
|
||||
|
||||
|
||||
def draw_asset_type_selector(context: bpy.types.Context, layout: bpy.types.UILayout) -> None:
|
||||
row = active_project_row(layout)
|
||||
row.prop(context.scene.kitsu, "asset_type_active_name")
|
||||
|
||||
|
||||
def draw_shot_selector(context: bpy.types.Context, layout: bpy.types.UILayout) -> None:
|
||||
row = active_episode_row(layout)
|
||||
row.prop(context.scene.kitsu, "shot_active_name")
|
||||
|
||||
|
||||
def draw_asset_selector(context: bpy.types.Context, layout: bpy.types.UILayout) -> None:
|
||||
row = active_project_row(layout)
|
||||
row.prop(context.scene.kitsu, "asset_active_name")
|
||||
|
||||
|
||||
def draw_task_type_selector(context: bpy.types.Context, layout: bpy.types.UILayout):
|
||||
layout.prop(context.scene.kitsu, "task_type_active_name")
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#
|
||||
# (c) 2021, Blender Foundation - Paul Golter
|
||||
|
||||
from typing import Dict, Optional, Set, Any
|
||||
from typing import Dict, Optional, Set
|
||||
from pathlib import Path
|
||||
|
||||
import bpy
|
||||
|
@ -26,7 +26,6 @@ import bpy
|
|||
from .. import bkglobals, cache, util, prefs
|
||||
from ..logger import LoggerFactory
|
||||
from ..types import TaskType, AssetType
|
||||
from ..context import core as context_core
|
||||
|
||||
logger = LoggerFactory.getLogger()
|
||||
|
||||
|
@ -70,223 +69,6 @@ class KITSU_OT_con_productions_load(bpy.types.Operator):
|
|||
return {"FINISHED"}
|
||||
|
||||
|
||||
class KITSU_OT_con_episodes_load(bpy.types.Operator):
|
||||
"""
|
||||
Gets all episodes that are available in server and let's user select. Invokes a search Popup (enum_prop) on click.
|
||||
"""
|
||||
|
||||
bl_idname = "kitsu.con_episodes_load"
|
||||
bl_label = "Episodes Load"
|
||||
bl_property = "enum_prop"
|
||||
bl_description = "Set active episode for this Production"
|
||||
|
||||
enum_prop: bpy.props.EnumProperty(items=cache.get_episodes_enum_list) # type: ignore
|
||||
|
||||
@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]:
|
||||
# Store vars to check if project / seq / shot changed.
|
||||
zep_prev_id = cache.episode_active_get().id
|
||||
|
||||
# Update kitsu metadata.
|
||||
cache.episode_active_set_by_id(context, self.enum_prop)
|
||||
|
||||
# Clear active shot when sequence changes.
|
||||
if self.enum_prop != zep_prev_id:
|
||||
cache.sequence_active_reset(context)
|
||||
cache.asset_type_active_reset(context)
|
||||
cache.shot_active_reset(context)
|
||||
cache.asset_active_reset(context)
|
||||
|
||||
util.ui_redraw()
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.invoke_search_popup(self)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class KITSU_OT_con_sequences_load(bpy.types.Operator):
|
||||
"""
|
||||
Gets all sequences that are available in server for active production and let's user select. Invokes a search Popup (enum_prop) on click.
|
||||
"""
|
||||
|
||||
bl_idname = "kitsu.con_sequences_load"
|
||||
bl_label = "Sequences Load"
|
||||
bl_property = "enum_prop"
|
||||
bl_description = "Sets active sequence for this scene"
|
||||
|
||||
enum_prop: bpy.props.EnumProperty(items=cache.get_sequences_enum_list) # type: ignore
|
||||
|
||||
@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]:
|
||||
# Store vars to check if project / seq / shot changed.
|
||||
zseq_prev_id = cache.sequence_active_get().id
|
||||
|
||||
# Update kitsu metadata.
|
||||
cache.sequence_active_set_by_id(context, self.enum_prop)
|
||||
|
||||
# Clear active shot when sequence changes.
|
||||
if self.enum_prop != zseq_prev_id:
|
||||
cache.shot_active_reset(context)
|
||||
|
||||
util.ui_redraw()
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.invoke_search_popup(self)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class KITSU_OT_con_shots_load(bpy.types.Operator):
|
||||
"""
|
||||
Gets all shots that are available in server for active production and let's user select. Invokes a search Popup (enum_prop) on click.
|
||||
"""
|
||||
|
||||
bl_idname = "kitsu.con_shots_load"
|
||||
bl_label = "Shots Load"
|
||||
bl_property = "enum_prop"
|
||||
bl_description = "Sets active shot for this scene"
|
||||
|
||||
enum_prop: bpy.props.EnumProperty(items=cache.get_shots_enum_for_active_seq) # type: ignore
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context: bpy.types.Context) -> bool:
|
||||
# Only if session is auth active_project and active sequence selected.
|
||||
return bool(
|
||||
prefs.session_auth(context)
|
||||
and cache.sequence_active_get()
|
||||
and cache.project_active_get()
|
||||
)
|
||||
|
||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||
# Update kitsu metadata.
|
||||
if self.enum_prop:
|
||||
cache.shot_active_set_by_id(context, self.enum_prop)
|
||||
util.ui_redraw()
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.invoke_search_popup(self)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class KITSU_OT_con_asset_types_load(bpy.types.Operator):
|
||||
"""
|
||||
Gets all asset_types that are available in server and let's user select. Invokes a search Popup (enum_prop) on click.
|
||||
"""
|
||||
|
||||
bl_idname = "kitsu.con_asset_types_load"
|
||||
bl_label = "Asset Types Load"
|
||||
bl_property = "enum_prop"
|
||||
bl_description = "Sets active asset type for this scene"
|
||||
|
||||
enum_prop: bpy.props.EnumProperty(items=cache.get_assetypes_enum_list) # type: ignore
|
||||
|
||||
@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]:
|
||||
# Store vars to check if project / seq / shot changed.
|
||||
asset_type_prev_id = cache.asset_type_active_get().id
|
||||
|
||||
# Update kitsu metadata.
|
||||
cache.asset_type_active_set_by_id(context, self.enum_prop)
|
||||
|
||||
# Clear active shot when sequence changes.
|
||||
if self.enum_prop != asset_type_prev_id:
|
||||
cache.asset_active_reset(context)
|
||||
|
||||
util.ui_redraw()
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.invoke_search_popup(self)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class KITSU_OT_con_assets_load(bpy.types.Operator):
|
||||
"""
|
||||
Gets all assets that are available on server for active production and let's user select. Invokes a search Popup (enum_prop) on click.
|
||||
"""
|
||||
|
||||
bl_idname = "kitsu.con_assets_load"
|
||||
bl_label = "Assets Load"
|
||||
bl_property = "enum_prop"
|
||||
bl_description = "Sets active asset for this scene"
|
||||
|
||||
enum_prop: bpy.props.EnumProperty(items=cache.get_assets_enum_for_active_asset_type) # type: ignore
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context: bpy.types.Context) -> bool:
|
||||
return bool(
|
||||
prefs.session_auth(context)
|
||||
and cache.project_active_get()
|
||||
and cache.asset_type_active_get()
|
||||
)
|
||||
|
||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||
if not self.enum_prop:
|
||||
return {"CANCELLED"}
|
||||
|
||||
# Update kitsu metadata.
|
||||
cache.asset_active_set_by_id(context, self.enum_prop)
|
||||
util.ui_redraw()
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.invoke_search_popup(self)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class KITSU_OT_con_task_types_load(bpy.types.Operator):
|
||||
"""
|
||||
Gets all task types that are available on server for active asset/shot and let's user select. Invokes a search Popup (enum_prop) on click.
|
||||
"""
|
||||
|
||||
bl_idname = "kitsu.con_task_types_load"
|
||||
bl_label = "Task Types Load"
|
||||
bl_property = "enum_prop"
|
||||
bl_description = "Sets active task type for this scene"
|
||||
|
||||
enum_prop: bpy.props.EnumProperty(items=cache.get_task_types_enum_for_current_context) # type: ignore
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context: bpy.types.Context) -> bool:
|
||||
addon_prefs = prefs.addon_prefs_get(context)
|
||||
precon = bool(prefs.session_auth(context) and cache.project_active_get())
|
||||
|
||||
if context_core.is_shot_context():
|
||||
return bool(precon and cache.sequence_active_get() and cache.shot_active_get())
|
||||
|
||||
if context_core.is_asset_context():
|
||||
return bool(precon and cache.asset_type_active_get() and cache.asset_active_get())
|
||||
if context_core.is_sequence_context():
|
||||
return bool(precon and cache.sequence_active_get())
|
||||
|
||||
return False
|
||||
|
||||
def execute(self, context: bpy.types.Context) -> Set[str]:
|
||||
# Store vars to check if project / seq / shot changed.
|
||||
asset_task_type_id = cache.task_type_active_get().id
|
||||
|
||||
# Update kitsu metadata.
|
||||
cache.task_type_active_set_by_id(context, self.enum_prop)
|
||||
|
||||
util.ui_redraw()
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.invoke_search_popup(self)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class KITSU_OT_con_detect_context(bpy.types.Operator):
|
||||
bl_idname = "kitsu.con_detect_context"
|
||||
bl_label = "Detect Context"
|
||||
|
@ -303,6 +85,8 @@ class KITSU_OT_con_detect_context(bpy.types.Operator):
|
|||
filepath = Path(bpy.data.filepath)
|
||||
active_project = cache.project_active_get()
|
||||
|
||||
kitsu_props = context.scene.kitsu
|
||||
|
||||
# TODO REFACTOR THIS WHOLE THING, BAD HACK
|
||||
# Path is different for tvshow
|
||||
if (
|
||||
|
@ -322,7 +106,7 @@ class KITSU_OT_con_detect_context(bpy.types.Operator):
|
|||
# TODO: check if frame range update gets triggered.
|
||||
|
||||
# Set category.
|
||||
context.scene.kitsu.category = "SHOT"
|
||||
kitsu_props.category = "SHOT"
|
||||
|
||||
# Detect ad load sequence.
|
||||
sequence = active_project.get_sequence_by_name(item_group)
|
||||
|
@ -330,7 +114,7 @@ class KITSU_OT_con_detect_context(bpy.types.Operator):
|
|||
self.report({"ERROR"}, f"Failed to find sequence: '{item_group}' on server")
|
||||
return {"CANCELLED"}
|
||||
|
||||
bpy.ops.kitsu.con_sequences_load(enum_prop=sequence.id)
|
||||
kitsu_props.sequence_active_name = sequence.name
|
||||
|
||||
# Detect and load shot.
|
||||
shot = active_project.get_shot_by_name(sequence, item)
|
||||
|
@ -338,7 +122,7 @@ class KITSU_OT_con_detect_context(bpy.types.Operator):
|
|||
self.report({"ERROR"}, f"Failed to find shot: '{item}' on server")
|
||||
return {"CANCELLED"}
|
||||
|
||||
bpy.ops.kitsu.con_shots_load(enum_prop=shot.id)
|
||||
kitsu_props.shot_active_name = shot.name
|
||||
|
||||
# Detect and load shot task type.
|
||||
kitsu_task_type_name = self._find_in_mapping(
|
||||
|
@ -355,11 +139,11 @@ class KITSU_OT_con_detect_context(bpy.types.Operator):
|
|||
)
|
||||
return {"CANCELLED"}
|
||||
|
||||
bpy.ops.kitsu.con_task_types_load(enum_prop=task_type.id)
|
||||
kitsu_props.task_type_active_name = task_type.name
|
||||
|
||||
if category == bkglobals.SEQ_DIR_NAME:
|
||||
# Set category.
|
||||
context.scene.kitsu.category = "SEQ"
|
||||
kitsu_props.category = "SEQ"
|
||||
|
||||
# Detect and load seqeunce.
|
||||
sequence = active_project.get_sequence_by_name(item_group)
|
||||
|
@ -367,7 +151,7 @@ class KITSU_OT_con_detect_context(bpy.types.Operator):
|
|||
self.report({"ERROR"}, f"Failed to find sequence: '{item_group}' on server")
|
||||
return {"CANCELLED"}
|
||||
|
||||
bpy.ops.kitsu.con_sequences_load(enum_prop=sequence.id)
|
||||
kitsu_props.sequence_active_name = sequence.name
|
||||
|
||||
# Detect and load shot task type.
|
||||
kitsu_task_type_name = self._find_in_mapping(
|
||||
|
@ -384,11 +168,11 @@ class KITSU_OT_con_detect_context(bpy.types.Operator):
|
|||
)
|
||||
return {"CANCELLED"}
|
||||
|
||||
bpy.ops.kitsu.con_task_types_load(enum_prop=task_type.id)
|
||||
kitsu_props.task_type_active_name = task_type.name
|
||||
|
||||
elif category == bkglobals.ASSET_DIR_NAME:
|
||||
# Set category.
|
||||
context.scene.kitsu.category = "ASSET"
|
||||
kitsu_props.category = "ASSET"
|
||||
|
||||
# Detect and load asset type.
|
||||
kitsu_asset_type_name = self._find_in_mapping(
|
||||
|
@ -405,15 +189,13 @@ class KITSU_OT_con_detect_context(bpy.types.Operator):
|
|||
)
|
||||
return {"CANCELLED"}
|
||||
|
||||
bpy.ops.kitsu.con_asset_types_load(enum_prop=asset_type.id)
|
||||
|
||||
kitsu_props.asset_type_active_name = asset_type.name
|
||||
# Detect and load asset.
|
||||
asset = active_project.get_asset_by_name(item)
|
||||
if not asset:
|
||||
self.report({"ERROR"}, f"Failed to find asset: '{item}' on server")
|
||||
return {"CANCELLED"}
|
||||
|
||||
bpy.ops.kitsu.con_assets_load(enum_prop=asset.id)
|
||||
kitsu_props.asset_active_name = asset.name
|
||||
|
||||
# Detect and load asset task_type.
|
||||
kitsu_task_type_name = self._find_in_mapping(
|
||||
|
@ -430,7 +212,7 @@ class KITSU_OT_con_detect_context(bpy.types.Operator):
|
|||
)
|
||||
return {"CANCELLED"}
|
||||
|
||||
bpy.ops.kitsu.con_task_types_load(enum_prop=task_type.id)
|
||||
kitsu_props.task_type_active_name = task_type.name
|
||||
|
||||
else:
|
||||
self.report(
|
||||
|
@ -462,12 +244,6 @@ class KITSU_OT_con_detect_context(bpy.types.Operator):
|
|||
|
||||
classes = [
|
||||
KITSU_OT_con_productions_load,
|
||||
KITSU_OT_con_episodes_load,
|
||||
KITSU_OT_con_sequences_load,
|
||||
KITSU_OT_con_shots_load,
|
||||
KITSU_OT_con_asset_types_load,
|
||||
KITSU_OT_con_assets_load,
|
||||
KITSU_OT_con_task_types_load,
|
||||
KITSU_OT_con_detect_context,
|
||||
]
|
||||
|
||||
|
|
|
@ -23,13 +23,7 @@ import bpy
|
|||
from ..context import core as context_core
|
||||
from .. import cache, prefs, ui
|
||||
from ..context.ops import (
|
||||
KITSU_OT_con_sequences_load,
|
||||
KITSU_OT_con_shots_load,
|
||||
KITSU_OT_con_asset_types_load,
|
||||
KITSU_OT_con_assets_load,
|
||||
KITSU_OT_con_task_types_load,
|
||||
KITSU_OT_con_detect_context,
|
||||
KITSU_OT_con_episodes_load,
|
||||
)
|
||||
|
||||
|
||||
|
@ -56,86 +50,10 @@ class KITSU_PT_vi3d_context(bpy.types.Panel):
|
|||
project_active = cache.project_active_get()
|
||||
return bool(not project_active)
|
||||
|
||||
def draw_episode_selector(self, layout, project_active, episode_active):
|
||||
row = layout.row(align=True)
|
||||
|
||||
if not project_active:
|
||||
row.enabled = False
|
||||
|
||||
label_text = "Select Episode" if not episode_active else episode_active.name
|
||||
|
||||
if project_active.nb_episodes > 0:
|
||||
row.operator(
|
||||
KITSU_OT_con_episodes_load.bl_idname,
|
||||
text=label_text,
|
||||
icon="DOWNARROW_HLT",
|
||||
)
|
||||
|
||||
def draw_sequence_selector(self, layout, project_active, episode_active):
|
||||
row = layout.row(align=True)
|
||||
|
||||
if not project_active:
|
||||
row.enabled = False
|
||||
|
||||
elif project_active.nb_episodes > 0 and not episode_active:
|
||||
row.enabled = False
|
||||
|
||||
sequence = cache.sequence_active_get()
|
||||
label_text = "Select Sequence" if not sequence else sequence.name
|
||||
|
||||
row.operator(
|
||||
KITSU_OT_con_sequences_load.bl_idname,
|
||||
text=label_text,
|
||||
icon="DOWNARROW_HLT",
|
||||
)
|
||||
|
||||
def draw_asset_type_selector(self, layout, project_active):
|
||||
row = layout.row(align=True)
|
||||
|
||||
if not project_active:
|
||||
row.enabled = False
|
||||
|
||||
asset_type = cache.asset_type_active_get()
|
||||
label_text = "Select Asset Type" if not asset_type else asset_type.name
|
||||
|
||||
row.operator(
|
||||
KITSU_OT_con_asset_types_load.bl_idname,
|
||||
text=label_text,
|
||||
icon="DOWNARROW_HLT",
|
||||
)
|
||||
|
||||
def draw_shot_selector(self, layout, project_active):
|
||||
row = layout.row(align=True)
|
||||
|
||||
if not project_active:
|
||||
row.enabled = False
|
||||
|
||||
shot = cache.shot_active_get()
|
||||
label_text = "Select Shot" if not shot else shot.name
|
||||
|
||||
row.operator(
|
||||
KITSU_OT_con_shots_load.bl_idname,
|
||||
text=label_text,
|
||||
icon="DOWNARROW_HLT",
|
||||
)
|
||||
|
||||
def draw_asset_selector(self, layout, project_active):
|
||||
row = layout.row(align=True)
|
||||
|
||||
if not project_active:
|
||||
row.enabled = False
|
||||
|
||||
asset = cache.asset_active_get()
|
||||
label_text = "Select Asset" if not asset else asset.name
|
||||
|
||||
row.operator(
|
||||
KITSU_OT_con_assets_load.bl_idname,
|
||||
text=label_text,
|
||||
icon="DOWNARROW_HLT",
|
||||
)
|
||||
|
||||
def draw(self, context: bpy.types.Context) -> None:
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
project_active = cache.project_active_get()
|
||||
episode_active = cache.episode_active_get()
|
||||
|
||||
|
@ -160,38 +78,36 @@ class KITSU_PT_vi3d_context(bpy.types.Panel):
|
|||
emboss=False,
|
||||
)
|
||||
|
||||
flow = layout.grid_flow(
|
||||
row_major=True, columns=0, even_columns=True, even_rows=False, align=False
|
||||
)
|
||||
col = flow.column()
|
||||
# Entity context
|
||||
row = layout.row(align=True)
|
||||
row.prop(context.scene.kitsu, "category")
|
||||
col.prop(context.scene.kitsu, "category")
|
||||
|
||||
if not prefs.session_auth(context) or not project_active:
|
||||
row.enabled = False
|
||||
|
||||
# Episode selector
|
||||
if project_active.nb_episodes > 0:
|
||||
self.draw_episode_selector(layout, project_active, episode_active)
|
||||
context_core.draw_episode_selector(context, col)
|
||||
|
||||
# Sequence selector (if context is Sequence)
|
||||
if context_core.is_sequence_context():
|
||||
self.draw_sequence_selector(layout, project_active, episode_active)
|
||||
context_core.draw_sequence_selector(context, col)
|
||||
|
||||
# Shot selector
|
||||
if context_core.is_shot_context():
|
||||
self.draw_sequence_selector(layout, project_active, episode_active)
|
||||
self.draw_shot_selector(layout, project_active)
|
||||
context_core.draw_sequence_selector(context, col)
|
||||
context_core.draw_shot_selector(context, col)
|
||||
|
||||
# AssetType selector (if context is Asset)
|
||||
if context_core.is_asset_context():
|
||||
self.draw_asset_type_selector(layout, project_active)
|
||||
self.draw_asset_selector(layout, project_active)
|
||||
context_core.draw_asset_type_selector(context, col)
|
||||
context_core.draw_asset_selector(context, col)
|
||||
|
||||
# Task Type selector
|
||||
t_text = "Select Task Type"
|
||||
task_type_active = cache.task_type_active_get()
|
||||
if task_type_active:
|
||||
t_text = task_type_active.name
|
||||
row = layout.row(align=True)
|
||||
row.operator(KITSU_OT_con_task_types_load.bl_idname, text=t_text, icon="DOWNARROW_HLT")
|
||||
context_core.draw_task_type_selector(context, col)
|
||||
|
||||
|
||||
class KITSU_PT_comp_context(KITSU_PT_vi3d_context):
|
||||
|
|
|
@ -19,13 +19,14 @@
|
|||
# (c) 2021, Blender Foundation - Paul Golter
|
||||
|
||||
|
||||
from typing import Any, Union, List, Dict, Optional
|
||||
from typing import Any, Union, List, Dict, Optional, Tuple
|
||||
|
||||
import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
|
||||
from . import propsdata, bkglobals
|
||||
from .logger import LoggerFactory
|
||||
from . import cache
|
||||
|
||||
logger = LoggerFactory.getLogger()
|
||||
|
||||
|
@ -123,9 +124,327 @@ class KITSU_property_group_sequence(bpy.types.PropertyGroup):
|
|||
self.linked = False
|
||||
|
||||
|
||||
def set_kitsu_entity_id_via_enum_name(
|
||||
self,
|
||||
items: List[Tuple[str, str, str]],
|
||||
input_name: str,
|
||||
name_prop: str,
|
||||
id_prop: str,
|
||||
) -> str:
|
||||
"""Set the ID and Name of a Kitsu entity by finding the matching ID for a given name
|
||||
and updating both values in their corrisponding String Properties (Kitsu Context Properties)
|
||||
|
||||
Args:
|
||||
items (List[Tuple[str, str, str]]): Enum items in the format List[Tuple[id, name, description]]
|
||||
input_name (str): Name, used to find matching ID in a tuple
|
||||
name_prop (str): Name of String Property where Kitsu Enitity's Name is stored
|
||||
id_prop (str): Name of String Property where Kitsu Enitity's ID is stored
|
||||
|
||||
Returns:
|
||||
str: ID of Kitsu entity
|
||||
"""
|
||||
|
||||
if input_name == "":
|
||||
self[id_prop] = ""
|
||||
self[name_prop] = input_name
|
||||
return
|
||||
for key, value, _ in items:
|
||||
if value == input_name:
|
||||
self[id_prop] = key
|
||||
self[name_prop] = input_name
|
||||
return key
|
||||
|
||||
|
||||
def get_enum_item_names(enum_items: List[Tuple[str, str, str]]) -> List[str]:
|
||||
"""Return a list of names from a list of enum items used by (Kitsu Context Properties)
|
||||
|
||||
Args:
|
||||
enum_items (List[Tuple[str, str, str]]): Enum items in the format List[Tuple[id, name, description]]
|
||||
|
||||
Returns:
|
||||
List[str]: List of avaliable names
|
||||
"""
|
||||
return [item[1] for item in enum_items]
|
||||
|
||||
|
||||
def get_safely_string_prop(self, name: str) -> str:
|
||||
"""Return Value of String Property, and return "" if value isn't set"""
|
||||
try:
|
||||
return self[name]
|
||||
except KeyError:
|
||||
return ""
|
||||
|
||||
|
||||
class KITSU_property_group_scene(bpy.types.PropertyGroup):
|
||||
""""""
|
||||
|
||||
################################
|
||||
# Kitsu Context Properties
|
||||
################################
|
||||
"""
|
||||
Kitsu Context Properties
|
||||
|
||||
These are properties used to store/manage the current "Context"
|
||||
for a Kitsu Entity. Kitsu Entities represents things like Asset,
|
||||
Shot and Sequence for a given production.
|
||||
|
||||
Each Enitity has an 'ID' Property which is used internally by the add-on
|
||||
and a 'Name' Property which is used as part of the user interface. When a user selects
|
||||
the 'Name' of a Kitsu Entity a custom Set function on the property will also update
|
||||
the Entity's ID.
|
||||
|
||||
NOTE: It would be nice to have searchable enums instead of doing all this work manually.
|
||||
"""
|
||||
|
||||
###########
|
||||
# Sequence
|
||||
###########
|
||||
sequence_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Sequence ID",
|
||||
description="ID that refers to the active sequence on server",
|
||||
default="",
|
||||
)
|
||||
|
||||
def get_sequences_via_name(self):
|
||||
return get_safely_string_prop(self, "sequence_active_name")
|
||||
|
||||
def set_sequences_via_name(self, input):
|
||||
key = set_kitsu_entity_id_via_enum_name(
|
||||
self=self,
|
||||
input_name=input,
|
||||
items=cache.get_sequences_enum_list(self, bpy.context),
|
||||
name_prop='sequence_active_name',
|
||||
id_prop='sequence_active_id',
|
||||
)
|
||||
if key:
|
||||
cache.sequence_active_set_by_id(bpy.context, key)
|
||||
else:
|
||||
cache.sequence_active_reset_entity()
|
||||
return
|
||||
|
||||
def get_sequence_search_list(self, context, edit_text):
|
||||
return get_enum_item_names(cache.get_sequences_enum_list(self, bpy.context))
|
||||
|
||||
sequence_active_name: bpy.props.StringProperty(
|
||||
name="Sequence",
|
||||
description="Sequence",
|
||||
default="", # type: ignore
|
||||
get=get_sequences_via_name,
|
||||
set=set_sequences_via_name,
|
||||
options=set(),
|
||||
search=get_sequence_search_list,
|
||||
search_options={'SORT'},
|
||||
)
|
||||
|
||||
###########
|
||||
# Episode
|
||||
###########
|
||||
episode_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Episode ID",
|
||||
description="ID that refers to the active episode on server",
|
||||
default="",
|
||||
)
|
||||
|
||||
def get_episode_via_name(self):
|
||||
return get_safely_string_prop(self, "episode_active_name")
|
||||
|
||||
def set_episode_via_name(self, input):
|
||||
key = set_kitsu_entity_id_via_enum_name(
|
||||
self=self,
|
||||
input_name=input,
|
||||
items=cache.get_episodes_enum_list(self, bpy.context),
|
||||
name_prop='episode_active_name',
|
||||
id_prop='episode_active_id',
|
||||
)
|
||||
|
||||
# Clear active shot when sequence changes.
|
||||
if cache.episode_active_get().id != key:
|
||||
cache.sequence_active_reset(bpy.context)
|
||||
cache.asset_type_active_reset(bpy.context)
|
||||
cache.shot_active_reset(bpy.context)
|
||||
cache.asset_active_reset(bpy.context)
|
||||
|
||||
if key:
|
||||
cache.episode_active_set_by_id(bpy.context, key)
|
||||
return
|
||||
|
||||
def get_episode_search_list(self, context, edit_text):
|
||||
return get_enum_item_names(cache.get_episodes_enum_list(self, bpy.context))
|
||||
|
||||
episode_active_name: bpy.props.StringProperty(
|
||||
name="Episode",
|
||||
description="Selet Active Episode",
|
||||
default="", # type: ignore
|
||||
get=get_episode_via_name,
|
||||
set=set_episode_via_name,
|
||||
options=set(),
|
||||
search=get_episode_search_list,
|
||||
search_options={'SORT'},
|
||||
)
|
||||
|
||||
###########
|
||||
# Shot
|
||||
###########
|
||||
shot_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Shot ID",
|
||||
description="IDthat refers to the active shot on server",
|
||||
default="",
|
||||
# update=propsdata.on_shot_change,
|
||||
)
|
||||
|
||||
def get_shot_via_name(self):
|
||||
return get_safely_string_prop(self, "shot_active_name")
|
||||
|
||||
def set_shot_via_name(self, input):
|
||||
key = set_kitsu_entity_id_via_enum_name(
|
||||
self=self,
|
||||
input_name=input,
|
||||
items=cache.get_shots_enum_for_active_seq(self, bpy.context),
|
||||
name_prop='shot_active_name',
|
||||
id_prop='shot_active_id',
|
||||
)
|
||||
if key:
|
||||
cache.shot_active_set_by_id(bpy.context, key)
|
||||
else:
|
||||
cache.shot_active_reset_entity()
|
||||
return
|
||||
|
||||
def get_shot_search_list(self, context, edit_text):
|
||||
return get_enum_item_names(cache.get_shots_enum_for_active_seq(self, bpy.context))
|
||||
|
||||
shot_active_name: bpy.props.StringProperty(
|
||||
name="Shot",
|
||||
description="Shot",
|
||||
default="", # type: ignore
|
||||
get=get_shot_via_name,
|
||||
set=set_shot_via_name,
|
||||
options=set(),
|
||||
search=get_shot_search_list,
|
||||
search_options={'SORT'},
|
||||
)
|
||||
|
||||
###########
|
||||
# Asset
|
||||
###########
|
||||
asset_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Asset ID",
|
||||
description="ID that refers to the active asset on server",
|
||||
default="",
|
||||
)
|
||||
|
||||
def get_asset_via_name(self):
|
||||
return get_safely_string_prop(self, "asset_active_name")
|
||||
|
||||
def set_asset_via_name(self, input):
|
||||
key = set_kitsu_entity_id_via_enum_name(
|
||||
self=self,
|
||||
input_name=input,
|
||||
items=cache.get_assets_enum_for_active_asset_type(self, bpy.context),
|
||||
name_prop='asset_active_name',
|
||||
id_prop='asset_active_id',
|
||||
)
|
||||
if key:
|
||||
cache.asset_active_set_by_id(bpy.context, key) # TODO
|
||||
else:
|
||||
cache.asset_active_reset_entity()
|
||||
return
|
||||
|
||||
def get_asset_type_search_list(self, context, edit_text):
|
||||
return get_enum_item_names(cache.get_assets_enum_for_active_asset_type(self, bpy.context))
|
||||
|
||||
asset_active_name: bpy.props.StringProperty(
|
||||
name="Asset",
|
||||
description="Active Asset",
|
||||
default="", # type: ignore
|
||||
get=get_asset_via_name,
|
||||
set=set_asset_via_name,
|
||||
options=set(),
|
||||
search=get_asset_type_search_list,
|
||||
search_options={'SORT'},
|
||||
)
|
||||
|
||||
############
|
||||
# Asset Type
|
||||
############
|
||||
|
||||
asset_type_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Asset Type ID",
|
||||
description="ID that refers to the active asset type on server",
|
||||
default="",
|
||||
)
|
||||
|
||||
def get_asset_type_via_name(self):
|
||||
return get_safely_string_prop(self, "asset_type_active_name")
|
||||
|
||||
def set_asset_type_via_name(self, input):
|
||||
key = set_kitsu_entity_id_via_enum_name(
|
||||
self=self,
|
||||
input_name=input,
|
||||
items=cache.get_assetypes_enum_list(self, bpy.context),
|
||||
name_prop='asset_type_active_name',
|
||||
id_prop='asset_type_active_id',
|
||||
)
|
||||
if key:
|
||||
cache.asset_type_active_set_by_id(bpy.context, key)
|
||||
else:
|
||||
cache.asset_type_active_reset_entity()
|
||||
return
|
||||
|
||||
def get_asset_type_search_list(self, context, edit_text):
|
||||
return get_enum_item_names(cache.get_assetypes_enum_list(self, bpy.context))
|
||||
|
||||
asset_type_active_name: bpy.props.StringProperty(
|
||||
name="Asset Type",
|
||||
description="Active Asset Type Name",
|
||||
default="", # type: ignore
|
||||
get=get_asset_type_via_name,
|
||||
set=set_asset_type_via_name,
|
||||
options=set(),
|
||||
search=get_asset_type_search_list,
|
||||
search_options={'SORT'},
|
||||
)
|
||||
|
||||
############
|
||||
# Task Type
|
||||
############
|
||||
|
||||
task_type_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Task Type ID",
|
||||
description="ID that refers to the active task type on server",
|
||||
default="",
|
||||
)
|
||||
|
||||
def get_task_type_via_name(self):
|
||||
return get_safely_string_prop(self, "task_type_active_name")
|
||||
|
||||
def set_task_type_via_name(self, input):
|
||||
key = set_kitsu_entity_id_via_enum_name(
|
||||
self=self,
|
||||
input_name=input,
|
||||
items=cache.get_task_types_enum_for_current_context(self, bpy.context),
|
||||
name_prop='task_type_active_name',
|
||||
id_prop='task_type_active_id',
|
||||
)
|
||||
if key:
|
||||
cache.task_type_active_set_by_id(bpy.context, key)
|
||||
else:
|
||||
cache.task_type_active_reset_entity()
|
||||
return
|
||||
|
||||
def get_task_type_search_list(self, context, edit_text):
|
||||
return get_enum_item_names(cache.get_task_types_enum_for_current_context(self, bpy.context))
|
||||
|
||||
task_type_active_name: bpy.props.StringProperty(
|
||||
name="Task Type",
|
||||
description="Active Task Type Name",
|
||||
default="", # type: ignore
|
||||
get=get_task_type_via_name,
|
||||
set=set_task_type_via_name,
|
||||
options=set(),
|
||||
search=get_task_type_search_list,
|
||||
search_options={'SORT'},
|
||||
)
|
||||
|
||||
category: bpy.props.EnumProperty( # type: ignore
|
||||
name="Type",
|
||||
description="Kitsu entity type",
|
||||
|
@ -136,46 +455,7 @@ class KITSU_property_group_scene(bpy.types.PropertyGroup):
|
|||
("EDIT", "Edit", "Edit related tasks", 3),
|
||||
),
|
||||
default="SHOT",
|
||||
update=propsdata.reset_task_type,
|
||||
)
|
||||
|
||||
# Context props.
|
||||
|
||||
sequence_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Sequence ID",
|
||||
description="ID that refers to the active sequence on server",
|
||||
default="",
|
||||
)
|
||||
|
||||
episode_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Episode ID",
|
||||
description="ID that refers to the active episode on server",
|
||||
default="",
|
||||
)
|
||||
|
||||
shot_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Shot ID",
|
||||
description="IDthat refers to the active shot on server",
|
||||
default="",
|
||||
update=propsdata.on_shot_change,
|
||||
)
|
||||
|
||||
asset_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Asset ID",
|
||||
description="ID that refers to the active asset on server",
|
||||
default="",
|
||||
)
|
||||
|
||||
asset_type_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Asset Type ID",
|
||||
description="ID that refers to the active asset type on server",
|
||||
default="",
|
||||
)
|
||||
|
||||
task_type_active_id: bpy.props.StringProperty( # type: ignore
|
||||
name="Active Task Type ID",
|
||||
description="ID that refers to the active task type on server",
|
||||
default="",
|
||||
update=propsdata.reset_all_kitsu_props,
|
||||
)
|
||||
|
||||
# Thumbnail props.
|
||||
|
|
|
@ -195,3 +195,12 @@ def on_shot_change(self: Any, context: bpy.types.Context) -> None:
|
|||
|
||||
# Check frame range.
|
||||
ops_playblast.load_post_handler_check_frame_range(context)
|
||||
|
||||
|
||||
def reset_all_kitsu_props(self: Any, context: bpy.types.Context) -> None:
|
||||
cache.sequence_active_reset(context)
|
||||
cache.asset_type_active_reset(context)
|
||||
cache.shot_active_reset(context)
|
||||
cache.asset_active_reset(context)
|
||||
cache.episode_active_reset(context)
|
||||
cache.task_type_active_reset(context)
|
||||
|
|
Loading…
Reference in New Issue