Nodes: Make context path breadcrumbs interactive

Make it possible to navigate in/out node groups through the breacrumbs
context path overlay.

See PR for details and screenshots.

Pull Request: https://projects.blender.org/blender/blender/pulls/141292
This commit is contained in:
Maxime-Cots
2025-08-20 17:53:34 +02:00
committed by Pablo Vazquez
parent 8b9e667eab
commit 7a01f736a5
5 changed files with 51 additions and 10 deletions

View File

@@ -328,6 +328,12 @@ class NODE_OT_tree_path_parent(Operator):
bl_label = "Parent Node Tree"
bl_options = {'REGISTER', 'UNDO'}
parent_tree_index: IntProperty(
name="Parent Index",
description="Parent index in context path",
default=0,
)
@classmethod
def poll(cls, context):
space = context.space_data
@@ -337,7 +343,9 @@ class NODE_OT_tree_path_parent(Operator):
def execute(self, context):
space = context.space_data
space.path.pop()
parent_number_to_pop = len(space.path) - 1 - self.parent_tree_index
for _ in range(parent_number_to_pop):
space.path.pop()
return {'FINISHED'}

View File

@@ -193,7 +193,8 @@ class NODE_HT_header(Header):
layout.separator_spacer()
if len(snode.path) > 1:
layout.operator("node.tree_path_parent", text="", icon='FILE_PARENT')
op = layout.operator("node.tree_path_parent", text="", icon='FILE_PARENT')
op.parent_tree_index = len(snode.path) - 2
# Backdrop
if is_compositor:

View File

@@ -76,12 +76,15 @@ struct ContextPathItem {
/* #BIFIconID */
int icon;
int icon_indicator_number;
std::function<void(bContext &)> handle_func;
};
void context_path_add_generic(Vector<ContextPathItem> &path,
StructRNA &rna_type,
void *ptr,
const BIFIconID icon_override = ICON_NONE);
const BIFIconID icon_override = ICON_NONE,
std::function<void(bContext &)> handle_func = nullptr);
void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path);

View File

@@ -6,6 +6,7 @@
* \ingroup edinterface
*/
#include "BLF_api.hh"
#include "BLI_vector.hh"
#include "RNA_access.hh"
@@ -21,7 +22,8 @@ namespace blender::ui {
void context_path_add_generic(Vector<ContextPathItem> &path,
StructRNA &rna_type,
void *ptr,
const BIFIconID icon_override)
const BIFIconID icon_override,
std::function<void(bContext &)> handle_func)
{
/* Add the null check here to make calling functions less verbose. */
if (!ptr) {
@@ -38,10 +40,10 @@ void context_path_add_generic(Vector<ContextPathItem> &path,
if (&rna_type == &RNA_NodeTree) {
ID *id = (ID *)ptr;
path.append({name, icon, ID_REAL_USERS(id)});
path.append({name, icon, ID_REAL_USERS(id), handle_func});
}
else {
path.append({name, icon, 1});
path.append({name, icon, 1, handle_func});
}
if (name != name_buf) {
MEM_freeN(name);
@@ -64,8 +66,15 @@ void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path)
if (i > 0) {
sub_row->label("", ICON_RIGHTARROW_THIN);
}
uiBut *but = uiItemL_ex(
sub_row, context_path[i].name.c_str(), context_path[i].icon, false, false);
uiBut *but;
int icon = context_path[i].icon;
std::string name = context_path[i].name;
if (context_path[i].handle_func) {
but = sub_row->button(name.c_str(), icon, context_path[i].handle_func);
}
else {
but = uiItemL_ex(sub_row, name.c_str(), icon, false, false);
}
UI_but_icon_indicator_number_set(but, context_path[i].icon_indicator_number);
}
}

View File

@@ -16,10 +16,13 @@
#include "BKE_material.hh"
#include "BKE_object.hh"
#include "RNA_access.hh"
#include "RNA_prototypes.hh"
#include "ED_screen.hh"
#include "WM_api.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
@@ -52,8 +55,25 @@ static void context_path_add_node_tree_and_node_groups(const SpaceNode &snode,
Vector<ui::ContextPathItem> &path,
const bool skip_base = false)
{
LISTBASE_FOREACH (const bNodeTreePath *, path_item, &snode.treepath) {
if (!(skip_base && path_item == snode.treepath.first)) {
int i = 0;
LISTBASE_FOREACH_INDEX (const bNodeTreePath *, path_item, &snode.treepath, i) {
if (skip_base && path_item == snode.treepath.first) {
continue;
}
if (path_item != snode.treepath.last) {
// We don't need to add handle function to last nodetree
ui::context_path_add_generic(
path, RNA_NodeTree, path_item->nodetree, ICON_NODETREE, [i](bContext &C) {
PointerRNA op_props;
wmOperatorType *ot = WM_operatortype_find("NODE_OT_tree_path_parent", false);
WM_operator_properties_create_ptr(&op_props, ot);
RNA_int_set(&op_props, "parent_tree_index", i);
WM_operator_name_call_ptr(
&C, ot, blender::wm::OpCallContext::InvokeDefault, &op_props, nullptr);
WM_operator_properties_free(&op_props);
});
}
else {
ui::context_path_add_generic(path, RNA_NodeTree, path_item->nodetree, ICON_NODETREE);
}
}