WIP: Rewrite asset browser as separate editor #107576
|
@ -1084,6 +1084,35 @@ const bTheme U_theme_default = {
|
|||
.edited_object = RGBA(0x00806266),
|
||||
.row_alternate = RGBA(0xffffff04),
|
||||
},
|
||||
.space_assets = {
|
||||
.back = RGBA(0x28282800),
|
||||
.title = RGBA(0xffffffff),
|
||||
.text = RGBA(0xe6e6e6ff),
|
||||
.text_hi = RGBA(0xffffffff),
|
||||
.header = RGBA(0x303030b3),
|
||||
.header_text = RGBA(0xeeeeeeff),
|
||||
.header_text_hi = RGBA(0xffffffff),
|
||||
.tab_active = RGBA(0x303030ff),
|
||||
.tab_inactive = RGBA(0x1d1d1dff),
|
||||
.tab_back = RGBA(0x181818ff),
|
||||
.tab_outline = RGBA(0x3d3d3dff),
|
||||
.button = RGBA(0x30303000),
|
||||
.button_title = RGBA(0xffffffff),
|
||||
.button_text = RGBA(0xccccccff),
|
||||
.button_text_hi = RGBA(0xffffffff),
|
||||
.navigation_bar = RGBA(0x303030ff),
|
||||
.execution_buts = RGBA(0x303030ff),
|
||||
.panelcolors = {
|
||||
.header = RGBA(0x3d3d3dff),
|
||||
.back = RGBA(0x3d3d3dff),
|
||||
.sub_back = RGBA(0x0000001f),
|
||||
},
|
||||
.hilite = RGBA(0x4772b3ff),
|
||||
.vertex_size = 3,
|
||||
.outline_width = 1,
|
||||
.facedot_size = 4,
|
||||
.row_alternate = RGBA(0xffffff04),
|
||||
},
|
||||
.tarm = {
|
||||
{
|
||||
.solid = RGBA(0x9a0000ff),
|
||||
|
|
|
@ -44,7 +44,7 @@ class AssetBrowserPanel:
|
|||
return cls.asset_browser_panel_poll(context)
|
||||
|
||||
|
||||
class AssetMetaDataPanel:
|
||||
class AssetMetaDataPanelOLD:
|
||||
bl_space_type = 'FILE_BROWSER'
|
||||
bl_region_type = 'TOOL_PROPS'
|
||||
|
||||
|
@ -52,3 +52,14 @@ class AssetMetaDataPanel:
|
|||
def poll(cls, context):
|
||||
active_file = context.active_file
|
||||
return SpaceAssetInfo.is_asset_browser_poll(context) and active_file and active_file.asset_data
|
||||
|
||||
|
||||
class AssetMetaDataPanel:
|
||||
bl_space_type = 'ASSET_BROWSER'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = 'Metadata'
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
active_asset = context.asset_handle
|
||||
return active_asset
|
||||
|
|
|
@ -1388,6 +1388,42 @@
|
|||
</space_list>
|
||||
</ThemeSpreadsheet>
|
||||
</spreadsheet>
|
||||
<asset_browser>
|
||||
<ThemeAssetBrowser
|
||||
row_alternate="#ffffff0f"
|
||||
>
|
||||
<space>
|
||||
<ThemeSpaceGeneric
|
||||
back="#999999"
|
||||
title="#000000"
|
||||
text="#000000"
|
||||
text_hi="#ffffff"
|
||||
header="#adadadff"
|
||||
header_text="#000000"
|
||||
header_text_hi="#ffffff"
|
||||
button="#999999e6"
|
||||
button_title="#1a1a1a"
|
||||
button_text="#000000"
|
||||
button_text_hi="#000000"
|
||||
navigation_bar="#00000000"
|
||||
execution_buts="#999999e6"
|
||||
tab_active="#6697e6"
|
||||
tab_inactive="#cccccc"
|
||||
tab_back="#999999ff"
|
||||
tab_outline="#999999"
|
||||
>
|
||||
<panelcolors>
|
||||
<ThemePanelColors
|
||||
header="#42424200"
|
||||
back="#00000028"
|
||||
sub_back="#00000024"
|
||||
>
|
||||
</ThemePanelColors>
|
||||
</panelcolors>
|
||||
</ThemeSpaceGeneric>
|
||||
</space>
|
||||
</ThemeAssetBrowser>
|
||||
</asset_browser>
|
||||
<bone_color_sets>
|
||||
<ThemeBoneColorSet
|
||||
normal="#9a0000"
|
||||
|
|
|
@ -986,7 +986,7 @@ def km_view2d_buttons_list(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_user_interface(_params):
|
||||
def km_user_interface(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"User Interface",
|
||||
|
@ -1022,6 +1022,13 @@ def km_user_interface(_params):
|
|||
("ui.list_start_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
|
||||
# UI views (polls check if there's a UI view under the cursor).
|
||||
("ui.view_start_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
|
||||
*_template_items_select_actions(params, "ui.view_select_all"),
|
||||
("ui.view_item_select", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("deselect_all", not params.legacy)]}),
|
||||
("ui.view_item_select", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True},
|
||||
{"properties": [("extend", True), ("toggle", True)]}),
|
||||
("ui.view_item_select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
|
||||
{"properties": [("extend", True), ("fill", True)]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
@ -2455,6 +2462,32 @@ def km_file_browser_buttons(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (Asset Browser)
|
||||
|
||||
def km_asset_browser(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Asset Browser",
|
||||
{"space_type": 'ASSET_BROWSER', "region_type": 'WINDOW'},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("wm.context_toggle", {"type": 'T', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'space_data.show_region_nav_bar')]}),
|
||||
*_template_space_region_type_toggle(
|
||||
params,
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
# UI keymap already adds "select all" items for the hovered view. We add our own here that
|
||||
# don't rely on the hovered view, so they can be displayed with shortcuts in menus.
|
||||
*_template_items_select_actions(params, "assetbrowser.select_all"),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (Dope Sheet)
|
||||
|
||||
|
@ -8371,6 +8404,7 @@ def generate_keymaps(params=None):
|
|||
km_node_editor(params),
|
||||
km_spreadsheet_generic(params),
|
||||
km_info(params),
|
||||
km_asset_browser(params),
|
||||
km_file_browser(params),
|
||||
km_file_browser_main(params),
|
||||
km_file_browser_buttons(params),
|
||||
|
|
|
@ -4424,6 +4424,7 @@ def generate_keymaps_impl(params=None):
|
|||
km_clip_editor(params),
|
||||
km_clip_graph_editor(params),
|
||||
km_clip_dopesheet_editor(params),
|
||||
# TODO asset browser
|
||||
|
||||
# Animation.
|
||||
km_frames(params),
|
||||
|
|
|
@ -68,6 +68,7 @@ _modules = [
|
|||
"space_toolsystem_common",
|
||||
"space_toolsystem_toolbar",
|
||||
|
||||
"space_assets",
|
||||
"space_clip",
|
||||
"space_console",
|
||||
"space_dopesheet",
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
import bpy
|
||||
from bpy.types import Header, Menu, Panel, UIList
|
||||
|
||||
from bpy_extras import (
|
||||
asset_utils,
|
||||
)
|
||||
|
||||
|
||||
class ASSETBROWSER_HT_header(Header):
|
||||
bl_space_type = 'ASSET_BROWSER'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
space = context.space_data
|
||||
|
||||
layout.template_header()
|
||||
|
||||
ASSETBROWSER_MT_editor_menus.draw_collapsible(context, layout)
|
||||
|
||||
layout.separator_spacer()
|
||||
|
||||
layout.operator(
|
||||
"screen.region_toggle",
|
||||
text="",
|
||||
icon='PREFERENCES',
|
||||
depress=is_option_region_visible(context, space)
|
||||
).region_type = 'UI'
|
||||
|
||||
|
||||
def is_option_region_visible(context, space):
|
||||
for region in context.area.regions:
|
||||
if region.type == 'UI' and region.width <= 1:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_editor_menus(Menu):
|
||||
bl_idname = "ASSETBROWSER_MT_editor_menus"
|
||||
bl_label = ""
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.menu("ASSETBROWSER_MT_view")
|
||||
layout.menu("ASSETBROWSER_MT_select")
|
||||
layout.menu("ASSETBROWSER_MT_edit")
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_view(Menu):
|
||||
bl_label = "View"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
st = context.space_data
|
||||
|
||||
layout.prop(st, "show_region_nav_bar", text="Navigation")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.menu("INFO_MT_area")
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_select(Menu):
|
||||
bl_label = "Select"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
|
||||
layout.operator("assetbrowser.select_all", text="All").action = 'SELECT'
|
||||
layout.operator("assetbrowser.select_all", text="None").action = 'DESELECT'
|
||||
layout.operator("assetbrowser.select_all", text="Inverse").action = 'INVERT'
|
||||
|
||||
# TODO box select
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_edit(Menu):
|
||||
bl_label = "Edit"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("asset.catalog_undo", text="Undo")
|
||||
layout.operator("asset.catalog_redo", text="Redo")
|
||||
|
||||
|
||||
# Doesn't use the AssetMetaDataPanel mixin because when there is no active asset
|
||||
# this shows a info label instead.
|
||||
class ASSETBROWSER_PT_metadata(Panel):
|
||||
bl_space_type = 'ASSET_BROWSER'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "Asset Metadata"
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
bl_category = 'Metadata'
|
||||
|
||||
@staticmethod
|
||||
def metadata_prop(layout, asset_data, propname):
|
||||
"""
|
||||
Only display properties that are either set or can be modified (i.e. the
|
||||
asset is in the current file). Empty, non-editable fields are not really useful.
|
||||
"""
|
||||
if getattr(asset_data, propname) or not asset_data.is_property_readonly(propname):
|
||||
layout.prop(asset_data, propname)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
wm = context.window_manager
|
||||
asset_handle = context.asset_handle
|
||||
|
||||
if asset_handle is None:
|
||||
layout.label(text="No active asset", icon='INFO')
|
||||
return
|
||||
|
||||
asset_file = asset_handle.file_data
|
||||
|
||||
prefs = context.preferences
|
||||
show_asset_debug_info = prefs.view.show_developer_ui and prefs.experimental.show_asset_debug_info
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
if asset_handle.local_id:
|
||||
# If the active file is an ID, use its name directly so renaming is possible from right here.
|
||||
layout.prop(asset_handle.local_id, "name")
|
||||
|
||||
if show_asset_debug_info:
|
||||
col = layout.column(align=True)
|
||||
col.label(text="Asset Catalog:")
|
||||
col.prop(asset_handle.local_id.asset_data, "catalog_id", text="UUID")
|
||||
col.prop(asset_handle.local_id.asset_data, "catalog_simple_name", text="Simple Name")
|
||||
else:
|
||||
layout.prop(asset_file, "name")
|
||||
|
||||
if show_asset_debug_info:
|
||||
col = layout.column(align=True)
|
||||
col.enabled = False
|
||||
col.label(text="Asset Catalog:")
|
||||
col.prop(asset_file.asset_data, "catalog_id", text="UUID")
|
||||
col.prop(asset_file.asset_data, "catalog_simple_name", text="Simple Name")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(wm, "asset_path_dummy", text="Source")
|
||||
row.operator("asset.open_containing_blend_file", text="", icon='TOOL_SETTINGS')
|
||||
|
||||
asset_data = asset_file.asset_data
|
||||
self.metadata_prop(layout, asset_data, "description")
|
||||
self.metadata_prop(layout, asset_data, "license")
|
||||
self.metadata_prop(layout, asset_data, "copyright")
|
||||
self.metadata_prop(layout, asset_data, "author")
|
||||
|
||||
|
||||
class ASSETBROWSER_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel):
|
||||
bl_label = "Preview"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
asset_handle = context.asset_handle
|
||||
|
||||
row = layout.row()
|
||||
box = row.box()
|
||||
box.template_icon(icon_value=asset_handle.preview_icon_id, scale=5.0)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("ed.lib_id_load_custom_preview", icon='FILEBROWSER', text="")
|
||||
col.separator()
|
||||
col.operator("ed.lib_id_generate_preview", icon='FILE_REFRESH', text="")
|
||||
col.menu("ASSETBROWSER_MT_metadata_preview_menu", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_metadata_preview_menu(Menu):
|
||||
bl_label = "Preview"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator("ed.lib_id_generate_preview_from_object", text="Render Active Object")
|
||||
|
||||
|
||||
class ASSETBROWSER_PT_metadata_tags(asset_utils.AssetMetaDataPanel, Panel):
|
||||
bl_label = "Tags"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
asset = context.asset_handle
|
||||
asset_data = asset.file_data.asset_data
|
||||
|
||||
row = layout.row()
|
||||
row.template_list("ASSETBROWSEROLD_UL_metadata_tags", "asset_tags", asset_data, "tags",
|
||||
asset_data, "active_tag", rows=4)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("asset.tag_add", icon='ADD', text="")
|
||||
col.operator("asset.tag_remove", icon='REMOVE', text="")
|
||||
|
||||
|
||||
class ASSETBROWSER_UL_metadata_tags(UIList):
|
||||
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
||||
tag = item
|
||||
|
||||
row = layout.row(align=True)
|
||||
# Non-editable entries would show grayed-out, which is bad in this specific case, so switch to mere label.
|
||||
if tag.is_property_readonly("name"):
|
||||
row.label(text=tag.name, icon_value=icon)
|
||||
else:
|
||||
row.prop(tag, "name", text="", emboss=False, icon_value=icon)
|
||||
|
||||
|
||||
classes = (
|
||||
ASSETBROWSER_HT_header,
|
||||
ASSETBROWSER_MT_editor_menus,
|
||||
ASSETBROWSER_MT_view,
|
||||
ASSETBROWSER_MT_select,
|
||||
ASSETBROWSER_MT_edit,
|
||||
ASSETBROWSER_PT_metadata,
|
||||
ASSETBROWSER_PT_metadata_preview,
|
||||
ASSETBROWSER_MT_metadata_preview_menu,
|
||||
ASSETBROWSER_PT_metadata_tags,
|
||||
ASSETBROWSER_UL_metadata_tags,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
|
@ -66,7 +66,7 @@ class FILEBROWSER_HT_header(Header):
|
|||
layout.template_header()
|
||||
|
||||
if SpaceAssetInfo.is_asset_browser(space_data):
|
||||
ASSETBROWSER_MT_editor_menus.draw_collapsible(context, layout)
|
||||
ASSETBROWSEROLD_MT_editor_menus.draw_collapsible(context, layout)
|
||||
layout.separator()
|
||||
self.draw_asset_browser_buttons(context)
|
||||
else:
|
||||
|
@ -641,19 +641,19 @@ class AssetBrowserMenu:
|
|||
return SpaceAssetInfo.is_asset_browser_poll(context)
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_editor_menus(AssetBrowserMenu, Menu):
|
||||
bl_idname = "ASSETBROWSER_MT_editor_menus"
|
||||
class ASSETBROWSEROLD_MT_editor_menus(AssetBrowserMenu, Menu):
|
||||
bl_idname = "ASSETBROWSEROLD_MT_editor_menus"
|
||||
bl_label = ""
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.menu("ASSETBROWSER_MT_view")
|
||||
layout.menu("ASSETBROWSER_MT_select")
|
||||
layout.menu("ASSETBROWSEROLD_MT_view")
|
||||
layout.menu("ASSETBROWSEROLD_MT_select")
|
||||
layout.menu("ASSETBROWSER_MT_catalog")
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_view(AssetBrowserMenu, Menu):
|
||||
class ASSETBROWSEROLD_MT_view(AssetBrowserMenu, Menu):
|
||||
bl_label = "View"
|
||||
|
||||
def draw(self, context):
|
||||
|
@ -674,7 +674,7 @@ class ASSETBROWSER_MT_view(AssetBrowserMenu, Menu):
|
|||
layout.menu("INFO_MT_area")
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_select(AssetBrowserMenu, Menu):
|
||||
class ASSETBROWSEROLD_MT_select(AssetBrowserMenu, Menu):
|
||||
bl_label = "Select"
|
||||
|
||||
def draw(self, _context):
|
||||
|
@ -703,7 +703,7 @@ class ASSETBROWSER_MT_catalog(AssetBrowserMenu, Menu):
|
|||
layout.operator("asset.catalog_new").parent_path = ""
|
||||
|
||||
|
||||
class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
|
||||
class ASSETBROWSEROLD_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
|
||||
bl_region_type = 'TOOL_PROPS'
|
||||
bl_label = "Asset Metadata"
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
|
@ -763,7 +763,7 @@ class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
|
|||
self.metadata_prop(layout, metadata, "author")
|
||||
|
||||
|
||||
class ASSETBROWSER_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel):
|
||||
class ASSETBROWSEROLD_PT_metadata_preview(asset_utils.AssetMetaDataPanelOLD, Panel):
|
||||
bl_label = "Preview"
|
||||
|
||||
def draw(self, context):
|
||||
|
@ -778,10 +778,10 @@ class ASSETBROWSER_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel):
|
|||
col.operator("ed.lib_id_load_custom_preview", icon='FILEBROWSER', text="")
|
||||
col.separator()
|
||||
col.operator("ed.lib_id_generate_preview", icon='FILE_REFRESH', text="")
|
||||
col.menu("ASSETBROWSER_MT_metadata_preview_menu", icon='DOWNARROW_HLT', text="")
|
||||
col.menu("ASSETBROWSEROLD_MT_metadata_preview_menu", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_metadata_preview_menu(bpy.types.Menu):
|
||||
class ASSETBROWSEROLD_MT_metadata_preview_menu(bpy.types.Menu):
|
||||
bl_label = "Preview"
|
||||
|
||||
def draw(self, _context):
|
||||
|
@ -789,7 +789,7 @@ class ASSETBROWSER_MT_metadata_preview_menu(bpy.types.Menu):
|
|||
layout.operator("ed.lib_id_generate_preview_from_object", text="Render Active Object")
|
||||
|
||||
|
||||
class ASSETBROWSER_PT_metadata_tags(asset_utils.AssetMetaDataPanel, Panel):
|
||||
class ASSETBROWSEROLD_PT_metadata_tags(asset_utils.AssetMetaDataPanelOLD, Panel):
|
||||
bl_label = "Tags"
|
||||
|
||||
def draw(self, context):
|
||||
|
@ -797,7 +797,7 @@ class ASSETBROWSER_PT_metadata_tags(asset_utils.AssetMetaDataPanel, Panel):
|
|||
asset_data = asset_utils.SpaceAssetInfo.get_active_asset(context)
|
||||
|
||||
row = layout.row()
|
||||
row.template_list("ASSETBROWSER_UL_metadata_tags", "asset_tags", asset_data, "tags",
|
||||
row.template_list("ASSETBROWSEROLD_UL_metadata_tags", "asset_tags", asset_data, "tags",
|
||||
asset_data, "active_tag", rows=4)
|
||||
|
||||
col = row.column(align=True)
|
||||
|
@ -805,7 +805,7 @@ class ASSETBROWSER_PT_metadata_tags(asset_utils.AssetMetaDataPanel, Panel):
|
|||
col.operator("asset.tag_remove", icon='REMOVE', text="")
|
||||
|
||||
|
||||
class ASSETBROWSER_UL_metadata_tags(UIList):
|
||||
class ASSETBROWSEROLD_UL_metadata_tags(UIList):
|
||||
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
||||
tag = item
|
||||
|
||||
|
@ -863,15 +863,15 @@ classes = (
|
|||
FILEBROWSER_MT_view_pie,
|
||||
ASSETBROWSER_PT_display,
|
||||
ASSETBROWSER_PT_filter,
|
||||
ASSETBROWSER_MT_editor_menus,
|
||||
ASSETBROWSER_MT_view,
|
||||
ASSETBROWSER_MT_select,
|
||||
ASSETBROWSEROLD_MT_editor_menus,
|
||||
ASSETBROWSEROLD_MT_view,
|
||||
ASSETBROWSEROLD_MT_select,
|
||||
ASSETBROWSER_MT_catalog,
|
||||
ASSETBROWSER_MT_metadata_preview_menu,
|
||||
ASSETBROWSER_PT_metadata,
|
||||
ASSETBROWSER_PT_metadata_preview,
|
||||
ASSETBROWSER_PT_metadata_tags,
|
||||
ASSETBROWSER_UL_metadata_tags,
|
||||
ASSETBROWSEROLD_MT_metadata_preview_menu,
|
||||
ASSETBROWSEROLD_PT_metadata,
|
||||
ASSETBROWSEROLD_PT_metadata_preview,
|
||||
ASSETBROWSEROLD_PT_metadata_tags,
|
||||
ASSETBROWSEROLD_UL_metadata_tags,
|
||||
ASSETBROWSER_MT_context_menu,
|
||||
)
|
||||
|
||||
|
|
|
@ -1226,6 +1226,7 @@ class ThemeGenericClassGenerator:
|
|||
def generate_panel_classes_for_wcols():
|
||||
wcols = [
|
||||
("Box", "wcol_box"),
|
||||
("Data-View Item", "wcol_view_item"),
|
||||
("List Item", "wcol_list_item"),
|
||||
("Menu", "wcol_menu"),
|
||||
("Menu Background", "wcol_menu_back"),
|
||||
|
|
|
@ -209,6 +209,7 @@ struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C);
|
|||
struct SpaceClip *CTX_wm_space_clip(const bContext *C);
|
||||
struct SpaceTopBar *CTX_wm_space_topbar(const bContext *C);
|
||||
struct SpaceSpreadsheet *CTX_wm_space_spreadsheet(const bContext *C);
|
||||
struct SpaceAssets *CTX_wm_space_assets(const bContext *C);
|
||||
|
||||
void CTX_wm_manager_set(bContext *C, struct wmWindowManager *wm);
|
||||
void CTX_wm_window_set(bContext *C, struct wmWindow *win);
|
||||
|
@ -413,6 +414,8 @@ bool CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
|
|||
bool CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
|
||||
|
||||
const struct AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C);
|
||||
struct AssetHandle *CTX_wm_asset_handle_ptr(const bContext *C);
|
||||
|
||||
#ifdef __cplusplus
|
||||
class blender::asset_system::AssetRepresentation *CTX_wm_asset(const bContext *C);
|
||||
#endif
|
||||
|
|
|
@ -938,6 +938,15 @@ SpaceSpreadsheet *CTX_wm_space_spreadsheet(const bContext *C)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
struct SpaceAssets *CTX_wm_space_assets(const bContext *C)
|
||||
{
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
if (area && area->spacetype == SPACE_ASSETS) {
|
||||
return static_cast<SpaceAssets *>(area->spacedata.first);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
|
||||
{
|
||||
C->wm.manager = wm;
|
||||
|
@ -1512,6 +1521,17 @@ static AssetHandle ctx_wm_asset_handle(const bContext *C, bool *r_is_valid)
|
|||
return AssetHandle{nullptr};
|
||||
}
|
||||
|
||||
/**
|
||||
* \note Only works in the new Asset Browser and the asset view template (not in the old File
|
||||
* Browser based Asset Browser).
|
||||
* TODO Replace #CTX_wm_asset_handle() with this.
|
||||
*/
|
||||
AssetHandle *CTX_wm_asset_handle_ptr(const bContext *C)
|
||||
{
|
||||
return static_cast<AssetHandle *>(
|
||||
CTX_data_pointer_get_type(C, "asset_handle", &RNA_AssetHandle).data);
|
||||
}
|
||||
|
||||
blender::asset_system::AssetRepresentation *CTX_wm_asset(const bContext *C)
|
||||
{
|
||||
if (auto *asset = static_cast<blender::asset_system::AssetRepresentation *>(
|
||||
|
|
|
@ -405,6 +405,9 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size)
|
|||
|
||||
ImBuf *thumb = IMB_thumb_manage(prv_deferred.filepath.c_str(), THB_LARGE, prv_deferred.source);
|
||||
if (!thumb) {
|
||||
/* Thumbnail loading doesn't differentiate between sizes, so if loading for one size fails
|
||||
* it would fail for the other too. No point in tagging the sizes separately. */
|
||||
prv->tag |= PRV_TAG_LOADING_FAILED;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1070,6 +1070,10 @@ static void write_area(BlendWriter *writer, ScrArea *area)
|
|||
if (space_type && space_type->blend_write) {
|
||||
space_type->blend_write(writer, sl);
|
||||
}
|
||||
else if (sl->spacetype == SPACE_ASSETS) {
|
||||
BLO_write_struct(writer, SpaceAssets, sl);
|
||||
// SpaceAssets *space_assets = (SpaceAssets *)sl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -125,6 +125,9 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
|
|||
/* Keep this block, even when empty. */
|
||||
FROM_DEFAULT_V4_UCHAR(space_sequencer.transition);
|
||||
FROM_DEFAULT_V4_UCHAR(tui.wcol_list_item.inner_sel);
|
||||
|
||||
/* TODO version bump. */
|
||||
btheme->space_assets = btheme->space_file;
|
||||
}
|
||||
|
||||
#undef FROM_DEFAULT_V4_UCHAR
|
||||
|
|
|
@ -30,6 +30,7 @@ if(WITH_BLENDER)
|
|||
add_subdirectory(sound)
|
||||
add_subdirectory(space_action)
|
||||
add_subdirectory(space_api)
|
||||
add_subdirectory(space_assets)
|
||||
add_subdirectory(space_buttons)
|
||||
add_subdirectory(space_clip)
|
||||
add_subdirectory(space_console)
|
||||
|
|
|
@ -40,6 +40,7 @@ set(SRC
|
|||
intern/asset_shelf_settings.cc
|
||||
intern/asset_temp_id_consumer.cc
|
||||
intern/asset_type.cc
|
||||
intern/asset_view_catalog_filter.cc
|
||||
|
||||
ED_asset_catalog.h
|
||||
ED_asset_catalog.hh
|
||||
|
@ -54,6 +55,7 @@ set(SRC
|
|||
ED_asset_shelf.h
|
||||
ED_asset_temp_id_consumer.h
|
||||
ED_asset_type.h
|
||||
ED_asset_view_catalog_filter.h
|
||||
intern/asset_library_reference.hh
|
||||
intern/asset_shelf.hh
|
||||
)
|
||||
|
|
|
@ -35,6 +35,8 @@ extern "C" {
|
|||
struct AssetHandle;
|
||||
|
||||
AssetRepresentationHandle *ED_asset_handle_get_representation(const struct AssetHandle *asset);
|
||||
const char *ED_asset_handle_get_name(const AssetHandle *asset_handle);
|
||||
const char *ED_asset_handle_get_identifier(const struct AssetHandle *asset);
|
||||
ID_Type ED_asset_handle_get_id_type(const struct AssetHandle *asset);
|
||||
int ED_asset_handle_get_preview_icon_id(const struct AssetHandle *asset);
|
||||
int ED_asset_handle_get_preview_or_type_icon_id(const struct AssetHandle *asset);
|
||||
|
|
|
@ -20,6 +20,7 @@ class AssetRepresentation;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct AssetCatalogFilterSettings;
|
||||
struct AssetLibraryReference;
|
||||
struct ID;
|
||||
struct bContext;
|
||||
|
@ -35,11 +36,12 @@ struct wmRegionListenerParams;
|
|||
*/
|
||||
void ED_assetlist_storage_fetch(const struct AssetLibraryReference *library_reference,
|
||||
const struct bContext *C);
|
||||
void ED_assetlist_catalog_filter_set(const struct AssetLibraryReference *,
|
||||
const struct AssetCatalogFilterSettings *catalog_filter);
|
||||
bool ED_assetlist_is_loaded(const struct AssetLibraryReference *library_reference);
|
||||
void ED_assetlist_ensure_previews_job(const struct AssetLibraryReference *library_reference,
|
||||
const struct bContext *C);
|
||||
void ED_assetlist_clear(const struct AssetLibraryReference *library_reference, struct bContext *C);
|
||||
bool ED_assetlist_storage_has_list_for_library(const AssetLibraryReference *library_reference);
|
||||
|
||||
/**
|
||||
* Tag all asset lists in the storage that show main data as needing an update (re-fetch).
|
||||
*
|
||||
|
@ -59,21 +61,27 @@ void ED_assetlist_storage_id_remap(struct ID *id_old, struct ID *id_new);
|
|||
*/
|
||||
void ED_assetlist_storage_exit(void);
|
||||
|
||||
AssetHandle ED_assetlist_asset_handle_get_by_index(const AssetLibraryReference *library_reference,
|
||||
int asset_index);
|
||||
AssetHandle *ED_assetlist_asset_handle_get_by_index(const AssetLibraryReference *library_reference,
|
||||
int asset_index);
|
||||
#ifdef __cplusplus
|
||||
blender::asset_system::AssetRepresentation *ED_assetlist_asset_get_by_index(
|
||||
const AssetLibraryReference &library_reference, int asset_index);
|
||||
#endif
|
||||
|
||||
PreviewImage *ED_assetlist_asset_preview_request(AssetHandle *asset_handle);
|
||||
int ED_assetlist_asset_preview_icon_id_request(AssetHandle *asset_handle);
|
||||
int ED_assetlist_asset_preview_or_type_icon_id_request(AssetHandle *asset_handle);
|
||||
bool ED_assetlist_asset_image_is_loading(const AssetLibraryReference *library_reference,
|
||||
const AssetHandle *asset_handle);
|
||||
struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);
|
||||
|
||||
struct AssetLibrary *ED_assetlist_library_get(
|
||||
const struct AssetLibraryReference *library_reference);
|
||||
|
||||
/**
|
||||
* \return True if the region needs a UI redraw.
|
||||
*/
|
||||
bool ED_assetlist_listen(const struct wmNotifier *notifier);
|
||||
bool ED_assetlist_listen(const AssetLibraryReference *library_reference,
|
||||
const struct wmNotifier *notifier);
|
||||
/**
|
||||
* \return The number of assets stored in the asset list for \a library_reference, or -1 if there
|
||||
* is no list fetched for it.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
|
@ -32,10 +33,14 @@ blender::asset_system::AssetLibrary *ED_assetlist_library_get_once_available(
|
|||
const AssetLibraryReference &library_reference);
|
||||
|
||||
/* Can return false to stop iterating. */
|
||||
using AssetListHandleIterFn = blender::FunctionRef<bool(AssetHandle)>;
|
||||
using AssetListHandleIterFn = blender::FunctionRef<bool(AssetHandle &)>;
|
||||
using AssetListIterFn = blender::FunctionRef<bool(blender::asset_system::AssetRepresentation &)>;
|
||||
|
||||
/**
|
||||
* Iterate the currently loaded assets for the referenced asset library, calling \a fn for each
|
||||
* asset. This may be executed while the asset list is loading asynchronously. Assets will then be
|
||||
* included as they get done loading.
|
||||
*
|
||||
* \warning Never keep the asset handle passed to \a fn outside of \a fn's scope. While iterating,
|
||||
* the file data wrapped by the asset handle can be freed, since the file cache has a maximum size.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edasset
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
struct AssetLibrary;
|
||||
struct AssetMetaData;
|
||||
struct bUUID;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct AssetViewCatalogFilterSettingsHandle AssetViewCatalogFilterSettingsHandle;
|
||||
|
||||
AssetViewCatalogFilterSettingsHandle *asset_view_create_catalog_filter_settings(void);
|
||||
void asset_view_delete_catalog_filter_settings(
|
||||
AssetViewCatalogFilterSettingsHandle **filter_settings_handle);
|
||||
bool asset_view_set_catalog_filter_settings(
|
||||
AssetViewCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
AssetCatalogFilterMode catalog_visibility,
|
||||
bUUID catalog_id);
|
||||
void asset_view_ensure_updated_catalog_filter_data(
|
||||
AssetViewCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const AssetLibrary *asset_library);
|
||||
bool asset_view_is_asset_visible_in_catalog_filter_settings(
|
||||
const AssetViewCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const AssetMetaData *asset_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -110,7 +110,6 @@ AssetItemTree build_filtered_all_catalog_tree(
|
|||
Vector<asset_system::AssetRepresentation *> unassigned_assets;
|
||||
|
||||
ED_assetlist_storage_fetch(&library_ref, &C);
|
||||
ED_assetlist_ensure_previews_job(&library_ref, &C);
|
||||
asset_system::AssetLibrary *library = ED_assetlist_library_get_once_available(library_ref);
|
||||
if (!library) {
|
||||
return {};
|
||||
|
|
|
@ -25,9 +25,19 @@
|
|||
#include "ED_asset_handle.h"
|
||||
|
||||
blender::asset_system::AssetRepresentation *ED_asset_handle_get_representation(
|
||||
const AssetHandle *asset)
|
||||
const AssetHandle *asset_handle)
|
||||
{
|
||||
return asset->file_data->asset;
|
||||
return asset_handle->file_data->asset;
|
||||
}
|
||||
|
||||
const char *ED_asset_handle_get_identifier(const AssetHandle *asset_handle)
|
||||
{
|
||||
return asset_handle->file_data->asset->get_identifier().library_relative_identifier().c_str();
|
||||
}
|
||||
|
||||
const char *ED_asset_handle_get_name(const AssetHandle *asset_handle)
|
||||
{
|
||||
return asset_handle->file_data->asset->get_name().c_str();
|
||||
}
|
||||
|
||||
ID_Type ED_asset_handle_get_id_type(const AssetHandle *asset_handle)
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
#include <string>
|
||||
|
||||
#include "AS_asset_library.hh"
|
||||
#include "AS_asset_representation.hh"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_preview_image.hh"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "BLI_map.hh"
|
||||
|
@ -26,6 +28,7 @@
|
|||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_icons.h"
|
||||
#include "BKE_preferences.h"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
@ -34,12 +37,16 @@
|
|||
#include "../space_file/file_indexer.hh"
|
||||
#include "../space_file/filelist.hh"
|
||||
|
||||
#include "ED_asset_handle.h"
|
||||
#include "ED_asset_indexer.h"
|
||||
#include "ED_asset_list.h"
|
||||
#include "ED_asset_list.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "asset_library_reference.hh"
|
||||
|
||||
#include "UI_interface_icons.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
namespace blender::ed::asset {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -79,32 +86,13 @@ class FileListWrapper {
|
|||
}
|
||||
};
|
||||
|
||||
class PreviewTimer {
|
||||
/* Non-owning! The Window-Manager registers and owns this. */
|
||||
wmTimer *timer_ = nullptr;
|
||||
|
||||
public:
|
||||
void ensureRunning(const bContext *C)
|
||||
{
|
||||
if (!timer_) {
|
||||
timer_ = WM_event_timer_add_notifier(
|
||||
CTX_wm_manager(C), CTX_wm_window(C), NC_ASSET | ND_ASSET_LIST_PREVIEW, 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
void stop(const bContext *C)
|
||||
{
|
||||
if (timer_) {
|
||||
WM_event_timer_remove_notifier(CTX_wm_manager(C), CTX_wm_window(C), timer_);
|
||||
timer_ = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class AssetList : NonCopyable {
|
||||
FileListWrapper filelist_;
|
||||
/** Storage for asset handles, items are lazy-created on request.
|
||||
* Asset handles are stored as a pointer here, to ensure a consistent memory address (address
|
||||
* inside the map changes as the map changes). */
|
||||
mutable Map<uint32_t, std::unique_ptr<AssetHandle>> asset_handle_map_;
|
||||
AssetLibraryReference library_ref_;
|
||||
PreviewTimer previews_timer_;
|
||||
|
||||
public:
|
||||
AssetList() = delete;
|
||||
|
@ -112,19 +100,20 @@ class AssetList : NonCopyable {
|
|||
AssetList(AssetList &&other) = default;
|
||||
~AssetList() = default;
|
||||
|
||||
static bool listen(const wmNotifier ¬ifier);
|
||||
bool listen(const wmNotifier ¬ifier);
|
||||
|
||||
void setup();
|
||||
void fetch(const bContext &C);
|
||||
void ensurePreviewsJob(const bContext *C);
|
||||
void setCatalogFilterSettings(const AssetCatalogFilterSettings &settings);
|
||||
void clear(bContext *C);
|
||||
|
||||
AssetHandle asset_get_by_index(int index) const;
|
||||
AssetHandle *asset_get_by_index(int index) const;
|
||||
|
||||
bool needsRefetch() const;
|
||||
bool isLoaded() const;
|
||||
bool isAssetPreviewLoading(const AssetHandle &asset) const;
|
||||
asset_system::AssetLibrary *asset_library() const;
|
||||
AssetHandle &asset_handle_from_file(const FileDirEntry &) const;
|
||||
void iterate(AssetListHandleIterFn fn) const;
|
||||
void iterate(AssetListIterFn fn) const;
|
||||
int size() const;
|
||||
|
@ -175,6 +164,7 @@ void AssetList::fetch(const bContext &C)
|
|||
if (filelist_needs_force_reset(files)) {
|
||||
filelist_readjob_stop(files, CTX_wm_manager(&C));
|
||||
filelist_clear_from_reset_tag(files);
|
||||
asset_handle_map_.clear();
|
||||
}
|
||||
|
||||
if (filelist_needs_reading(files)) {
|
||||
|
@ -186,6 +176,12 @@ void AssetList::fetch(const bContext &C)
|
|||
filelist_filter(files);
|
||||
}
|
||||
|
||||
void AssetList::setCatalogFilterSettings(const AssetCatalogFilterSettings &settings)
|
||||
{
|
||||
filelist_set_asset_catalog_filter_options(
|
||||
filelist_, (AssetCatalogFilterMode)settings.filter_mode, &settings.active_catalog_id);
|
||||
}
|
||||
|
||||
bool AssetList::needsRefetch() const
|
||||
{
|
||||
return filelist_needs_force_reset(filelist_) || filelist_needs_reading(filelist_);
|
||||
|
@ -206,6 +202,15 @@ asset_system::AssetLibrary *AssetList::asset_library() const
|
|||
return reinterpret_cast<asset_system::AssetLibrary *>(filelist_asset_library(filelist_));
|
||||
}
|
||||
|
||||
AssetHandle &AssetList::asset_handle_from_file(const FileDirEntry &file) const
|
||||
{
|
||||
AssetHandle &asset = *asset_handle_map_.lookup_or_add(
|
||||
file.uid, std::make_unique<AssetHandle>(AssetHandle{&file}));
|
||||
/* The file is recreated while loading, update the pointer here. */
|
||||
asset.file_data = &file;
|
||||
return asset;
|
||||
}
|
||||
|
||||
void AssetList::iterate(AssetListHandleIterFn fn) const
|
||||
{
|
||||
FileList *files = filelist_;
|
||||
|
@ -217,7 +222,7 @@ void AssetList::iterate(AssetListHandleIterFn fn) const
|
|||
continue;
|
||||
}
|
||||
|
||||
AssetHandle asset_handle = {file};
|
||||
AssetHandle &asset_handle = asset_handle_from_file(*file);
|
||||
if (!fn(asset_handle)) {
|
||||
/* If the callback returns false, we stop iterating. */
|
||||
break;
|
||||
|
@ -235,31 +240,6 @@ void AssetList::iterate(AssetListIterFn fn) const
|
|||
});
|
||||
}
|
||||
|
||||
void AssetList::ensurePreviewsJob(const bContext *C)
|
||||
{
|
||||
FileList *files = filelist_;
|
||||
int numfiles = filelist_files_ensure(files);
|
||||
|
||||
filelist_cache_previews_set(files, true);
|
||||
/* TODO fetch all previews for now. */
|
||||
/* Add one extra entry to ensure nothing is lost because of integer division. */
|
||||
filelist_file_cache_slidingwindow_set(files, numfiles / 2 + 1);
|
||||
filelist_file_cache_block(files, 0);
|
||||
filelist_cache_previews_update(files);
|
||||
|
||||
{
|
||||
const bool previews_running = filelist_cache_previews_running(files) &&
|
||||
!filelist_cache_previews_done(files);
|
||||
if (previews_running) {
|
||||
previews_timer_.ensureRunning(C);
|
||||
}
|
||||
else {
|
||||
/* Preview is not running, no need to keep generating update events! */
|
||||
previews_timer_.stop(C);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssetList::clear(bContext *C)
|
||||
{
|
||||
/* Based on #ED_fileselect_clear() */
|
||||
|
@ -268,13 +248,18 @@ void AssetList::clear(bContext *C)
|
|||
filelist_readjob_stop(files, CTX_wm_manager(C));
|
||||
filelist_freelib(files);
|
||||
filelist_clear(files);
|
||||
asset_handle_map_.clear();
|
||||
|
||||
WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST, nullptr);
|
||||
}
|
||||
|
||||
AssetHandle AssetList::asset_get_by_index(int index) const
|
||||
AssetHandle *AssetList::asset_get_by_index(int index) const
|
||||
{
|
||||
return {filelist_file(filelist_, index)};
|
||||
FileDirEntry *file = filelist_file(filelist_, index);
|
||||
if (!file) {
|
||||
return nullptr;
|
||||
}
|
||||
return &asset_handle_from_file(*file);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -290,7 +275,11 @@ bool AssetList::listen(const wmNotifier ¬ifier)
|
|||
break;
|
||||
}
|
||||
case NC_ASSET:
|
||||
if (ELEM(notifier.data, ND_ASSET_LIST, ND_ASSET_LIST_READING, ND_ASSET_LIST_PREVIEW)) {
|
||||
if (ELEM(notifier.data, ND_ASSET_LIST)) {
|
||||
filelist_tag_needs_filtering(filelist_);
|
||||
return true;
|
||||
}
|
||||
if (ELEM(notifier.data, ND_ASSET_LIST_READING)) {
|
||||
return true;
|
||||
}
|
||||
if (ELEM(notifier.action, NA_ADDED, NA_REMOVED, NA_EDITED)) {
|
||||
|
@ -476,13 +465,12 @@ bool ED_assetlist_is_loaded(const AssetLibraryReference *library_reference)
|
|||
return list->isLoaded();
|
||||
}
|
||||
|
||||
void ED_assetlist_ensure_previews_job(const AssetLibraryReference *library_reference,
|
||||
const bContext *C)
|
||||
void ED_assetlist_catalog_filter_set(const struct AssetLibraryReference *library_reference,
|
||||
const struct AssetCatalogFilterSettings *settings)
|
||||
{
|
||||
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
if (list) {
|
||||
list->ensurePreviewsJob(C);
|
||||
list->setCatalogFilterSettings(*settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,8 +513,8 @@ asset_system::AssetLibrary *ED_assetlist_library_get_once_available(
|
|||
return list->asset_library();
|
||||
}
|
||||
|
||||
AssetHandle ED_assetlist_asset_handle_get_by_index(const AssetLibraryReference *library_reference,
|
||||
int asset_index)
|
||||
AssetHandle *ED_assetlist_asset_handle_get_by_index(const AssetLibraryReference *library_reference,
|
||||
int asset_index)
|
||||
{
|
||||
const AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
return list->asset_get_by_index(asset_index);
|
||||
|
@ -535,9 +523,56 @@ AssetHandle ED_assetlist_asset_handle_get_by_index(const AssetLibraryReference *
|
|||
asset_system::AssetRepresentation *ED_assetlist_asset_get_by_index(
|
||||
const AssetLibraryReference &library_reference, int asset_index)
|
||||
{
|
||||
AssetHandle asset_handle = ED_assetlist_asset_handle_get_by_index(&library_reference,
|
||||
asset_index);
|
||||
return reinterpret_cast<asset_system::AssetRepresentation *>(asset_handle.file_data->asset);
|
||||
AssetHandle *asset_handle = ED_assetlist_asset_handle_get_by_index(&library_reference,
|
||||
asset_index);
|
||||
return reinterpret_cast<asset_system::AssetRepresentation *>(asset_handle->file_data->asset);
|
||||
}
|
||||
|
||||
PreviewImage *ED_assetlist_asset_preview_request(AssetHandle *asset_handle)
|
||||
{
|
||||
if (asset_handle->preview) {
|
||||
return asset_handle->preview;
|
||||
}
|
||||
|
||||
asset_system::AssetRepresentation *asset = ED_asset_handle_get_representation(asset_handle);
|
||||
if (ID *local_id = asset->local_id()) {
|
||||
asset_handle->preview = BKE_previewimg_id_get(local_id);
|
||||
}
|
||||
else {
|
||||
const char *asset_identifier = asset->get_identifier().library_relative_identifier().c_str();
|
||||
const int source = filelist_preview_source_get(asset_handle->file_data->typeflag);
|
||||
const std::string asset_path = asset->get_identifier().full_path();
|
||||
|
||||
asset_handle->preview = BKE_previewimg_cached_thumbnail_read(
|
||||
asset_identifier, asset_path.c_str(), source, false);
|
||||
}
|
||||
|
||||
return asset_handle->preview;
|
||||
}
|
||||
|
||||
static int preview_icon_id_ensure(AssetHandle *asset_handle, PreviewImage *preview)
|
||||
{
|
||||
asset_system::AssetRepresentation *asset = ED_asset_handle_get_representation(asset_handle);
|
||||
return BKE_icon_preview_ensure(asset->local_id(), preview);
|
||||
}
|
||||
|
||||
int ED_assetlist_asset_preview_icon_id_request(AssetHandle *asset_handle)
|
||||
{
|
||||
PreviewImage *preview = ED_assetlist_asset_preview_request(asset_handle);
|
||||
return preview_icon_id_ensure(asset_handle, preview);
|
||||
}
|
||||
|
||||
int ED_assetlist_asset_preview_or_type_icon_id_request(AssetHandle *asset_handle)
|
||||
{
|
||||
PreviewImage *preview = ED_assetlist_asset_preview_request(asset_handle);
|
||||
|
||||
/* Preview is invalid or still loading. Return an icon ID based on the type. */
|
||||
if (preview->tag & (PRV_TAG_LOADING_FAILED | PRV_TAG_DEFFERED_RENDERING)) {
|
||||
ID_Type id_type = ED_asset_handle_get_id_type(asset_handle);
|
||||
return UI_icon_from_idcode(id_type);
|
||||
}
|
||||
|
||||
return preview_icon_id_ensure(asset_handle, preview);
|
||||
}
|
||||
|
||||
bool ED_assetlist_asset_image_is_loading(const AssetLibraryReference *library_reference,
|
||||
|
@ -557,9 +592,23 @@ ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
|||
return filelist_geticon_image_ex(asset_handle->file_data);
|
||||
}
|
||||
|
||||
bool ED_assetlist_listen(const wmNotifier *notifier)
|
||||
AssetLibrary *ED_assetlist_library_get(const AssetLibraryReference *library_reference)
|
||||
{
|
||||
return AssetList::listen(*notifier);
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
if (list) {
|
||||
return reinterpret_cast<AssetLibrary *>(list->asset_library());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ED_assetlist_listen(const AssetLibraryReference *library_reference,
|
||||
const wmNotifier *notifier)
|
||||
{
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
if (list) {
|
||||
return list->listen(*notifier);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int ED_assetlist_size(const AssetLibraryReference *library_reference)
|
||||
|
|
|
@ -71,7 +71,6 @@ static const asset_system::AssetRepresentation *get_local_asset_from_relative_id
|
|||
AssetLibraryReference library_ref{};
|
||||
library_ref.type = ASSET_LIBRARY_LOCAL;
|
||||
ED_assetlist_storage_fetch(&library_ref, &C);
|
||||
ED_assetlist_ensure_previews_job(&library_ref, &C);
|
||||
|
||||
const asset_system::AssetRepresentation *matching_asset = nullptr;
|
||||
ED_assetlist_iterate(library_ref, [&](asset_system::AssetRepresentation &asset) {
|
||||
|
@ -104,7 +103,6 @@ static const asset_system::AssetRepresentation *find_asset_from_weak_ref(
|
|||
|
||||
const AssetLibraryReference library_ref = asset_system::all_library_reference();
|
||||
ED_assetlist_storage_fetch(&library_ref, &C);
|
||||
ED_assetlist_ensure_previews_job(&library_ref, &C);
|
||||
asset_system::AssetLibrary *all_library = ED_assetlist_library_get_once_available(
|
||||
asset_system::all_library_reference());
|
||||
if (!all_library) {
|
||||
|
|
|
@ -439,13 +439,24 @@ static void ASSET_OT_library_refresh(wmOperatorType *ot)
|
|||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static AssetLibrary *get_asset_library(const bContext *C)
|
||||
{
|
||||
if (const SpaceFile *sfile = CTX_wm_space_file(C)) {
|
||||
return ED_fileselect_active_asset_library_get(sfile);
|
||||
}
|
||||
if (const AssetLibraryReference *library_ref = CTX_wm_asset_library_ref(C)) {
|
||||
return ED_assetlist_library_get(library_ref);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool asset_catalog_operator_poll(bContext *C)
|
||||
{
|
||||
const SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
if (!sfile) {
|
||||
return false;
|
||||
}
|
||||
const AssetLibrary *asset_library = ED_fileselect_active_asset_library_get(sfile);
|
||||
const AssetLibrary *asset_library = get_asset_library(C);
|
||||
if (!asset_library) {
|
||||
return false;
|
||||
}
|
||||
|
@ -458,16 +469,20 @@ static bool asset_catalog_operator_poll(bContext *C)
|
|||
|
||||
static int asset_catalog_new_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
AssetLibrary *asset_library = ED_fileselect_active_asset_library_get(sfile);
|
||||
AssetLibrary *asset_library = get_asset_library(C);
|
||||
char *parent_path = RNA_string_get_alloc(op->ptr, "parent_path", nullptr, 0, nullptr);
|
||||
|
||||
blender::asset_system::AssetCatalog *new_catalog = ED_asset_catalog_add(
|
||||
asset_library, DATA_("Catalog"), parent_path);
|
||||
|
||||
if (sfile) {
|
||||
if (SpaceFile *sfile = CTX_wm_space_file(C)) {
|
||||
ED_fileselect_activate_asset_catalog(sfile, new_catalog->catalog_id);
|
||||
}
|
||||
else if (SpaceAssets *sassets = CTX_wm_space_assets(C)) {
|
||||
/* TODO how can we select the catalog here in a nice way, without being space dependent? Idea:
|
||||
* use an operator macro instead? */
|
||||
UNUSED_VARS(sassets);
|
||||
}
|
||||
|
||||
MEM_freeN(parent_path);
|
||||
|
||||
|
@ -498,8 +513,7 @@ static void ASSET_OT_catalog_new(wmOperatorType *ot)
|
|||
|
||||
static int asset_catalog_delete_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
AssetLibrary *asset_library = ED_fileselect_active_asset_library_get(sfile);
|
||||
AssetLibrary *asset_library = get_asset_library(C);
|
||||
char *catalog_id_str = RNA_string_get_alloc(op->ptr, "catalog_id", nullptr, 0, nullptr);
|
||||
asset_system::CatalogID catalog_id;
|
||||
if (!BLI_uuid_parse_string(&catalog_id, catalog_id_str)) {
|
||||
|
@ -534,13 +548,16 @@ static void ASSET_OT_catalog_delete(wmOperatorType *ot)
|
|||
|
||||
static asset_system::AssetCatalogService *get_catalog_service(bContext *C)
|
||||
{
|
||||
const SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
if (!sfile) {
|
||||
return nullptr;
|
||||
if (const SpaceFile *sfile = CTX_wm_space_file(C)) {
|
||||
AssetLibrary *asset_lib = ED_fileselect_active_asset_library_get(sfile);
|
||||
return AS_asset_library_get_catalog_service(asset_lib);
|
||||
}
|
||||
if (const AssetLibraryReference *library_ref = CTX_wm_asset_library_ref(C)) {
|
||||
AssetLibrary *asset_lib = ED_assetlist_library_get(library_ref);
|
||||
return AS_asset_library_get_catalog_service(asset_lib);
|
||||
}
|
||||
|
||||
AssetLibrary *asset_lib = ED_fileselect_active_asset_library_get(sfile);
|
||||
return AS_asset_library_get_catalog_service(asset_lib);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static int asset_catalog_undo_exec(bContext *C, wmOperator * /*op*/)
|
||||
|
@ -551,7 +568,7 @@ static int asset_catalog_undo_exec(bContext *C, wmOperator * /*op*/)
|
|||
}
|
||||
|
||||
catalog_service->undo();
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
|
||||
WM_event_add_notifier(C, NC_ASSET | ND_ASSET_CATALOGS, nullptr);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
@ -581,7 +598,7 @@ static int asset_catalog_redo_exec(bContext *C, wmOperator * /*op*/)
|
|||
}
|
||||
|
||||
catalog_service->redo();
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
|
||||
WM_event_add_notifier(C, NC_ASSET | ND_ASSET_CATALOGS, nullptr);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
@ -658,8 +675,7 @@ static bool asset_catalogs_save_poll(bContext *C)
|
|||
|
||||
static int asset_catalogs_save_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
const SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
::AssetLibrary *asset_library = ED_fileselect_active_asset_library_get(sfile);
|
||||
::AssetLibrary *asset_library = get_asset_library(C);
|
||||
|
||||
ED_asset_catalogs_save_from_main_path(asset_library, CTX_data_main(C));
|
||||
|
||||
|
@ -694,11 +710,12 @@ static bool has_external_files(Main *bmain, ReportList *reports);
|
|||
static bool asset_bundle_install_poll(bContext *C)
|
||||
{
|
||||
/* This operator only works when the asset browser is set to Current File. */
|
||||
const SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
if (sfile == nullptr) {
|
||||
const AssetLibraryReference *asset_library_ref = CTX_wm_asset_library_ref(C);
|
||||
if (asset_library_ref == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!ED_fileselect_is_local_asset_library(sfile)) {
|
||||
|
||||
if (asset_library_ref->type == ASSET_LIBRARY_LOCAL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ using namespace blender;
|
|||
using namespace blender::ed::asset;
|
||||
|
||||
static int asset_shelf_default_tile_height();
|
||||
static const AssetLibraryReference &asset_shelf_library_ref();
|
||||
|
||||
namespace blender::ed::asset::shelf {
|
||||
|
||||
|
@ -250,7 +251,8 @@ static void asset_shelf_region_listen(const wmRegionListenerParams *params)
|
|||
|
||||
void ED_asset_shelf_region_listen(const wmRegionListenerParams *params)
|
||||
{
|
||||
if (ED_assetlist_listen(params->notifier)) {
|
||||
const AssetLibraryReference &library_ref = asset_shelf_library_ref();
|
||||
if (ED_assetlist_listen(&library_ref, params->notifier)) {
|
||||
ED_region_tag_redraw_no_rebuild(params->region);
|
||||
}
|
||||
/* If the asset list didn't catch the notifier, let the region itself listen. */
|
||||
|
|
|
@ -248,7 +248,6 @@ void build_asset_view(uiLayout &layout,
|
|||
ARegion ®ion)
|
||||
{
|
||||
ED_assetlist_storage_fetch(&library_ref, &C);
|
||||
ED_assetlist_ensure_previews_job(&library_ref, &C);
|
||||
|
||||
const asset_system::AssetLibrary *library = ED_assetlist_library_get_once_available(library_ref);
|
||||
if (!library) {
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edasset
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "AS_asset_catalog.hh"
|
||||
#include "AS_asset_library.hh"
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "ED_asset_view_catalog_filter.h"
|
||||
|
||||
namespace asset_system = blender::asset_system;
|
||||
|
||||
struct AssetViewCatalogFilter {
|
||||
AssetCatalogFilterSettings filter_settings;
|
||||
std::unique_ptr<asset_system::AssetCatalogFilter> catalog_filter;
|
||||
};
|
||||
|
||||
AssetViewCatalogFilterSettingsHandle *asset_view_create_catalog_filter_settings()
|
||||
{
|
||||
AssetViewCatalogFilter *filter_settings = MEM_new<AssetViewCatalogFilter>(__func__);
|
||||
return reinterpret_cast<AssetViewCatalogFilterSettingsHandle *>(filter_settings);
|
||||
}
|
||||
|
||||
void asset_view_delete_catalog_filter_settings(
|
||||
AssetViewCatalogFilterSettingsHandle **filter_settings_handle)
|
||||
{
|
||||
AssetViewCatalogFilter **filter_settings = reinterpret_cast<AssetViewCatalogFilter **>(
|
||||
filter_settings_handle);
|
||||
MEM_delete(*filter_settings);
|
||||
*filter_settings = nullptr;
|
||||
}
|
||||
|
||||
bool asset_view_set_catalog_filter_settings(
|
||||
AssetViewCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
AssetCatalogFilterMode catalog_visibility,
|
||||
::bUUID catalog_id)
|
||||
{
|
||||
AssetViewCatalogFilter *filter_settings = reinterpret_cast<AssetViewCatalogFilter *>(
|
||||
filter_settings_handle);
|
||||
bool needs_update = false;
|
||||
|
||||
if (filter_settings->filter_settings.filter_mode != catalog_visibility) {
|
||||
filter_settings->filter_settings.filter_mode = catalog_visibility;
|
||||
needs_update = true;
|
||||
}
|
||||
|
||||
if (filter_settings->filter_settings.filter_mode == ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG &&
|
||||
!BLI_uuid_equal(filter_settings->filter_settings.active_catalog_id, catalog_id))
|
||||
{
|
||||
filter_settings->filter_settings.active_catalog_id = catalog_id;
|
||||
needs_update = true;
|
||||
}
|
||||
|
||||
return needs_update;
|
||||
}
|
||||
|
||||
void asset_view_ensure_updated_catalog_filter_data(
|
||||
AssetViewCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const ::AssetLibrary *asset_library)
|
||||
{
|
||||
AssetViewCatalogFilter *filter_settings = reinterpret_cast<AssetViewCatalogFilter *>(
|
||||
filter_settings_handle);
|
||||
const asset_system::AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(
|
||||
asset_library);
|
||||
|
||||
if (filter_settings->filter_settings.filter_mode != ASSET_CATALOG_SHOW_ALL_ASSETS) {
|
||||
filter_settings->catalog_filter = std::make_unique<asset_system::AssetCatalogFilter>(
|
||||
catalog_service->create_catalog_filter(
|
||||
filter_settings->filter_settings.active_catalog_id));
|
||||
}
|
||||
}
|
||||
|
||||
bool asset_view_is_asset_visible_in_catalog_filter_settings(
|
||||
const AssetViewCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const AssetMetaData *asset_data)
|
||||
{
|
||||
const AssetViewCatalogFilter *filter_settings = reinterpret_cast<const AssetViewCatalogFilter *>(
|
||||
filter_settings_handle);
|
||||
|
||||
switch (filter_settings->filter_settings.filter_mode) {
|
||||
case ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG:
|
||||
return !filter_settings->catalog_filter->is_known(asset_data->catalog_id);
|
||||
case ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG:
|
||||
return filter_settings->catalog_filter->contains(asset_data->catalog_id);
|
||||
case ASSET_CATALOG_SHOW_ALL_ASSETS:
|
||||
/* All asset files should be visible. */
|
||||
return true;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return false;
|
||||
}
|
|
@ -506,6 +506,7 @@ bool ED_operator_file_active(bContext *C);
|
|||
*/
|
||||
bool ED_operator_file_browsing_active(bContext *C);
|
||||
bool ED_operator_asset_browsing_active(bContext *C);
|
||||
bool ED_operator_asset_browser_active(bContext *C);
|
||||
bool ED_operator_spreadsheet_active(bContext *C);
|
||||
bool ED_operator_action_active(bContext *C);
|
||||
bool ED_operator_buttons_active(bContext *C);
|
||||
|
|
|
@ -14,12 +14,12 @@ struct KDTree_1d;
|
|||
struct PointerRNA;
|
||||
struct wmOperatorType;
|
||||
|
||||
enum {
|
||||
typedef enum SelectAction {
|
||||
SEL_TOGGLE = 0,
|
||||
SEL_SELECT = 1,
|
||||
SEL_DESELECT = 2,
|
||||
SEL_INVERT = 3,
|
||||
};
|
||||
} SelectAction;
|
||||
|
||||
enum WalkSelectDirection {
|
||||
UI_SELECT_WALK_UP,
|
||||
|
|
|
@ -23,6 +23,7 @@ void ED_spacemacros_init();
|
|||
* Calls for registering default spaces, only called once, from #ED_spacetypes_init
|
||||
* \{ */
|
||||
|
||||
void ED_spacetype_assets();
|
||||
void ED_spacetype_outliner();
|
||||
void ED_spacetype_view3d();
|
||||
void ED_spacetype_ipo();
|
||||
|
|
|
@ -88,6 +88,10 @@ class AbstractView {
|
|||
|
||||
virtual void draw_overlays(const ARegion ®ion) const;
|
||||
|
||||
/**
|
||||
* Iterate over all elements in the view executing \a iter_fn for each. Typically views would
|
||||
* want to implement their own `foreach_item()` function with a more specific type.
|
||||
*/
|
||||
virtual void foreach_view_item(FunctionRef<void(AbstractViewItem &)> iter_fn) const = 0;
|
||||
|
||||
/**
|
||||
|
@ -149,9 +153,13 @@ class AbstractViewItem {
|
|||
AbstractView *view_ = nullptr;
|
||||
/** See #view_item_button() */
|
||||
uiButViewItem *view_item_but_ = nullptr;
|
||||
/* Behavior toggles. */
|
||||
bool is_activatable_ = true;
|
||||
bool is_interactive_ = true;
|
||||
bool is_selectable_ = false;
|
||||
/* State properties. */
|
||||
bool is_active_ = false;
|
||||
bool is_selected_ = false;
|
||||
bool is_renaming_ = false;
|
||||
|
||||
/** Cache filtered state here to avoid having to re-query. */
|
||||
|
@ -237,8 +245,10 @@ class AbstractViewItem {
|
|||
*
|
||||
* Requires the view to have completed reconstruction, see #is_reconstructed(). Otherwise the
|
||||
* actual item state is unknown, possibly calling state-change update functions incorrectly.
|
||||
*
|
||||
* \return True if the item was activated successfully.
|
||||
*/
|
||||
void activate(bContext &C);
|
||||
bool activate(bContext &C);
|
||||
void deactivate();
|
||||
/**
|
||||
* Requires the view to have completed reconstruction, see #is_reconstructed(). Otherwise we
|
||||
|
@ -246,6 +256,25 @@ class AbstractViewItem {
|
|||
*/
|
||||
bool is_active() const;
|
||||
|
||||
void enable_selectable();
|
||||
bool is_selectable() const;
|
||||
/**
|
||||
* Mark this item as selected if it supports selection (#AbstractViewItem::supports_selection()
|
||||
* returns true).
|
||||
* \return True if the selection state changed (redraw needed).
|
||||
*/
|
||||
bool select();
|
||||
/**
|
||||
* Mark this item as not selected.
|
||||
* \return True if the selection state changed (redraw needed).
|
||||
*/
|
||||
bool deselect();
|
||||
/**
|
||||
* Requires the view to have completed reconstruction, see #is_reconstructed(). Otherwise we
|
||||
* can't be sure about the item state.
|
||||
*/
|
||||
bool is_selected() const;
|
||||
|
||||
bool is_renaming() const;
|
||||
void begin_renaming();
|
||||
void end_renaming();
|
||||
|
|
|
@ -202,7 +202,7 @@ class PreviewGridItem : public AbstractGridViewItem {
|
|||
std::string label{};
|
||||
int preview_icon_id = ICON_NONE;
|
||||
|
||||
PreviewGridItem(StringRef identifier, StringRef label, int preview_icon_id);
|
||||
PreviewGridItem(StringRef identifier, StringRef label, int preview_icon_id = ICON_NONE);
|
||||
|
||||
void build_grid_tile(uiLayout &layout) const override;
|
||||
|
||||
|
|
|
@ -194,6 +194,18 @@ std::unique_ptr<DropTargetInterface> view_item_drop_target(uiViewItemHandle *ite
|
|||
std::unique_ptr<DropTargetInterface> region_views_find_drop_target_at(const ARegion *region,
|
||||
const int xy[2]);
|
||||
|
||||
/**
|
||||
* \note #SEL_TOGGLE is ignored here as it has no meaning for individual items (should be refined
|
||||
* to #SEL_SELECT or #SEL_DESELECT based on the selection state of other items).
|
||||
* \return True if any selection state changed (redraw necessary).
|
||||
*/
|
||||
bool view_item_select_from_action(uiViewItemHandle *item_handle,
|
||||
const int /*SelectAction*/ action);
|
||||
/**
|
||||
* \return True if any selection state changed (redraw necessary).
|
||||
*/
|
||||
bool view_select_all_from_action(uiViewHandle *view_handle, int /*SelectAction*/ action);
|
||||
|
||||
} // namespace blender::ui
|
||||
|
||||
enum eUIListFilterResult {
|
||||
|
|
|
@ -3275,7 +3275,11 @@ void UI_interface_tag_script_reload();
|
|||
bool UI_view_begin_filtering(const bContext *C, const uiViewHandle *view_handle);
|
||||
|
||||
bool UI_view_item_is_interactive(const uiViewItemHandle *item_handle);
|
||||
/** \return True if the active state changed (requiring redraw). */
|
||||
bool UI_view_item_activate(bContext *C, uiViewItemHandle *item_handle);
|
||||
bool UI_view_item_is_active(const uiViewItemHandle *item_handle);
|
||||
bool UI_view_item_is_selectable(const uiViewItemHandle *item_handle);
|
||||
bool UI_view_item_is_selected(const uiViewItemHandle *item_handle);
|
||||
bool UI_view_item_matches(const uiViewItemHandle *a_handle, const uiViewItemHandle *b_handle);
|
||||
/**
|
||||
* Can \a item_handle be renamed right now? Note that this isn't just a mere wrapper around
|
||||
|
@ -3297,11 +3301,14 @@ bool UI_view_item_supports_drag(const uiViewItemHandle *item_);
|
|||
*/
|
||||
bool UI_view_item_drag_start(bContext *C, const uiViewItemHandle *item_);
|
||||
|
||||
uiViewHandle *UI_region_view_find_from_idname(const struct ARegion *region, const char *idname);
|
||||
/**
|
||||
* \param xy: Coordinate to find a view item at, in window space.
|
||||
* \param pad: Extra padding added to the bounding box of the view.
|
||||
*/
|
||||
uiViewHandle *UI_region_view_find_at(const ARegion *region, const int xy[2], int pad);
|
||||
uiViewHandle *UI_region_view_find_at(const ARegion *region,
|
||||
const int xy[2],
|
||||
int pad CPP_ARG_DEFAULT(0));
|
||||
/**
|
||||
* \param xy: Coordinate to find a view item at, in window space.
|
||||
*/
|
||||
|
|
|
@ -2282,10 +2282,21 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
|
|||
break;
|
||||
case UI_BTYPE_VIEW_ITEM: {
|
||||
const uiButViewItem *view_item_but = (const uiButViewItem *)but;
|
||||
const uiViewItemHandle *view_item = view_item_but->view_item;
|
||||
|
||||
is_push = -1;
|
||||
if (view_item_but->view_item) {
|
||||
is_push = UI_view_item_is_active(view_item_but->view_item);
|
||||
if (!view_item) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Highlights for active items tend to look as if they were selected, so don't highlight
|
||||
* them when the item is also selectable. For not selectable items, the active state is
|
||||
* important to display though. */
|
||||
if (UI_view_item_is_selectable(view_item)) {
|
||||
is_push = UI_view_item_is_selected(view_item);
|
||||
}
|
||||
else {
|
||||
is_push = UI_view_item_is_active(view_item);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -4581,8 +4581,8 @@ static void ui_litem_layout_grid_flow(uiLayout *litem)
|
|||
BLI_assert(gflow->tot_columns > 0);
|
||||
BLI_assert(gflow->tot_rows > 0);
|
||||
|
||||
const int space_x = style->columnspace;
|
||||
const int space_y = style->buttonspacey;
|
||||
const int space_x = litem->align ? 0 : style->columnspace;
|
||||
const int space_y = litem->align ? 0 : style->buttonspacey;
|
||||
|
||||
blender::Array<int, 64> widths(gflow->tot_columns);
|
||||
blender::Array<int, 64> heights(gflow->tot_rows);
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
|
||||
#include "ED_object.hh"
|
||||
#include "ED_paint.hh"
|
||||
#include "ED_select_utils.hh"
|
||||
|
||||
/* for Copy As Driver */
|
||||
#include "ED_keyframing.hh"
|
||||
|
@ -2453,6 +2454,127 @@ static void UI_OT_view_start_filter(wmOperatorType *ot)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name UI View Item Select Operator
|
||||
* \{ */
|
||||
|
||||
static int ui_view_item_select_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
||||
const bool extend = RNA_boolean_get(op->ptr, "extend");
|
||||
const bool deselect = RNA_boolean_get(op->ptr, "deselect");
|
||||
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
|
||||
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
|
||||
// const bool fill = RNA_boolean_get(op->ptr, "fill");
|
||||
|
||||
int xy[2];
|
||||
xy[0] = RNA_int_get(op->ptr, "mouse_x");
|
||||
xy[1] = RNA_int_get(op->ptr, "mouse_y");
|
||||
ui_region_to_window(region, &xy[0], &xy[1]);
|
||||
|
||||
uiViewHandle *view = UI_region_view_find_at(region, xy);
|
||||
uiViewItemHandle *hovered_item = UI_region_views_find_item_at(region, xy);
|
||||
|
||||
bool changed = false;
|
||||
|
||||
bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others");
|
||||
|
||||
if (extend || toggle) {
|
||||
wait_to_deselect_others = false;
|
||||
}
|
||||
|
||||
if (hovered_item) {
|
||||
const bool is_selected = UI_view_item_is_selected(hovered_item);
|
||||
|
||||
if (wait_to_deselect_others && is_selected) {
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
else if (!extend) {
|
||||
changed |= view_select_all_from_action(view, SEL_DESELECT);
|
||||
}
|
||||
|
||||
SelectAction action = deselect ? SEL_DESELECT : SEL_SELECT;
|
||||
if (toggle) {
|
||||
action = SEL_INVERT;
|
||||
}
|
||||
changed |= view_item_select_from_action(hovered_item, action);
|
||||
|
||||
/* The last selected item should be activated. */
|
||||
if (UI_view_item_is_selected(hovered_item) ||
|
||||
/* Items may not support selection but a click should still activate it. */
|
||||
(action == SEL_SELECT))
|
||||
{
|
||||
changed |= UI_view_item_activate(C, hovered_item);
|
||||
}
|
||||
}
|
||||
/* Click on empty space, deselect all if requested. */
|
||||
else if (deselect_all) {
|
||||
changed |= view_select_all_from_action(view, SEL_DESELECT);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
ED_region_tag_redraw(region);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void UI_OT_view_item_select(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "View Item Select";
|
||||
ot->idname = "UI_OT_view_item_select";
|
||||
ot->description = "Select or deselect the item under the cursor";
|
||||
|
||||
ot->poll = ui_view_focused_poll;
|
||||
ot->exec = ui_view_item_select_exec;
|
||||
ot->invoke = WM_generic_select_invoke;
|
||||
ot->modal = WM_generic_select_modal;
|
||||
|
||||
PropertyRNA *prop;
|
||||
|
||||
WM_operator_properties_generic_select(ot);
|
||||
WM_operator_properties_mouse_select(ot);
|
||||
|
||||
prop = RNA_def_boolean(
|
||||
ot->srna, "fill", false, "Fill", "Select everything beginning with the last selection");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name UI View Select All Operator
|
||||
* \{ */
|
||||
|
||||
static int ui_view_select_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
uiViewHandle *view = UI_region_view_find_at(region, event->xy);
|
||||
|
||||
const int action = RNA_enum_get(op->ptr, "action");
|
||||
|
||||
if (view_select_all_from_action(view, action)) {
|
||||
ED_region_tag_redraw(region);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void UI_OT_view_select_all(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "View Select All";
|
||||
ot->idname = "UI_OT_view_select_all";
|
||||
ot->description = "Select or deselect all items in the view";
|
||||
|
||||
ot->invoke = ui_view_select_all_invoke;
|
||||
ot->poll = ui_view_focused_poll;
|
||||
|
||||
WM_operator_properties_select_all(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name UI View Drop Operator
|
||||
* \{ */
|
||||
|
@ -2646,6 +2768,8 @@ void ED_operatortypes_ui()
|
|||
WM_operatortype_append(UI_OT_list_start_filter);
|
||||
|
||||
WM_operatortype_append(UI_OT_view_start_filter);
|
||||
WM_operatortype_append(UI_OT_view_item_select);
|
||||
WM_operatortype_append(UI_OT_view_select_all);
|
||||
WM_operatortype_append(UI_OT_view_drop);
|
||||
WM_operatortype_append(UI_OT_view_item_rename);
|
||||
|
||||
|
|
|
@ -54,12 +54,12 @@ static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle)
|
|||
return;
|
||||
}
|
||||
|
||||
BIFIconID preview_icon_id = ED_assetlist_asset_preview_icon_id_request(asset_handle);
|
||||
const eAssetImportMethod import_method = asset->get_import_method().value_or(
|
||||
ASSET_IMPORT_APPEND_REUSE);
|
||||
|
||||
ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle);
|
||||
UI_but_drag_set_asset(
|
||||
but, asset, import_method, ED_asset_handle_get_preview_icon_id(asset_handle), imbuf, 1.0f);
|
||||
UI_but_drag_set_asset(but, asset, import_method, preview_icon_id, imbuf, 1.0f);
|
||||
}
|
||||
|
||||
static void asset_view_draw_item(uiList *ui_list,
|
||||
|
@ -75,12 +75,12 @@ static void asset_view_draw_item(uiList *ui_list,
|
|||
{
|
||||
AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
||||
|
||||
AssetHandle asset_handle = ED_assetlist_asset_handle_get_by_index(&list_data->asset_library_ref,
|
||||
index);
|
||||
AssetHandle *asset_handle = ED_assetlist_asset_handle_get_by_index(&list_data->asset_library_ref,
|
||||
index);
|
||||
|
||||
PointerRNA file_ptr = RNA_pointer_create(&list_data->screen->id,
|
||||
&RNA_FileSelectEntry,
|
||||
const_cast<FileDirEntry *>(asset_handle.file_data));
|
||||
const_cast<FileDirEntry *>(asset_handle->file_data));
|
||||
uiLayoutSetContextPointer(layout, "active_file", &file_ptr);
|
||||
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
|
@ -91,8 +91,8 @@ static void asset_view_draw_item(uiList *ui_list,
|
|||
block,
|
||||
UI_BTYPE_PREVIEW_TILE,
|
||||
0,
|
||||
ED_asset_handle_get_preview_icon_id(&asset_handle),
|
||||
show_names ? ED_asset_handle_get_representation(&asset_handle)->get_name().c_str() : "",
|
||||
ED_assetlist_asset_preview_icon_id_request(asset_handle),
|
||||
show_names ? ED_asset_handle_get_representation(asset_handle)->get_name().c_str() : "",
|
||||
0,
|
||||
0,
|
||||
size_x,
|
||||
|
@ -104,12 +104,12 @@ static void asset_view_draw_item(uiList *ui_list,
|
|||
0,
|
||||
"");
|
||||
ui_def_but_icon(but,
|
||||
ED_asset_handle_get_preview_icon_id(&asset_handle),
|
||||
ED_assetlist_asset_preview_icon_id_request(asset_handle),
|
||||
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
|
||||
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
|
||||
but->emboss = UI_EMBOSS_NONE;
|
||||
if (!ui_list->dyn_data->custom_drag_optype) {
|
||||
asset_view_item_but_drag_set(but, &asset_handle);
|
||||
asset_view_item_but_drag_set(but, asset_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,8 +146,9 @@ static void asset_view_filter_items(uiList *ui_list,
|
|||
});
|
||||
}
|
||||
|
||||
static void asset_view_listener(uiList * /*ui_list*/, wmRegionListenerParams *params)
|
||||
static void asset_view_listener(uiList *ui_list, wmRegionListenerParams *params)
|
||||
{
|
||||
const AssetViewListData *list_data = (AssetViewListData *)ui_list->dyn_data->customdata;
|
||||
const wmNotifier *notifier = params->notifier;
|
||||
|
||||
switch (notifier->category) {
|
||||
|
@ -159,7 +160,7 @@ static void asset_view_listener(uiList * /*ui_list*/, wmRegionListenerParams *pa
|
|||
}
|
||||
}
|
||||
|
||||
if (ED_assetlist_listen(params->notifier)) {
|
||||
if (ED_assetlist_listen(&list_data->asset_library_ref, params->notifier)) {
|
||||
ED_region_tag_redraw(params->region);
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +256,6 @@ void uiTemplateAssetView(uiLayout *layout,
|
|||
}
|
||||
|
||||
ED_assetlist_storage_fetch(&asset_library_ref, C);
|
||||
ED_assetlist_ensure_previews_job(&asset_library_ref, C);
|
||||
const int tot_items = ED_assetlist_size(&asset_library_ref);
|
||||
|
||||
populate_asset_collection(asset_library_ref, *assets_dataptr, assets_propname);
|
||||
|
|
|
@ -652,6 +652,8 @@ static MenuSearch_Data *menu_items_from_ui_create(bContext *C,
|
|||
SPACE_MENU_NOP(SPACE_STATUSBAR);
|
||||
SPACE_MENU_NOP(SPACE_TOPBAR);
|
||||
SPACE_MENU_NOP(SPACE_SPREADSHEET);
|
||||
/* TODO */
|
||||
SPACE_MENU_NOP(SPACE_ASSETS);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < idname_array_len; i++) {
|
||||
|
|
|
@ -5595,8 +5595,9 @@ void ui_draw_preview_item_stateless(const uiFontStyle *fstyle,
|
|||
bool draw_as_icon)
|
||||
{
|
||||
rcti trect = *rect;
|
||||
const float text_size = UI_UNIT_Y;
|
||||
float font_dims[2] = {0.0f, 0.0f};
|
||||
const bool has_text = name && name[0];
|
||||
const float padding = PREVIEW_PAD;
|
||||
|
||||
float alpha = 1.0f;
|
||||
|
||||
|
@ -5611,8 +5612,12 @@ void ui_draw_preview_item_stateless(const uiFontStyle *fstyle,
|
|||
}
|
||||
|
||||
if (has_text) {
|
||||
UI_fontstyle_set(fstyle);
|
||||
BLF_width_and_height(
|
||||
fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
|
||||
|
||||
/* draw icon in rect above the space reserved for the label */
|
||||
rect->ymin += text_size;
|
||||
rect->ymin += round_fl_to_int(font_dims[1] + 2 * padding);
|
||||
}
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
if (draw_as_icon) {
|
||||
|
@ -5628,10 +5633,8 @@ void ui_draw_preview_item_stateless(const uiFontStyle *fstyle,
|
|||
}
|
||||
|
||||
/* text rect */
|
||||
trect.ymax = trect.ymin + text_size;
|
||||
trect.ymin += PREVIEW_PAD;
|
||||
trect.xmin += PREVIEW_PAD;
|
||||
trect.xmax -= PREVIEW_PAD;
|
||||
BLI_rcti_pad(&trect, -padding * 2, -padding * 2);
|
||||
trect.ymax = round_fl_to_int(trect.ymin + font_dims[1]);
|
||||
|
||||
{
|
||||
char drawstr[UI_MAX_DRAW_STR];
|
||||
|
|
|
@ -141,6 +141,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
|
|||
case SPACE_SPREADSHEET:
|
||||
ts = &btheme->space_spreadsheet;
|
||||
break;
|
||||
case SPACE_ASSETS:
|
||||
ts = &btheme->space_assets;
|
||||
break;
|
||||
default:
|
||||
ts = &btheme->space_view3d;
|
||||
break;
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
* \ingroup edinterface
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ED_select_utils.hh"
|
||||
|
||||
#include "interface_intern.hh"
|
||||
|
||||
#include "UI_abstract_view.hh"
|
||||
|
@ -159,14 +163,80 @@ std::optional<rcti> AbstractView::get_bounds() const
|
|||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::ui
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Selection
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* If \a action is #SEL_TOGGLE, check the selection if the actual action to apply should be
|
||||
* #SEL_DESELECT or #SEL_SELECT and return that.
|
||||
*/
|
||||
static SelectAction select_all_refine_action_type(const AbstractView &view, SelectAction action)
|
||||
{
|
||||
if (action != SEL_TOGGLE) {
|
||||
return action;
|
||||
}
|
||||
|
||||
bool any_selected = false;
|
||||
view.foreach_view_item([&any_selected](AbstractViewItem &item) {
|
||||
if (item.is_selected()) {
|
||||
any_selected = true;
|
||||
}
|
||||
});
|
||||
|
||||
return any_selected ? SEL_DESELECT : SEL_SELECT;
|
||||
}
|
||||
|
||||
static bool view_item_select_from_action(AbstractViewItem &item, const SelectAction action)
|
||||
{
|
||||
switch (action) {
|
||||
case SEL_SELECT:
|
||||
return item.select();
|
||||
case SEL_DESELECT:
|
||||
return item.deselect();
|
||||
case SEL_INVERT:
|
||||
if (item.is_selected()) {
|
||||
item.deselect();
|
||||
}
|
||||
else {
|
||||
item.select();
|
||||
}
|
||||
return true;
|
||||
case SEL_TOGGLE:
|
||||
BLI_assert_msg(
|
||||
false,
|
||||
"TOGGLE action should have been refined to be either SELECT or DESELECT at this point");
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool view_item_select_from_action(uiViewItemHandle *item_handle, const int /*SelectAction*/ action)
|
||||
{
|
||||
AbstractViewItem &item = reinterpret_cast<AbstractViewItem &>(*item_handle);
|
||||
return view_item_select_from_action(item, SelectAction(action));
|
||||
}
|
||||
|
||||
bool view_select_all_from_action(uiViewHandle *view_handle, const int /*SelectAction*/ action)
|
||||
{
|
||||
AbstractView &view = reinterpret_cast<AbstractView &>(*view_handle);
|
||||
const SelectAction refined_action = select_all_refine_action_type(view, SelectAction(action));
|
||||
|
||||
bool changed = false;
|
||||
view.foreach_view_item([&changed, refined_action](AbstractViewItem &item) {
|
||||
changed |= view_item_select_from_action(item, refined_action);
|
||||
});
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name General API functions
|
||||
* \{ */
|
||||
|
||||
namespace blender::ui {
|
||||
|
||||
std::unique_ptr<DropTargetInterface> view_drop_target(uiViewHandle *view_handle)
|
||||
{
|
||||
AbstractView &view = reinterpret_cast<AbstractView &>(*view_handle);
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace blender::ui {
|
|||
void AbstractViewItem::update_from_old(const AbstractViewItem &old)
|
||||
{
|
||||
is_active_ = old.is_active_;
|
||||
is_selected_ = old.is_selected_;
|
||||
is_renaming_ = old.is_renaming_;
|
||||
}
|
||||
|
||||
|
@ -67,11 +68,13 @@ bool AbstractViewItem::set_state_active()
|
|||
return true;
|
||||
}
|
||||
|
||||
void AbstractViewItem::activate(bContext &C)
|
||||
bool AbstractViewItem::activate(bContext &C)
|
||||
{
|
||||
if (set_state_active()) {
|
||||
on_activate(C);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AbstractViewItem::deactivate()
|
||||
|
@ -317,6 +320,44 @@ bool AbstractViewItem::is_active() const
|
|||
return is_active_;
|
||||
}
|
||||
|
||||
void AbstractViewItem::enable_selectable()
|
||||
{
|
||||
is_selectable_ = true;
|
||||
}
|
||||
|
||||
bool AbstractViewItem::is_selectable() const
|
||||
{
|
||||
return is_selectable_;
|
||||
}
|
||||
|
||||
bool AbstractViewItem::select()
|
||||
{
|
||||
if (!is_selectable_) {
|
||||
return false;
|
||||
}
|
||||
if (is_selected_) {
|
||||
return false;
|
||||
}
|
||||
is_selected_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AbstractViewItem::deselect()
|
||||
{
|
||||
if (!is_selected_) {
|
||||
return false;
|
||||
}
|
||||
is_selected_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AbstractViewItem::is_selected() const
|
||||
{
|
||||
BLI_assert_msg(get_view().is_reconstructed(),
|
||||
"State can't be queried until reconstruction is completed");
|
||||
return is_selected_;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
@ -400,12 +441,30 @@ bool UI_view_item_is_interactive(const uiViewItemHandle *item_handle)
|
|||
return item.is_interactive();
|
||||
}
|
||||
|
||||
bool UI_view_item_activate(bContext *C, uiViewItemHandle *item_handle)
|
||||
{
|
||||
AbstractViewItem &item = reinterpret_cast<AbstractViewItem &>(*item_handle);
|
||||
return item.activate(*C);
|
||||
}
|
||||
|
||||
bool UI_view_item_is_active(const uiViewItemHandle *item_handle)
|
||||
{
|
||||
const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_handle);
|
||||
return item.is_active();
|
||||
}
|
||||
|
||||
bool UI_view_item_is_selectable(const uiViewItemHandle *item_handle)
|
||||
{
|
||||
const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_handle);
|
||||
return item.is_selectable();
|
||||
}
|
||||
|
||||
bool UI_view_item_is_selected(const uiViewItemHandle *item_handle)
|
||||
{
|
||||
const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_handle);
|
||||
return item.is_selected();
|
||||
}
|
||||
|
||||
bool UI_view_item_matches(const uiViewItemHandle *a_handle, const uiViewItemHandle *b_handle)
|
||||
{
|
||||
const AbstractViewItem &a = reinterpret_cast<const AbstractViewItem &>(*a_handle);
|
||||
|
|
|
@ -129,15 +129,6 @@ bool AbstractGridViewItem::matches(const AbstractViewItem &other) const
|
|||
return identifier_ == other_grid_item.identifier_;
|
||||
}
|
||||
|
||||
void AbstractGridViewItem::grid_tile_click_fn(bContext *C, void *but_arg1, void * /*arg2*/)
|
||||
{
|
||||
uiButViewItem *view_item_but = (uiButViewItem *)but_arg1;
|
||||
AbstractGridViewItem &grid_item = reinterpret_cast<AbstractGridViewItem &>(
|
||||
*view_item_but->view_item);
|
||||
|
||||
grid_item.activate(*C);
|
||||
}
|
||||
|
||||
void AbstractGridViewItem::add_grid_tile_button(uiBlock &block)
|
||||
{
|
||||
const GridViewStyle &style = get_view().get_style();
|
||||
|
@ -157,7 +148,6 @@ void AbstractGridViewItem::add_grid_tile_button(uiBlock &block)
|
|||
"");
|
||||
|
||||
view_item_but_->view_item = reinterpret_cast<uiViewItemHandle *>(this);
|
||||
UI_but_func_set(view_item_but_, grid_tile_click_fn, view_item_but_, nullptr);
|
||||
}
|
||||
|
||||
AbstractGridView &AbstractGridViewItem::get_view() const
|
||||
|
|
|
@ -142,6 +142,19 @@ void ui_block_views_listen(const uiBlock *block, const wmRegionListenerParams *l
|
|||
}
|
||||
}
|
||||
|
||||
uiViewHandle *UI_region_view_find_from_idname(const ARegion *region, const char *idname)
|
||||
{
|
||||
LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) {
|
||||
LISTBASE_FOREACH (ViewLink *, view_link, &block->views) {
|
||||
if (view_link->idname == idname) {
|
||||
return reinterpret_cast<uiViewHandle *>(view_link->view.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ui_block_views_draw_overlays(const ARegion *region, const uiBlock *block)
|
||||
{
|
||||
LISTBASE_FOREACH (ViewLink *, view_link, &block->views) {
|
||||
|
|
|
@ -51,7 +51,8 @@ AbstractTreeViewItem &TreeViewItemContainer::add_tree_item(
|
|||
return added_item;
|
||||
}
|
||||
|
||||
void TreeViewItemContainer::foreach_item_recursive(ItemIterFn iter_fn, IterOptions options) const
|
||||
void TreeViewItemContainer::foreach_item_recursive(
|
||||
FunctionRef<void(AbstractTreeViewItem &)> iter_fn, IterOptions options) const
|
||||
{
|
||||
for (const auto &child : children_) {
|
||||
bool skip = false;
|
||||
|
@ -282,12 +283,11 @@ std::optional<DropLocation> TreeViewItemDropTarget::choose_drop_location(
|
|||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AbstractTreeViewItem::tree_row_click_fn(bContext *C, void *but_arg1, void * /*arg2*/)
|
||||
void AbstractTreeViewItem::tree_row_click_fn(bContext * /*C*/, void *but_arg1, void * /*arg2*/)
|
||||
{
|
||||
uiButViewItem *item_but = (uiButViewItem *)but_arg1;
|
||||
AbstractTreeViewItem &tree_item = reinterpret_cast<AbstractTreeViewItem &>(*item_but->view_item);
|
||||
|
||||
tree_item.activate(*C);
|
||||
/* Not only activate the item, also show its children. Maybe this should be optional, or
|
||||
* controlled by the specific tree-view. */
|
||||
tree_item.set_collapsed(false);
|
||||
|
|
|
@ -1833,6 +1833,9 @@ void PreviewLoadJob::run_fn(void *customdata, bool *stop, bool *do_update, float
|
|||
preview->rect[request->icon_size]);
|
||||
IMB_freeImBuf(thumb);
|
||||
}
|
||||
else {
|
||||
preview->tag |= PRV_TAG_LOADING_FAILED;
|
||||
}
|
||||
|
||||
*do_update = true;
|
||||
}
|
||||
|
|
|
@ -317,6 +317,11 @@ bool ED_operator_asset_browsing_active(bContext *C)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ED_operator_asset_browser_active(bContext *C)
|
||||
{
|
||||
return ed_spacetype_test(C, SPACE_ASSETS);
|
||||
}
|
||||
|
||||
bool ED_operator_spreadsheet_active(bContext *C)
|
||||
{
|
||||
return ed_spacetype_test(C, SPACE_SPREADSHEET);
|
||||
|
|
|
@ -25,6 +25,7 @@ set(LIB
|
|||
PRIVATE bf::dna
|
||||
bf_editor_geometry
|
||||
bf_editor_space_action
|
||||
bf_editor_space_assets
|
||||
bf_editor_space_buttons
|
||||
bf_editor_space_clip
|
||||
bf_editor_space_console
|
||||
|
|
|
@ -65,6 +65,7 @@ void ED_spacetypes_init()
|
|||
U.widget_unit = 20;
|
||||
|
||||
/* Create space types. */
|
||||
ED_spacetype_assets();
|
||||
ED_spacetype_outliner();
|
||||
ED_spacetype_view3d();
|
||||
ED_spacetype_ipo();
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
# SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(INC
|
||||
../include
|
||||
../../asset_system
|
||||
../../blenfont
|
||||
../../blenkernel
|
||||
../../blentranslation
|
||||
../../gpu
|
||||
../../makesrna
|
||||
../../windowmanager
|
||||
../../../../extern/fmtlib/include
|
||||
# RNA_prototypes.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
||||
set(SRC
|
||||
asset_browser_draw.cc
|
||||
asset_browser_ops.cc
|
||||
asset_browser_panels.cc
|
||||
asset_catalog_tree_view.cc
|
||||
asset_view.cc
|
||||
space_assets.cc
|
||||
|
||||
asset_browser_intern.hh
|
||||
asset_view.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
bf_blenkernel
|
||||
PRIVATE bf::blenlib
|
||||
PRIVATE bf::dna
|
||||
PRIVATE bf::intern::guardedalloc
|
||||
extern_fmtlib
|
||||
)
|
||||
|
||||
blender_add_lib(bf_editor_space_assets "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_editor_space_assets bf_rna)
|
|
@ -0,0 +1,77 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
#include "UI_view2d.hh"
|
||||
|
||||
#include "asset_browser_intern.hh"
|
||||
#include "asset_view.hh"
|
||||
|
||||
namespace blender::ed::asset_browser {
|
||||
|
||||
} // namespace blender::ed::asset_browser
|
||||
|
||||
using namespace blender::ed::asset_browser;
|
||||
|
||||
void asset_browser_main_region_draw(const bContext *C, ARegion *region)
|
||||
{
|
||||
SpaceAssets *asset_space = CTX_wm_space_assets(C);
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
View2D *v2d = ®ion->v2d;
|
||||
|
||||
UI_ThemeClearColor(TH_BACK);
|
||||
|
||||
UI_view2d_view_ortho(v2d);
|
||||
|
||||
const uiStyle *style = UI_style_get_dpi();
|
||||
const float padding = style->panelouter;
|
||||
uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
|
||||
uiLayout *layout = UI_block_layout(
|
||||
block,
|
||||
UI_LAYOUT_VERTICAL,
|
||||
UI_LAYOUT_PANEL,
|
||||
padding,
|
||||
-padding,
|
||||
/* 3x (instead of 2x) padding to add extra space for the scrollbar on the right. */
|
||||
region->winx - 3 * padding,
|
||||
1,
|
||||
0,
|
||||
style);
|
||||
|
||||
PointerRNA asset_space_ptr = RNA_pointer_create(
|
||||
&screen->id, &RNA_SpaceAssetBrowser, asset_space);
|
||||
PropertyRNA *active_asset_idx_prop = RNA_struct_find_property(&asset_space_ptr,
|
||||
"active_asset_idx");
|
||||
|
||||
asset_view_create_in_layout(*C,
|
||||
asset_space->asset_library_ref,
|
||||
asset_space->catalog_filter,
|
||||
asset_space_ptr,
|
||||
active_asset_idx_prop,
|
||||
*v2d,
|
||||
*layout);
|
||||
|
||||
/* Update main region View2d dimensions. */
|
||||
int layout_width, layout_height;
|
||||
UI_block_layout_resolve(block, &layout_width, &layout_height);
|
||||
UI_view2d_totRect_set(v2d, layout_width, layout_height);
|
||||
|
||||
UI_block_end(C, block);
|
||||
UI_block_draw(C, block);
|
||||
|
||||
/* reset view matrix */
|
||||
UI_view2d_view_restore(C);
|
||||
UI_view2d_scrollers_draw(v2d, nullptr);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void asset_browser_operatortypes();
|
||||
|
||||
struct ARegion;
|
||||
struct ARegionType;
|
||||
struct AssetLibrary;
|
||||
struct bContext;
|
||||
struct PointerRNA;
|
||||
struct PropertyRNA;
|
||||
struct uiLayout;
|
||||
struct wmMsgBus;
|
||||
|
||||
void asset_browser_main_region_draw(const bContext *C, ARegion *region);
|
||||
|
||||
void asset_browser_navigation_region_panels_register(ARegionType *art);
|
||||
|
||||
void asset_view_create_catalog_tree_view_in_layout(::AssetLibrary *asset_library,
|
||||
uiLayout *layout,
|
||||
PointerRNA *catalog_filter_owner_ptr,
|
||||
PropertyRNA *catalog_filter_prop,
|
||||
wmMsgBus *msg_bus);
|
|
@ -0,0 +1,62 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "ED_screen.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
|
||||
#include "asset_browser_intern.hh"
|
||||
|
||||
using namespace blender;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Select All Operator
|
||||
*
|
||||
* Asset Browser specific version of #UI_OT_view_select_all() that looks up the asset view, so that
|
||||
* it doesn't require the view to be under the cursor. So this operator can be displayed in menus
|
||||
* too.
|
||||
*
|
||||
* \{ */
|
||||
|
||||
static int select_all_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
uiViewHandle *view = UI_region_view_find_from_idname(region, "asset grid view");
|
||||
|
||||
const int action = RNA_enum_get(op->ptr, "action");
|
||||
|
||||
if (ui::view_select_all_from_action(view, action)) {
|
||||
ED_region_tag_redraw(region);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void ASSETBROWSER_OT_select_all(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select All";
|
||||
ot->idname = "ASSETBROWSER_OT_select_all";
|
||||
ot->description = "Select or deselect all displayed assets";
|
||||
|
||||
ot->exec = select_all_exec;
|
||||
ot->poll = ED_operator_asset_browser_active;
|
||||
|
||||
WM_operator_properties_select_all(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
void asset_browser_operatortypes()
|
||||
{
|
||||
WM_operatortype_append(ASSETBROWSER_OT_select_all);
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "ED_asset.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
#include "asset_browser_intern.hh"
|
||||
|
||||
static void assets_panel_asset_catalog_buttons_draw(const bContext *C, Panel *panel)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
SpaceAssets *assets_space = CTX_wm_space_assets(C);
|
||||
|
||||
uiLayout *col = uiLayoutColumn(panel->layout, false);
|
||||
uiLayout *row = uiLayoutRow(col, true);
|
||||
|
||||
PointerRNA assets_space_ptr = RNA_pointer_create(
|
||||
&screen->id, &RNA_SpaceAssetBrowser, assets_space);
|
||||
|
||||
uiItemR(row, &assets_space_ptr, "asset_library_reference", UI_ITEM_NONE, "", ICON_NONE);
|
||||
if (assets_space->asset_library_ref.type == ASSET_LIBRARY_LOCAL) {
|
||||
bContext *mutable_ctx = CTX_copy(C);
|
||||
if (WM_operator_name_poll(mutable_ctx, "asset.bundle_install")) {
|
||||
uiItemS(col);
|
||||
uiItemMenuEnumO(col,
|
||||
mutable_ctx,
|
||||
"asset.bundle_install",
|
||||
"asset_library_reference",
|
||||
"Copy Bundle to Asset Library...",
|
||||
ICON_IMPORT);
|
||||
}
|
||||
CTX_free(mutable_ctx);
|
||||
}
|
||||
else {
|
||||
uiItemO(row, "", ICON_FILE_REFRESH, "ASSET_OT_library_refresh");
|
||||
}
|
||||
|
||||
uiItemS(col);
|
||||
|
||||
AssetLibrary *library = ED_assetlist_library_get(&assets_space->asset_library_ref);
|
||||
PropertyRNA *catalog_filter_prop = RNA_struct_find_property(&assets_space_ptr, "catalog_filter");
|
||||
|
||||
asset_view_create_catalog_tree_view_in_layout(
|
||||
library, col, &assets_space_ptr, catalog_filter_prop, CTX_wm_message_bus(C));
|
||||
}
|
||||
|
||||
void asset_browser_navigation_region_panels_register(ARegionType *art)
|
||||
{
|
||||
PanelType *pt;
|
||||
|
||||
pt = MEM_cnew<PanelType>("asset browser catalog buttons");
|
||||
strcpy(pt->idname, "FILE_PT_asset_catalog_buttons");
|
||||
strcpy(pt->label, N_("Asset Catalogs"));
|
||||
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
pt->flag = PANEL_TYPE_NO_HEADER;
|
||||
pt->draw = assets_panel_asset_catalog_buttons_draw;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
}
|
|
@ -0,0 +1,752 @@
|
|||
/* SPDX-FileCopyrightText: 2021 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
|
||||
#include "AS_asset_catalog.hh"
|
||||
#include "AS_asset_catalog_tree.hh"
|
||||
#include "AS_asset_library.hh"
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_asset.h"
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "ED_asset.hh"
|
||||
#include "ED_undo.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
#include "UI_tree_view.hh"
|
||||
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_message.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "asset_browser_intern.hh"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
using namespace blender;
|
||||
using namespace blender::asset_system;
|
||||
|
||||
namespace blender::ed::asset_browser {
|
||||
|
||||
class AssetCatalogTreeViewAllItem;
|
||||
|
||||
class AssetCatalogTreeView : public ui::AbstractTreeView {
|
||||
/** The asset library this catalog tree comes from. May be null when drawing the catalog tree
|
||||
* before the library was read. */
|
||||
::AssetLibrary *asset_library_;
|
||||
/** The asset catalog tree this tree-view represents. */
|
||||
AssetCatalogTree *catalog_tree_;
|
||||
|
||||
PointerRNA catalog_filter_owner_;
|
||||
PropertyRNA &catalog_filter_prop_;
|
||||
/** Used to notify the parts of the UI that display the filtered assets. */
|
||||
wmMsgBus *msg_bus_;
|
||||
|
||||
friend class AssetCatalogTreeViewItem;
|
||||
friend class AssetCatalogDropTarget;
|
||||
friend class AssetCatalogTreeViewAllItem;
|
||||
|
||||
public:
|
||||
AssetCatalogTreeView(::AssetLibrary *library,
|
||||
const PointerRNA &catalog_filter_owner,
|
||||
PropertyRNA &catalog_filter_prop,
|
||||
wmMsgBus *msg_bus);
|
||||
|
||||
void build_tree() override;
|
||||
bool listen(const wmNotifier ¬ifier) const override;
|
||||
|
||||
void activate_catalog_by_id(asset_system::CatalogID catalog_id);
|
||||
|
||||
private:
|
||||
ui::BasicTreeViewItem &build_catalog_items_recursive(ui::TreeViewOrItem &view_parent_item,
|
||||
AssetCatalogTreeItem &catalog);
|
||||
|
||||
AssetCatalogTreeViewAllItem &add_all_item();
|
||||
void add_unassigned_item();
|
||||
bool is_active_catalog(CatalogID catalog_id) const;
|
||||
|
||||
AssetCatalogFilterSettings &catalog_filter_settings() const;
|
||||
void notify_catalog_filter_change();
|
||||
void notify_catalog_tree_change();
|
||||
void notify_catalog_assignments_change();
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
class AssetCatalogTreeViewItem : public ui::BasicTreeViewItem {
|
||||
/** The catalog tree item this tree view item represents. */
|
||||
AssetCatalogTreeItem &catalog_item_;
|
||||
|
||||
public:
|
||||
AssetCatalogTreeViewItem(AssetCatalogTreeItem *catalog_item);
|
||||
|
||||
void on_activate(bContext &C) override;
|
||||
|
||||
void build_row(uiLayout &row) override;
|
||||
void build_context_menu(bContext &C, uiLayout &column) const override;
|
||||
|
||||
bool supports_renaming() const override;
|
||||
bool rename(const bContext &C, StringRefNull new_name) override;
|
||||
|
||||
/** Add drag support for catalog items. */
|
||||
std::unique_ptr<ui::AbstractViewItemDragController> create_drag_controller() const override;
|
||||
/** Add dropping support for catalog items. */
|
||||
std::unique_ptr<ui::TreeViewItemDropTarget> create_drop_target() override;
|
||||
};
|
||||
|
||||
class AssetCatalogDragController : public ui::AbstractViewItemDragController {
|
||||
AssetCatalogTreeItem &catalog_item_;
|
||||
|
||||
public:
|
||||
explicit AssetCatalogDragController(AssetCatalogTreeView &tree_view,
|
||||
AssetCatalogTreeItem &catalog_item);
|
||||
|
||||
eWM_DragDataType get_drag_type() const override;
|
||||
void *create_drag_data() const override;
|
||||
void on_drag_start() override;
|
||||
};
|
||||
|
||||
class AssetCatalogDropTarget : public ui::TreeViewItemDropTarget {
|
||||
AssetCatalogTreeItem &catalog_item_;
|
||||
|
||||
public:
|
||||
AssetCatalogDropTarget(AssetCatalogTreeView &tree_view, AssetCatalogTreeItem &catalog_item);
|
||||
|
||||
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
|
||||
std::string drop_tooltip(const ui::DragInfo &drag) const override;
|
||||
bool on_drop(bContext *C, const ui::DragInfo &drag) const override;
|
||||
|
||||
::AssetLibrary &get_asset_library() const;
|
||||
|
||||
static AssetCatalog *get_drag_catalog(const wmDrag &drag, const ::AssetLibrary &asset_library);
|
||||
static bool has_droppable_asset(const wmDrag &drag, const char **r_disabled_hint);
|
||||
static bool can_modify_catalogs(const ::AssetLibrary &asset_library,
|
||||
const char **r_disabled_hint);
|
||||
static bool drop_assets_into_catalog(bContext *C,
|
||||
AssetCatalogTreeView &tree_view,
|
||||
const ui::DragInfo &drag,
|
||||
CatalogID catalog_id,
|
||||
StringRefNull simple_name = "");
|
||||
/**
|
||||
* \param drop_catalog_id: Can be unset to drop into the root level of the tree.
|
||||
*/
|
||||
static bool drop_asset_catalog_into_catalog(
|
||||
const ui::DragInfo &drag,
|
||||
AssetCatalogTreeView &tree_view,
|
||||
const std::optional<CatalogID> drop_catalog_id = std::nullopt);
|
||||
|
||||
private:
|
||||
std::string drop_tooltip_asset_list(const ui::DragInfo &drag) const;
|
||||
std::string drop_tooltip_asset_catalog(const ui::DragInfo &drag) const;
|
||||
};
|
||||
|
||||
/** Only reason this isn't just `BasicTreeViewItem` is to add a '+' icon for adding a root level
|
||||
* catalog. */
|
||||
class AssetCatalogTreeViewAllItem : public ui::BasicTreeViewItem {
|
||||
using BasicTreeViewItem::BasicTreeViewItem;
|
||||
|
||||
void build_row(uiLayout &row) override;
|
||||
|
||||
struct DropTarget : public ui::TreeViewItemDropTarget {
|
||||
DropTarget(AssetCatalogTreeView &tree_view);
|
||||
|
||||
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
|
||||
std::string drop_tooltip(const ui::DragInfo &drag) const override;
|
||||
bool on_drop(bContext *C, const ui::DragInfo &drag) const override;
|
||||
};
|
||||
|
||||
std::unique_ptr<ui::TreeViewItemDropTarget> create_drop_target() override;
|
||||
};
|
||||
|
||||
class AssetCatalogTreeViewUnassignedItem : public ui::BasicTreeViewItem {
|
||||
using BasicTreeViewItem::BasicTreeViewItem;
|
||||
|
||||
struct DropTarget : public ui::TreeViewItemDropTarget {
|
||||
DropTarget(AssetCatalogTreeView &tree_view);
|
||||
|
||||
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
|
||||
std::string drop_tooltip(const ui::DragInfo &drag) const override;
|
||||
bool on_drop(bContext *C, const ui::DragInfo &drag) const override;
|
||||
};
|
||||
|
||||
std::unique_ptr<ui::TreeViewItemDropTarget> create_drop_target() override;
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AssetCatalogTreeView::AssetCatalogTreeView(::AssetLibrary *library,
|
||||
const PointerRNA &catalog_filter_owner,
|
||||
PropertyRNA &catalog_filter_prop,
|
||||
wmMsgBus *msg_bus)
|
||||
: asset_library_(library),
|
||||
catalog_tree_(AS_asset_library_get_catalog_tree(library)),
|
||||
catalog_filter_owner_(catalog_filter_owner),
|
||||
catalog_filter_prop_(catalog_filter_prop),
|
||||
msg_bus_(msg_bus)
|
||||
{
|
||||
}
|
||||
|
||||
void AssetCatalogTreeView::build_tree()
|
||||
{
|
||||
AssetCatalogTreeViewAllItem &all_item = add_all_item();
|
||||
all_item.set_collapsed(false);
|
||||
|
||||
if (catalog_tree_) {
|
||||
/* Pass the "All" item on as parent of the actual catalog items. */
|
||||
catalog_tree_->foreach_root_item([this, &all_item](AssetCatalogTreeItem &item) {
|
||||
build_catalog_items_recursive(all_item, item);
|
||||
});
|
||||
}
|
||||
|
||||
add_unassigned_item();
|
||||
}
|
||||
|
||||
ui::BasicTreeViewItem &AssetCatalogTreeView::build_catalog_items_recursive(
|
||||
ui::TreeViewOrItem &view_parent_item, AssetCatalogTreeItem &catalog)
|
||||
{
|
||||
ui::BasicTreeViewItem &view_item = view_parent_item.add_tree_item<AssetCatalogTreeViewItem>(
|
||||
&catalog);
|
||||
view_item.set_is_active_fn(
|
||||
[this, &catalog]() { return is_active_catalog(catalog.get_catalog_id()); });
|
||||
|
||||
catalog.foreach_child([&view_item, this](AssetCatalogTreeItem &child) {
|
||||
build_catalog_items_recursive(view_item, child);
|
||||
});
|
||||
return view_item;
|
||||
}
|
||||
|
||||
AssetCatalogTreeViewAllItem &AssetCatalogTreeView::add_all_item()
|
||||
{
|
||||
AssetCatalogTreeViewAllItem &item = add_tree_item<AssetCatalogTreeViewAllItem>(IFACE_("All"));
|
||||
item.set_on_activate_fn([this](bContext & /*C*/, ui::BasicTreeViewItem & /*item*/) {
|
||||
catalog_filter_settings().filter_mode = ASSET_CATALOG_SHOW_ALL_ASSETS;
|
||||
notify_catalog_filter_change();
|
||||
});
|
||||
item.set_is_active_fn(
|
||||
[this]() { return catalog_filter_settings().filter_mode == ASSET_CATALOG_SHOW_ALL_ASSETS; });
|
||||
return item;
|
||||
}
|
||||
|
||||
void AssetCatalogTreeView::add_unassigned_item()
|
||||
{
|
||||
AssetCatalogTreeViewUnassignedItem &item = add_tree_item<AssetCatalogTreeViewUnassignedItem>(
|
||||
IFACE_("Unassigned"), ICON_FILE_HIDDEN);
|
||||
|
||||
item.set_on_activate_fn([this](bContext & /*C*/, ui::BasicTreeViewItem & /*item*/) {
|
||||
catalog_filter_settings().filter_mode = ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG;
|
||||
notify_catalog_filter_change();
|
||||
});
|
||||
item.set_is_active_fn([this]() {
|
||||
return catalog_filter_settings().filter_mode == ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG;
|
||||
});
|
||||
}
|
||||
|
||||
void AssetCatalogTreeView::activate_catalog_by_id(CatalogID catalog_id)
|
||||
{
|
||||
AssetCatalogFilterSettings &catalog_filter = catalog_filter_settings();
|
||||
catalog_filter.filter_mode = ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG;
|
||||
catalog_filter.active_catalog_id = catalog_id;
|
||||
notify_catalog_filter_change();
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeView::is_active_catalog(CatalogID catalog_id) const
|
||||
{
|
||||
const AssetCatalogFilterSettings &catalog_filter = catalog_filter_settings();
|
||||
return (catalog_filter.filter_mode == ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG) &&
|
||||
(catalog_filter.active_catalog_id == catalog_id);
|
||||
}
|
||||
|
||||
AssetCatalogFilterSettings &AssetCatalogTreeView::catalog_filter_settings() const
|
||||
{
|
||||
/* Copy so we can pass a non-const pointer to this to RNA functions. */
|
||||
PointerRNA catalog_filter_owner = catalog_filter_owner_;
|
||||
PointerRNA catalog_filter_ptr = RNA_property_pointer_get(&catalog_filter_owner,
|
||||
&catalog_filter_prop_);
|
||||
BLI_assert(catalog_filter_ptr.type == &RNA_AssetCatalogFilterSettings);
|
||||
|
||||
return *reinterpret_cast<AssetCatalogFilterSettings *>(catalog_filter_ptr.data);
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeView::listen(const wmNotifier ¬ifier) const
|
||||
{
|
||||
switch (notifier.category) {
|
||||
case NC_ASSET:
|
||||
if (ELEM(notifier.data, ND_ASSET_CATALOGS, ND_ASSET_LIST_READING)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AssetCatalogTreeView::notify_catalog_filter_change()
|
||||
{
|
||||
WM_msg_publish_rna(msg_bus_, &catalog_filter_owner_, &catalog_filter_prop_);
|
||||
}
|
||||
|
||||
void AssetCatalogTreeView::notify_catalog_tree_change()
|
||||
{
|
||||
WM_main_add_notifier(NC_ASSET | ND_ASSET_CATALOGS, nullptr);
|
||||
}
|
||||
|
||||
void AssetCatalogTreeView::notify_catalog_assignments_change()
|
||||
{
|
||||
WM_main_add_notifier(NC_ASSET | ND_ASSET_LIST, nullptr);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AssetCatalogTreeViewItem::AssetCatalogTreeViewItem(AssetCatalogTreeItem *catalog_item)
|
||||
: BasicTreeViewItem(catalog_item->get_name()), catalog_item_(*catalog_item)
|
||||
{
|
||||
}
|
||||
|
||||
void AssetCatalogTreeViewItem::on_activate(bContext & /*C*/)
|
||||
{
|
||||
AssetCatalogTreeView &tree_view = static_cast<AssetCatalogTreeView &>(get_tree_view());
|
||||
tree_view.activate_catalog_by_id(catalog_item_.get_catalog_id());
|
||||
}
|
||||
|
||||
void AssetCatalogTreeViewItem::build_row(uiLayout &row)
|
||||
{
|
||||
const std::string label_override = catalog_item_.has_unsaved_changes() ? (label_ + "*") : label_;
|
||||
add_label(row, label_override);
|
||||
|
||||
if (!is_hovered()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uiButViewItem *item_but = view_item_button();
|
||||
PointerRNA *props;
|
||||
|
||||
props = UI_but_extra_operator_icon_add(
|
||||
(uiBut *)item_but, "ASSET_OT_catalog_new", WM_OP_INVOKE_DEFAULT, ICON_ADD);
|
||||
RNA_string_set(props, "parent_path", catalog_item_.catalog_path().c_str());
|
||||
}
|
||||
|
||||
void AssetCatalogTreeViewItem::build_context_menu(bContext &C, uiLayout &column) const
|
||||
{
|
||||
PointerRNA props;
|
||||
|
||||
uiItemFullO(&column,
|
||||
"ASSET_OT_catalog_new",
|
||||
"New Catalog",
|
||||
ICON_NONE,
|
||||
nullptr,
|
||||
WM_OP_INVOKE_DEFAULT,
|
||||
UI_ITEM_NONE,
|
||||
&props);
|
||||
RNA_string_set(&props, "parent_path", catalog_item_.catalog_path().c_str());
|
||||
|
||||
char catalog_id_str_buffer[UUID_STRING_SIZE] = "";
|
||||
BLI_uuid_format(catalog_id_str_buffer, catalog_item_.get_catalog_id());
|
||||
uiItemFullO(&column,
|
||||
"ASSET_OT_catalog_delete",
|
||||
"Delete Catalog",
|
||||
ICON_NONE,
|
||||
nullptr,
|
||||
WM_OP_INVOKE_DEFAULT,
|
||||
UI_ITEM_NONE,
|
||||
&props);
|
||||
RNA_string_set(&props, "catalog_id", catalog_id_str_buffer);
|
||||
uiItemO(&column, "Rename", ICON_NONE, "UI_OT_view_item_rename");
|
||||
|
||||
/* Doesn't actually exist right now, but could be defined in Python. Reason that this isn't done
|
||||
* in Python yet is that catalogs are not exposed in BPY, and we'd somehow pass the clicked on
|
||||
* catalog to the menu draw callback (via context probably). */
|
||||
MenuType *mt = WM_menutype_find("ASSETBROWSER_MT_catalog_context_menu", true);
|
||||
if (!mt) {
|
||||
return;
|
||||
}
|
||||
UI_menutype_draw(&C, mt, &column);
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewItem::supports_renaming() const
|
||||
{
|
||||
const AssetCatalogTreeView &tree_view = static_cast<const AssetCatalogTreeView &>(
|
||||
get_tree_view());
|
||||
return !ED_asset_catalogs_read_only(*tree_view.asset_library_);
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewItem::rename(const bContext &C, StringRefNull new_name)
|
||||
{
|
||||
/* Important to keep state. */
|
||||
BasicTreeViewItem::rename(C, new_name);
|
||||
|
||||
const AssetCatalogTreeView &tree_view = static_cast<const AssetCatalogTreeView &>(
|
||||
get_tree_view());
|
||||
ED_asset_catalog_rename(tree_view.asset_library_, catalog_item_.get_catalog_id(), new_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<ui::TreeViewItemDropTarget> AssetCatalogTreeViewItem::create_drop_target()
|
||||
{
|
||||
return std::make_unique<AssetCatalogDropTarget>(
|
||||
static_cast<AssetCatalogTreeView &>(get_tree_view()), catalog_item_);
|
||||
}
|
||||
|
||||
std::unique_ptr<ui::AbstractViewItemDragController> AssetCatalogTreeViewItem::
|
||||
create_drag_controller() const
|
||||
{
|
||||
return std::make_unique<AssetCatalogDragController>(
|
||||
static_cast<AssetCatalogTreeView &>(get_tree_view()), catalog_item_);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AssetCatalogDropTarget::AssetCatalogDropTarget(AssetCatalogTreeView &tree_view,
|
||||
AssetCatalogTreeItem &catalog_item)
|
||||
: ui::TreeViewItemDropTarget(tree_view), catalog_item_(catalog_item)
|
||||
{
|
||||
}
|
||||
|
||||
bool AssetCatalogDropTarget::can_drop(const wmDrag &drag, const char **r_disabled_hint) const
|
||||
{
|
||||
if (drag.type == WM_DRAG_ASSET_CATALOG) {
|
||||
const ::AssetLibrary &library = get_asset_library();
|
||||
if (!can_modify_catalogs(library, r_disabled_hint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const AssetCatalog *drag_catalog = get_drag_catalog(drag, library);
|
||||
/* NOTE: Technically it's not an issue to allow this (the catalog will just receive a new
|
||||
* path and the catalog system will generate missing parents from the path). But it does
|
||||
* appear broken to users, so disabling entirely. */
|
||||
if (catalog_item_.catalog_path().is_contained_in(drag_catalog->path)) {
|
||||
*r_disabled_hint = TIP_("Catalog cannot be dropped into itself");
|
||||
return false;
|
||||
}
|
||||
if (catalog_item_.catalog_path() == drag_catalog->path.parent()) {
|
||||
*r_disabled_hint = TIP_("Catalog is already placed inside this catalog");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (drag.type == WM_DRAG_ASSET_LIST && has_droppable_asset(drag, r_disabled_hint)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string AssetCatalogDropTarget::drop_tooltip(const ui::DragInfo &drag) const
|
||||
{
|
||||
if (drag.drag_data.type == WM_DRAG_ASSET_CATALOG) {
|
||||
return drop_tooltip_asset_catalog(drag);
|
||||
}
|
||||
return drop_tooltip_asset_list(drag);
|
||||
}
|
||||
|
||||
std::string AssetCatalogDropTarget::drop_tooltip_asset_catalog(const ui::DragInfo &drag) const
|
||||
{
|
||||
BLI_assert(drag.drag_data.type == WM_DRAG_ASSET_CATALOG);
|
||||
const AssetCatalog *src_catalog = get_drag_catalog(drag.drag_data, get_asset_library());
|
||||
|
||||
return fmt::format(TIP_("Move catalog {} into {}"),
|
||||
std::string_view(src_catalog->path.name()),
|
||||
std::string_view(catalog_item_.get_name()));
|
||||
}
|
||||
|
||||
std::string AssetCatalogDropTarget::drop_tooltip_asset_list(const ui::DragInfo &drag) const
|
||||
{
|
||||
BLI_assert(drag.drag_data.type == WM_DRAG_ASSET_LIST);
|
||||
|
||||
const ListBase *asset_drags = WM_drag_asset_list_get(&drag.drag_data);
|
||||
const bool is_multiple_assets = !BLI_listbase_is_single(asset_drags);
|
||||
|
||||
/* Don't try to be smart by dynamically adding the 's' for the plural. Just makes translation
|
||||
* harder, so use full literals. */
|
||||
std::string basic_tip = is_multiple_assets ? TIP_("Move assets to catalog") :
|
||||
TIP_("Move asset to catalog");
|
||||
|
||||
basic_tip += ": " + catalog_item_.get_name();
|
||||
|
||||
/* Display the full catalog path, but only if it's not exactly the same as the already shown name
|
||||
* (i.e. not a root level catalog with no parent). */
|
||||
if (catalog_item_.get_name() != catalog_item_.catalog_path().str()) {
|
||||
basic_tip += " (" + catalog_item_.catalog_path().str() + ")";
|
||||
}
|
||||
|
||||
return basic_tip;
|
||||
}
|
||||
|
||||
bool AssetCatalogDropTarget::on_drop(bContext *C, const ui::DragInfo &drag) const
|
||||
{
|
||||
if (drag.drag_data.type == WM_DRAG_ASSET_CATALOG) {
|
||||
return drop_asset_catalog_into_catalog(
|
||||
drag, get_view<AssetCatalogTreeView>(), catalog_item_.get_catalog_id());
|
||||
}
|
||||
return drop_assets_into_catalog(C,
|
||||
get_view<AssetCatalogTreeView>(),
|
||||
drag,
|
||||
catalog_item_.get_catalog_id(),
|
||||
catalog_item_.get_simple_name());
|
||||
}
|
||||
|
||||
bool AssetCatalogDropTarget::drop_asset_catalog_into_catalog(
|
||||
const ui::DragInfo &drag,
|
||||
AssetCatalogTreeView &tree_view,
|
||||
const std::optional<CatalogID> drop_catalog_id)
|
||||
{
|
||||
BLI_assert(drag.drag_data.type == WM_DRAG_ASSET_CATALOG);
|
||||
wmDragAssetCatalog *catalog_drag = WM_drag_get_asset_catalog_data(&drag.drag_data);
|
||||
ED_asset_catalog_move(tree_view.asset_library_, catalog_drag->drag_catalog_id, drop_catalog_id);
|
||||
tree_view.activate_catalog_by_id(catalog_drag->drag_catalog_id);
|
||||
|
||||
tree_view.notify_catalog_tree_change();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AssetCatalogDropTarget::drop_assets_into_catalog(bContext *C,
|
||||
AssetCatalogTreeView &tree_view,
|
||||
const ui::DragInfo &drag,
|
||||
CatalogID catalog_id,
|
||||
StringRefNull simple_name)
|
||||
{
|
||||
BLI_assert(drag.drag_data.type == WM_DRAG_ASSET_LIST);
|
||||
const ListBase *asset_drags = WM_drag_asset_list_get(&drag.drag_data);
|
||||
if (!asset_drags) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool did_update = false;
|
||||
LISTBASE_FOREACH (wmDragAssetListItem *, asset_item, asset_drags) {
|
||||
if (asset_item->is_external) {
|
||||
/* Only internal assets can be modified! */
|
||||
continue;
|
||||
}
|
||||
|
||||
did_update = true;
|
||||
BKE_asset_metadata_catalog_id_set(
|
||||
asset_item->asset_data.local_id->asset_data, catalog_id, simple_name.c_str());
|
||||
|
||||
/* TODO */
|
||||
/* Trigger re-run of filtering to update visible assets. */
|
||||
// filelist_tag_needs_filtering(tree_view.space_file_.files);
|
||||
// file_select_deselect_all(&tree_view.space_file_, FILE_SEL_SELECTED |
|
||||
// FILE_SEL_HIGHLIGHTED);
|
||||
}
|
||||
|
||||
if (did_update) {
|
||||
tree_view.notify_catalog_assignments_change();
|
||||
ED_undo_push(C, "Assign Asset Catalog");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
AssetCatalog *AssetCatalogDropTarget::get_drag_catalog(const wmDrag &drag,
|
||||
const ::AssetLibrary &asset_library)
|
||||
{
|
||||
if (drag.type != WM_DRAG_ASSET_CATALOG) {
|
||||
return nullptr;
|
||||
}
|
||||
const asset_system::AssetCatalogService *catalog_service = AS_asset_library_get_catalog_service(
|
||||
&asset_library);
|
||||
const wmDragAssetCatalog *catalog_drag = WM_drag_get_asset_catalog_data(&drag);
|
||||
|
||||
return catalog_service->find_catalog(catalog_drag->drag_catalog_id);
|
||||
}
|
||||
|
||||
bool AssetCatalogDropTarget::has_droppable_asset(const wmDrag &drag, const char **r_disabled_hint)
|
||||
{
|
||||
const ListBase *asset_drags = WM_drag_asset_list_get(&drag);
|
||||
|
||||
*r_disabled_hint = nullptr;
|
||||
/* There needs to be at least one asset from the current file. */
|
||||
LISTBASE_FOREACH (const wmDragAssetListItem *, asset_item, asset_drags) {
|
||||
if (!asset_item->is_external) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
*r_disabled_hint = TIP_("Only assets from this current file can be moved between catalogs");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AssetCatalogDropTarget::can_modify_catalogs(const ::AssetLibrary &library,
|
||||
const char **r_disabled_hint)
|
||||
{
|
||||
if (ED_asset_catalogs_read_only(library)) {
|
||||
*r_disabled_hint = TIP_("Catalogs cannot be edited in this asset library");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
::AssetLibrary &AssetCatalogDropTarget::get_asset_library() const
|
||||
{
|
||||
return *get_view<AssetCatalogTreeView>().asset_library_;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AssetCatalogDragController::AssetCatalogDragController(AssetCatalogTreeView &tree_view,
|
||||
AssetCatalogTreeItem &catalog_item)
|
||||
: ui::AbstractViewItemDragController(tree_view), catalog_item_(catalog_item)
|
||||
{
|
||||
}
|
||||
|
||||
eWM_DragDataType AssetCatalogDragController::get_drag_type() const
|
||||
{
|
||||
return WM_DRAG_ASSET_CATALOG;
|
||||
}
|
||||
|
||||
void *AssetCatalogDragController::create_drag_data() const
|
||||
{
|
||||
wmDragAssetCatalog *drag_catalog = (wmDragAssetCatalog *)MEM_callocN(sizeof(*drag_catalog),
|
||||
__func__);
|
||||
drag_catalog->drag_catalog_id = catalog_item_.get_catalog_id();
|
||||
return drag_catalog;
|
||||
}
|
||||
|
||||
void AssetCatalogDragController::on_drag_start()
|
||||
{
|
||||
AssetCatalogTreeView &tree_view_ = get_view<AssetCatalogTreeView>();
|
||||
tree_view_.activate_catalog_by_id(catalog_item_.get_catalog_id());
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AssetCatalogTreeViewAllItem::build_row(uiLayout &row)
|
||||
{
|
||||
ui::BasicTreeViewItem::build_row(row);
|
||||
|
||||
PointerRNA *props;
|
||||
|
||||
UI_but_extra_operator_icon_add(
|
||||
(uiBut *)view_item_button(), "ASSET_OT_catalogs_save", WM_OP_INVOKE_DEFAULT, ICON_FILE_TICK);
|
||||
|
||||
props = UI_but_extra_operator_icon_add(
|
||||
(uiBut *)view_item_button(), "ASSET_OT_catalog_new", WM_OP_INVOKE_DEFAULT, ICON_ADD);
|
||||
/* No parent path to use the root level. */
|
||||
RNA_string_set(props, "parent_path", nullptr);
|
||||
}
|
||||
|
||||
std::unique_ptr<ui::TreeViewItemDropTarget> AssetCatalogTreeViewAllItem::create_drop_target()
|
||||
{
|
||||
return std::make_unique<AssetCatalogTreeViewAllItem::DropTarget>(
|
||||
static_cast<AssetCatalogTreeView &>(get_tree_view()));
|
||||
}
|
||||
|
||||
AssetCatalogTreeViewAllItem::DropTarget::DropTarget(AssetCatalogTreeView &tree_view)
|
||||
: ui::TreeViewItemDropTarget(tree_view)
|
||||
{
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewAllItem::DropTarget::can_drop(const wmDrag &drag,
|
||||
const char **r_disabled_hint) const
|
||||
{
|
||||
if (drag.type != WM_DRAG_ASSET_CATALOG) {
|
||||
return false;
|
||||
}
|
||||
::AssetLibrary &library = *get_view<AssetCatalogTreeView>().asset_library_;
|
||||
if (!AssetCatalogDropTarget::can_modify_catalogs(library, r_disabled_hint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const AssetCatalog *drag_catalog = AssetCatalogDropTarget::get_drag_catalog(drag, library);
|
||||
if (drag_catalog->path.parent() == "") {
|
||||
*r_disabled_hint = TIP_("Catalog is already placed at the highest level");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string AssetCatalogTreeViewAllItem::DropTarget::drop_tooltip(const ui::DragInfo &drag) const
|
||||
{
|
||||
BLI_assert(drag.drag_data.type == WM_DRAG_ASSET_CATALOG);
|
||||
const AssetCatalog *drag_catalog = AssetCatalogDropTarget::get_drag_catalog(
|
||||
drag.drag_data, *get_view<AssetCatalogTreeView>().asset_library_);
|
||||
|
||||
return fmt::format(TIP_("Move catalog {} to the top level of the tree"),
|
||||
std::string_view(drag_catalog->path.name()));
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewAllItem::DropTarget::on_drop(bContext * /*C*/,
|
||||
const ui::DragInfo &drag) const
|
||||
{
|
||||
BLI_assert(drag.drag_data.type == WM_DRAG_ASSET_CATALOG);
|
||||
return AssetCatalogDropTarget::drop_asset_catalog_into_catalog(
|
||||
drag,
|
||||
get_view<AssetCatalogTreeView>(),
|
||||
/* No value to drop into the root level. */
|
||||
std::nullopt);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
std::unique_ptr<ui::TreeViewItemDropTarget> AssetCatalogTreeViewUnassignedItem::
|
||||
create_drop_target()
|
||||
{
|
||||
return std::make_unique<AssetCatalogTreeViewUnassignedItem::DropTarget>(
|
||||
static_cast<AssetCatalogTreeView &>(get_tree_view()));
|
||||
}
|
||||
|
||||
AssetCatalogTreeViewUnassignedItem::DropTarget::DropTarget(AssetCatalogTreeView &tree_view)
|
||||
: ui::TreeViewItemDropTarget(tree_view)
|
||||
{
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewUnassignedItem::DropTarget::can_drop(const wmDrag &drag,
|
||||
const char **r_disabled_hint) const
|
||||
{
|
||||
if (drag.type != WM_DRAG_ASSET_LIST) {
|
||||
return false;
|
||||
}
|
||||
return AssetCatalogDropTarget::has_droppable_asset(drag, r_disabled_hint);
|
||||
}
|
||||
|
||||
std::string AssetCatalogTreeViewUnassignedItem::DropTarget::drop_tooltip(
|
||||
const ui::DragInfo &drag) const
|
||||
{
|
||||
const ListBase *asset_drags = WM_drag_asset_list_get(&drag.drag_data);
|
||||
const bool is_multiple_assets = !BLI_listbase_is_single(asset_drags);
|
||||
|
||||
return is_multiple_assets ? TIP_("Move assets out of any catalog") :
|
||||
TIP_("Move asset out of any catalog");
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewUnassignedItem::DropTarget::on_drop(bContext *C,
|
||||
const ui::DragInfo &drag) const
|
||||
{
|
||||
/* Assign to nil catalog ID. */
|
||||
return AssetCatalogDropTarget::drop_assets_into_catalog(
|
||||
C, get_view<AssetCatalogTreeView>(), drag, CatalogID{});
|
||||
}
|
||||
|
||||
} // namespace blender::ed::asset_browser
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void asset_view_create_catalog_tree_view_in_layout(::AssetLibrary *asset_library,
|
||||
uiLayout *layout,
|
||||
PointerRNA *catalog_filter_owner_ptr,
|
||||
PropertyRNA *catalog_filter_prop,
|
||||
wmMsgBus *msg_bus)
|
||||
{
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
|
||||
UI_block_layout_set_current(block, layout);
|
||||
|
||||
ui::AbstractTreeView *tree_view = UI_block_add_view(
|
||||
*block,
|
||||
"asset catalog tree view",
|
||||
std::make_unique<ed::asset_browser::AssetCatalogTreeView>(
|
||||
asset_library, *catalog_filter_owner_ptr, *catalog_filter_prop, msg_bus));
|
||||
|
||||
ui::TreeViewBuilder::build_tree_view(*tree_view, *layout);
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_types.hh"
|
||||
|
||||
#include "ED_asset.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
|
||||
#include "WM_message.hh"
|
||||
|
||||
#include "asset_view.hh"
|
||||
|
||||
namespace blender::ed::asset_browser {
|
||||
|
||||
AssetGridView::AssetGridView(const AssetLibraryReference &asset_library_ref,
|
||||
const PointerRNA &active_asset_idx_owner_ptr,
|
||||
PropertyRNA *active_asset_idx_prop,
|
||||
wmMsgBus *msg_bus)
|
||||
: asset_library_ref_(asset_library_ref),
|
||||
active_asset_idx_owner_(active_asset_idx_owner_ptr),
|
||||
active_asset_idx_prop_(*active_asset_idx_prop),
|
||||
msg_bus_(*msg_bus)
|
||||
{
|
||||
}
|
||||
|
||||
void AssetGridView::build_items()
|
||||
{
|
||||
int idx = 0;
|
||||
ED_assetlist_iterate(asset_library_ref_, [this, &idx](AssetHandle &asset) {
|
||||
AssetGridViewItem &item = add_item<AssetGridViewItem>(asset);
|
||||
|
||||
item.set_is_active_fn([this, idx]() -> bool {
|
||||
return idx == RNA_property_int_get(&active_asset_idx_owner_, &active_asset_idx_prop_);
|
||||
});
|
||||
item.set_on_activate_fn([this, idx](bContext & /*C*/, ui::PreviewGridItem & /*item*/) {
|
||||
RNA_property_int_set(&active_asset_idx_owner_, &active_asset_idx_prop_, idx);
|
||||
WM_msg_publish_rna(&msg_bus_, &active_asset_idx_owner_, &active_asset_idx_prop_);
|
||||
});
|
||||
|
||||
idx++;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool AssetGridView::listen(const wmNotifier ¬ifier) const
|
||||
{
|
||||
return ED_assetlist_listen(&asset_library_ref_, ¬ifier);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AssetGridViewItem::AssetGridViewItem(AssetHandle &asset)
|
||||
: ui::PreviewGridItem(ED_asset_handle_get_identifier(&asset),
|
||||
ED_asset_handle_get_name(&asset)),
|
||||
/* Get a copy so the identifier is always available (the file data wrapped by the handle may
|
||||
* be freed). */
|
||||
asset_identifier_(identifier_)
|
||||
{
|
||||
preview_icon_id = ED_assetlist_asset_preview_or_type_icon_id_request(&asset);
|
||||
|
||||
/* Update reference so we don't point into the possibly freed file data. */
|
||||
identifier_ = asset_identifier_;
|
||||
|
||||
enable_selectable();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void asset_view_create_in_layout(const bContext &C,
|
||||
const AssetLibraryReference &asset_library_ref,
|
||||
const AssetCatalogFilterSettings &catalog_filter_settings,
|
||||
const PointerRNA &active_asset_idx_owner_ptr,
|
||||
PropertyRNA *active_asset_idx_prop,
|
||||
const View2D &v2d,
|
||||
uiLayout &layout)
|
||||
{
|
||||
uiBlock *block = uiLayoutGetBlock(&layout);
|
||||
UI_block_layout_set_current(block, &layout);
|
||||
|
||||
ED_assetlist_storage_fetch(&asset_library_ref, &C);
|
||||
ED_assetlist_catalog_filter_set(&asset_library_ref, &catalog_filter_settings);
|
||||
|
||||
ui::AbstractGridView *grid_view = UI_block_add_view(
|
||||
*block,
|
||||
"asset grid view",
|
||||
std::make_unique<AssetGridView>(asset_library_ref,
|
||||
active_asset_idx_owner_ptr,
|
||||
active_asset_idx_prop,
|
||||
CTX_wm_message_bus(&C)));
|
||||
|
||||
ui::GridViewBuilder builder(*block);
|
||||
builder.build_grid_view(*grid_view, v2d, layout);
|
||||
}
|
||||
|
||||
} // namespace blender::ed::asset_browser
|
|
@ -0,0 +1,59 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
|
||||
#include "UI_grid_view.hh"
|
||||
|
||||
struct AssetCatalogFilterSettings;
|
||||
struct bContext;
|
||||
struct PointerRNA;
|
||||
struct PropertyRNA;
|
||||
struct uiLayout;
|
||||
struct View2D;
|
||||
struct wmMsgBus;
|
||||
|
||||
namespace blender::ed::asset_browser {
|
||||
|
||||
class AssetGridView : public blender::ui::AbstractGridView {
|
||||
AssetLibraryReference asset_library_ref_;
|
||||
|
||||
/** Reference to bind the active asset of the editor to the view. */
|
||||
PointerRNA active_asset_idx_owner_;
|
||||
PropertyRNA &active_asset_idx_prop_;
|
||||
wmMsgBus &msg_bus_;
|
||||
|
||||
public:
|
||||
AssetGridView(const AssetLibraryReference &,
|
||||
const PointerRNA &active_asset_idx_owner_ptr,
|
||||
PropertyRNA *active_asset_idx_prop,
|
||||
wmMsgBus *msg_bus);
|
||||
|
||||
void build_items() override;
|
||||
bool listen(const wmNotifier &) const override;
|
||||
};
|
||||
|
||||
class AssetGridViewItem : public ui::PreviewGridItem {
|
||||
/* Can't store this here, since the wrapped FileDirEntry will be freed while progressively
|
||||
* loading items. */
|
||||
// AssetHandle &asset_;
|
||||
std::string asset_identifier_;
|
||||
|
||||
public:
|
||||
AssetGridViewItem(AssetHandle &);
|
||||
};
|
||||
|
||||
void asset_view_create_in_layout(const bContext &C,
|
||||
const AssetLibraryReference &asset_library_ref,
|
||||
const AssetCatalogFilterSettings &catalog_filter_settings,
|
||||
const PointerRNA &active_asset_idx_owner_ptr,
|
||||
PropertyRNA *active_asset_idx_prop,
|
||||
const View2D &v2d,
|
||||
uiLayout &layout);
|
||||
|
||||
} // namespace blender::ed::asset_browser
|
|
@ -0,0 +1,312 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "ED_asset.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "ED_space_api.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
#include "UI_view2d.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_message.hh"
|
||||
|
||||
#include "asset_browser_intern.hh"
|
||||
#include "asset_view.hh"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Asset Browser Space */
|
||||
|
||||
static SpaceLink *asset_browser_create(const ScrArea * /*area*/, const Scene * /*scene*/)
|
||||
{
|
||||
SpaceAssets *assets_space = MEM_cnew<SpaceAssets>("asset browser space");
|
||||
assets_space->spacetype = SPACE_ASSETS;
|
||||
|
||||
BKE_asset_library_reference_init_default(&assets_space->asset_library_ref);
|
||||
|
||||
{
|
||||
/* Header. */
|
||||
ARegion *region = MEM_cnew<ARegion>("asset browser header");
|
||||
BLI_addtail(&assets_space->regionbase, region);
|
||||
region->regiontype = RGN_TYPE_HEADER;
|
||||
region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
|
||||
}
|
||||
|
||||
{
|
||||
/* Navigation region */
|
||||
ARegion *region = MEM_cnew<ARegion>("asset browser navigation region");
|
||||
|
||||
BLI_addtail(&assets_space->regionbase, region);
|
||||
region->regiontype = RGN_TYPE_NAV_BAR;
|
||||
region->alignment = RGN_ALIGN_LEFT;
|
||||
}
|
||||
|
||||
{
|
||||
/* Sidebar region */
|
||||
ARegion *region = MEM_cnew<ARegion>("asset browser sidebar region");
|
||||
|
||||
BLI_addtail(&assets_space->regionbase, region);
|
||||
region->regiontype = RGN_TYPE_UI;
|
||||
region->alignment = RGN_ALIGN_RIGHT;
|
||||
region->flag = RGN_FLAG_HIDDEN;
|
||||
}
|
||||
|
||||
{
|
||||
/* Main region. */
|
||||
ARegion *region = MEM_cnew<ARegion>("asset browser main region");
|
||||
BLI_addtail(&assets_space->regionbase, region);
|
||||
region->regiontype = RGN_TYPE_WINDOW;
|
||||
|
||||
region->v2d.scroll = V2D_SCROLL_RIGHT;
|
||||
region->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
|
||||
region->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
|
||||
region->v2d.keeptot = V2D_KEEPTOT_STRICT;
|
||||
region->v2d.minzoom = region->v2d.maxzoom = 1.0f;
|
||||
}
|
||||
|
||||
return (SpaceLink *)assets_space;
|
||||
}
|
||||
|
||||
static void asset_browser_free(SpaceLink * /*sl*/) {}
|
||||
|
||||
static void asset_browser_init(wmWindowManager * /*wm*/, ScrArea * /*area*/) {}
|
||||
|
||||
static SpaceLink *asset_browser_duplicate(SpaceLink *sl)
|
||||
{
|
||||
const SpaceAssets *asset_browser_old = (SpaceAssets *)sl;
|
||||
SpaceAssets *asset_browser_new = reinterpret_cast<SpaceAssets *>(
|
||||
MEM_dupallocN(asset_browser_old));
|
||||
|
||||
return (SpaceLink *)asset_browser_new;
|
||||
}
|
||||
|
||||
static void asset_browser_keymap(wmKeyConfig *keyconf)
|
||||
{
|
||||
/* keys for all regions */
|
||||
WM_keymap_ensure(keyconf, "Asset Browser", SPACE_ASSETS, 0);
|
||||
}
|
||||
|
||||
const char *asset_browser_context_dir[] = {
|
||||
"asset_handle",
|
||||
"asset_library_reference",
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int /*eContextResult*/ asset_browser_context(const bContext *C,
|
||||
const char *member,
|
||||
bContextDataResult *result)
|
||||
{
|
||||
if (CTX_data_dir(member)) {
|
||||
CTX_data_dir_set(result, asset_browser_context_dir);
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
SpaceAssets *assets_space = CTX_wm_space_assets(C);
|
||||
|
||||
if (CTX_data_equals(member, "asset_library_reference")) {
|
||||
CTX_data_pointer_set(
|
||||
result, &screen->id, &RNA_AssetLibraryReference, &assets_space->asset_library_ref);
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
|
||||
if (CTX_data_equals(member, "asset_handle")) {
|
||||
AssetHandle *asset = ED_assetlist_asset_handle_get_by_index(&assets_space->asset_library_ref,
|
||||
assets_space->active_asset_idx);
|
||||
if (!asset) {
|
||||
return CTX_RESULT_NO_DATA;
|
||||
}
|
||||
|
||||
CTX_data_pointer_set(result, &screen->id, &RNA_AssetHandle, asset);
|
||||
return CTX_RESULT_OK;
|
||||
}
|
||||
|
||||
return CTX_RESULT_MEMBER_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Main Region */
|
||||
|
||||
static void asset_browser_main_region_init(wmWindowManager *wm, ARegion *region)
|
||||
{
|
||||
UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
|
||||
|
||||
{
|
||||
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Asset Browser", SPACE_ASSETS, 0);
|
||||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
}
|
||||
}
|
||||
|
||||
static void asset_browser_main_region_listener(const wmRegionListenerParams *params)
|
||||
{
|
||||
const wmNotifier *notifier = params->notifier;
|
||||
ARegion *region = params->region;
|
||||
|
||||
switch (notifier->category) {
|
||||
case NC_ASSET:
|
||||
if (ELEM(notifier->data, ND_SPACE_ASSET_PARAMS)) {
|
||||
ED_region_tag_redraw(region);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void asset_browser_main_region_message_subscribe(
|
||||
const wmRegionMessageSubscribeParams *params)
|
||||
{
|
||||
struct wmMsgBus *mbus = params->message_bus;
|
||||
bScreen *screen = params->screen;
|
||||
SpaceAssets *assets_space = reinterpret_cast<SpaceAssets *>(params->area->spacedata.first);
|
||||
|
||||
wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
|
||||
msg_sub_value_region_tag_redraw.owner = params->region;
|
||||
msg_sub_value_region_tag_redraw.user_data = params->region;
|
||||
msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
|
||||
|
||||
WM_msg_subscribe_rna_prop(mbus,
|
||||
&screen->id,
|
||||
assets_space,
|
||||
SpaceAssetBrowser,
|
||||
catalog_filter,
|
||||
&msg_sub_value_region_tag_redraw);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Header Region */
|
||||
|
||||
static void asset_browser_header_init(wmWindowManager * /*wm*/, ARegion *region)
|
||||
{
|
||||
ED_region_header_init(region);
|
||||
}
|
||||
|
||||
static void asset_browser_header_listener(const wmRegionListenerParams * /*params*/) {}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Navigation Region */
|
||||
|
||||
static void asset_browser_navigation_region_init(wmWindowManager *wm, ARegion *region)
|
||||
{
|
||||
region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
|
||||
ED_region_panels_init(wm, region);
|
||||
|
||||
{
|
||||
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Asset Browser", SPACE_ASSETS, 0);
|
||||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
}
|
||||
}
|
||||
|
||||
static void asset_browser_navigation_region_draw(const bContext *C, ARegion *region)
|
||||
{
|
||||
ED_region_panels(C, region);
|
||||
}
|
||||
|
||||
static void asset_browser_navigation_region_listener(
|
||||
const wmRegionListenerParams * /*listener_params*/)
|
||||
{
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Sidebar Region */
|
||||
|
||||
static void asset_browser_sidebar_region_init(wmWindowManager *wm, ARegion *region)
|
||||
{
|
||||
region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
|
||||
ED_region_panels_init(wm, region);
|
||||
|
||||
{
|
||||
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Asset Browser", SPACE_ASSETS, 0);
|
||||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
}
|
||||
}
|
||||
|
||||
static void asset_browser_sidebar_region_draw(const bContext *C, ARegion *region)
|
||||
{
|
||||
ED_region_panels(C, region);
|
||||
}
|
||||
|
||||
static void asset_browser_sidebar_region_listener(
|
||||
const wmRegionListenerParams * /*listener_params*/)
|
||||
{
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Asset Browser Space-Type */
|
||||
|
||||
void ED_spacetype_assets(void)
|
||||
{
|
||||
SpaceType *st = MEM_cnew<SpaceType>("spacetype asset browser");
|
||||
ARegionType *art;
|
||||
|
||||
st->spaceid = SPACE_ASSETS;
|
||||
strncpy(st->name, "Asset Browser", BKE_ST_MAXNAME);
|
||||
|
||||
st->create = asset_browser_create;
|
||||
st->free = asset_browser_free;
|
||||
st->init = asset_browser_init;
|
||||
st->duplicate = asset_browser_duplicate;
|
||||
st->operatortypes = asset_browser_operatortypes;
|
||||
st->keymap = asset_browser_keymap;
|
||||
st->context = asset_browser_context;
|
||||
|
||||
/* Main region. */
|
||||
art = MEM_cnew<ARegionType>("spacetype asset browser main region");
|
||||
art->regionid = RGN_TYPE_WINDOW;
|
||||
art->init = asset_browser_main_region_init;
|
||||
art->draw = asset_browser_main_region_draw;
|
||||
art->listener = asset_browser_main_region_listener;
|
||||
art->message_subscribe = asset_browser_main_region_message_subscribe;
|
||||
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
/* Header region. */
|
||||
art = MEM_cnew<ARegionType>("spacetype asset browser header region");
|
||||
art->regionid = RGN_TYPE_HEADER;
|
||||
art->prefsizey = HEADERY;
|
||||
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
|
||||
art->listener = asset_browser_header_listener;
|
||||
art->init = asset_browser_header_init;
|
||||
art->layout = ED_region_header_layout;
|
||||
art->draw = ED_region_header_draw;
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
/* Navigation region */
|
||||
art = MEM_cnew<ARegionType>("spacetype asset browser navigation region");
|
||||
art->regionid = RGN_TYPE_NAV_BAR;
|
||||
art->prefsizex = 240;
|
||||
art->init = asset_browser_navigation_region_init;
|
||||
art->draw = asset_browser_navigation_region_draw;
|
||||
art->listener = asset_browser_navigation_region_listener;
|
||||
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_NAVBAR;
|
||||
asset_browser_navigation_region_panels_register(art);
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
/* Sidebar region */
|
||||
art = MEM_cnew<ARegionType>("spacetype asset browser sidebar region");
|
||||
art->regionid = RGN_TYPE_UI;
|
||||
art->prefsizex = 240;
|
||||
art->init = asset_browser_sidebar_region_init;
|
||||
art->draw = asset_browser_sidebar_region_draw;
|
||||
art->listener = asset_browser_sidebar_region_listener;
|
||||
art->keymapflag = ED_KEYMAP_UI;
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
BKE_spacetype_register(st);
|
||||
}
|
|
@ -39,7 +39,7 @@
|
|||
using namespace blender;
|
||||
using namespace blender::asset_system;
|
||||
|
||||
namespace blender::ed::asset_browser {
|
||||
namespace blender::ed::space_file::asset_browser {
|
||||
|
||||
class AssetCatalogTreeViewAllItem;
|
||||
|
||||
|
@ -220,11 +220,11 @@ AssetCatalogTreeViewAllItem &AssetCatalogTreeView::add_all_item()
|
|||
|
||||
AssetCatalogTreeViewAllItem &item = add_tree_item<AssetCatalogTreeViewAllItem>(IFACE_("All"));
|
||||
item.set_on_activate_fn([params](bContext & /*C*/, ui::BasicTreeViewItem & /*item*/) {
|
||||
params->asset_catalog_visibility = FILE_SHOW_ASSETS_ALL_CATALOGS;
|
||||
params->asset_catalog_visibility = ASSET_CATALOG_SHOW_ALL_ASSETS;
|
||||
WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
|
||||
});
|
||||
item.set_is_active_fn(
|
||||
[params]() { return params->asset_catalog_visibility == FILE_SHOW_ASSETS_ALL_CATALOGS; });
|
||||
[params]() { return params->asset_catalog_visibility == ASSET_CATALOG_SHOW_ALL_ASSETS; });
|
||||
return item;
|
||||
}
|
||||
|
||||
|
@ -236,23 +236,24 @@ void AssetCatalogTreeView::add_unassigned_item()
|
|||
IFACE_("Unassigned"), ICON_FILE_HIDDEN);
|
||||
|
||||
item.set_on_activate_fn([params](bContext & /*C*/, ui::BasicTreeViewItem & /*item*/) {
|
||||
params->asset_catalog_visibility = FILE_SHOW_ASSETS_WITHOUT_CATALOG;
|
||||
params->asset_catalog_visibility = ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG;
|
||||
WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
|
||||
});
|
||||
item.set_is_active_fn(
|
||||
[params]() { return params->asset_catalog_visibility == FILE_SHOW_ASSETS_WITHOUT_CATALOG; });
|
||||
item.set_is_active_fn([params]() {
|
||||
return params->asset_catalog_visibility == ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG;
|
||||
});
|
||||
}
|
||||
|
||||
void AssetCatalogTreeView::activate_catalog_by_id(CatalogID catalog_id)
|
||||
{
|
||||
params_->asset_catalog_visibility = FILE_SHOW_ASSETS_FROM_CATALOG;
|
||||
params_->asset_catalog_visibility = ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG;
|
||||
params_->catalog_id = catalog_id;
|
||||
WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeView::is_active_catalog(CatalogID catalog_id) const
|
||||
{
|
||||
return (params_->asset_catalog_visibility == FILE_SHOW_ASSETS_FROM_CATALOG) &&
|
||||
return (params_->asset_catalog_visibility == ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG) &&
|
||||
(params_->catalog_id == catalog_id);
|
||||
}
|
||||
|
||||
|
@ -676,99 +677,11 @@ bool AssetCatalogTreeViewUnassignedItem::DropTarget::on_drop(bContext *C,
|
|||
C, get_view<AssetCatalogTreeView>(), drag.drag_data, CatalogID{});
|
||||
}
|
||||
|
||||
} // namespace blender::ed::asset_browser
|
||||
} // namespace blender::ed::space_file::asset_browser
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
namespace blender::ed::asset_browser {
|
||||
|
||||
class AssetCatalogFilterSettings {
|
||||
public:
|
||||
eFileSel_Params_AssetCatalogVisibility asset_catalog_visibility;
|
||||
bUUID asset_catalog_id;
|
||||
|
||||
std::unique_ptr<AssetCatalogFilter> catalog_filter;
|
||||
};
|
||||
|
||||
} // namespace blender::ed::asset_browser
|
||||
|
||||
using namespace blender::ed::asset_browser;
|
||||
|
||||
FileAssetCatalogFilterSettingsHandle *file_create_asset_catalog_filter_settings()
|
||||
{
|
||||
AssetCatalogFilterSettings *filter_settings = MEM_new<AssetCatalogFilterSettings>(__func__);
|
||||
return reinterpret_cast<FileAssetCatalogFilterSettingsHandle *>(filter_settings);
|
||||
}
|
||||
|
||||
void file_delete_asset_catalog_filter_settings(
|
||||
FileAssetCatalogFilterSettingsHandle **filter_settings_handle)
|
||||
{
|
||||
AssetCatalogFilterSettings **filter_settings = reinterpret_cast<AssetCatalogFilterSettings **>(
|
||||
filter_settings_handle);
|
||||
MEM_delete(*filter_settings);
|
||||
*filter_settings = nullptr;
|
||||
}
|
||||
|
||||
bool file_set_asset_catalog_filter_settings(
|
||||
FileAssetCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
eFileSel_Params_AssetCatalogVisibility catalog_visibility,
|
||||
::bUUID catalog_id)
|
||||
{
|
||||
AssetCatalogFilterSettings *filter_settings = reinterpret_cast<AssetCatalogFilterSettings *>(
|
||||
filter_settings_handle);
|
||||
bool needs_update = false;
|
||||
|
||||
if (filter_settings->asset_catalog_visibility != catalog_visibility) {
|
||||
filter_settings->asset_catalog_visibility = catalog_visibility;
|
||||
needs_update = true;
|
||||
}
|
||||
|
||||
if (filter_settings->asset_catalog_visibility == FILE_SHOW_ASSETS_FROM_CATALOG &&
|
||||
!BLI_uuid_equal(filter_settings->asset_catalog_id, catalog_id))
|
||||
{
|
||||
filter_settings->asset_catalog_id = catalog_id;
|
||||
needs_update = true;
|
||||
}
|
||||
|
||||
return needs_update;
|
||||
}
|
||||
|
||||
void file_ensure_updated_catalog_filter_data(
|
||||
FileAssetCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const asset_system::AssetLibrary *asset_library)
|
||||
{
|
||||
AssetCatalogFilterSettings *filter_settings = reinterpret_cast<AssetCatalogFilterSettings *>(
|
||||
filter_settings_handle);
|
||||
const AssetCatalogService *catalog_service = asset_library->catalog_service.get();
|
||||
|
||||
if (filter_settings->asset_catalog_visibility != FILE_SHOW_ASSETS_ALL_CATALOGS) {
|
||||
filter_settings->catalog_filter = std::make_unique<AssetCatalogFilter>(
|
||||
catalog_service->create_catalog_filter(filter_settings->asset_catalog_id));
|
||||
}
|
||||
}
|
||||
|
||||
bool file_is_asset_visible_in_catalog_filter_settings(
|
||||
const FileAssetCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const AssetMetaData *asset_data)
|
||||
{
|
||||
const AssetCatalogFilterSettings *filter_settings =
|
||||
reinterpret_cast<const AssetCatalogFilterSettings *>(filter_settings_handle);
|
||||
|
||||
switch (filter_settings->asset_catalog_visibility) {
|
||||
case FILE_SHOW_ASSETS_WITHOUT_CATALOG:
|
||||
return !filter_settings->catalog_filter->is_known(asset_data->catalog_id);
|
||||
case FILE_SHOW_ASSETS_FROM_CATALOG:
|
||||
return filter_settings->catalog_filter->contains(asset_data->catalog_id);
|
||||
case FILE_SHOW_ASSETS_ALL_CATALOGS:
|
||||
/* All asset files should be visible. */
|
||||
return true;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
namespace asset_browser = blender::ed::space_file::asset_browser;
|
||||
|
||||
void file_create_asset_catalog_tree_view_in_layout(::AssetLibrary *asset_library,
|
||||
uiLayout *layout,
|
||||
|
@ -782,8 +695,7 @@ void file_create_asset_catalog_tree_view_in_layout(::AssetLibrary *asset_library
|
|||
ui::AbstractTreeView *tree_view = UI_block_add_view(
|
||||
*block,
|
||||
"asset catalog tree view",
|
||||
std::make_unique<ed::asset_browser::AssetCatalogTreeView>(
|
||||
asset_library, params, *space_file));
|
||||
std::make_unique<asset_browser::AssetCatalogTreeView>(asset_library, params, *space_file));
|
||||
|
||||
ui::TreeViewBuilder::build_tree_view(*tree_view, *layout);
|
||||
}
|
||||
|
|
|
@ -223,32 +223,7 @@ void file_path_to_ui_path(const char *path, char *r_pathi, int max_size);
|
|||
|
||||
/* asset_catalog_tree_view.cc */
|
||||
|
||||
/* C-handle for #ed::asset_browser::AssetCatalogFilterSettings. */
|
||||
typedef struct FileAssetCatalogFilterSettingsHandle FileAssetCatalogFilterSettingsHandle;
|
||||
|
||||
void file_create_asset_catalog_tree_view_in_layout(::AssetLibrary *asset_library,
|
||||
uiLayout *layout,
|
||||
SpaceFile *space_file,
|
||||
FileAssetSelectParams *params);
|
||||
|
||||
namespace blender::asset_system {
|
||||
class AssetLibrary;
|
||||
}
|
||||
|
||||
FileAssetCatalogFilterSettingsHandle *file_create_asset_catalog_filter_settings();
|
||||
void file_delete_asset_catalog_filter_settings(
|
||||
FileAssetCatalogFilterSettingsHandle **filter_settings_handle);
|
||||
/**
|
||||
* \return True if the file list should update its filtered results
|
||||
* (e.g. because filtering parameters changed).
|
||||
*/
|
||||
bool file_set_asset_catalog_filter_settings(
|
||||
FileAssetCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
eFileSel_Params_AssetCatalogVisibility catalog_visibility,
|
||||
::bUUID catalog_id);
|
||||
void file_ensure_updated_catalog_filter_data(
|
||||
FileAssetCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const blender::asset_system::AssetLibrary *asset_library);
|
||||
bool file_is_asset_visible_in_catalog_filter_settings(
|
||||
const FileAssetCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const AssetMetaData *asset_data);
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
#include "DNA_asset_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "ED_asset_view_catalog_filter.h"
|
||||
#include "ED_datafiles.h"
|
||||
#include "ED_fileselect.hh"
|
||||
#include "ED_screen.hh"
|
||||
|
@ -199,7 +200,7 @@ struct FileListFilter {
|
|||
char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
|
||||
short flags;
|
||||
|
||||
FileAssetCatalogFilterSettingsHandle *asset_catalog_filter;
|
||||
AssetViewCatalogFilterSettingsHandle *asset_catalog_filter;
|
||||
};
|
||||
|
||||
/** #FileListFilter.flags */
|
||||
|
@ -814,7 +815,8 @@ static void prepare_filter_asset_library(const FileList *filelist, FileListFilte
|
|||
"prepare_filter_asset_library() should only be called when the file browser is "
|
||||
"in asset browser mode");
|
||||
|
||||
file_ensure_updated_catalog_filter_data(filter->asset_catalog_filter, filelist->asset_library);
|
||||
asset_view_ensure_updated_catalog_filter_data(
|
||||
filter->asset_catalog_filter, reinterpret_cast<::AssetLibrary *>(filelist->asset_library));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -844,8 +846,8 @@ static bool is_filtered_asset(FileListInternEntry *file, FileListFilter *filter)
|
|||
const AssetMetaData *asset_data = filelist_file_internal_get_asset_data(file);
|
||||
|
||||
/* Not used yet for the asset view template. */
|
||||
if (filter->asset_catalog_filter &&
|
||||
!file_is_asset_visible_in_catalog_filter_settings(filter->asset_catalog_filter, asset_data))
|
||||
if (filter->asset_catalog_filter && !asset_view_is_asset_visible_in_catalog_filter_settings(
|
||||
filter->asset_catalog_filter, asset_data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1033,17 +1035,16 @@ void filelist_setindexer(FileList *filelist, const FileIndexerType *indexer)
|
|||
filelist->indexer = indexer;
|
||||
}
|
||||
|
||||
void filelist_set_asset_catalog_filter_options(
|
||||
FileList *filelist,
|
||||
eFileSel_Params_AssetCatalogVisibility catalog_visibility,
|
||||
const ::bUUID *catalog_id)
|
||||
void filelist_set_asset_catalog_filter_options(FileList *filelist,
|
||||
AssetCatalogFilterMode catalog_visibility,
|
||||
const ::bUUID *catalog_id)
|
||||
{
|
||||
if (!filelist->filter_data.asset_catalog_filter) {
|
||||
/* There's no filter data yet. */
|
||||
filelist->filter_data.asset_catalog_filter = file_create_asset_catalog_filter_settings();
|
||||
filelist->filter_data.asset_catalog_filter = asset_view_create_catalog_filter_settings();
|
||||
}
|
||||
|
||||
const bool needs_update = file_set_asset_catalog_filter_settings(
|
||||
const bool needs_update = asset_view_set_catalog_filter_settings(
|
||||
filelist->filter_data.asset_catalog_filter, catalog_visibility, *catalog_id);
|
||||
|
||||
if (needs_update) {
|
||||
|
@ -1496,6 +1497,29 @@ static int filelist_intern_free_main_files(FileList *filelist)
|
|||
return removed_counter;
|
||||
}
|
||||
|
||||
int filelist_preview_source_get(int /* eFileSel_File_Types */ file_type)
|
||||
{
|
||||
if (file_type & FILE_TYPE_IMAGE) {
|
||||
return THB_SOURCE_IMAGE;
|
||||
}
|
||||
else if (file_type & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB)) {
|
||||
return THB_SOURCE_BLEND;
|
||||
}
|
||||
else if (file_type & FILE_TYPE_MOVIE) {
|
||||
return THB_SOURCE_MOVIE;
|
||||
}
|
||||
else if (file_type & FILE_TYPE_FTFONT) {
|
||||
return THB_SOURCE_FONT;
|
||||
}
|
||||
else if (file_type & FILE_TYPE_OBJECT_IO) {
|
||||
return THB_SOURCE_OBJECT_IO;
|
||||
}
|
||||
else {
|
||||
BLI_assert_unreachable();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdata)
|
||||
{
|
||||
FileListEntryCache *cache = static_cast<FileListEntryCache *>(BLI_task_pool_user_data(pool));
|
||||
|
@ -1503,33 +1527,11 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat
|
|||
taskdata);
|
||||
FileListEntryPreview *preview = preview_taskdata->preview;
|
||||
|
||||
/* XXX #THB_SOURCE_IMAGE for "historic" reasons. The case of an undefined source should be
|
||||
* handled better. */
|
||||
ThumbSource source = THB_SOURCE_IMAGE;
|
||||
ThumbSource source = static_cast<ThumbSource>(filelist_preview_source_get(preview->flags));
|
||||
|
||||
// printf("%s: Start (%d)...\n", __func__, threadid);
|
||||
|
||||
// printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
|
||||
BLI_assert(preview->flags &
|
||||
(FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT | FILE_TYPE_BLENDER |
|
||||
FILE_TYPE_OBJECT_IO | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB));
|
||||
|
||||
if (preview->flags & FILE_TYPE_IMAGE) {
|
||||
source = THB_SOURCE_IMAGE;
|
||||
}
|
||||
else if (preview->flags & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB))
|
||||
{
|
||||
source = THB_SOURCE_BLEND;
|
||||
}
|
||||
else if (preview->flags & FILE_TYPE_MOVIE) {
|
||||
source = THB_SOURCE_MOVIE;
|
||||
}
|
||||
else if (preview->flags & FILE_TYPE_FTFONT) {
|
||||
source = THB_SOURCE_FONT;
|
||||
}
|
||||
else if (preview->flags & FILE_TYPE_OBJECT_IO) {
|
||||
source = THB_SOURCE_OBJECT_IO;
|
||||
}
|
||||
|
||||
IMB_thumb_path_lock(preview->filepath);
|
||||
/* Always generate biggest preview size for now, it's simpler and avoids having to re-generate
|
||||
|
@ -1845,7 +1847,7 @@ static void filelist_clear_asset_library(FileList *filelist)
|
|||
{
|
||||
/* The AssetLibraryService owns the AssetLibrary pointer, so no need for us to free it. */
|
||||
filelist->asset_library = nullptr;
|
||||
file_delete_asset_catalog_filter_settings(&filelist->filter_data.asset_catalog_filter);
|
||||
asset_view_delete_catalog_filter_settings(&filelist->filter_data.asset_catalog_filter);
|
||||
}
|
||||
|
||||
void filelist_clear_ex(FileList *filelist,
|
||||
|
|
|
@ -56,12 +56,11 @@ void filelist_setfilter_options(FileList *filelist,
|
|||
void filelist_setindexer(FileList *filelist, const FileIndexerType *indexer);
|
||||
/**
|
||||
* \param catalog_id: The catalog that should be filtered by if \a catalog_visibility is
|
||||
* #FILE_SHOW_ASSETS_FROM_CATALOG. May be NULL otherwise.
|
||||
* #ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG. May be NULL otherwise.
|
||||
*/
|
||||
void filelist_set_asset_catalog_filter_options(
|
||||
FileList *filelist,
|
||||
eFileSel_Params_AssetCatalogVisibility catalog_visibility,
|
||||
const bUUID *catalog_id);
|
||||
void filelist_set_asset_catalog_filter_options(FileList *filelist,
|
||||
AssetCatalogFilterMode catalog_visibility,
|
||||
const bUUID *catalog_id);
|
||||
void filelist_tag_needs_filtering(FileList *filelist);
|
||||
void filelist_filter(FileList *filelist);
|
||||
/**
|
||||
|
@ -80,6 +79,7 @@ ImBuf *filelist_file_getimage(const FileDirEntry *file);
|
|||
ImBuf *filelist_geticon_image_ex(const FileDirEntry *file);
|
||||
ImBuf *filelist_geticon_image(FileList *filelist, int index);
|
||||
int filelist_geticon(FileList *filelist, int index, bool is_main);
|
||||
int /* ThumbSource */ filelist_preview_source_get(int /* eFileSel_File_Types */ file_type);
|
||||
|
||||
FileList *filelist_new(short type);
|
||||
void filelist_settype(FileList *filelist, short type);
|
||||
|
|
|
@ -500,7 +500,7 @@ void ED_fileselect_activate_asset_catalog(const SpaceFile *sfile, const bUUID ca
|
|||
}
|
||||
|
||||
FileAssetSelectParams *params = ED_fileselect_get_asset_params(sfile);
|
||||
params->asset_catalog_visibility = FILE_SHOW_ASSETS_FROM_CATALOG;
|
||||
params->asset_catalog_visibility = ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG;
|
||||
params->catalog_id = catalog_id;
|
||||
WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr);
|
||||
}
|
||||
|
|
|
@ -252,7 +252,7 @@ static void file_refresh(const bContext *C, ScrArea *area)
|
|||
if (asset_params) {
|
||||
filelist_set_asset_catalog_filter_options(
|
||||
sfile->files,
|
||||
eFileSel_Params_AssetCatalogVisibility(asset_params->asset_catalog_visibility),
|
||||
AssetCatalogFilterMode(asset_params->asset_catalog_visibility),
|
||||
&asset_params->catalog_id);
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,6 @@ static void gather_search_link_ops_for_asset_library(const bContext &C,
|
|||
filter_settings.id_types = FILTER_ID_NT;
|
||||
|
||||
ED_assetlist_storage_fetch(&library_ref, &C);
|
||||
ED_assetlist_ensure_previews_job(&library_ref, &C);
|
||||
ED_assetlist_iterate(library_ref, [&](asset_system::AssetRepresentation &asset) {
|
||||
if (!ED_asset_filter_matches_asset(&filter_settings, asset)) {
|
||||
return true;
|
||||
|
|
|
@ -602,6 +602,8 @@ enum {
|
|||
PRV_TAG_DEFFERED_RENDERING = (1 << 1),
|
||||
/** Deferred preview should be deleted asap. */
|
||||
PRV_TAG_DEFFERED_DELETE = (1 << 2),
|
||||
/** Attempted to load this preview from disk (deferred loading), but it couldn't be found. */
|
||||
PRV_TAG_LOADING_FAILED = (1 << 3),
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -206,6 +206,7 @@ typedef struct AssetWeakReference {
|
|||
#
|
||||
typedef struct AssetHandle {
|
||||
const struct FileDirEntry *file_data;
|
||||
struct PreviewImage *preview;
|
||||
} AssetHandle;
|
||||
|
||||
typedef enum eUserExtensionRepo_Flag {
|
||||
|
|
|
@ -840,10 +840,10 @@ typedef struct FileAssetSelectParams {
|
|||
FileSelectParams base_params;
|
||||
|
||||
AssetLibraryReference asset_library_ref;
|
||||
short asset_catalog_visibility; /* eFileSel_Params_AssetCatalogVisibility */
|
||||
short asset_catalog_visibility; /* AssetCatalogFilterMode */
|
||||
char _pad[6];
|
||||
/** If #asset_catalog_visibility is #FILE_SHOW_ASSETS_FROM_CATALOG, this sets the ID of the
|
||||
* catalog to show. */
|
||||
/** If #asset_catalog_visibility is #ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG, this sets the ID of
|
||||
* the catalog to show. */
|
||||
bUUID catalog_id;
|
||||
|
||||
short import_type; /* eFileAssetImportType */
|
||||
|
@ -1050,12 +1050,6 @@ typedef enum eFileSel_Params_Flag {
|
|||
} eFileSel_Params_Flag;
|
||||
ENUM_OPERATORS(eFileSel_Params_Flag, FILE_FILTER_ASSET_CATALOG);
|
||||
|
||||
typedef enum eFileSel_Params_AssetCatalogVisibility {
|
||||
FILE_SHOW_ASSETS_ALL_CATALOGS,
|
||||
FILE_SHOW_ASSETS_FROM_CATALOG,
|
||||
FILE_SHOW_ASSETS_WITHOUT_CATALOG,
|
||||
} eFileSel_Params_AssetCatalogVisibility;
|
||||
|
||||
/**
|
||||
* #FileSelectParams.rename_flag / `sfile->params->rename_flag`.
|
||||
* \note short flag. Defined as bit-flags, but currently only used as exclusive status markers.
|
||||
|
@ -2066,6 +2060,42 @@ typedef enum eSpreadsheetColumnValueType {
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Asset Browser
|
||||
* \{ */
|
||||
|
||||
typedef enum AssetCatalogFilterMode {
|
||||
ASSET_CATALOG_SHOW_ALL_ASSETS,
|
||||
ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG,
|
||||
ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG,
|
||||
} AssetCatalogFilterMode;
|
||||
|
||||
typedef struct AssetCatalogFilterSettings {
|
||||
short filter_mode; /* AssetCatalogFilterMode */
|
||||
char _pad[6];
|
||||
/** If #visibility_mode is #ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG, this sets the ID of the
|
||||
* catalog to show. */
|
||||
bUUID active_catalog_id;
|
||||
} AssetCatalogFilterSettings;
|
||||
|
||||
typedef struct SpaceAssets {
|
||||
SpaceLink *next, *prev;
|
||||
/** Storage of regions for inactive spaces. */
|
||||
ListBase regionbase;
|
||||
char spacetype;
|
||||
char link_flag;
|
||||
char _pad0[6];
|
||||
/* End 'SpaceLink' header. */
|
||||
|
||||
AssetLibraryReference asset_library_ref;
|
||||
AssetCatalogFilterSettings catalog_filter;
|
||||
/** For now store active asset as index. In future, this could store an #AssetIdentifier. */
|
||||
int active_asset_idx;
|
||||
char _pad1[4];
|
||||
} SpaceAssets;
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Space Defines (eSpace_Type)
|
||||
* \{ */
|
||||
|
@ -2105,9 +2135,10 @@ typedef enum eSpace_Type {
|
|||
SPACE_CLIP = 20,
|
||||
SPACE_TOPBAR = 21,
|
||||
SPACE_STATUSBAR = 22,
|
||||
SPACE_SPREADSHEET = 23
|
||||
SPACE_SPREADSHEET = 23,
|
||||
SPACE_ASSETS = 24
|
||||
|
||||
#define SPACE_TYPE_NUM (SPACE_SPREADSHEET + 1)
|
||||
#define SPACE_TYPE_NUM (SPACE_ASSETS + 1)
|
||||
} eSpace_Type;
|
||||
|
||||
/* use for function args */
|
||||
|
|
|
@ -515,6 +515,7 @@ typedef struct bTheme {
|
|||
ThemeSpace space_topbar;
|
||||
ThemeSpace space_statusbar;
|
||||
ThemeSpace space_spreadsheet;
|
||||
ThemeSpace space_assets;
|
||||
|
||||
/* 20 sets of bone colors for this theme */
|
||||
ThemeWireColor tarm[20];
|
||||
|
@ -532,7 +533,7 @@ typedef struct bTheme {
|
|||
#define UI_THEMESPACE_START(btheme) \
|
||||
(CHECK_TYPE_INLINE(btheme, bTheme *), &((btheme)->space_properties))
|
||||
#define UI_THEMESPACE_END(btheme) \
|
||||
(CHECK_TYPE_INLINE(btheme, bTheme *), (&((btheme)->space_spreadsheet) + 1))
|
||||
(CHECK_TYPE_INLINE(btheme, bTheme *), (&((btheme)->space_assets) + 1))
|
||||
|
||||
typedef struct bAddon {
|
||||
struct bAddon *next, *prev;
|
||||
|
|
|
@ -88,13 +88,17 @@ static int rna_AssetTag_editable(PointerRNA *ptr, const char **r_info)
|
|||
{
|
||||
AssetTag *asset_tag = static_cast<AssetTag *>(ptr->data);
|
||||
ID *owner_id = ptr->owner_id;
|
||||
if (owner_id && owner_id->asset_data) {
|
||||
if (!owner_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (owner_id->asset_data) {
|
||||
BLI_assert_msg(BLI_findindex(&owner_id->asset_data->tags, asset_tag) != -1,
|
||||
"The owner of the asset tag pointer is not the asset ID containing the tag");
|
||||
UNUSED_VARS_NDEBUG(asset_tag);
|
||||
}
|
||||
|
||||
return rna_AssetMetaData_editable_from_owner_id(ptr->owner_id, owner_id->asset_data, r_info) ?
|
||||
return rna_AssetMetaData_editable_from_owner_id(owner_id, owner_id->asset_data, r_info) ?
|
||||
PROP_EDITABLE :
|
||||
PropertyFlag(0);
|
||||
}
|
||||
|
@ -425,6 +429,12 @@ static int rna_AssetRepresentation_full_library_path_length(PointerRNA *ptr)
|
|||
return full_library_path.size();
|
||||
}
|
||||
|
||||
static int rna_AssetHandle_preview_icon_id_get(PointerRNA *ptr)
|
||||
{
|
||||
AssetHandle *asset = static_cast<AssetHandle *>(ptr->data);
|
||||
return ED_assetlist_asset_preview_or_type_icon_id_request(asset);
|
||||
}
|
||||
|
||||
const EnumPropertyItem *rna_asset_library_reference_itemf(bContext * /*C*/,
|
||||
PointerRNA * /*ptr*/,
|
||||
PropertyRNA * /*prop*/,
|
||||
|
@ -598,6 +608,19 @@ static void rna_def_asset_handle(BlenderRNA *brna)
|
|||
prop, "rna_AssetHandle_file_data_get", "rna_AssetHandle_file_data_set", nullptr, nullptr);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "File Entry", "TEMPORARY, DO NOT USE - File data used to refer to the asset");
|
||||
|
||||
prop = RNA_def_int(
|
||||
srna,
|
||||
"preview_icon_id",
|
||||
0,
|
||||
INT_MIN,
|
||||
INT_MAX,
|
||||
"Icon ID",
|
||||
"Unique integer identifying the preview of this asset as an icon (zero means invalid)",
|
||||
INT_MIN,
|
||||
INT_MAX);
|
||||
RNA_def_property_int_funcs(prop, "rna_AssetHandle_preview_icon_id_get", NULL, NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
}
|
||||
|
||||
static void rna_def_asset_representation(BlenderRNA *brna)
|
||||
|
|
|
@ -131,6 +131,13 @@ static PointerRNA rna_Context_asset_get(PointerRNA *ptr)
|
|||
return RNA_pointer_create(nullptr, &RNA_AssetRepresentation, CTX_wm_asset(C));
|
||||
}
|
||||
|
||||
static PointerRNA rna_Context_asset_handle_get(PointerRNA *ptr)
|
||||
{
|
||||
bContext *C = (bContext *)ptr->data;
|
||||
PointerRNA newptr = RNA_pointer_create(NULL, &RNA_AssetHandle, CTX_wm_asset_handle_ptr(C));
|
||||
return newptr;
|
||||
}
|
||||
|
||||
static PointerRNA rna_Context_main_get(PointerRNA *ptr)
|
||||
{
|
||||
bContext *C = (bContext *)ptr->data;
|
||||
|
@ -286,6 +293,11 @@ void RNA_def_context(BlenderRNA *brna)
|
|||
RNA_def_property_struct_type(prop, "AssetRepresentation");
|
||||
RNA_def_property_pointer_funcs(prop, "rna_Context_asset_get", nullptr, nullptr, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "asset_handle", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_struct_type(prop, "AssetHandle");
|
||||
RNA_def_property_pointer_funcs(prop, "rna_Context_asset_handle_get", nullptr, nullptr, nullptr);
|
||||
|
||||
/* Data */
|
||||
prop = RNA_def_property(srna, "blend_data", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
|
|
@ -169,6 +169,11 @@ const EnumPropertyItem rna_enum_space_type_items[] = {
|
|||
ICON_PROPERTIES,
|
||||
"Properties",
|
||||
"Edit properties of active object and related data-blocks"},
|
||||
{SPACE_ASSETS,
|
||||
"ASSET_BROWSER",
|
||||
ICON_ASSET_MANAGER,
|
||||
"Asset Browser",
|
||||
"Browse in asset libraries"},
|
||||
{SPACE_FILE, "FILE_BROWSER", ICON_FILEBROWSER, "File Browser", "Browse for files and assets"},
|
||||
{SPACE_SPREADSHEET,
|
||||
"SPREADSHEET",
|
||||
|
@ -618,6 +623,8 @@ static StructRNA *rna_Space_refine(PointerRNA *ptr)
|
|||
return &RNA_SpaceClipEditor;
|
||||
case SPACE_SPREADSHEET:
|
||||
return &RNA_SpaceSpreadsheet;
|
||||
case SPACE_ASSETS:
|
||||
return &RNA_SpaceAssetBrowser;
|
||||
|
||||
/* Currently no type info. */
|
||||
case SPACE_SCRIPT:
|
||||
|
@ -873,6 +880,20 @@ static void rna_Space_show_region_asset_shelf_update(bContext *C, PointerRNA *pt
|
|||
rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_ASSET_SHELF, RGN_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
/* Navigation Region. */
|
||||
static bool rna_Space_show_region_nav_bar_get(PointerRNA *ptr)
|
||||
{
|
||||
return !rna_Space_bool_from_region_flag_get_by_type(ptr, RGN_TYPE_NAV_BAR, RGN_FLAG_HIDDEN);
|
||||
}
|
||||
static void rna_Space_show_region_nav_bar_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
rna_Space_bool_from_region_flag_set_by_type(ptr, RGN_TYPE_NAV_BAR, RGN_FLAG_HIDDEN, !value);
|
||||
}
|
||||
static void rna_Space_show_region_nav_bar_update(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_NAV_BAR, RGN_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
static bool rna_Space_view2d_sync_get(PointerRNA *ptr)
|
||||
|
@ -3325,7 +3346,7 @@ static void rna_FileAssetSelectParams_catalog_id_set(PointerRNA *ptr, const char
|
|||
|
||||
if (value[0] == '\0') {
|
||||
params->catalog_id = BLI_uuid_nil();
|
||||
params->asset_catalog_visibility = FILE_SHOW_ASSETS_ALL_CATALOGS;
|
||||
params->asset_catalog_visibility = ASSET_CATALOG_SHOW_ALL_ASSETS;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3336,7 +3357,31 @@ static void rna_FileAssetSelectParams_catalog_id_set(PointerRNA *ptr, const char
|
|||
}
|
||||
|
||||
params->catalog_id = new_uuid;
|
||||
params->asset_catalog_visibility = FILE_SHOW_ASSETS_FROM_CATALOG;
|
||||
params->asset_catalog_visibility = ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG;
|
||||
}
|
||||
|
||||
static int RNA_SpaceAssetBrowser_asset_library_get(PointerRNA *ptr)
|
||||
{
|
||||
SpaceAssets *asset_space = static_cast<SpaceAssets *>(ptr->data);
|
||||
return ED_asset_library_reference_to_enum_value(&asset_space->asset_library_ref);
|
||||
}
|
||||
|
||||
static void RNA_SpaceAssetBrowser_asset_library_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
SpaceAssets *asset_space = static_cast<SpaceAssets *>(ptr->data);
|
||||
asset_space->asset_library_ref = ED_asset_library_reference_from_enum_value(value);
|
||||
}
|
||||
|
||||
static void rna_AssetCatalogFilterSettings_active_catalog_id_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
const AssetCatalogFilterSettings *settings = static_cast<AssetCatalogFilterSettings *>(
|
||||
ptr->data);
|
||||
BLI_uuid_format(value, settings->active_catalog_id);
|
||||
}
|
||||
|
||||
static int rna_AssetCatalogFilterSettings_active_catalog_id_length(PointerRNA * /*ptr*/)
|
||||
{
|
||||
return UUID_STRING_SIZE - 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -3440,6 +3485,10 @@ static void rna_def_space_generic_show_region_toggles(StructRNA *srna, int regio
|
|||
region_type_mask &= ~((1 << RGN_TYPE_ASSET_SHELF) | (1 << RGN_TYPE_ASSET_SHELF_HEADER));
|
||||
DEF_SHOW_REGION_PROPERTY(show_region_asset_shelf, "Asset Shelf", "");
|
||||
}
|
||||
if (region_type_mask & (1 << RGN_TYPE_NAV_BAR)) {
|
||||
region_type_mask &= ~(1 << RGN_TYPE_NAV_BAR);
|
||||
DEF_SHOW_REGION_PROPERTY(show_region_nav_bar, "Navigation Bar", "");
|
||||
}
|
||||
BLI_assert(region_type_mask == 0);
|
||||
}
|
||||
|
||||
|
@ -8222,6 +8271,83 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
|
|||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, nullptr);
|
||||
}
|
||||
|
||||
static void rna_def_asset_catalog_filter_settings(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem asset_catalog_filter_mode[] = {
|
||||
{ASSET_CATALOG_SHOW_ALL_ASSETS,
|
||||
"SHOW_ALL_ASSETS",
|
||||
ICON_NONE,
|
||||
"All Assets",
|
||||
"Show all assets, regardless of catalogs"},
|
||||
{ASSET_CATALOG_SHOW_ASSETS_FROM_CATALOG,
|
||||
"SHOW_ASSETS_FROM_CATALOG",
|
||||
ICON_NONE,
|
||||
"From Catalog",
|
||||
"Show assets assigned to a specific catalog"},
|
||||
{ASSET_CATALOG_SHOW_ASSETS_WITHOUT_CATALOG,
|
||||
"SHOW_ASSETS_WITHOUT_CATALOG",
|
||||
ICON_NONE,
|
||||
"Assets Without Catalog",
|
||||
"Show any asset that doesn't have a recognized asset catalog assigned to it"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "AssetCatalogFilterSettings", NULL);
|
||||
RNA_def_struct_ui_text(
|
||||
srna,
|
||||
"Asset Catalog Filter Settings",
|
||||
"Options to determine how catalogs should affect which assets are visible");
|
||||
|
||||
prop = RNA_def_property(srna, "filter_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, asset_catalog_filter_mode);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Asset Catalog Filter Mode",
|
||||
"Determine how filtering based on asset catalogs should be done");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "active_catalog_id", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_funcs(prop,
|
||||
"rna_AssetCatalogFilterSettings_active_catalog_id_get",
|
||||
"rna_AssetCatalogFilterSettings_active_catalog_id_length",
|
||||
NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Catalog UUID", "The UUID of the catalog to show assets from");
|
||||
}
|
||||
|
||||
static void rna_def_space_assets(BlenderRNA *brna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
StructRNA *srna;
|
||||
|
||||
rna_def_asset_catalog_filter_settings(brna);
|
||||
|
||||
srna = RNA_def_struct(brna, "SpaceAssetBrowser", "Space");
|
||||
RNA_def_struct_sdna(srna, "SpaceAssets");
|
||||
RNA_def_struct_ui_text(srna, "Space Asset Browser", "Asset browser space data");
|
||||
|
||||
rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_NAV_BAR) | (1 << RGN_TYPE_UI));
|
||||
|
||||
prop = rna_def_asset_library_reference_common(
|
||||
srna, "RNA_SpaceAssetBrowser_asset_library_get", "RNA_SpaceAssetBrowser_asset_library_set");
|
||||
RNA_def_property_ui_text(prop, "Asset Library", "");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "catalog_filter", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_struct_type(prop, "AssetCatalogFilterSettings");
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Asset Catalog Filter",
|
||||
"Parameters to set up rules for filtering assets based on the catalogs "
|
||||
"they are assigned to");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "active_asset_idx", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL);
|
||||
}
|
||||
|
||||
void RNA_def_space(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_space(brna);
|
||||
|
@ -8250,6 +8376,7 @@ void RNA_def_space(BlenderRNA *brna)
|
|||
rna_def_space_node(brna);
|
||||
rna_def_space_clip(brna);
|
||||
rna_def_space_spreadsheet(brna);
|
||||
rna_def_space_assets(brna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2710,6 +2710,26 @@ static void rna_def_userdef_theme_space_file(BlenderRNA *brna)
|
|||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
}
|
||||
|
||||
static void rna_def_userdef_theme_space_assets(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* space_file */
|
||||
|
||||
srna = RNA_def_struct(brna, "ThemeAssetBrowser", NULL);
|
||||
RNA_def_struct_sdna(srna, "ThemeSpace");
|
||||
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
|
||||
RNA_def_struct_ui_text(srna, "Theme Asset Browser", "Theme settings for the Asset Browser");
|
||||
|
||||
rna_def_userdef_theme_spaces_main(srna);
|
||||
|
||||
prop = RNA_def_property(srna, "row_alternate", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_array(prop, 4);
|
||||
RNA_def_property_ui_text(prop, "Alternate Rows", "Overlay color on every other row");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
}
|
||||
|
||||
static void rna_def_userdef_theme_space_outliner(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
@ -4134,6 +4154,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
|
|||
{1, "VIEW_3D", ICON_VIEW3D, "3D Viewport", ""},
|
||||
{4, "DOPESHEET_EDITOR", ICON_ACTION, "Dope Sheet/Timeline", ""},
|
||||
{16, "FILE_BROWSER", ICON_FILEBROWSER, "File/Asset Browser", ""},
|
||||
{24, "ASSET_BROWSER", ICON_ASSET_MANAGER, "Asset Browser", ""},
|
||||
{3, "GRAPH_EDITOR", ICON_GRAPH, "Graph Editor/Drivers", ""},
|
||||
{6, "IMAGE_EDITOR", ICON_IMAGE, "Image/UV Editor", ""},
|
||||
{15, "INFO", ICON_INFO, "Info", ""},
|
||||
|
@ -4284,6 +4305,13 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
|
|||
RNA_def_property_pointer_sdna(prop, nullptr, "space_spreadsheet");
|
||||
RNA_def_property_struct_type(prop, "ThemeSpreadsheet");
|
||||
RNA_def_property_ui_text(prop, "Spreadsheet", "");
|
||||
|
||||
prop = RNA_def_property(srna, "asset_browser", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "space_assets");
|
||||
RNA_def_property_struct_type(prop, "ThemeAssetBrowser");
|
||||
RNA_def_property_ui_text(prop, "Asset Browser", "");
|
||||
|
||||
/* end space types */
|
||||
|
||||
prop = RNA_def_property(srna, "bone_color_sets", PROP_COLLECTION, PROP_NONE);
|
||||
|
@ -4536,6 +4564,7 @@ static void rna_def_userdef_dothemes(BlenderRNA *brna)
|
|||
rna_def_userdef_theme_space_view3d(brna);
|
||||
rna_def_userdef_theme_space_graph(brna);
|
||||
rna_def_userdef_theme_space_file(brna);
|
||||
rna_def_userdef_theme_space_assets(brna);
|
||||
rna_def_userdef_theme_space_nla(brna);
|
||||
rna_def_userdef_theme_space_action(brna);
|
||||
rna_def_userdef_theme_space_image(brna);
|
||||
|
|
|
@ -499,10 +499,9 @@ struct wmNotifier {
|
|||
#define ND_REGIONS_ASSET_SHELF (23 << 16)
|
||||
|
||||
/* NC_ASSET */
|
||||
/* Denotes that the AssetList is done reading some previews. NOT that the preview generation of
|
||||
* assets is done. */
|
||||
/* Denote that something in the contents of an AssetList may have changed. Triggers re-filtering of
|
||||
* items. */
|
||||
#define ND_ASSET_LIST (1 << 16)
|
||||
#define ND_ASSET_LIST_PREVIEW (2 << 16)
|
||||
#define ND_ASSET_LIST_READING (3 << 16)
|
||||
/* Catalog data changed, requiring a redraw of catalog UIs. Note that this doesn't denote a
|
||||
* reloading of asset libraries & their catalogs should happen. That only happens on explicit user
|
||||
|
|
|
@ -648,6 +648,10 @@ static void wm_file_read_pre(bool use_data, bool /*use_userdef*/)
|
|||
UI_view2d_zoom_cache_reset();
|
||||
|
||||
ED_preview_restart_queue_free();
|
||||
/* #AssetLibraryService and the contained #AssetLibrary instances are destroyed on file loading.
|
||||
* Asset lists may still reference them, so clear the asset list storage entirely for now. Later
|
||||
* on, asset lists should actually live in the library, so this can be solved differently. */
|
||||
ED_assetlist_storage_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -427,6 +427,10 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
|
|||
else if (STRPREFIX(opname, "FILE_OT")) {
|
||||
km = WM_keymap_find_all(wm, "File Browser", sl->spacetype, RGN_TYPE_WINDOW);
|
||||
}
|
||||
/* Asset browser */
|
||||
else if (STRPREFIX(opname, "ASSET_OT")) {
|
||||
km = WM_keymap_find_all(wm, "Asset Browser", sl->spacetype, 0);
|
||||
}
|
||||
/* Logic Editor */
|
||||
else if (STRPREFIX(opname, "LOGIC_OT")) {
|
||||
km = WM_keymap_find_all(wm, "Logic Editor", sl->spacetype, RGN_TYPE_WINDOW);
|
||||
|
|
Loading…
Reference in New Issue