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:
committed by
Pablo Vazquez
parent
8b9e667eab
commit
7a01f736a5
@@ -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'}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user