344 lines
10 KiB
Python
344 lines
10 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
"""
|
|
Action Library - GUI definition.
|
|
"""
|
|
|
|
import bpy
|
|
from pathlib import Path
|
|
|
|
from bpy.types import (
|
|
AssetHandle,
|
|
Context,
|
|
Header,
|
|
Menu,
|
|
Panel,
|
|
UIList,
|
|
WindowManager,
|
|
WorkSpace,
|
|
)
|
|
|
|
from bpy_extras import asset_utils
|
|
from asset_library.common.bl_utils import (
|
|
get_addon_prefs,
|
|
get_object_libraries,
|
|
)
|
|
|
|
from asset_library.common.functions import get_active_library
|
|
|
|
|
|
def pose_library_panel_poll():
|
|
return bpy.context.object and bpy.context.object.mode == "POSE"
|
|
|
|
|
|
class PoseLibraryPanel:
|
|
@classmethod
|
|
def pose_library_panel_poll(cls, context: Context) -> bool:
|
|
return bool(context.object and context.object.mode == "POSE")
|
|
|
|
@classmethod
|
|
def poll(cls, context: Context) -> bool:
|
|
return cls.pose_library_panel_poll(context)
|
|
|
|
|
|
class AssetLibraryMenu:
|
|
@classmethod
|
|
def poll(cls, context):
|
|
from bpy_extras.asset_utils import SpaceAssetInfo
|
|
|
|
return SpaceAssetInfo.is_asset_browser_poll(context)
|
|
|
|
|
|
class ASSETLIB_PT_libraries(Panel):
|
|
bl_label = "Libraries"
|
|
bl_space_type = "VIEW_3D"
|
|
bl_region_type = "UI"
|
|
bl_category = "Item"
|
|
|
|
@classmethod
|
|
def poll(cls, context: Context) -> bool:
|
|
return context.object and get_object_libraries(context.object)
|
|
|
|
def draw(self, context: Context) -> None:
|
|
layout = self.layout
|
|
|
|
for f in get_object_libraries(context.object):
|
|
row = layout.row(align=True)
|
|
row.label(text=f)
|
|
row.operator("assetlib.open_blend", icon="FILE_BLEND", text="").filepath = f
|
|
|
|
|
|
"""
|
|
class ASSETLIB_PT_pose_library_usage(Panel):
|
|
bl_space_type = 'FILE_BROWSER'
|
|
bl_region_type = "TOOLS"
|
|
bl_label = "Action Library"
|
|
# asset_categories = {'ANIMATIONS'}
|
|
|
|
@classmethod
|
|
def poll(cls, context: Context) -> bool:
|
|
sp = context.space_data
|
|
|
|
if not context.object or not context.object.mode == 'POSE':
|
|
return False
|
|
|
|
if not (sp and sp.type == 'FILE_BROWSER' and sp.browse_mode == 'ASSETS'):
|
|
return False
|
|
|
|
return True
|
|
|
|
def draw(self, context: Context) -> None:
|
|
layout = self.layout
|
|
wm = context.window_manager
|
|
|
|
sp = context.space_data
|
|
sp.params.asset_library_ref
|
|
|
|
if sp.params.asset_library_ref == 'LOCAL':
|
|
col = layout.column(align=True)
|
|
row = col.row(align=True)
|
|
row.operator("poselib.create_pose_asset", text="Create Pose", icon='POSE_HLT').activate_new_action = False
|
|
row.operator("actionlib.replace_pose", text='Replace Pose', icon='FILE_REFRESH')
|
|
col.operator("actionlib.create_anim_asset", text="Create Anim", icon='ANIM')
|
|
|
|
col.separator()
|
|
row = col.row(align=True)
|
|
row.operator("actionlib.edit_action", text='Edit Action', icon='ACTION')
|
|
row.operator("actionlib.clear_action", text='Finish Edit', icon='CHECKBOX_HLT')
|
|
|
|
col.separator()
|
|
col.operator("actionlib.generate_preview", icon='RESTRICT_RENDER_OFF', text="Generate Thumbnail")
|
|
col.operator("actionlib.update_action_data", icon='FILE_TEXT', text="Update Action Data")
|
|
else:
|
|
col = layout.column(align=True)
|
|
row = col.row(align=True)
|
|
row.operator("actionlib.store_anim_pose", text='Store Anim/Pose', icon='ACTION')
|
|
"""
|
|
|
|
|
|
class ASSETLIB_PT_pose_library_editing(
|
|
PoseLibraryPanel, asset_utils.AssetBrowserPanel, Panel
|
|
):
|
|
bl_space_type = "FILE_BROWSER"
|
|
bl_region_type = "TOOL_PROPS"
|
|
bl_label = "Metadata"
|
|
# bl_options = {'HIDE_HEADER'}
|
|
# asset_categories = {'ANIMATIONS'}
|
|
|
|
@classmethod
|
|
def poll(cls, context: Context) -> bool:
|
|
sp = context.space_data
|
|
|
|
if not (sp and sp.type == "FILE_BROWSER" and sp.browse_mode == "ASSETS"):
|
|
return False
|
|
|
|
if not (context.active_file and context.active_file.asset_data):
|
|
return False
|
|
|
|
return True
|
|
|
|
def draw(self, context: Context) -> None:
|
|
layout = self.layout
|
|
|
|
layout.use_property_split = True
|
|
asset_data = context.active_file.asset_data
|
|
metadata = ["camera", "is_single_frame", "rest_pose"]
|
|
|
|
if "camera" in asset_data.keys():
|
|
layout.prop(asset_data, f'["camera"]', text="Camera", icon="CAMERA_DATA")
|
|
if "is_single_frame" in asset_data.keys():
|
|
layout.prop(asset_data, f'["is_single_frame"]', text="Is Single Frame")
|
|
if "rest_pose" in asset_data.keys():
|
|
layout.prop(asset_data, f'["rest_pose"]', text="Rest Pose", icon="ACTION")
|
|
if "filepath" in asset_data.keys():
|
|
layout.prop(asset_data, f'["filepath"]', text="Filepath")
|
|
|
|
|
|
class ASSETLIB_MT_context_menu(AssetLibraryMenu, Menu):
|
|
bl_label = "Asset Library Menu"
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
if not asset_utils.SpaceAssetInfo.is_asset_browser(context.space_data):
|
|
cls.poll_message_set("Current editor is not an asset browser")
|
|
return False
|
|
|
|
prefs = get_addon_prefs()
|
|
asset_lib_ref = context.space_data.params.asset_library_ref
|
|
|
|
lib = get_active_library()
|
|
if not lib:
|
|
return False
|
|
|
|
return True
|
|
|
|
def draw(self, context):
|
|
lib = get_active_library()
|
|
lib.library_type.draw_context_menu(self.layout)
|
|
|
|
|
|
def is_option_region_visible(context, space):
|
|
from bpy_extras.asset_utils import SpaceAssetInfo
|
|
|
|
if SpaceAssetInfo.is_asset_browser(space):
|
|
pass
|
|
# For the File Browser, there must be an operator for there to be options
|
|
# (irrelevant for the Asset Browser).
|
|
elif not space.active_operator:
|
|
return False
|
|
|
|
for region in context.area.regions:
|
|
if region.type == "TOOL_PROPS" and region.width <= 1:
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def draw_assetbrowser_header(self, context):
|
|
lib = get_active_library()
|
|
|
|
if not lib:
|
|
bpy.types.FILEBROWSER_HT_header._draw_asset_browser_buttons(self, context)
|
|
return
|
|
|
|
space_data = context.space_data
|
|
params = context.space_data.params
|
|
|
|
row = self.layout.row(align=True)
|
|
row.separator()
|
|
|
|
row.operator("assetlib.bundle", icon="UV_SYNC_SELECT", text="").name = lib.name
|
|
# op
|
|
# op.clean = False
|
|
# op.only_recent = True
|
|
|
|
lib.library_type.draw_header(row)
|
|
|
|
if context.selected_files and context.active_file:
|
|
row.separator()
|
|
row.label(text=context.active_file.name)
|
|
|
|
row.separator_spacer()
|
|
|
|
sub = row.row()
|
|
sub.ui_units_x = 10
|
|
sub.prop(params, "filter_search", text="", icon="VIEWZOOM")
|
|
|
|
row.separator_spacer()
|
|
|
|
row.prop_with_popover(
|
|
params,
|
|
"display_type",
|
|
panel="ASSETBROWSER_PT_display",
|
|
text="",
|
|
icon_only=True,
|
|
)
|
|
|
|
row.operator(
|
|
"screen.region_toggle",
|
|
text="",
|
|
icon="PREFERENCES",
|
|
depress=is_option_region_visible(context, space_data),
|
|
).region_type = "TOOL_PROPS"
|
|
|
|
|
|
### Messagebus subscription to monitor asset library changes.
|
|
_msgbus_owner = object()
|
|
|
|
|
|
def _on_asset_library_changed() -> None:
|
|
"""Update areas when a different asset library is selected."""
|
|
refresh_area_types = {"DOPESHEET_EDITOR", "VIEW_3D"}
|
|
for win in bpy.context.window_manager.windows:
|
|
for area in win.screen.areas:
|
|
if area.type not in refresh_area_types:
|
|
continue
|
|
|
|
area.tag_redraw()
|
|
|
|
|
|
def register_message_bus() -> None:
|
|
|
|
bpy.msgbus.subscribe_rna(
|
|
key=(bpy.types.FileAssetSelectParams, "asset_library_ref"),
|
|
owner=_msgbus_owner,
|
|
args=(),
|
|
notify=_on_asset_library_changed,
|
|
options={"PERSISTENT"},
|
|
)
|
|
|
|
|
|
def unregister_message_bus() -> None:
|
|
bpy.msgbus.clear_by_owner(_msgbus_owner)
|
|
|
|
|
|
@bpy.app.handlers.persistent
|
|
def _on_blendfile_load_pre(none, other_none) -> None:
|
|
# The parameters are required, but both are None.
|
|
unregister_message_bus()
|
|
|
|
|
|
@bpy.app.handlers.persistent
|
|
def _on_blendfile_load_post(none, other_none) -> None:
|
|
# The parameters are required, but both are None.
|
|
register_message_bus()
|
|
|
|
|
|
classes = (
|
|
ASSETLIB_PT_pose_library_editing,
|
|
# ASSETLIB_PT_pose_library_usage,
|
|
ASSETLIB_MT_context_menu,
|
|
ASSETLIB_PT_libraries,
|
|
)
|
|
|
|
|
|
def register() -> None:
|
|
for cls in classes:
|
|
bpy.utils.register_class(cls)
|
|
|
|
bpy.types.FILEBROWSER_HT_header._draw_asset_browser_buttons = (
|
|
bpy.types.FILEBROWSER_HT_header.draw_asset_browser_buttons
|
|
)
|
|
bpy.types.FILEBROWSER_HT_header.draw_asset_browser_buttons = (
|
|
draw_assetbrowser_header
|
|
)
|
|
|
|
# WorkSpace.active_pose_asset_index = bpy.props.IntProperty(
|
|
# name="Active Pose Asset",
|
|
# # TODO explain which list the index belongs to, or how it can be used to get the pose.
|
|
# description="Per workspace index of the active pose asset"
|
|
# )
|
|
# Register for window-manager. This is a global property that shouldn't be
|
|
# written to files.
|
|
# WindowManager.pose_assets = bpy.props.CollectionProperty(type=AssetHandle)
|
|
|
|
# bpy.types.UI_MT_list_item_context_menu.prepend(pose_library_list_item_context_menu)
|
|
# bpy.types.ASSETLIB_MT_context_menu.prepend(pose_library_list_item_context_menu)
|
|
# bpy.types.ACTIONLIB_MT_context_menu.prepend(pose_library_list_item_context_menu)
|
|
# bpy.types.ASSETBROWSER_MT_editor_menus.append(draw_assetbrowser_header)
|
|
|
|
register_message_bus()
|
|
bpy.app.handlers.load_pre.append(_on_blendfile_load_pre)
|
|
bpy.app.handlers.load_post.append(_on_blendfile_load_post)
|
|
|
|
|
|
def unregister() -> None:
|
|
for cls in reversed(classes):
|
|
bpy.utils.unregister_class(cls)
|
|
|
|
bpy.types.FILEBROWSER_HT_header.draw_asset_browser_buttons = (
|
|
bpy.types.FILEBROWSER_HT_header._draw_asset_browser_buttons
|
|
)
|
|
del bpy.types.FILEBROWSER_HT_header._draw_asset_browser_buttons
|
|
|
|
unregister_message_bus()
|
|
|
|
# del WorkSpace.active_pose_asset_index
|
|
# del WindowManager.pose_assets
|
|
|
|
# bpy.types.UI_MT_list_item_context_menu.remove(pose_library_list_item_context_menu)
|
|
# bpy.types.ASSETLIB_MT_context_menu.remove(pose_library_list_item_context_menu)
|
|
# bpy.types.ACTIONLIB_MT_context_menu.remove(pose_library_list_item_context_menu)
|
|
# bpy.types.ASSETBROWSER_MT_editor_menus.remove(draw_assetbrowser_header)
|