Compare commits
61 Commits
temp-chunk
...
file-brows
Author | SHA1 | Date | |
---|---|---|---|
3a97c4056f | |||
9dbcefb10e | |||
85f0b2ef5d | |||
bffc1fbf31 | |||
6bae10ef45 | |||
0f8e58e7b8 | |||
6fc388743d | |||
66204860ca | |||
e1ced645fa | |||
5162632a20 | |||
3f7015a79f | |||
560c20e067 | |||
63cc972402 | |||
c8c8783088 | |||
1049b0c818 | |||
46934eaf25 | |||
c67a650718 | |||
065bc42ce5 | |||
063689b8a8 | |||
eaa58a1607 | |||
72e67691ed | |||
e1a8a15945 | |||
e91e4bf8e5 | |||
9ae2259db5 | |||
9bac0894f6 | |||
731c1be92a | |||
3d31ad823a | |||
fdc5301205 | |||
2ce7f02a06 | |||
91853d95a9 | |||
eafd98c920 | |||
39eab45c8e | |||
ef58467594 | |||
8f48dd8f72 | |||
d46357dd25 | |||
696295f849 | |||
c9c332f422 | |||
18f8749fb7 | |||
947c73578c | |||
f41368cf02 | |||
f29fa9895f | |||
ff213c802c | |||
5fcf6822dd | |||
9530fb60ad | |||
86ea1ad5df | |||
2011d1f6d0 | |||
f17ea3da02 | |||
400d7235c3 | |||
29fdd43605 | |||
eab2a8479a | |||
ee013f44b5 | |||
f20814892a | |||
39e3580065 | |||
d2c4918d77 | |||
11d0c91ba5 | |||
925b82efb0 | |||
3df2e4e888 | |||
a54bd5fe19 | |||
4b43bd820e | |||
b8b7b0af70 | |||
b3597b1128 |
@@ -1082,6 +1082,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),
|
||||
|
@@ -1363,6 +1363,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"
|
||||
|
@@ -2187,7 +2187,6 @@ def km_info(params):
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (File Browser)
|
||||
|
||||
@@ -2344,6 +2343,28 @@ 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(
|
||||
sidebar_key={"type": 'N', "value": 'PRESS'},
|
||||
),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Editor (Dope Sheet)
|
||||
|
||||
@@ -7962,6 +7983,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),
|
||||
|
@@ -4155,6 +4155,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),
|
||||
|
@@ -57,6 +57,7 @@ _modules = [
|
||||
"space_toolsystem_common",
|
||||
"space_toolsystem_toolbar",
|
||||
|
||||
"space_assets",
|
||||
"space_clip",
|
||||
"space_console",
|
||||
"space_dopesheet",
|
||||
|
211
release/scripts/startup/bl_ui/space_assets.py
Normal file
211
release/scripts/startup/bl_ui/space_assets.py
Normal file
@@ -0,0 +1,211 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
import bpy
|
||||
from bpy.types import Header, Menu, Panel, UIList
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
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")
|
||||
|
||||
|
||||
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'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
wm = context.window_manager
|
||||
asset_handle = context.asset_handle
|
||||
asset_file = asset_handle.file_data
|
||||
|
||||
if asset_handle is None:
|
||||
layout.label(text="No active asset", icon='INFO')
|
||||
return
|
||||
|
||||
asset_library_ref = context.asset_library_ref
|
||||
asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file, asset_library_ref)
|
||||
|
||||
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')
|
||||
|
||||
layout.prop(asset_file.asset_data, "description")
|
||||
layout.prop(asset_file.asset_data, "author")
|
||||
|
||||
|
||||
class ASSETBROWSER_PT_metadata_preview(Panel):
|
||||
bl_space_type = 'ASSET_BROWSER'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "Preview"
|
||||
bl_category = 'Metadata'
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
asset_handle = context.asset_handle
|
||||
asset_file = asset_handle.file_data
|
||||
|
||||
row = layout.row()
|
||||
box = row.box()
|
||||
box.template_icon(icon_value=asset_file.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(Panel):
|
||||
bl_space_type = 'ASSET_BROWSER'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "Tags"
|
||||
bl_category = 'Metadata'
|
||||
|
||||
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)
|
@@ -62,7 +62,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:
|
||||
@@ -620,19 +620,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_edit")
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_view(AssetBrowserMenu, Menu):
|
||||
class ASSETBROWSEROLD_MT_view(AssetBrowserMenu, Menu):
|
||||
bl_label = "View"
|
||||
|
||||
def draw(self, context):
|
||||
@@ -653,7 +653,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):
|
||||
@@ -668,7 +668,7 @@ class ASSETBROWSER_MT_select(AssetBrowserMenu, Menu):
|
||||
layout.operator("file.select_box")
|
||||
|
||||
|
||||
class ASSETBROWSER_MT_edit(AssetBrowserMenu, Menu):
|
||||
class ASSETBROWSEROLD_MT_edit(AssetBrowserMenu, Menu):
|
||||
bl_label = "Edit"
|
||||
|
||||
def draw(self, _context):
|
||||
@@ -678,7 +678,7 @@ class ASSETBROWSER_MT_edit(AssetBrowserMenu, Menu):
|
||||
layout.operator("asset.catalog_redo", text="Redo")
|
||||
|
||||
|
||||
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'}
|
||||
@@ -726,7 +726,7 @@ class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
|
||||
layout.prop(asset_file_handle.asset_data, "author")
|
||||
|
||||
|
||||
class ASSETBROWSER_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel):
|
||||
class ASSETBROWSEROLD_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel):
|
||||
bl_label = "Preview"
|
||||
|
||||
def draw(self, context):
|
||||
@@ -741,10 +741,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):
|
||||
@@ -752,7 +752,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.AssetMetaDataPanel, Panel):
|
||||
bl_label = "Tags"
|
||||
|
||||
def draw(self, context):
|
||||
@@ -760,7 +760,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)
|
||||
@@ -768,7 +768,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
|
||||
|
||||
@@ -825,15 +825,15 @@ classes = (
|
||||
FILEBROWSER_MT_context_menu,
|
||||
ASSETBROWSER_PT_display,
|
||||
ASSETBROWSER_PT_filter,
|
||||
ASSETBROWSER_MT_editor_menus,
|
||||
ASSETBROWSER_MT_view,
|
||||
ASSETBROWSER_MT_select,
|
||||
ASSETBROWSER_MT_edit,
|
||||
ASSETBROWSER_MT_metadata_preview_menu,
|
||||
ASSETBROWSER_PT_metadata,
|
||||
ASSETBROWSER_PT_metadata_preview,
|
||||
ASSETBROWSER_PT_metadata_tags,
|
||||
ASSETBROWSER_UL_metadata_tags,
|
||||
ASSETBROWSEROLD_MT_editor_menus,
|
||||
ASSETBROWSEROLD_MT_view,
|
||||
ASSETBROWSEROLD_MT_select,
|
||||
ASSETBROWSEROLD_MT_edit,
|
||||
ASSETBROWSEROLD_MT_metadata_preview_menu,
|
||||
ASSETBROWSEROLD_PT_metadata,
|
||||
ASSETBROWSEROLD_PT_metadata_preview,
|
||||
ASSETBROWSEROLD_PT_metadata_tags,
|
||||
ASSETBROWSEROLD_UL_metadata_tags,
|
||||
ASSETBROWSER_MT_context_menu,
|
||||
)
|
||||
|
||||
|
@@ -1190,8 +1190,7 @@ class ThemeGenericClassGenerator:
|
||||
("Scroll Bar", "wcol_scroll"),
|
||||
("Progress Bar", "wcol_progress"),
|
||||
("List Item", "wcol_list_item"),
|
||||
# Not used yet, so hide this from the UI.
|
||||
# ("Data-View Item", "wcol_view_item"),
|
||||
("Data-View Item", "wcol_view_item"),
|
||||
("Tab", "wcol_tab"),
|
||||
]
|
||||
|
||||
|
@@ -192,6 +192,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);
|
||||
@@ -367,6 +368,7 @@ int 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(const bContext *C, bool *r_is_valid);
|
||||
struct AssetHandle *CTX_wm_asset_handle_ptr(const bContext *C);
|
||||
|
||||
bool CTX_wm_interface_locked(const bContext *C);
|
||||
|
||||
|
@@ -77,7 +77,9 @@ struct PreviewImage;
|
||||
struct StudioLight;
|
||||
struct bGPDlayer;
|
||||
|
||||
#ifndef __cplusplus
|
||||
enum eIconSizes;
|
||||
#endif
|
||||
|
||||
void BKE_icons_init(int first_dyn_id);
|
||||
|
||||
|
@@ -947,6 +947,15 @@ struct SpaceSpreadsheet *CTX_wm_space_spreadsheet(const bContext *C)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct SpaceAssets *CTX_wm_space_assets(const bContext *C)
|
||||
{
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
if (area && area->spacetype == SPACE_ASSETS) {
|
||||
return area->spacedata.first;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
|
||||
{
|
||||
C->wm.manager = wm;
|
||||
@@ -1502,6 +1511,16 @@ AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid)
|
||||
return (AssetHandle){0};
|
||||
}
|
||||
|
||||
/**
|
||||
* \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 CTX_data_pointer_get_type(C, "asset_handle", &RNA_AssetHandle).data;
|
||||
}
|
||||
|
||||
Depsgraph *CTX_data_depsgraph_pointer(const bContext *C)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
@@ -1340,6 +1340,10 @@ static void write_area(BlendWriter *writer, ScrArea *area)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sl->spacetype == SPACE_ASSETS) {
|
||||
BLO_write_struct(writer, SpaceAssets, sl);
|
||||
// SpaceAssets *space_assets = (SpaceAssets *)sl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -94,6 +94,8 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
|
||||
*/
|
||||
{
|
||||
/* Keep this block, even when empty. */
|
||||
/* TODO version bump. */
|
||||
btheme->space_assets = btheme->space_file;
|
||||
btheme->tui.wcol_view_item = U_theme_default.tui.wcol_view_item;
|
||||
}
|
||||
|
||||
|
@@ -27,6 +27,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)
|
||||
|
@@ -31,6 +31,7 @@ set(SRC
|
||||
intern/asset_ops.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
|
||||
@@ -43,6 +44,7 @@ set(SRC
|
||||
ED_asset_mark_clear.h
|
||||
ED_asset_temp_id_consumer.h
|
||||
ED_asset_type.h
|
||||
ED_asset_view_catalog_filter.h
|
||||
intern/asset_library_reference.hh
|
||||
)
|
||||
|
||||
|
@@ -23,10 +23,10 @@ struct AssetLibraryReference;
|
||||
struct bContext;
|
||||
|
||||
const char *ED_asset_handle_get_name(const struct AssetHandle *asset);
|
||||
const char *ED_asset_handle_get_identifier(const struct AssetHandle *asset);
|
||||
struct AssetMetaData *ED_asset_handle_get_metadata(const struct AssetHandle *asset);
|
||||
struct ID *ED_asset_handle_get_local_id(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);
|
||||
void ED_asset_handle_get_full_library_path(const struct bContext *C,
|
||||
const struct AssetLibraryReference *asset_library_ref,
|
||||
const struct AssetHandle *asset,
|
||||
|
@@ -10,8 +10,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct AssetCatalogFilterSettings;
|
||||
struct AssetFilterSettings;
|
||||
struct AssetHandle;
|
||||
struct AssetLibrary;
|
||||
struct AssetLibraryReference;
|
||||
struct ID;
|
||||
struct bContext;
|
||||
@@ -23,10 +25,11 @@ struct wmNotifier;
|
||||
*/
|
||||
void ED_assetlist_storage_fetch(const struct AssetLibraryReference *library_reference,
|
||||
const struct bContext *C);
|
||||
void ED_assetlist_ensure_previews_job(const struct AssetLibraryReference *library_reference,
|
||||
struct bContext *C);
|
||||
void ED_assetlist_catalog_filter_set(const struct AssetLibraryReference *,
|
||||
const struct AssetCatalogFilterSettings *catalog_filter);
|
||||
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).
|
||||
*
|
||||
@@ -46,9 +49,16 @@ void ED_assetlist_storage_id_remap(struct ID *id_old, struct ID *id_new);
|
||||
*/
|
||||
void ED_assetlist_storage_exit(void);
|
||||
|
||||
struct PreviewImage *ED_assetlist_asset_preview_request(
|
||||
const struct AssetLibraryReference *library_reference, AssetHandle *asset_handle);
|
||||
int ED_assetlist_asset_preview_icon_id_request(const AssetLibraryReference *library_reference,
|
||||
AssetHandle *asset_handle);
|
||||
struct ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle);
|
||||
const char *ED_assetlist_library_path(const struct AssetLibraryReference *library_reference);
|
||||
|
||||
struct AssetLibrary *ED_assetlist_library_get(
|
||||
const struct AssetLibraryReference *library_reference);
|
||||
|
||||
/**
|
||||
* \return True if the region needs a UI redraw.
|
||||
*/
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
@@ -19,6 +20,14 @@ std::string ED_assetlist_asset_filepath_get(const bContext *C,
|
||||
const AssetLibraryReference &library_reference,
|
||||
const AssetHandle &asset_handle);
|
||||
|
||||
AssetHandle *ED_assetlist_asset_get_from_index(const AssetLibraryReference *library_reference,
|
||||
int index);
|
||||
|
||||
/* Can return false to stop iterating. */
|
||||
using AssetListIterFn = blender::FunctionRef<bool(AssetHandle)>;
|
||||
using AssetListIterFn = blender::FunctionRef<bool(AssetHandle &)>;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void ED_assetlist_iterate(const AssetLibraryReference &library_reference, AssetListIterFn fn);
|
||||
|
37
source/blender/editors/asset/ED_asset_view_catalog_filter.h
Normal file
37
source/blender/editors/asset/ED_asset_view_catalog_filter.h
Normal file
@@ -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
|
@@ -18,6 +18,11 @@ const char *ED_asset_handle_get_name(const AssetHandle *asset)
|
||||
return asset->file_data->name;
|
||||
}
|
||||
|
||||
const char *ED_asset_handle_get_identifier(const AssetHandle *asset)
|
||||
{
|
||||
return asset->file_data->relpath;
|
||||
}
|
||||
|
||||
AssetMetaData *ED_asset_handle_get_metadata(const AssetHandle *asset)
|
||||
{
|
||||
return asset->file_data->asset_data;
|
||||
@@ -33,11 +38,6 @@ ID_Type ED_asset_handle_get_id_type(const AssetHandle *asset)
|
||||
return static_cast<ID_Type>(asset->file_data->blentype);
|
||||
}
|
||||
|
||||
int ED_asset_handle_get_preview_icon_id(const AssetHandle *asset)
|
||||
{
|
||||
return asset->file_data->preview_icon_id;
|
||||
}
|
||||
|
||||
void ED_asset_handle_get_full_library_path(const bContext *C,
|
||||
const AssetLibraryReference *asset_library_ref,
|
||||
const AssetHandle *asset,
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_icons.h"
|
||||
#include "BKE_preferences.h"
|
||||
|
||||
#include "ED_fileselect.h"
|
||||
@@ -75,32 +76,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_add_timer_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_remove_timer_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;
|
||||
@@ -110,15 +92,17 @@ class AssetList : NonCopyable {
|
||||
|
||||
void setup();
|
||||
void fetch(const bContext &C);
|
||||
void ensurePreviewsJob(bContext *C);
|
||||
void setCatalogFilterSettings(const AssetCatalogFilterSettings &settings);
|
||||
void clear(bContext *C);
|
||||
|
||||
bool needsRefetch() const;
|
||||
AssetHandle &asset_handle_from_file(const FileDirEntry &) const;
|
||||
void iterate(AssetListIterFn fn) const;
|
||||
bool listen(const wmNotifier ¬ifier) const;
|
||||
int size() const;
|
||||
void tagMainDataDirty() const;
|
||||
void remapID(ID *id_old, ID *id_new) const;
|
||||
AssetLibrary *asset_library() const;
|
||||
StringRef filepath() const;
|
||||
};
|
||||
|
||||
@@ -148,7 +132,7 @@ void AssetList::setup()
|
||||
filelist_setlibrary(files, &library_ref_);
|
||||
filelist_setfilter_options(
|
||||
files,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true, /* Just always hide parent, prefer to not add an extra user option for this. */
|
||||
FILE_TYPE_BLENDERLIB,
|
||||
@@ -177,6 +161,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)) {
|
||||
@@ -188,11 +173,26 @@ 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_);
|
||||
}
|
||||
|
||||
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(AssetListIterFn fn) const
|
||||
{
|
||||
FileList *files = filelist_;
|
||||
@@ -204,7 +204,7 @@ void AssetList::iterate(AssetListIterFn 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;
|
||||
@@ -212,30 +212,6 @@ void AssetList::iterate(AssetListIterFn fn) const
|
||||
}
|
||||
}
|
||||
|
||||
void AssetList::ensurePreviewsJob(bContext *C)
|
||||
{
|
||||
FileList *files = filelist_;
|
||||
int numfiles = filelist_files_ensure(files);
|
||||
|
||||
filelist_cache_previews_set(files, true);
|
||||
filelist_file_cache_slidingwindow_set(files, 256);
|
||||
/* TODO fetch all previews for now. */
|
||||
filelist_file_cache_block(files, numfiles / 2);
|
||||
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() */
|
||||
@@ -244,6 +220,7 @@ 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);
|
||||
}
|
||||
@@ -261,7 +238,11 @@ bool AssetList::listen(const wmNotifier ¬ifier) const
|
||||
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)) {
|
||||
@@ -301,6 +282,11 @@ StringRef AssetList::filepath() const
|
||||
return filelist_dir(filelist_);
|
||||
}
|
||||
|
||||
AssetLibrary *AssetList::asset_library() const
|
||||
{
|
||||
return filelist_asset_library(filelist_);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -351,7 +337,7 @@ void AssetListStorage::fetch_library(const AssetLibraryReference &library_refere
|
||||
|
||||
void AssetListStorage::destruct()
|
||||
{
|
||||
global_storage().~AssetListMap();
|
||||
global_storage().clear();
|
||||
}
|
||||
|
||||
AssetList *AssetListStorage::lookup_list(const AssetLibraryReference &library_ref)
|
||||
@@ -422,12 +408,12 @@ void ED_assetlist_storage_fetch(const AssetLibraryReference *library_reference,
|
||||
AssetListStorage::fetch_library(*library_reference, *C);
|
||||
}
|
||||
|
||||
void ED_assetlist_ensure_previews_job(const AssetLibraryReference *library_reference, 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,6 +478,37 @@ std::string ED_assetlist_asset_filepath_get(const bContext *C,
|
||||
return path;
|
||||
}
|
||||
|
||||
PreviewImage *ED_assetlist_asset_preview_request(const AssetLibraryReference *library_reference,
|
||||
AssetHandle *asset_handle)
|
||||
{
|
||||
if (asset_handle->preview) {
|
||||
return asset_handle->preview;
|
||||
}
|
||||
|
||||
if (ID *local_id = ED_asset_handle_get_local_id(asset_handle)) {
|
||||
asset_handle->preview = BKE_previewimg_id_get(local_id);
|
||||
}
|
||||
else {
|
||||
const char *asset_identifier = ED_asset_handle_get_identifier(asset_handle);
|
||||
const int source = filelist_preview_source_get(asset_handle->file_data->typeflag);
|
||||
const std::string asset_path = ED_assetlist_asset_filepath_get(
|
||||
nullptr, *library_reference, *asset_handle);
|
||||
|
||||
asset_handle->preview = BKE_previewimg_cached_thumbnail_read(
|
||||
asset_identifier, asset_path.c_str(), source, false);
|
||||
}
|
||||
|
||||
return asset_handle->preview;
|
||||
}
|
||||
|
||||
int ED_assetlist_asset_preview_icon_id_request(const AssetLibraryReference *library_reference,
|
||||
AssetHandle *asset_handle)
|
||||
{
|
||||
PreviewImage *preview = ED_assetlist_asset_preview_request(library_reference, asset_handle);
|
||||
ID *local_id = ED_asset_handle_get_local_id(asset_handle);
|
||||
return BKE_icon_preview_ensure(local_id, preview);
|
||||
}
|
||||
|
||||
ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
||||
{
|
||||
ImBuf *imbuf = filelist_file_getimage(asset_handle->file_data);
|
||||
@@ -502,6 +519,29 @@ ImBuf *ED_assetlist_asset_image_get(const AssetHandle *asset_handle)
|
||||
return filelist_geticon_image_ex(asset_handle->file_data);
|
||||
}
|
||||
|
||||
AssetHandle *ED_assetlist_asset_get_from_index(const AssetLibraryReference *library_reference,
|
||||
const int index)
|
||||
{
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
if (!list) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AssetHandle *asset = nullptr;
|
||||
|
||||
int i = 0;
|
||||
list->iterate([&](AssetHandle &iter_asset) {
|
||||
if (i == index) {
|
||||
asset = &iter_asset;
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
return true;
|
||||
});
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
const char *ED_assetlist_library_path(const AssetLibraryReference *library_reference)
|
||||
{
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
@@ -511,6 +551,15 @@ const char *ED_assetlist_library_path(const AssetLibraryReference *library_refer
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AssetLibrary *ED_assetlist_library_get(const AssetLibraryReference *library_reference)
|
||||
{
|
||||
AssetList *list = AssetListStorage::lookup_list(*library_reference);
|
||||
if (list) {
|
||||
return list->asset_library();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ED_assetlist_listen(const AssetLibraryReference *library_reference,
|
||||
const wmNotifier *notifier)
|
||||
{
|
||||
|
@@ -433,24 +433,38 @@ static void ASSET_OT_library_refresh(struct 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);
|
||||
return sfile && ED_fileselect_active_asset_library_get(sfile);
|
||||
return get_asset_library(C) != nullptr;
|
||||
}
|
||||
|
||||
static int asset_catalog_new_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
struct 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::bke::AssetCatalog *new_catalog = ED_asset_catalog_add(
|
||||
asset_library, "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);
|
||||
|
||||
@@ -481,8 +495,7 @@ static void ASSET_OT_catalog_new(struct wmOperatorType *ot)
|
||||
|
||||
static int asset_catalog_delete_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
struct 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);
|
||||
bke::CatalogID catalog_id;
|
||||
if (!BLI_uuid_parse_string(&catalog_id, catalog_id_str)) {
|
||||
@@ -517,13 +530,16 @@ static void ASSET_OT_catalog_delete(struct wmOperatorType *ot)
|
||||
|
||||
static bke::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 BKE_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 BKE_asset_library_get_catalog_service(asset_lib);
|
||||
}
|
||||
|
||||
AssetLibrary *asset_lib = ED_fileselect_active_asset_library_get(sfile);
|
||||
return BKE_asset_library_get_catalog_service(asset_lib);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static int asset_catalog_undo_exec(bContext *C, wmOperator * /*op*/)
|
||||
@@ -534,7 +550,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;
|
||||
}
|
||||
|
||||
@@ -564,7 +580,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;
|
||||
}
|
||||
|
||||
@@ -641,8 +657,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));
|
||||
|
||||
@@ -677,11 +692,12 @@ static bool has_external_files(Main *bmain, struct 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;
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,96 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edasset
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_asset_catalog.hh"
|
||||
#include "BKE_asset_library.hh"
|
||||
|
||||
#include "ED_asset_view_catalog_filter.h"
|
||||
|
||||
namespace bke = blender::bke;
|
||||
|
||||
struct AssetViewCatalogFilter {
|
||||
AssetCatalogFilterSettings filter_settings;
|
||||
std::unique_ptr<bke::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 bke::AssetCatalogService *catalog_service = BKE_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<bke::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;
|
||||
}
|
@@ -26,6 +26,7 @@ void ED_spacemacros_init(void);
|
||||
* Calls for registering default spaces, only called once, from #ED_spacetypes_init
|
||||
* \{ */
|
||||
|
||||
void ED_spacetype_assets(void);
|
||||
void ED_spacetype_outliner(void);
|
||||
void ED_spacetype_view3d(void);
|
||||
void ED_spacetype_ipo(void);
|
||||
|
@@ -194,7 +194,11 @@ 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);
|
||||
|
||||
uiBut *add_preview_button(uiLayout &layout,
|
||||
int preview_icon_id,
|
||||
const uchar mono_color[4] = nullptr) const;
|
||||
|
||||
void build_grid_tile(uiLayout &layout) const override;
|
||||
|
||||
|
@@ -1228,6 +1228,15 @@ uiBut *uiDefIconButO_ptr(uiBlock *block,
|
||||
short width,
|
||||
short height,
|
||||
const char *tip);
|
||||
uiBut *uiDefButPadding(uiBlock *block, int x, int y, short width, short height);
|
||||
uiBut *uiDefButPreviewTile(uiBlock *block,
|
||||
int preview_icon_id,
|
||||
const char *label,
|
||||
int x,
|
||||
int y,
|
||||
short width,
|
||||
short height,
|
||||
const uchar mono_color[4]);
|
||||
uiBut *uiDefButImage(
|
||||
uiBlock *block, void *imbuf, int x, int y, short width, short height, const uchar color[4]);
|
||||
uiBut *uiDefButAlert(uiBlock *block, int icon, int x, int y, short width, short height);
|
||||
@@ -1746,6 +1755,7 @@ struct PointerRNA *UI_but_extra_operator_icon_opptr_get(struct uiButExtraOpIcon
|
||||
int UI_preview_tile_size_x(void);
|
||||
int UI_preview_tile_size_y(void);
|
||||
int UI_preview_tile_size_y_no_label(void);
|
||||
rcti UI_preview_tile_but_preview_rect_get(const uiBut *but);
|
||||
|
||||
/* Autocomplete
|
||||
*
|
||||
|
@@ -96,7 +96,8 @@ int UI_icon_preview_to_render_size(enum eIconSizes size);
|
||||
*/
|
||||
void UI_icon_draw(float x, float y, int icon_id);
|
||||
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha);
|
||||
void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size);
|
||||
void UI_icon_draw_preview(
|
||||
float x, float y, int icon_id, float aspect, float alpha, int size, const uchar mono_color[4]);
|
||||
|
||||
void UI_icon_draw_ex(float x,
|
||||
float y,
|
||||
|
@@ -4826,6 +4826,37 @@ uiBut *uiDefBut(uiBlock *block,
|
||||
return but;
|
||||
}
|
||||
|
||||
uiBut *uiDefButPadding(uiBlock *block, int x, int y, short width, short height)
|
||||
{
|
||||
uiBut *but = ui_def_but(
|
||||
block, UI_BTYPE_LABEL, 0, "", x, y, width, height, nullptr, 0, 0, 0, 0, "");
|
||||
ui_but_update(but);
|
||||
return but;
|
||||
}
|
||||
|
||||
uiBut *uiDefButPreviewTile(uiBlock *block,
|
||||
int preview_icon_id,
|
||||
const char *label,
|
||||
int x,
|
||||
int y,
|
||||
short width,
|
||||
short height,
|
||||
const uchar mono_color[4])
|
||||
{
|
||||
uiBut *but = ui_def_but(
|
||||
block, UI_BTYPE_PREVIEW_TILE, 0, label, x, y, width, height, nullptr, 0, 0, 0, 0, "");
|
||||
ui_def_but_icon(but,
|
||||
preview_icon_id,
|
||||
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
|
||||
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
|
||||
if (mono_color) {
|
||||
copy_v4_v4_uchar(but->col, mono_color);
|
||||
}
|
||||
|
||||
ui_but_update(but);
|
||||
return but;
|
||||
}
|
||||
|
||||
uiBut *uiDefButImage(
|
||||
uiBlock *block, void *imbuf, int x, int y, short width, short height, const uchar color[4])
|
||||
{
|
||||
@@ -4993,6 +5024,30 @@ int UI_preview_tile_size_y_no_label(void)
|
||||
return round_fl_to_int((96.0f / 20.0f) * UI_UNIT_Y + 2.0f * pad);
|
||||
}
|
||||
|
||||
#define PREVIEW_PAD 4
|
||||
|
||||
rcti UI_preview_tile_but_preview_rect_get(const uiBut *but)
|
||||
{
|
||||
rcti rect;
|
||||
|
||||
BLI_rcti_rctf_copy_round(&rect, &but->rect);
|
||||
|
||||
if (but->drawstr[0]) {
|
||||
const uiStyle *style = UI_style_get();
|
||||
const uiFontStyle *fstyle = &style->widget;
|
||||
float font_dims[2] = {0.0f, 0.0f};
|
||||
|
||||
UI_fontstyle_set(fstyle);
|
||||
BLF_width_and_height(
|
||||
fstyle->uifont_id, but->drawstr, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
|
||||
/* draw icon in rect above the space reserved for the label */
|
||||
rect.ymin += round_fl_to_int(font_dims[1] + 2 * PREVIEW_PAD);
|
||||
}
|
||||
|
||||
return ui_preview_draw_rect_get(&rect);
|
||||
}
|
||||
|
||||
#undef PREVIEW_PAD
|
||||
#undef PREVIEW_TILE_PAD
|
||||
|
||||
static void ui_but_update_and_icon_set(uiBut *but, int icon)
|
||||
|
@@ -1503,6 +1503,7 @@ static void icon_draw_rect(float x,
|
||||
int rh,
|
||||
uint *rect,
|
||||
float alpha,
|
||||
const uchar mono_rgba[4],
|
||||
const float desaturate)
|
||||
{
|
||||
int draw_w = w;
|
||||
@@ -1518,7 +1519,12 @@ static void icon_draw_rect(float x,
|
||||
return;
|
||||
}
|
||||
/* modulate color */
|
||||
const float col[4] = {alpha, alpha, alpha, alpha};
|
||||
float col[4] = {alpha, alpha, alpha, alpha};
|
||||
if (mono_rgba) {
|
||||
/* Optionally use a mono color to recolor the image. */
|
||||
rgba_uchar_to_float(col, mono_rgba);
|
||||
mul_v4_fl(col, alpha);
|
||||
}
|
||||
|
||||
float scale_x = 1.0f;
|
||||
float scale_y = 1.0f;
|
||||
@@ -1813,9 +1819,10 @@ static void icon_draw_size(float x,
|
||||
if (di->type == ICON_TYPE_IMBUF) {
|
||||
ImBuf *ibuf = icon->obj;
|
||||
|
||||
GPU_blend(GPU_BLEND_ALPHA_PREMULT);
|
||||
icon_draw_rect(x, y, w, h, aspect, ibuf->x, ibuf->y, ibuf->rect, alpha, desaturate);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
/* TODO preview images are premultiplied apparently (see ICON_TYPE_PREVIEW). */
|
||||
// GPU_blend(GPU_BLEND_ALPHA_PREMULT);
|
||||
icon_draw_rect(x, y, w, h, aspect, ibuf->x, ibuf->y, ibuf->rect, alpha, mono_rgba, desaturate);
|
||||
// GPU_blend(GPU_BLEND_ALPHA);
|
||||
}
|
||||
else if (di->type == ICON_TYPE_VECTOR) {
|
||||
/* vector icons use the uiBlock transformation, they are not drawn
|
||||
@@ -1854,7 +1861,7 @@ static void icon_draw_size(float x,
|
||||
}
|
||||
|
||||
GPU_blend(GPU_BLEND_ALPHA_PREMULT);
|
||||
icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, desaturate);
|
||||
icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, NULL, desaturate);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
}
|
||||
else if (di->type == ICON_TYPE_EVENT) {
|
||||
@@ -1922,7 +1929,7 @@ static void icon_draw_size(float x,
|
||||
return;
|
||||
}
|
||||
|
||||
icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, desaturate);
|
||||
icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, NULL, desaturate);
|
||||
}
|
||||
else if (di->type == ICON_TYPE_PREVIEW) {
|
||||
PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) :
|
||||
@@ -1938,7 +1945,7 @@ static void icon_draw_size(float x,
|
||||
/* Preview images use premultiplied alpha. */
|
||||
GPU_blend(GPU_BLEND_ALPHA_PREMULT);
|
||||
icon_draw_rect(
|
||||
x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, desaturate);
|
||||
x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, NULL, desaturate);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
}
|
||||
}
|
||||
@@ -2433,9 +2440,10 @@ void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
|
||||
UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
|
||||
}
|
||||
|
||||
void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size)
|
||||
void UI_icon_draw_preview(
|
||||
float x, float y, int icon_id, float aspect, float alpha, int size, const uchar mono_color[4])
|
||||
{
|
||||
icon_draw_size(x, y, icon_id, aspect, alpha, ICON_SIZE_PREVIEW, size, false, NULL, false);
|
||||
icon_draw_size(x, y, icon_id, aspect, alpha, ICON_SIZE_PREVIEW, size, 0.0f, mono_color, false);
|
||||
}
|
||||
|
||||
void UI_icon_draw_ex(float x,
|
||||
|
@@ -1236,6 +1236,8 @@ void ui_draw_preview_item(const struct uiFontStyle *fstyle,
|
||||
int iconid,
|
||||
int but_flag,
|
||||
eFontStyle_Align text_align);
|
||||
rcti ui_preview_draw_rect_get(const rcti *bounds_rect);
|
||||
|
||||
/**
|
||||
* Version of #ui_draw_preview_item() that does not draw the menu background and item text based on
|
||||
* state. It just draws the preview and text directly.
|
||||
@@ -1245,6 +1247,7 @@ void ui_draw_preview_item_stateless(const struct uiFontStyle *fstyle,
|
||||
const char *name,
|
||||
int iconid,
|
||||
const uchar text_col[4],
|
||||
const uchar mono_col[4],
|
||||
eFontStyle_Align text_align);
|
||||
|
||||
#define UI_TEXT_MARGIN_X 0.4f
|
||||
|
@@ -4473,8 +4473,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;
|
||||
|
||||
int *widths = BLI_array_alloca(widths, gflow->tot_columns);
|
||||
int *heights = BLI_array_alloca(heights, gflow->tot_rows);
|
||||
|
@@ -54,14 +54,15 @@ static void asset_view_item_but_drag_set(uiBut *but,
|
||||
|
||||
if (blend_path[0]) {
|
||||
ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle);
|
||||
UI_but_drag_set_asset(but,
|
||||
asset_handle,
|
||||
BLI_strdup(blend_path),
|
||||
ED_asset_handle_get_metadata(asset_handle),
|
||||
FILE_ASSET_IMPORT_APPEND,
|
||||
ED_asset_handle_get_preview_icon_id(asset_handle),
|
||||
imbuf,
|
||||
1.0f);
|
||||
UI_but_drag_set_asset(
|
||||
but,
|
||||
asset_handle,
|
||||
BLI_strdup(blend_path),
|
||||
ED_asset_handle_get_metadata(asset_handle),
|
||||
FILE_ASSET_IMPORT_APPEND,
|
||||
ED_assetlist_asset_preview_icon_id_request(&list_data->asset_library_ref, asset_handle),
|
||||
imbuf,
|
||||
1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,28 +86,29 @@ static void asset_view_draw_item(uiList *ui_list,
|
||||
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
const bool show_names = list_data->show_names;
|
||||
/* TODO ED_fileselect_init_layout(). Share somehow? */
|
||||
const float size_x = (96.0f / 20.0f) * UI_UNIT_X;
|
||||
const float size_y = (96.0f / 20.0f) * UI_UNIT_Y - (show_names ? 0 : UI_UNIT_Y);
|
||||
uiBut *but = uiDefIconTextBut(block,
|
||||
UI_BTYPE_PREVIEW_TILE,
|
||||
0,
|
||||
ED_asset_handle_get_preview_icon_id(asset_handle),
|
||||
show_names ? ED_asset_handle_get_name(asset_handle) : "",
|
||||
0,
|
||||
0,
|
||||
size_x,
|
||||
size_y,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"");
|
||||
ui_def_but_icon(but,
|
||||
ED_asset_handle_get_preview_icon_id(asset_handle),
|
||||
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
|
||||
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
|
||||
const int size_x = UI_preview_tile_size_x();
|
||||
const int size_y = show_names ? UI_preview_tile_size_y() : UI_preview_tile_size_y_no_label();
|
||||
uiBut *but = uiDefIconTextBut(
|
||||
block,
|
||||
UI_BTYPE_PREVIEW_TILE,
|
||||
0,
|
||||
ED_assetlist_asset_preview_icon_id_request(&list_data->asset_library_ref, asset_handle),
|
||||
show_names ? ED_asset_handle_get_name(asset_handle) : "",
|
||||
0,
|
||||
0,
|
||||
size_x,
|
||||
size_y,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"");
|
||||
ui_def_but_icon(
|
||||
but,
|
||||
ED_assetlist_asset_preview_icon_id_request(&list_data->asset_library_ref, asset_handle),
|
||||
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
|
||||
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
|
||||
if (!ui_list->dyn_data->custom_drag_optype) {
|
||||
asset_view_item_but_drag_set(but, list_data, asset_handle);
|
||||
}
|
||||
@@ -165,7 +167,7 @@ static void asset_view_template_refresh_asset_collection(
|
||||
|
||||
RNA_property_collection_clear(&assets_dataptr, assets_prop);
|
||||
|
||||
ED_assetlist_iterate(asset_library_ref, [&](AssetHandle asset) {
|
||||
ED_assetlist_iterate(asset_library_ref, [&](AssetHandle &asset) {
|
||||
if (!ED_asset_filter_matches_asset(&filter_settings, &asset)) {
|
||||
/* Don't do anything else, but return true to continue iterating. */
|
||||
return true;
|
||||
@@ -219,7 +221,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);
|
||||
|
||||
asset_view_template_refresh_asset_collection(
|
||||
|
@@ -644,6 +644,8 @@ static MenuSearch_Data *menu_items_from_ui_create(
|
||||
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++) {
|
||||
|
@@ -1316,22 +1316,40 @@ static float widget_alpha_factor(const uiWidgetStateInfo *state)
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect)
|
||||
rcti ui_preview_draw_rect_get(const rcti *bounds_rect)
|
||||
{
|
||||
const int max_width = BLI_rcti_size_x(bounds_rect);
|
||||
const int max_height = BLI_rcti_size_y(bounds_rect);
|
||||
|
||||
rcti rect = {0};
|
||||
|
||||
const int draw_size = MIN2(max_width, max_height) - PREVIEW_PAD * 2;
|
||||
if (draw_size > 0) {
|
||||
rect.xmin = bounds_rect->xmin + max_width / 2 - draw_size / 2;
|
||||
rect.ymin = bounds_rect->ymin + max_height / 2 - draw_size / 2;
|
||||
rect.xmax = rect.xmin + draw_size;
|
||||
rect.ymax = rect.ymin + draw_size;
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
static void widget_draw_preview(BIFIconID icon,
|
||||
float alpha,
|
||||
const rcti *rect,
|
||||
const uchar mono_color[4])
|
||||
{
|
||||
if (icon == ICON_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int w = BLI_rcti_size_x(rect);
|
||||
const int h = BLI_rcti_size_y(rect);
|
||||
const int size = MIN2(w, h) - PREVIEW_PAD * 2;
|
||||
|
||||
if (size > 0) {
|
||||
const int x = rect->xmin + w / 2 - size / 2;
|
||||
const int y = rect->ymin + h / 2 - size / 2;
|
||||
|
||||
UI_icon_draw_preview(x, y, icon, 1.0f, alpha, size);
|
||||
const rcti draw_rect = ui_preview_draw_rect_get(rect);
|
||||
if (BLI_rcti_is_empty(&draw_rect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UI_icon_draw_preview(
|
||||
draw_rect.xmin, draw_rect.ymin, icon, 1.0f, alpha, BLI_rcti_size_x(&draw_rect), mono_color);
|
||||
}
|
||||
|
||||
static int ui_but_draw_menu_icon(const uiBut *but)
|
||||
@@ -1346,7 +1364,7 @@ static void widget_draw_icon(
|
||||
{
|
||||
if (but->flag & UI_BUT_ICON_PREVIEW) {
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
widget_draw_preview(icon, alpha, rect);
|
||||
widget_draw_preview(icon, alpha, rect, mono_color);
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
return;
|
||||
}
|
||||
@@ -1625,9 +1643,9 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
|
||||
}
|
||||
|
||||
strwidth = BLF_width(fstyle->uifont_id, str, max_len);
|
||||
}
|
||||
|
||||
BLI_assert(strwidth <= okwidth);
|
||||
BLI_assert(strwidth <= okwidth);
|
||||
}
|
||||
|
||||
return strwidth;
|
||||
}
|
||||
@@ -2313,7 +2331,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
|
||||
/* draw icon in rect above the space reserved for the label */
|
||||
rect->ymin += text_size;
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
widget_draw_preview(icon, alpha, rect);
|
||||
widget_draw_preview(icon, alpha, rect, but->col[3] != 0 ? but->col : NULL);
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
|
||||
/* offset rect to draw label in */
|
||||
@@ -4002,8 +4020,13 @@ static void widget_preview_tile(uiBut *but,
|
||||
const float UNUSED(zoom))
|
||||
{
|
||||
const uiStyle *style = UI_style_get();
|
||||
ui_draw_preview_item_stateless(
|
||||
&style->widget, rect, but->drawstr, but->icon, wcol->text, UI_STYLE_TEXT_CENTER);
|
||||
ui_draw_preview_item_stateless(&style->widget,
|
||||
rect,
|
||||
but->drawstr,
|
||||
but->icon,
|
||||
wcol->text,
|
||||
but->col[3] ? but->col : NULL,
|
||||
UI_STYLE_TEXT_CENTER);
|
||||
}
|
||||
|
||||
static void widget_menuiconbut(uiWidgetColors *wcol,
|
||||
@@ -5510,34 +5533,33 @@ void ui_draw_preview_item_stateless(const uiFontStyle *fstyle,
|
||||
const char *name,
|
||||
int iconid,
|
||||
const uchar text_col[4],
|
||||
const uchar mono_col[4],
|
||||
eFontStyle_Align text_align)
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
widget_draw_preview(iconid, 1.0f, rect);
|
||||
widget_draw_preview(iconid, 1.0f, rect, mono_col);
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
|
||||
if (!has_text) {
|
||||
return;
|
||||
}
|
||||
|
||||
BLF_width_and_height(
|
||||
fstyle->uifont_id, name, BLF_DRAW_STR_DUMMY_MAX, &font_dims[0], &font_dims[1]);
|
||||
|
||||
/* text rect */
|
||||
trect.ymin += U.widget_unit / 2;
|
||||
trect.ymax = trect.ymin + font_dims[1];
|
||||
if (trect.xmax > rect->xmax - PREVIEW_PAD) {
|
||||
trect.xmax = rect->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];
|
||||
@@ -5575,7 +5597,7 @@ void ui_draw_preview_item(const uiFontStyle *fstyle,
|
||||
wt->state(wt, &state, UI_EMBOSS_UNDEFINED);
|
||||
wt->draw(&wt->wcol, rect, &STATE_INFO_NULL, 0, 1.0f);
|
||||
|
||||
ui_draw_preview_item_stateless(fstyle, rect, name, iconid, wt->wcol.text, text_align);
|
||||
ui_draw_preview_item_stateless(fstyle, rect, name, iconid, wt->wcol.text, NULL, text_align);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@@ -147,6 +147,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;
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <stdexcept>
|
||||
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
@@ -410,29 +411,26 @@ PreviewGridItem::PreviewGridItem(StringRef identifier, StringRef label, int prev
|
||||
{
|
||||
}
|
||||
|
||||
void PreviewGridItem::build_grid_tile(uiLayout &layout) const
|
||||
uiBut *PreviewGridItem::add_preview_button(uiLayout &layout,
|
||||
const int preview_icon_id,
|
||||
const uchar mono_color[4]) const
|
||||
{
|
||||
const GridViewStyle &style = get_view().get_style();
|
||||
uiBlock *block = uiLayoutGetBlock(&layout);
|
||||
|
||||
uiBut *but = uiDefBut(block,
|
||||
UI_BTYPE_PREVIEW_TILE,
|
||||
0,
|
||||
label.c_str(),
|
||||
0,
|
||||
0,
|
||||
style.tile_width,
|
||||
style.tile_height,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"");
|
||||
ui_def_but_icon(but,
|
||||
preview_icon_id,
|
||||
/* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
|
||||
UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
|
||||
return uiDefButPreviewTile(block,
|
||||
preview_icon_id,
|
||||
label.c_str(),
|
||||
0,
|
||||
0,
|
||||
style.tile_width,
|
||||
style.tile_height,
|
||||
mono_color);
|
||||
}
|
||||
|
||||
void PreviewGridItem::build_grid_tile(uiLayout &layout) const
|
||||
{
|
||||
add_preview_button(layout, preview_icon_id);
|
||||
}
|
||||
|
||||
void PreviewGridItem::set_on_activate_fn(ActivateFn fn)
|
||||
|
@@ -23,6 +23,7 @@ set(SRC
|
||||
set(LIB
|
||||
bf_editor_geometry
|
||||
bf_editor_space_action
|
||||
bf_editor_space_assets
|
||||
bf_editor_space_buttons
|
||||
bf_editor_space_clip
|
||||
bf_editor_space_console
|
||||
|
@@ -63,6 +63,7 @@ void ED_spacetypes_init(void)
|
||||
U.widget_unit = 20;
|
||||
|
||||
/* Create space types. */
|
||||
ED_spacetype_assets();
|
||||
ED_spacetype_outliner();
|
||||
ED_spacetype_view3d();
|
||||
ED_spacetype_ipo();
|
||||
|
37
source/blender/editors/space_assets/CMakeLists.txt
Normal file
37
source/blender/editors/space_assets/CMakeLists.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(INC
|
||||
../include
|
||||
../../blenfont
|
||||
../../blenkernel
|
||||
../../blenlib
|
||||
../../blentranslation
|
||||
../../gpu
|
||||
../../makesdna
|
||||
../../makesrna
|
||||
../../windowmanager
|
||||
../../../../intern/glew-mx
|
||||
../../../../intern/guardedalloc
|
||||
# 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
|
||||
)
|
||||
|
||||
blender_add_lib(bf_editor_space_assets "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_editor_space_assets bf_rna)
|
77
source/blender/editors/space_assets/asset_browser_draw.cc
Normal file
77
source/blender/editors/space_assets/asset_browser_draw.cc
Normal file
@@ -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.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#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, &asset_space_ptr);
|
||||
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);
|
||||
}
|
28
source/blender/editors/space_assets/asset_browser_intern.hh
Normal file
28
source/blender/editors/space_assets/asset_browser_intern.hh
Normal file
@@ -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);
|
11
source/blender/editors/space_assets/asset_browser_ops.cc
Normal file
11
source/blender/editors/space_assets/asset_browser_ops.cc
Normal file
@@ -0,0 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
|
||||
#include "asset_browser_intern.hh"
|
||||
|
||||
void asset_browser_operatortypes()
|
||||
{
|
||||
}
|
81
source/blender/editors/space_assets/asset_browser_panels.cc
Normal file
81
source/blender/editors/space_assets/asset_browser_panels.cc
Normal file
@@ -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.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
#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, &assets_space_ptr);
|
||||
|
||||
uiItemR(row, &assets_space_ptr, "asset_library_ref", 0, "", 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_ref",
|
||||
"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);
|
||||
}
|
726
source/blender/editors/space_assets/asset_catalog_tree_view.cc
Normal file
726
source/blender/editors/space_assets/asset_catalog_tree_view.cc
Normal file
@@ -0,0 +1,726 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_asset_catalog.hh"
|
||||
#include "BKE_asset_library.hh"
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "ED_asset.h"
|
||||
#include "ED_undo.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_tree_view.hh"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_message.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "asset_browser_intern.hh"
|
||||
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
|
||||
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. */
|
||||
bke::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 AssetCatalogDropController;
|
||||
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(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() override;
|
||||
|
||||
void build_row(uiLayout &row) override;
|
||||
void build_context_menu(bContext &C, uiLayout &column) const override;
|
||||
|
||||
bool supports_renaming() const override;
|
||||
bool rename(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::AbstractViewItemDropController> create_drop_controller() const override;
|
||||
};
|
||||
|
||||
class AssetCatalogDragController : public ui::AbstractViewItemDragController {
|
||||
AssetCatalogTreeItem &catalog_item_;
|
||||
|
||||
public:
|
||||
explicit AssetCatalogDragController(AssetCatalogTreeView &tree_view,
|
||||
AssetCatalogTreeItem &catalog_item);
|
||||
|
||||
int get_drag_type() const override;
|
||||
void *create_drag_data() const override;
|
||||
void on_drag_start() override;
|
||||
};
|
||||
|
||||
class AssetCatalogDropController : public ui::AbstractViewItemDropController {
|
||||
AssetCatalogTreeItem &catalog_item_;
|
||||
|
||||
public:
|
||||
AssetCatalogDropController(AssetCatalogTreeView &tree_view, AssetCatalogTreeItem &catalog_item);
|
||||
|
||||
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
|
||||
std::string drop_tooltip(const wmDrag &drag) const override;
|
||||
bool on_drop(struct bContext *C, const wmDrag &drag) 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 drop_assets_into_catalog(struct bContext *C,
|
||||
AssetCatalogTreeView &tree_view,
|
||||
const wmDrag &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 wmDrag &drag,
|
||||
AssetCatalogTreeView &tree_view,
|
||||
const std::optional<CatalogID> drop_catalog_id = std::nullopt);
|
||||
|
||||
private:
|
||||
std::string drop_tooltip_asset_list(const wmDrag &drag) const;
|
||||
std::string drop_tooltip_asset_catalog(const wmDrag &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 DropController : public ui::AbstractViewItemDropController {
|
||||
DropController(AssetCatalogTreeView &tree_view);
|
||||
|
||||
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
|
||||
std::string drop_tooltip(const wmDrag &drag) const override;
|
||||
bool on_drop(struct bContext *C, const wmDrag &drag) override;
|
||||
};
|
||||
|
||||
std::unique_ptr<ui::AbstractViewItemDropController> create_drop_controller() const override;
|
||||
};
|
||||
|
||||
class AssetCatalogTreeViewUnassignedItem : public ui::BasicTreeViewItem {
|
||||
using BasicTreeViewItem::BasicTreeViewItem;
|
||||
|
||||
struct DropController : public ui::AbstractViewItemDropController {
|
||||
DropController(AssetCatalogTreeView &tree_view);
|
||||
|
||||
bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const override;
|
||||
std::string drop_tooltip(const wmDrag &drag) const override;
|
||||
bool on_drop(struct bContext *C, const wmDrag &drag) override;
|
||||
};
|
||||
|
||||
std::unique_ptr<ui::AbstractViewItemDropController> create_drop_controller() const override;
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AssetCatalogTreeView::AssetCatalogTreeView(::AssetLibrary *library,
|
||||
const PointerRNA &catalog_filter_owner,
|
||||
PropertyRNA &catalog_filter_prop,
|
||||
wmMsgBus *msg_bus)
|
||||
: asset_library_(library),
|
||||
catalog_tree_(BKE_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](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](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()
|
||||
{
|
||||
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,
|
||||
0,
|
||||
&props);
|
||||
RNA_string_set(&props, "parent_path", catalog_item_.catalog_path().c_str());
|
||||
|
||||
char catalog_id_str_buffer[UUID_STRING_LEN] = "";
|
||||
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,
|
||||
0,
|
||||
&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
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewItem::rename(StringRefNull new_name)
|
||||
{
|
||||
/* Important to keep state. */
|
||||
BasicTreeViewItem::rename(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::AbstractViewItemDropController> AssetCatalogTreeViewItem::
|
||||
create_drop_controller() const
|
||||
{
|
||||
return std::make_unique<AssetCatalogDropController>(
|
||||
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_);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AssetCatalogDropController::AssetCatalogDropController(AssetCatalogTreeView &tree_view,
|
||||
AssetCatalogTreeItem &catalog_item)
|
||||
: ui::AbstractViewItemDropController(tree_view), catalog_item_(catalog_item)
|
||||
{
|
||||
}
|
||||
|
||||
bool AssetCatalogDropController::can_drop(const wmDrag &drag, const char **r_disabled_hint) const
|
||||
{
|
||||
if (drag.type == WM_DRAG_ASSET_CATALOG) {
|
||||
const AssetCatalog *drag_catalog = get_drag_catalog(drag, get_asset_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 = "Catalog cannot be dropped into itself";
|
||||
return false;
|
||||
}
|
||||
if (catalog_item_.catalog_path() == drag_catalog->path.parent()) {
|
||||
*r_disabled_hint = "Catalog is already placed inside this catalog";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (drag.type == WM_DRAG_ASSET_LIST) {
|
||||
return has_droppable_asset(drag, r_disabled_hint);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string AssetCatalogDropController::drop_tooltip(const wmDrag &drag) const
|
||||
{
|
||||
if (drag.type == WM_DRAG_ASSET_CATALOG) {
|
||||
return drop_tooltip_asset_catalog(drag);
|
||||
}
|
||||
return drop_tooltip_asset_list(drag);
|
||||
}
|
||||
|
||||
std::string AssetCatalogDropController::drop_tooltip_asset_catalog(const wmDrag &drag) const
|
||||
{
|
||||
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
|
||||
const AssetCatalog *src_catalog = get_drag_catalog(drag, get_asset_library());
|
||||
|
||||
return std::string(TIP_("Move Catalog")) + " '" + src_catalog->path.name() + "' " +
|
||||
TIP_("into") + " '" + catalog_item_.get_name() + "'";
|
||||
}
|
||||
|
||||
std::string AssetCatalogDropController::drop_tooltip_asset_list(const wmDrag &drag) const
|
||||
{
|
||||
BLI_assert(drag.type == WM_DRAG_ASSET_LIST);
|
||||
|
||||
const ListBase *asset_drags = WM_drag_asset_list_get(&drag);
|
||||
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 AssetCatalogDropController::on_drop(struct bContext *C, const wmDrag &drag)
|
||||
{
|
||||
if (drag.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 AssetCatalogDropController::drop_asset_catalog_into_catalog(
|
||||
const wmDrag &drag,
|
||||
AssetCatalogTreeView &tree_view,
|
||||
const std::optional<CatalogID> drop_catalog_id)
|
||||
{
|
||||
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
|
||||
wmDragAssetCatalog *catalog_drag = WM_drag_get_asset_catalog_data(&drag);
|
||||
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 AssetCatalogDropController::drop_assets_into_catalog(struct bContext *C,
|
||||
AssetCatalogTreeView &tree_view,
|
||||
const wmDrag &drag,
|
||||
CatalogID catalog_id,
|
||||
StringRefNull simple_name)
|
||||
{
|
||||
BLI_assert(drag.type == WM_DRAG_ASSET_LIST);
|
||||
const ListBase *asset_drags = WM_drag_asset_list_get(&drag);
|
||||
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 *AssetCatalogDropController::get_drag_catalog(const wmDrag &drag,
|
||||
const ::AssetLibrary &asset_library)
|
||||
{
|
||||
if (drag.type != WM_DRAG_ASSET_CATALOG) {
|
||||
return nullptr;
|
||||
}
|
||||
const bke::AssetCatalogService *catalog_service = BKE_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 AssetCatalogDropController::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;
|
||||
}
|
||||
|
||||
::AssetLibrary &AssetCatalogDropController::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)
|
||||
{
|
||||
}
|
||||
|
||||
int 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::AbstractViewItemDropController> AssetCatalogTreeViewAllItem::
|
||||
create_drop_controller() const
|
||||
{
|
||||
return std::make_unique<AssetCatalogTreeViewAllItem::DropController>(
|
||||
static_cast<AssetCatalogTreeView &>(get_tree_view()));
|
||||
}
|
||||
|
||||
AssetCatalogTreeViewAllItem::DropController::DropController(AssetCatalogTreeView &tree_view)
|
||||
: ui::AbstractViewItemDropController(tree_view)
|
||||
{
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewAllItem::DropController::can_drop(const wmDrag &drag,
|
||||
const char **r_disabled_hint) const
|
||||
{
|
||||
if (drag.type != WM_DRAG_ASSET_CATALOG) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const AssetCatalog *drag_catalog = AssetCatalogDropController::get_drag_catalog(
|
||||
drag, *get_view<AssetCatalogTreeView>().asset_library_);
|
||||
if (drag_catalog->path.parent() == "") {
|
||||
*r_disabled_hint = "Catalog is already placed at the highest level";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string AssetCatalogTreeViewAllItem::DropController::drop_tooltip(const wmDrag &drag) const
|
||||
{
|
||||
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
|
||||
const AssetCatalog *drag_catalog = AssetCatalogDropController::get_drag_catalog(
|
||||
drag, *get_view<AssetCatalogTreeView>().asset_library_);
|
||||
|
||||
return std::string(TIP_("Move Catalog")) + " '" + drag_catalog->path.name() + "' " +
|
||||
TIP_("to the top level of the tree");
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewAllItem::DropController::on_drop(struct bContext *UNUSED(C),
|
||||
const wmDrag &drag)
|
||||
{
|
||||
BLI_assert(drag.type == WM_DRAG_ASSET_CATALOG);
|
||||
return AssetCatalogDropController::drop_asset_catalog_into_catalog(
|
||||
drag,
|
||||
get_view<AssetCatalogTreeView>(),
|
||||
/* No value to drop into the root level. */
|
||||
std::nullopt);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
std::unique_ptr<ui::AbstractViewItemDropController> AssetCatalogTreeViewUnassignedItem::
|
||||
create_drop_controller() const
|
||||
{
|
||||
return std::make_unique<AssetCatalogTreeViewUnassignedItem::DropController>(
|
||||
static_cast<AssetCatalogTreeView &>(get_tree_view()));
|
||||
}
|
||||
|
||||
AssetCatalogTreeViewUnassignedItem::DropController::DropController(AssetCatalogTreeView &tree_view)
|
||||
: ui::AbstractViewItemDropController(tree_view)
|
||||
{
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewUnassignedItem::DropController::can_drop(
|
||||
const wmDrag &drag, const char **r_disabled_hint) const
|
||||
{
|
||||
if (drag.type != WM_DRAG_ASSET_LIST) {
|
||||
return false;
|
||||
}
|
||||
return AssetCatalogDropController::has_droppable_asset(drag, r_disabled_hint);
|
||||
}
|
||||
|
||||
std::string AssetCatalogTreeViewUnassignedItem::DropController::drop_tooltip(
|
||||
const wmDrag &drag) const
|
||||
{
|
||||
const ListBase *asset_drags = WM_drag_asset_list_get(&drag);
|
||||
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::DropController::on_drop(struct bContext *C,
|
||||
const wmDrag &drag)
|
||||
{
|
||||
/* Assign to nil catalog ID. */
|
||||
return AssetCatalogDropController::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 builder(*block);
|
||||
builder.build_tree_view(*tree_view);
|
||||
}
|
102
source/blender/editors/space_assets/asset_view.cc
Normal file
102
source/blender/editors/space_assets/asset_view.cc
Normal file
@@ -0,0 +1,102 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spassets
|
||||
*/
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "ED_asset.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_interface.hh"
|
||||
|
||||
#include "WM_message.h"
|
||||
|
||||
#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_library_ref_, 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](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(const AssetLibraryReference &asset_library_ref,
|
||||
AssetHandle &asset)
|
||||
: ui::PreviewGridItem(ED_asset_handle_get_identifier(&asset),
|
||||
ED_asset_handle_get_name(&asset),
|
||||
ED_assetlist_asset_preview_icon_id_request(&asset_library_ref, &asset)),
|
||||
/* Get a copy so the identifier is always available (the file data wrapped by the handle may
|
||||
* be freed). */
|
||||
asset_identifier_(identifier_)
|
||||
{
|
||||
/* Update reference so we don't point into the possibly freed file data. */
|
||||
identifier_ = asset_identifier_;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace blender::ed::asset_browser
|
59
source/blender/editors/space_assets/asset_view.hh
Normal file
59
source/blender/editors/space_assets/asset_view.hh
Normal file
@@ -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(const AssetLibraryReference &asset_library_ref, 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
|
321
source/blender/editors/space_assets/space_assets.cc
Normal file
321
source/blender/editors/space_assets/space_assets.cc
Normal file
@@ -0,0 +1,321 @@
|
||||
/* 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.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_message.h"
|
||||
|
||||
#include "asset_browser_intern.hh"
|
||||
#include "asset_view.hh"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Asset Browser Space */
|
||||
|
||||
static SpaceLink *asset_browser_create(const ScrArea *UNUSED(area), const Scene *UNUSED(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 | V2D_SCROLL_BOTTOM);
|
||||
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 *UNUSED(sl))
|
||||
{
|
||||
}
|
||||
|
||||
static void asset_browser_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(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_ref",
|
||||
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_ref")) {
|
||||
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_get_from_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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: See comment above #WM_msg_publish_rna_prop(). */
|
||||
extern "C" {
|
||||
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 *UNUSED(wm), ARegion *region)
|
||||
{
|
||||
ED_region_header_init(region);
|
||||
}
|
||||
|
||||
static void asset_browser_header_listener(const wmRegionListenerParams *UNUSED(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 *UNUSED(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 *UNUSED(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 = UI_COMPACT_PANEL_WIDTH;
|
||||
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);
|
||||
}
|
@@ -28,6 +28,7 @@ set(SRC
|
||||
file_ops.c
|
||||
file_panels.c
|
||||
file_utils.c
|
||||
file_view_grid.cc
|
||||
filelist.c
|
||||
filesel.c
|
||||
fsmenu.c
|
||||
|
@@ -35,7 +35,7 @@
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
|
||||
namespace blender::ed::asset_browser {
|
||||
namespace blender::ed::space_file::asset_browser {
|
||||
|
||||
class AssetCatalogTreeViewAllItem;
|
||||
|
||||
@@ -214,11 +214,11 @@ AssetCatalogTreeViewAllItem &AssetCatalogTreeView::add_all_item()
|
||||
|
||||
AssetCatalogTreeViewAllItem &item = add_tree_item<AssetCatalogTreeViewAllItem>(IFACE_("All"));
|
||||
item.set_on_activate_fn([params](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;
|
||||
}
|
||||
|
||||
@@ -230,23 +230,23 @@ void AssetCatalogTreeView::add_unassigned_item()
|
||||
IFACE_("Unassigned"), ICON_FILE_HIDDEN);
|
||||
|
||||
item.set_on_activate_fn([params](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; });
|
||||
[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);
|
||||
}
|
||||
|
||||
@@ -650,99 +650,11 @@ bool AssetCatalogTreeViewUnassignedItem::DropController::on_drop(struct bContext
|
||||
C, get_view<AssetCatalogTreeView>(), drag, 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 ::AssetLibrary *asset_library)
|
||||
{
|
||||
AssetCatalogFilterSettings *filter_settings = reinterpret_cast<AssetCatalogFilterSettings *>(
|
||||
filter_settings_handle);
|
||||
const AssetCatalogService *catalog_service = BKE_asset_library_get_catalog_service(
|
||||
asset_library);
|
||||
|
||||
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,
|
||||
@@ -756,8 +668,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 builder(*block);
|
||||
builder.build_tree_view(*tree_view);
|
||||
|
@@ -1161,3 +1161,40 @@ bool file_draw_hint_if_invalid(const bContext *C, const SpaceFile *sfile, ARegio
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void file_view_preview_grid_draw(const bContext *C, ARegion *region)
|
||||
{
|
||||
SpaceFile *sfile = CTX_wm_space_file(C);
|
||||
// bScreen *screen = CTX_wm_screen(C);
|
||||
View2D *v2d = ®ion->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, &asset_space_ptr);
|
||||
// PropertyRNA *active_asset_idx_prop = RNA_struct_find_property(&asset_space_ptr,
|
||||
// "active_asset_idx");
|
||||
|
||||
file_grid_view_create_in_layout(sfile->files, 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);
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ struct ARegion;
|
||||
struct ARegionType;
|
||||
struct AssetLibrary;
|
||||
struct FileAssetSelectParams;
|
||||
struct FileList;
|
||||
struct FileSelectParams;
|
||||
struct SpaceFile;
|
||||
struct View2D;
|
||||
@@ -38,6 +39,7 @@ void file_draw_list(const bContext *C, ARegion *region);
|
||||
* \return true if the list is invalid and a hint was drawn.
|
||||
*/
|
||||
bool file_draw_hint_if_invalid(const bContext *C, const SpaceFile *sfile, ARegion *region);
|
||||
void file_view_preview_grid_draw(const bContext *C, ARegion *region);
|
||||
|
||||
void file_draw_check_ex(bContext *C, struct ScrArea *area);
|
||||
void file_draw_check(bContext *C);
|
||||
@@ -196,29 +198,14 @@ void file_tile_boundbox(const ARegion *region, FileLayout *layout, int file, rct
|
||||
*/
|
||||
void file_path_to_ui_path(const char *path, char *r_pathi, int max_size);
|
||||
|
||||
/* file_view_grid.cc */
|
||||
|
||||
void file_grid_view_create_in_layout(struct FileList *files,
|
||||
const View2D *v2d,
|
||||
struct uiLayout *layout);
|
||||
|
||||
/* asset_catalog_tree_view.cc */
|
||||
|
||||
/* C-handle for #ed::asset_browser::AssetCatalogFilterSettings. */
|
||||
typedef struct FileAssetCatalogFilterSettingsHandle FileAssetCatalogFilterSettingsHandle;
|
||||
|
||||
FileAssetCatalogFilterSettingsHandle *file_create_asset_catalog_filter_settings(void);
|
||||
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 struct AssetLibrary *asset_library);
|
||||
bool file_is_asset_visible_in_catalog_filter_settings(
|
||||
const FileAssetCatalogFilterSettingsHandle *filter_settings_handle,
|
||||
const AssetMetaData *asset_data);
|
||||
|
||||
void file_create_asset_catalog_tree_view_in_layout(struct AssetLibrary *asset_library,
|
||||
struct uiLayout *layout,
|
||||
struct SpaceFile *space_file,
|
||||
|
190
source/blender/editors/space_file/file_view_grid.cc
Normal file
190
source/blender/editors/space_file/file_view_grid.cc
Normal file
@@ -0,0 +1,190 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup spfile
|
||||
*/
|
||||
|
||||
#include "DNA_ID_enums.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_icons.h"
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
/* TODO temp for static ImBuf -> icon_id map. */
|
||||
#include "BLI_map.hh"
|
||||
#include "IMB_imbuf.h"
|
||||
|
||||
#include "ED_fileselect.h"
|
||||
|
||||
#include "UI_grid_view.hh"
|
||||
#include "UI_interface.h"
|
||||
#include "UI_interface.hh"
|
||||
|
||||
#include "file_intern.h"
|
||||
#include "filelist.h"
|
||||
|
||||
namespace blender::ed::file_browser {
|
||||
|
||||
class FilePreviewGridView : public ui::AbstractGridView {
|
||||
friend class FilePreviewGridItem;
|
||||
|
||||
FileList &files_;
|
||||
|
||||
public:
|
||||
FilePreviewGridView(FileList &filelist);
|
||||
void build_items() override;
|
||||
|
||||
BIFIconID file_preview_icon_id_get(const FileDirEntry &file);
|
||||
};
|
||||
|
||||
class FilePreviewGridItem : public ui::PreviewGridItem {
|
||||
const FileDirEntry &file_;
|
||||
std::string file_identifier_;
|
||||
/* Index in the file list. */
|
||||
const int file_idx_;
|
||||
|
||||
public:
|
||||
FilePreviewGridItem(const FileDirEntry &file, int file_idx);
|
||||
|
||||
void build_grid_tile(uiLayout &layout) const override;
|
||||
|
||||
FileList &get_file_list() const;
|
||||
void icon_mono_color_get(uchar r_mono_color[4]);
|
||||
void add_big_combined_file_icon(uiLayout &overlap) const;
|
||||
};
|
||||
|
||||
FilePreviewGridView::FilePreviewGridView(FileList &files) : files_(files)
|
||||
{
|
||||
}
|
||||
|
||||
void FilePreviewGridView::build_items()
|
||||
{
|
||||
|
||||
const int numfiles = filelist_files_ensure(&files_);
|
||||
|
||||
for (int file_idx = 0; file_idx < numfiles; file_idx++) {
|
||||
const FileDirEntry *file = filelist_file(&files_, file_idx);
|
||||
|
||||
add_item<FilePreviewGridItem>(*file, file_idx);
|
||||
}
|
||||
}
|
||||
|
||||
FilePreviewGridItem::FilePreviewGridItem(const FileDirEntry &file, const int file_idx)
|
||||
: ui::PreviewGridItem(file.relpath, file.name),
|
||||
file_(file),
|
||||
/* Get a copy so the identifier is always available (the file data may be freed). */
|
||||
file_identifier_(identifier_),
|
||||
file_idx_(file_idx)
|
||||
{
|
||||
/* Update reference so we don't point into the possibly freed file data. */
|
||||
/* TODO always store the identifier as std::string in the item base class? Avoids these issues.
|
||||
*/
|
||||
identifier_ = file_identifier_;
|
||||
}
|
||||
|
||||
FileList &FilePreviewGridItem::get_file_list() const
|
||||
{
|
||||
const FilePreviewGridView &view = dynamic_cast<const FilePreviewGridView &>(get_view());
|
||||
return view.files_;
|
||||
}
|
||||
|
||||
static BIFIconID file_big_file_icon_get(const FileDirEntry &file)
|
||||
{
|
||||
/* TODO temp!! Needs proper lifetime/memory management */
|
||||
static Map<const ImBuf *, BIFIconID> imbuf_icon_map;
|
||||
|
||||
ImBuf *imb = filelist_file_geticon_image(&file);
|
||||
return imbuf_icon_map.lookup_or_add_cb(imb,
|
||||
[&]() { return (BIFIconID)BKE_icon_imbuf_create(imb); });
|
||||
}
|
||||
|
||||
static void file_icon_mono_color_get(const FileDirEntry &file, uchar r_col[4])
|
||||
{
|
||||
uchar col[4] = {255, 255, 255, 255};
|
||||
if (file.typeflag & FILE_TYPE_DIR) {
|
||||
UI_GetThemeColor4ubv(TH_ICON_FOLDER, col);
|
||||
}
|
||||
else {
|
||||
UI_GetThemeColor4ubv(TH_TEXT, col);
|
||||
}
|
||||
|
||||
const bool is_hidden = (file.attributes & FILE_ATTR_HIDDEN);
|
||||
if (is_hidden) {
|
||||
col[3] *= 0.3f;
|
||||
}
|
||||
|
||||
copy_v4_v4_uchar(r_col, col);
|
||||
}
|
||||
|
||||
void FilePreviewGridItem::add_big_combined_file_icon(uiLayout &layout) const
|
||||
{
|
||||
uiLayout *overlap = uiLayoutOverlap(&layout);
|
||||
|
||||
BIFIconID file_icon_id = file_big_file_icon_get(file_);
|
||||
uiBut *preview_but = nullptr;
|
||||
if (file_icon_id != ICON_NONE) {
|
||||
uchar mono_col[4];
|
||||
file_icon_mono_color_get(file_, mono_col);
|
||||
|
||||
preview_but = add_preview_button(*overlap, file_icon_id, mono_col);
|
||||
}
|
||||
|
||||
/* Smaller file type icon in the middle of image, scaled to fit container and UI scale */
|
||||
{
|
||||
float icon_opacity = 0.3f;
|
||||
uchar icon_color[4] = {0, 0, 0, 255};
|
||||
float bgcolor[4];
|
||||
UI_GetThemeColor4fv(TH_ICON_FOLDER, bgcolor);
|
||||
if (rgb_to_grayscale(bgcolor) < 0.5f) {
|
||||
icon_color[0] = 255;
|
||||
icon_color[1] = 255;
|
||||
icon_color[2] = 255;
|
||||
}
|
||||
icon_color[3] *= icon_opacity;
|
||||
|
||||
FileList &files = get_file_list();
|
||||
const int icon_id = filelist_geticon(&files, file_idx_, false);
|
||||
|
||||
// uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_CENTER);
|
||||
const ui::GridViewStyle &style = get_view().get_style();
|
||||
int icon_size = style.tile_width / 3.5f;
|
||||
|
||||
uiLayout *col = uiLayoutColumn(overlap, false);
|
||||
uiBlock *block = uiLayoutGetBlock(col);
|
||||
|
||||
/* Add padding to vertically center the icon. */
|
||||
const rcti preview_img_rect = UI_preview_tile_but_preview_rect_get(preview_but);
|
||||
const int icon_ofs_y = style.tile_height - BLI_rcti_cent_y(&preview_img_rect) -
|
||||
(icon_size * ((file_.typeflag & FILE_TYPE_DIR) ? 0.78f : 0.75f)) / 2;
|
||||
uiDefButPadding(block, 0, 0, 0, icon_ofs_y);
|
||||
uiDefButPreviewTile(block, icon_id, "", 0, 0, icon_size, icon_size, icon_color);
|
||||
}
|
||||
}
|
||||
|
||||
void FilePreviewGridItem::build_grid_tile(uiLayout &layout) const
|
||||
{
|
||||
uiLayout &overlap = *uiLayoutOverlap(&layout);
|
||||
add_big_combined_file_icon(overlap);
|
||||
}
|
||||
|
||||
} // namespace blender::ed::file_browser
|
||||
|
||||
namespace ui = blender::ui;
|
||||
using namespace blender::ed::file_browser;
|
||||
|
||||
void file_grid_view_create_in_layout(FileList *files, const View2D *v2d, uiLayout *layout)
|
||||
{
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
UI_block_layout_set_current(block, layout);
|
||||
|
||||
ui::AbstractGridView *grid_view = UI_block_add_view(
|
||||
*block, "file preview grid view", std::make_unique<FilePreviewGridView>(*files));
|
||||
|
||||
ui::GridViewBuilder builder(*block);
|
||||
builder.build_grid_view(*grid_view, *v2d);
|
||||
}
|
@@ -55,6 +55,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.h"
|
||||
#include "ED_screen.h"
|
||||
@@ -356,7 +357,7 @@ typedef struct FileListFilter {
|
||||
char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
|
||||
short flags;
|
||||
|
||||
FileAssetCatalogFilterSettingsHandle *asset_catalog_filter;
|
||||
AssetViewCatalogFilterSettingsHandle *asset_catalog_filter;
|
||||
} FileListFilter;
|
||||
|
||||
/** #FileListFilter.flags */
|
||||
@@ -955,7 +956,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,
|
||||
filelist->asset_library);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -985,7 +987,7 @@ 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(
|
||||
if (filter->asset_catalog_filter && !asset_view_is_asset_visible_in_catalog_filter_settings(
|
||||
filter->asset_catalog_filter, asset_data)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1177,17 +1179,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) {
|
||||
@@ -1330,6 +1331,11 @@ ImBuf *filelist_geticon_image(struct FileList *filelist, const int index)
|
||||
return filelist_geticon_image_ex(file);
|
||||
}
|
||||
|
||||
ImBuf *filelist_file_geticon_image(const FileDirEntry *file)
|
||||
{
|
||||
return filelist_geticon_image_ex(file);
|
||||
}
|
||||
|
||||
static int filelist_geticon_ex(const FileDirEntry *file,
|
||||
const char *root,
|
||||
const bool is_main,
|
||||
@@ -1612,34 +1618,37 @@ static int filelist_intern_free_main_files(FileListIntern *filelist_intern)
|
||||
return removed_counter;
|
||||
}
|
||||
|
||||
int /* ThumbSource */ 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 {
|
||||
BLI_assert_unreachable();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdata)
|
||||
{
|
||||
FileListEntryCache *cache = BLI_task_pool_user_data(pool);
|
||||
FileListEntryPreviewTaskData *preview_taskdata = taskdata;
|
||||
FileListEntryPreview *preview = preview_taskdata->preview;
|
||||
|
||||
ThumbSource source = 0;
|
||||
ThumbSource source = 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_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;
|
||||
}
|
||||
|
||||
IMB_thumb_path_lock(preview->filepath);
|
||||
/* Always generate biggest preview size for now, it's simpler and avoids having to re-generate
|
||||
@@ -1936,7 +1945,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 = NULL;
|
||||
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(struct FileList *filelist,
|
||||
|
@@ -66,12 +66,11 @@ void filelist_setfilter_options(struct FileList *filelist,
|
||||
void filelist_setindexer(struct FileList *filelist, const struct 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(
|
||||
struct FileList *filelist,
|
||||
eFileSel_Params_AssetCatalogVisibility catalog_visibility,
|
||||
const struct bUUID *catalog_id);
|
||||
void filelist_set_asset_catalog_filter_options(struct FileList *filelist,
|
||||
AssetCatalogFilterMode catalog_visibility,
|
||||
const struct bUUID *catalog_id);
|
||||
void filelist_tag_needs_filtering(struct FileList *filelist);
|
||||
void filelist_filter(struct FileList *filelist);
|
||||
/**
|
||||
@@ -86,7 +85,9 @@ struct ImBuf *filelist_getimage(struct FileList *filelist, int index);
|
||||
struct ImBuf *filelist_file_getimage(const FileDirEntry *file);
|
||||
struct ImBuf *filelist_geticon_image_ex(const FileDirEntry *file);
|
||||
struct ImBuf *filelist_geticon_image(struct FileList *filelist, int index);
|
||||
struct ImBuf *filelist_file_geticon_image(const FileDirEntry *file);
|
||||
int filelist_geticon(struct FileList *filelist, int index, bool is_main);
|
||||
int /* ThumbSource */ filelist_preview_source_get(int /* eFileSel_File_Types */ file_type);
|
||||
|
||||
struct FileList *filelist_new(short type);
|
||||
void filelist_settype(struct FileList *filelist, short type);
|
||||
|
@@ -484,7 +484,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, NULL);
|
||||
}
|
||||
|
@@ -653,7 +653,13 @@ static void file_main_region_draw(const bContext *C, ARegion *region)
|
||||
file_highlight_set(sfile, region, event->xy[0], event->xy[1]);
|
||||
}
|
||||
|
||||
if (!file_draw_hint_if_invalid(C, sfile, region)) {
|
||||
if (file_draw_hint_if_invalid(C, sfile, region)) {
|
||||
/* Pass. */
|
||||
}
|
||||
else if (params->display == FILE_IMGDISPLAY) {
|
||||
file_view_preview_grid_draw(C, region);
|
||||
}
|
||||
else {
|
||||
file_draw_list(C, region);
|
||||
}
|
||||
|
||||
|
@@ -122,6 +122,7 @@ typedef struct AssetLibraryReference {
|
||||
#
|
||||
typedef struct AssetHandle {
|
||||
const struct FileDirEntry *file_data;
|
||||
struct PreviewImage *preview;
|
||||
} AssetHandle;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -824,10 +824,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 */
|
||||
@@ -1029,12 +1029,6 @@ typedef enum eFileSel_Params_Flag {
|
||||
FILE_FILTER_ASSET_CATALOG = (1 << 15),
|
||||
} eFileSel_Params_Flag;
|
||||
|
||||
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.
|
||||
@@ -2027,6 +2021,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)
|
||||
* \{ */
|
||||
@@ -2066,9 +2096,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 */
|
||||
|
@@ -492,6 +492,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];
|
||||
@@ -509,7 +510,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;
|
||||
|
@@ -59,13 +59,17 @@ static int rna_AssetTag_editable(PointerRNA *ptr, const char **r_info)
|
||||
{
|
||||
AssetTag *asset_tag = 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 :
|
||||
0;
|
||||
}
|
||||
|
@@ -140,6 +140,14 @@ static PointerRNA rna_Context_asset_file_handle_get(PointerRNA *ptr)
|
||||
return newptr;
|
||||
}
|
||||
|
||||
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), &newptr);
|
||||
return newptr;
|
||||
}
|
||||
|
||||
static PointerRNA rna_Context_main_get(PointerRNA *ptr)
|
||||
{
|
||||
bContext *C = (bContext *)ptr->data;
|
||||
@@ -298,6 +306,11 @@ void RNA_def_context(BlenderRNA *brna)
|
||||
"The file of an active asset. Avoid using this, it will be replaced by "
|
||||
"a proper AssetHandle design");
|
||||
|
||||
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", NULL, NULL, NULL);
|
||||
|
||||
/* Data */
|
||||
prop = RNA_def_property(srna, "blend_data", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
@@ -164,6 +164,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",
|
||||
@@ -605,6 +610,8 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr)
|
||||
return &RNA_SpaceClipEditor;
|
||||
case SPACE_SPREADSHEET:
|
||||
return &RNA_SpaceSpreadsheet;
|
||||
case SPACE_ASSETS:
|
||||
return &RNA_SpaceAssetBrowser;
|
||||
|
||||
/* Currently no type info. */
|
||||
case SPACE_SCRIPT:
|
||||
@@ -847,6 +854,20 @@ static void rna_Space_show_region_hud_update(bContext *C, PointerRNA *ptr)
|
||||
rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_HUD, RGN_FLAG_HIDDEN_BY_USER);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
@@ -3316,6 +3337,29 @@ static int rna_FileAssetSelectParams_catalog_id_length(PointerRNA *UNUSED(ptr))
|
||||
return UUID_STRING_LEN - 1;
|
||||
}
|
||||
|
||||
static int RNA_SpaceAssetBrowser_asset_library_get(PointerRNA *ptr)
|
||||
{
|
||||
SpaceAssets *asset_space = 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 = 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 = ptr->data;
|
||||
BLI_uuid_format(value, settings->active_catalog_id);
|
||||
}
|
||||
|
||||
static int rna_AssetCatalogFilterSettings_active_catalog_id_length(PointerRNA *UNUSED(ptr))
|
||||
{
|
||||
return UUID_STRING_LEN - 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static const EnumPropertyItem dt_uv_items[] = {
|
||||
@@ -3413,6 +3457,10 @@ static void rna_def_space_generic_show_region_toggles(StructRNA *srna, int regio
|
||||
region_type_mask &= ~(1 << RGN_TYPE_HUD);
|
||||
DEF_SHOW_REGION_PROPERTY(show_region_hud, "Adjust Last Operation", "");
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -8019,6 +8067,83 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SPREADSHEET, NULL);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -8046,6 +8171,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
|
||||
|
@@ -2449,6 +2449,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;
|
||||
@@ -3854,6 +3874,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
|
||||
{12, "OUTLINER", ICON_OUTLINER, "Outliner", ""},
|
||||
{14, "PREFERENCES", ICON_PREFERENCES, "Preferences", ""},
|
||||
{15, "INFO", ICON_INFO, "Info", ""},
|
||||
{24, "ASSET_BROWSER", ICON_ASSET_MANAGER, "Asset Browser", ""},
|
||||
{16, "FILE_BROWSER", ICON_FILEBROWSER, "File Browser", ""},
|
||||
{17, "CONSOLE", ICON_CONSOLE, "Python Console", ""},
|
||||
{20, "CLIP_EDITOR", ICON_TRACKER, "Movie Clip Editor", ""},
|
||||
@@ -3994,6 +4015,13 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "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);
|
||||
@@ -4239,6 +4267,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);
|
||||
|
@@ -484,10 +484,9 @@ typedef struct wmNotifier {
|
||||
#define ND_SPACE_SPREADSHEET (22 << 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
|
||||
|
@@ -607,6 +607,10 @@ static void wm_file_read_pre(bContext *C, bool use_data, bool UNUSED(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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -411,6 +411,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, 0);
|
||||
}
|
||||
/* 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, 0);
|
||||
|
Reference in New Issue
Block a user