Compositor: add asset shelf

Add an asset shelf to the compositor node editor.

This is part of simplifying the compositing workflow:
https://projects.blender.org/blender/blender/issues/134214.

The reasoning is:
- Assets will help users get started more easily with compositing
- Assets will help keeping users within Blender and use the compositor
instead of doing post processing in a different software.
- The asset shelf is better than the asset browser because it has a
better user interface; it's easily hidable and doesn't take much space

The asset shelf is hidden by default in this PR, since we have no
assets yet.

Previously, a similar implementation was proposed for all node editors,
see https://projects.blender.org/blender/blender/pulls/110589.
We didn't move forward with this PR for the following reasons:
- For geometry nodes, no concrete use case was known/proposed
- The PR didn't intend to actually show the asset shelf, only
implement the possibility that it can be shown in node editors

Known Issues:
- Can't hide the asset shelf if region overlap is off: #129737

Pull Request: https://projects.blender.org/blender/blender/pulls/138983
This commit is contained in:
Habib Gahbiche
2025-07-30 18:41:00 +02:00
parent 7186ab7e86
commit 0a0dd4ca37
8 changed files with 119 additions and 3 deletions

View File

@@ -1184,6 +1184,20 @@ def node_panel(cls):
return node_cls
class NODE_AST_compositor(bpy.types.AssetShelf):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
@classmethod
def poll(cls, context):
return context.space_data.tree_type == 'CompositorNodeTree'
@classmethod
def asset_poll(cls, asset):
compositing_type = bpy.types.NodeTree.bl_rna.properties["type"].enum_items["COMPOSITING"]
return asset.id_type == 'NODETREE' and asset.metadata.get("type") == compositing_type.value
classes = (
NODE_HT_header,
NODE_MT_editor_menus,
@@ -1216,6 +1230,7 @@ classes = (
NODE_PT_overlay,
NODE_PT_active_node_properties,
NODE_PT_gizmo_display,
NODE_AST_compositor,
node_panel(EEVEE_MATERIAL_PT_settings),
node_panel(EEVEE_MATERIAL_PT_settings_surface),

View File

@@ -27,7 +27,7 @@
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 45
#define BLENDER_FILE_SUBVERSION 46
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@@ -1961,6 +1961,42 @@ void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
FOREACH_NODETREE_END;
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 46)) {
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
if (sl->spacetype != SPACE_NODE) {
continue;
}
const SpaceNode *snode = reinterpret_cast<SpaceNode *>(sl);
if (!STREQ(snode->tree_idname, "CompositorNodeTree")) {
continue;
}
ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
&sl->regionbase;
if (ARegion *new_shelf_region = do_versions_add_region_if_not_found(
regionbase,
RGN_TYPE_ASSET_SHELF,
"Asset shelf for compositing (versioning)",
RGN_TYPE_HEADER))
{
new_shelf_region->alignment = RGN_ALIGN_BOTTOM;
}
if (ARegion *new_shelf_header = do_versions_add_region_if_not_found(
regionbase,
RGN_TYPE_ASSET_SHELF_HEADER,
"Asset shelf header for compositing (versioning)",
RGN_TYPE_ASSET_SHELF))
{
new_shelf_header->alignment = RGN_ALIGN_BOTTOM | RGN_ALIGN_HIDE_WITH_PREV;
}
}
}
}
}
/**
* Always bump subversion in BKE_blender_version.h when adding versioning
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.

View File

@@ -1433,7 +1433,12 @@ bool ED_region_is_overlap(int spacetype, int regiontype)
}
if (U.uiflag2 & USER_REGION_OVERLAP) {
if (spacetype == SPACE_NODE) {
if (ELEM(regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI)) {
if (ELEM(regiontype,
RGN_TYPE_TOOLS,
RGN_TYPE_UI,
RGN_TYPE_ASSET_SHELF,
RGN_TYPE_ASSET_SHELF_HEADER))
{
return true;
}
}

View File

@@ -12,6 +12,7 @@ set(INC
../../compositor/utilities
../../makesrna
../../nodes/geometry/include
../asset
# RNA_prototypes.hh
${CMAKE_BINARY_DIR}/source/blender/makesrna

View File

@@ -42,6 +42,7 @@
#include "BLT_translation.hh"
#include "ED_asset_shelf.hh"
#include "ED_image.hh"
#include "ED_node.hh"
#include "ED_node_preview.hh"
@@ -1048,6 +1049,21 @@ static SpaceLink *node_create(const ScrArea * /*area*/, const Scene * /*scene*/)
region->regiontype = RGN_TYPE_HEADER;
region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
/* asset shelf */
region = BKE_area_region_new();
BLI_addtail(&snode->regionbase, region);
region->regiontype = RGN_TYPE_ASSET_SHELF;
region->alignment = RGN_ALIGN_BOTTOM;
region->flag |= RGN_FLAG_HIDDEN;
/* asset shelf header */
region = BKE_area_region_new();
BLI_addtail(&snode->regionbase, region);
region->regiontype = RGN_TYPE_ASSET_SHELF_HEADER;
region->alignment = RGN_ALIGN_BOTTOM | RGN_ALIGN_HIDE_WITH_PREV;
/* buttons/list view */
region = BKE_area_region_new();
@@ -2212,10 +2228,21 @@ static void node_space_blend_write(BlendWriter *writer, SpaceLink *sl)
}
}
static void node_asset_shelf_region_init(wmWindowManager *wm, ARegion *region)
{
using namespace blender::ed;
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Node Generic", SPACE_NODE, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
asset::shelf::region_init(wm, region);
}
} // namespace blender::ed::space_node
void ED_spacetype_node()
{
using namespace blender::ed;
using namespace blender::ed::space_node;
std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
@@ -2273,6 +2300,36 @@ void ED_spacetype_node()
BLI_addhead(&st->regiontypes, art);
/* regions: asset shelf */
art = MEM_callocN<ARegionType>("spacetype node asset shelf region");
art->regionid = RGN_TYPE_ASSET_SHELF;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_ASSET_SHELF | ED_KEYMAP_FRAMES;
art->duplicate = asset::shelf::region_duplicate;
art->free = asset::shelf::region_free;
art->on_poll_success = asset::shelf::region_on_poll_success;
art->listener = asset::shelf::region_listen;
art->message_subscribe = asset::shelf::region_message_subscribe;
art->poll = asset::shelf::regions_poll;
art->snap_size = asset::shelf::region_snap;
art->on_user_resize = asset::shelf::region_on_user_resize;
art->context = asset::shelf::context;
art->init = node_asset_shelf_region_init;
art->layout = asset::shelf::region_layout;
art->draw = asset::shelf::region_draw;
BLI_addhead(&st->regiontypes, art);
/* regions: asset shelf header */
art = MEM_callocN<ARegionType>("spacetype node asset shelf header region");
art->regionid = RGN_TYPE_ASSET_SHELF_HEADER;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_ASSET_SHELF | ED_KEYMAP_VIEW2D | ED_KEYMAP_FOOTER;
art->init = asset::shelf::header_region_init;
art->poll = asset::shelf::regions_poll;
art->draw = asset::shelf::header_region;
art->listener = asset::shelf::header_region_listen;
art->context = asset::shelf::context;
BLI_addhead(&st->regiontypes, art);
asset::shelf::types_register(art, SPACE_NODE);
/* regions: list-view/buttons */
art = MEM_callocN<ARegionType>("spacetype node region");
art->regionid = RGN_TYPE_UI;

View File

@@ -8064,7 +8064,8 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SpaceNode");
RNA_def_struct_ui_text(srna, "Space Node Editor", "Node editor space data");
rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_TOOLS) | (1 << RGN_TYPE_UI));
rna_def_space_generic_show_region_toggles(
srna, (1 << RGN_TYPE_TOOLS) | (1 << RGN_TYPE_UI) | (1 << RGN_TYPE_ASSET_SHELF));
prop = RNA_def_property(srna, "tree_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_dummy_DEFAULT_items);

View File

@@ -3276,6 +3276,7 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
rna_def_userdef_theme_spaces_main(srna);
rna_def_userdef_theme_spaces_region_main(srna);
rna_def_userdef_theme_spaces_list_main(srna);
prop = RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);