diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/include/ED_node.h | 1 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.hh | 25 | ||||
-rw-r--r-- | source/blender/editors/interface/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_context_path.cc | 85 | ||||
-rw-r--r-- | source/blender/editors/space_node/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_context_path.cc | 184 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_draw.cc | 39 | ||||
-rw-r--r-- | source/blender/editors/space_node/node_intern.h | 8 | ||||
-rw-r--r-- | source/blender/editors/space_node/space_node.c | 21 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_gpencil_modifier.c | 4 |
10 files changed, 337 insertions, 32 deletions
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 1ba52552902..e68617f7867 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -64,7 +64,6 @@ void ED_node_cursor_location_set(struct SpaceNode *snode, const float value[2]); int ED_node_tree_path_length(struct SpaceNode *snode); void ED_node_tree_path_get(struct SpaceNode *snode, char *value); -void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length); void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh index 5edccfa8c88..b14ee6c4a59 100644 --- a/source/blender/editors/include/UI_interface.hh +++ b/source/blender/editors/include/UI_interface.hh @@ -23,15 +23,40 @@ #include <memory> #include "BLI_string_ref.hh" +#include "BLI_vector.hh" + +#include "UI_resources.h" namespace blender::nodes::geometry_nodes_eval_log { struct GeometryAttributeInfo; } struct uiBlock; +struct StructRNA; +struct uiSearchItems; + namespace blender::ui { + class AbstractTreeView; +/** + * An item in a breadcrumb-like context. Currently this struct is very simple, but more + * could be added to it in the future, to support interactivity or tooltips, for example. + */ +struct ContextPathItem { + /* Text to display in the UI. */ + std::string name; + /* #BIFIconID */ + int icon; +}; + +void context_path_add_generic(Vector<ContextPathItem> &path, + StructRNA &rna_type, + void *ptr, + const BIFIconID icon_override = ICON_NONE); + +void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path); + void attribute_search_add_items( StringRefNull str, const bool is_output, diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index b2659f5ed52..84172c7efce 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -43,6 +43,7 @@ set(SRC interface_anim.c interface_button_group.c interface_context_menu.c + interface_context_path.cc interface_draw.c interface_dropboxes.cc interface_eyedropper.c diff --git a/source/blender/editors/interface/interface_context_path.cc b/source/blender/editors/interface/interface_context_path.cc new file mode 100644 index 00000000000..b0f8d186afa --- /dev/null +++ b/source/blender/editors/interface/interface_context_path.cc @@ -0,0 +1,85 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2021 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edinterface + */ + +#include "BLI_vector.hh" + +#include "BKE_screen.h" + +#include "RNA_access.h" + +#include "ED_screen.h" + +#include "UI_interface.h" +#include "UI_interface.hh" +#include "UI_resources.h" + +#include "WM_api.h" + +namespace blender::ui { + +void context_path_add_generic(Vector<ContextPathItem> &path, + StructRNA &rna_type, + void *ptr, + const BIFIconID icon_override) +{ + /* Add the null check here to make calling functions less verbose. */ + if (!ptr) { + return; + } + + PointerRNA rna_ptr; + RNA_pointer_create(nullptr, &rna_type, ptr, &rna_ptr); + char name[128]; + RNA_struct_name_get_alloc(&rna_ptr, name, sizeof(name), nullptr); + + /* Use a blank icon by default to check whether to retrieve it automatically from the type. */ + const BIFIconID icon = icon_override == ICON_NONE ? + static_cast<BIFIconID>(RNA_struct_ui_icon(rna_ptr.type)) : + icon_override; + + path.append({name, static_cast<int>(icon)}); +} + +/* -------------------------------------------------------------------- */ +/** \name Breadcrumb Template + * \{ */ + +void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path) +{ + uiLayout *row = uiLayoutRow(&layout, true); + uiLayoutSetAlignment(&layout, UI_LAYOUT_ALIGN_LEFT); + + for (const int i : context_path.index_range()) { + uiLayout *sub_row = uiLayoutRow(row, true); + uiLayoutSetAlignment(sub_row, UI_LAYOUT_ALIGN_LEFT); + + if (i > 0) { + uiItemL(sub_row, "", ICON_RIGHTARROW_THIN); + } + uiItemL(sub_row, context_path[i].name.c_str(), context_path[i].icon); + } +} + +} // namespace blender::ui + +/** \} */
\ No newline at end of file diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index 80d3b43bf6b..600309c2c86 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -40,6 +40,7 @@ set(INC set(SRC drawnode.cc node_add.cc + node_context_path.cc node_draw.cc node_edit.cc node_geometry_attribute_search.cc diff --git a/source/blender/editors/space_node/node_context_path.cc b/source/blender/editors/space_node/node_context_path.cc new file mode 100644 index 00000000000..a0ff7f3ce25 --- /dev/null +++ b/source/blender/editors/space_node/node_context_path.cc @@ -0,0 +1,184 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup spnode + * \brief Node breadcrumbs drawing + */ + +#include "BLI_vector.hh" + +#include "DNA_node_types.h" + +#include "BKE_context.h" +#include "BKE_material.h" +#include "BKE_modifier.h" +#include "BKE_object.h" + +#include "BKE_screen.h" + +#include "RNA_access.h" + +#include "ED_screen.h" + +#include "UI_interface.h" +#include "UI_interface.hh" +#include "UI_resources.h" + +#include "UI_interface.hh" + +#include "node_intern.h" + +struct Mesh; +struct Curve; +struct Light; +struct World; +struct Material; + +namespace blender::ed::space_node { + +static void context_path_add_object_data(Vector<ui::ContextPathItem> &path, Object &object) +{ + if (object.type == OB_MESH && object.data) { + Mesh *mesh = (Mesh *)object.data; + ui::context_path_add_generic(path, RNA_Mesh, mesh); + } + if (object.type == OB_LAMP && object.data) { + Light *light = (Light *)object.data; + ui::context_path_add_generic(path, RNA_Light, light); + } + if (ELEM(object.type, OB_CURVE, OB_FONT, OB_SURF) && object.data) { + Curve *curve = (Curve *)object.data; + ui::context_path_add_generic(path, RNA_Curve, curve); + } +} + +static void context_path_add_node_tree_and_node_groups(const SpaceNode &snode, + Vector<ui::ContextPathItem> &path, + const bool skip_base = false) +{ + Vector<const bNodeTreePath *> tree_path = snode.treepath; + for (const bNodeTreePath *path_item : tree_path.as_span().drop_front(int(skip_base))) { + ui::context_path_add_generic(path, RNA_NodeTree, path_item->nodetree, ICON_NODETREE); + } +} + +static void get_context_path_node_shader(const bContext &C, + SpaceNode &snode, + Vector<ui::ContextPathItem> &path) +{ + if (snode.flag & SNODE_PIN) { + if (snode.shaderfrom == SNODE_SHADER_WORLD) { + Scene *scene = CTX_data_scene(&C); + ui::context_path_add_generic(path, RNA_Scene, scene); + if (scene != nullptr) { + World *world = scene->world; + ui::context_path_add_generic(path, RNA_World, world); + } + /* Skip the base node tree here, because the world contains a node tree already. */ + context_path_add_node_tree_and_node_groups(snode, path, true); + } + else { + context_path_add_node_tree_and_node_groups(snode, path); + } + } + else { + Object *object = CTX_data_active_object(&C); + if (snode.shaderfrom == SNODE_SHADER_OBJECT && object != nullptr) { + ui::context_path_add_generic(path, RNA_Object, object); + if (!(object->matbits && object->matbits[object->actcol - 1])) { + context_path_add_object_data(path, *object); + } + Material *material = BKE_object_material_get(object, object->actcol); + ui::context_path_add_generic(path, RNA_Material, material); + } + else if (snode.shaderfrom == SNODE_SHADER_WORLD) { + Scene *scene = CTX_data_scene(&C); + ui::context_path_add_generic(path, RNA_Scene, scene); + if (scene != nullptr) { + World *world = scene->world; + ui::context_path_add_generic(path, RNA_World, world); + } + } +#ifdef WITH_FREESTYLE + else if (snode.shaderfrom == SNODE_SHADER_LINESTYLE) { + ViewLayer *viewlayer = CTX_data_view_layer(&C); + FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(viewlayer); + ui::context_path_add_generic(path, RNA_ViewLayer, viewlayer); + Material *mat = BKE_object_material_get(object, object->actcol); + ui::context_path_add_generic(path, RNA_Material, mat); + } +#endif + context_path_add_node_tree_and_node_groups(snode, path, true); + } +} + +static void get_context_path_node_compositor(const bContext &C, + SpaceNode &snode, + Vector<ui::ContextPathItem> &path) +{ + if (snode.flag & SNODE_PIN) { + context_path_add_node_tree_and_node_groups(snode, path); + } + else { + Scene *scene = CTX_data_scene(&C); + ui::context_path_add_generic(path, RNA_Scene, scene); + context_path_add_node_tree_and_node_groups(snode, path); + } +} + +static void get_context_path_node_geometry(const bContext &C, + SpaceNode &snode, + Vector<ui::ContextPathItem> &path) +{ + if (snode.flag & SNODE_PIN) { + context_path_add_node_tree_and_node_groups(snode, path); + } + else { + Object *object = CTX_data_active_object(&C); + ui::context_path_add_generic(path, RNA_Object, object); + ModifierData *modifier = BKE_object_active_modifier(object); + ui::context_path_add_generic(path, RNA_Modifier, modifier, ICON_MODIFIER); + context_path_add_node_tree_and_node_groups(snode, path); + } +} + +Vector<ui::ContextPathItem> context_path_for_space_node(const bContext &C) +{ + SpaceNode *snode = CTX_wm_space_node(&C); + if (snode == nullptr) { + return {}; + } + + Vector<ui::ContextPathItem> context_path; + + if (snode->edittree->type == NTREE_GEOMETRY) { + get_context_path_node_geometry(C, *snode, context_path); + } + else if (snode->edittree->type == NTREE_SHADER) { + get_context_path_node_shader(C, *snode, context_path); + } + else if (snode->edittree->type == NTREE_COMPOSIT) { + get_context_path_node_compositor(C, *snode, context_path); + } + + return context_path; +} + +} // namespace blender::ed::space_node diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 9e91d394fef..ea65eaa0a14 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -71,8 +71,10 @@ #include "ED_gpencil.h" #include "ED_node.h" +#include "ED_screen.h" #include "ED_space_api.h" +#include "UI_interface.hh" #include "UI_resources.h" #include "UI_view2d.h" @@ -2158,15 +2160,34 @@ void node_draw_nodetree(const bContext *C, } } -/* Draw tree path info in lower left corner. */ -static void draw_tree_path(SpaceNode *snode) +/* Draw the breadcrumb on the bottom of the editor. */ +static void draw_tree_path(const bContext &C, ARegion ®ion) { - char info[256]; + using namespace blender; - ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info)); + GPU_matrix_push_projection(); + wmOrtho2_region_pixelspace(®ion); - UI_FontThemeColor(BLF_default(), TH_TEXT_HI); - BLF_draw_default(1.5f * UI_UNIT_X, 1.5f * UI_UNIT_Y, 0.0f, info, sizeof(info)); + const rcti *rect = ED_region_visible_rect(®ion); + + const uiStyle *style = UI_style_get_dpi(); + const float padding_x = 16 * UI_DPI_FAC; + const int x = rect->xmin + padding_x; + const int y = region.winy - UI_UNIT_Y * 0.6f; + const int width = BLI_rcti_size_x(rect) - 2 * padding_x; + + uiBlock *block = UI_block_begin(&C, ®ion, __func__, UI_EMBOSS_NONE); + uiLayout *layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y, width, 1, 0, style); + + Vector<ui::ContextPathItem> context_path = ed::space_node::context_path_for_space_node(C); + ui::template_breadcrumbs(*layout, context_path); + + UI_block_layout_resolve(block, nullptr, nullptr); + UI_block_end(&C, block); + UI_block_draw(&C, block); + + GPU_matrix_pop_projection(); } static void snode_setup_v2d(SpaceNode *snode, ARegion *region, const float center[2]) @@ -2336,8 +2357,10 @@ void node_draw_space(const bContext *C, ARegion *region) } } - /* Tree path info. */ - draw_tree_path(snode); + /* Draw context path. */ + if (snode->edittree) { + draw_tree_path(*C, *region); + } /* Scrollers. */ UI_view2d_scrollers_draw(v2d, nullptr); diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index f069038cc09..e7d9a12a52c 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -341,3 +341,11 @@ extern const char *node_context_dir[]; #ifdef __cplusplus } #endif + +#ifdef __cplusplus +# include "BLI_vector.hh" +# include "UI_interface.hh" +namespace blender::ed::space_node { +Vector<ui::ContextPathItem> context_path_for_space_node(const bContext &C); +} +#endif
\ No newline at end of file diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 8c015a56fa1..0b5d7cdda82 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -201,27 +201,6 @@ void ED_node_tree_path_get(SpaceNode *snode, char *value) } } -void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_length) -{ - int size; - - value[0] = '\0'; - int i = 0; - LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) { - if (i == 0) { - size = BLI_strncpy_rlen(value, path->display_name, max_length); - } - else { - size = BLI_snprintf_rlen(value, max_length, "/%s", path->display_name); - } - max_length -= size; - if (max_length <= 0) { - break; - } - value += size; - } -} - void ED_node_set_active_viewer_key(SpaceNode *snode) { bNodeTreePath *path = snode->treepath.last; diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index fdce35ba2de..79125e5d40e 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -3211,8 +3211,8 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna) "Stroke Depth Offset", "Move strokes slightly towards the camera to avoid clipping while " "preserve depth for the viewport"); - RNA_def_property_range(prop, 0.0f, FLT_MAX); - RNA_def_property_ui_range(prop, 0.0f, 0.5f, 0.001f, 4); + RNA_def_property_ui_range(prop, 0.0, 0.5, 0.001, 4); + RNA_def_property_range(prop, -0.1, FLT_MAX); RNA_def_property_update(prop, NC_SCENE, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "offset_towards_custom_camera", PROP_BOOLEAN, PROP_NONE); |