334 lines
10 KiB
Python
334 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)
|