Blender V5.0
node_geometry_layer_search.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_map.hh"
6#include "BLI_set.hh"
7#include "BLI_string.h"
8#include "BLI_string_ref.hh"
9#include "BLI_string_utf8.h"
10
11#include "DNA_node_types.h"
12#include "DNA_space_types.h"
13
14#include "BKE_context.hh"
17#include "BKE_node_runtime.hh"
20
21#include "RNA_access.hh"
22#include "RNA_enum_types.hh"
23
24#include "ED_node.hh"
25#include "ED_screen.hh"
26#include "ED_undo.hh"
27
29#include "UI_resources.hh"
30
32#include "NOD_socket.hh"
33
34#include "node_intern.hh"
35
37
39
44
45/* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */
46BLI_STATIC_ASSERT(std::is_trivially_destructible_v<LayerSearchData>, "");
47
50{
51 using namespace nodes::geo_eval_log;
52
53 SpaceNode *snode = CTX_wm_space_node(&C);
54 if (!snode) {
56 return {};
57 }
58 bNodeTree *node_tree = snode->edittree;
59 if (node_tree == nullptr) {
61 return {};
62 }
63 const bNode *node = node_tree->node_by_id(data.node_id);
64 if (node == nullptr) {
66 return {};
67 }
68 const bke::bNodeTreeZones *tree_zones = node_tree->zones();
69 if (!tree_zones) {
70 return {};
71 }
72 const ContextualGeoTreeLogs tree_logs = GeoNodesLog::get_contextual_tree_logs(*snode);
73
74 Set<StringRef> names;
75
76 /* For the named layer selection input node, collect layer names from all nodes in the group. */
79 tree_logs.foreach_tree_log([&](GeoTreeLog &tree_log) {
80 tree_log.ensure_socket_values();
81 tree_log.ensure_layer_names();
82 for (const std::string &name : tree_log.all_layer_names) {
83 if (!names.add(name)) {
84 continue;
85 }
86 layer_names.append(&name);
87 }
88 });
89 return layer_names;
90 }
91 GeoTreeLog *tree_log = tree_logs.get_main_tree_log(*node);
92 if (!tree_log) {
93 return {};
94 }
95 tree_log->ensure_socket_values();
96 GeoNodeLog *node_log = tree_log->nodes.lookup_ptr(node->identifier);
97 if (node_log == nullptr) {
98 return {};
99 }
100
101 Vector<const std::string *> layer_names;
102 for (const bNodeSocket *input_socket : node->input_sockets()) {
103 if (input_socket->type != SOCK_GEOMETRY) {
104 continue;
105 }
106 const ValueLog *value_log = tree_log->find_socket_value_log(*input_socket);
107 if (value_log == nullptr) {
108 continue;
109 }
110 if (const GeometryInfoLog *geo_log = dynamic_cast<const GeometryInfoLog *>(value_log)) {
111 if (const std::optional<GeometryInfoLog::GreasePencilInfo> &grease_pencil_info =
112 geo_log->grease_pencil_info)
113 {
114 for (const std::string &name : grease_pencil_info->layer_names) {
115 if (names.add(name)) {
116 layer_names.append(&name);
117 }
118 }
119 }
120 }
121 }
122 return layer_names;
123}
124
126 const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
127{
129 return;
130 }
131
132 LayerSearchData *data = static_cast<LayerSearchData *>(arg);
133
135
136 BLI_assert(items);
137 ui::grease_pencil_layer_search_add_items(str, names, *items, is_first);
138}
139
140static void layer_search_exec_fn(bContext *C, void *data_v, void *item_v)
141{
143 return;
144 }
145 std::string *item = static_cast<std::string *>(item_v);
146 if (item == nullptr) {
147 return;
148 }
149 SpaceNode *snode = CTX_wm_space_node(C);
150 if (!snode) {
152 return;
153 }
154 bNodeTree *node_tree = snode->edittree;
155 if (node_tree == nullptr) {
157 return;
158 }
159 LayerSearchData *data = static_cast<LayerSearchData *>(data_v);
160 bNode *node = node_tree->node_by_id(data->node_id);
161 if (node == nullptr) {
163 return;
164 }
165
166 bNodeSocket *socket = bke::node_find_enabled_input_socket(*node, data->socket_identifier);
167 if (socket == nullptr) {
169 return;
170 }
171 BLI_assert(socket->type == SOCK_STRING);
172
173 bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket->default_value);
174 BLI_strncpy_utf8(value->value, item->c_str(), MAX_NAME);
175
176 ED_undo_push(C, "Assign Layer Name");
177}
178
180 const bNode &node,
181 PointerRNA &socket_ptr,
182 uiLayout &layout,
183 const StringRef placeholder)
184{
185 uiBlock *block = layout.block();
186 uiBut *but = uiDefIconTextButR(block,
188 0,
189 ICON_OUTLINER_DATA_GP_LAYER,
190 "",
191 0,
192 0,
193 10 * UI_UNIT_X, /* Dummy value, replaced by layout system. */
194 UI_UNIT_Y,
195 &socket_ptr,
196 "default_value",
197 0,
198 "");
199 UI_but_placeholder_set(but, placeholder);
200
201 const bNodeSocket &socket = *static_cast<const bNodeSocket *>(socket_ptr.data);
203 data->node_id = node.identifier;
204 STRNCPY_UTF8(data->socket_identifier, socket.identifier);
205
209 nullptr,
211 static_cast<void *>(data),
212 true,
213 nullptr,
215 nullptr);
216}
217
218} // namespace blender::ed::space_node
SpaceNode * CTX_wm_space_node(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
#define GEO_NODE_INPUT_NAMED_LAYER_SELECTION
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:83
#define BLI_assert(a)
Definition BLI_assert.h:46
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
#define MAX_NAME
Definition DNA_defs.h:50
@ SOCK_GEOMETRY
@ SOCK_STRING
bScreen * ED_screen_animation_playing(const wmWindowManager *wm)
void ED_undo_push(bContext *C, const char *str)
Definition ed_undo.cc:98
#define C
Definition RandGen.cpp:29
void UI_but_placeholder_set(uiBut *but, blender::StringRef placeholder_text)
#define UI_UNIT_Y
void UI_but_func_search_set_results_are_suggestions(uiBut *but, bool value)
void UI_but_func_search_set(uiBut *but, uiButSearchCreateFn search_create_fn, uiButSearchUpdateFn search_update_fn, void *arg, bool free_arg, uiFreeArgFunc search_arg_free_fn, uiButHandleFunc search_exec_fn, void *active)
void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string)
uiBut * uiDefIconTextButR(uiBlock *block, ButType type, int retval, int icon, std::optional< blender::StringRefNull > str, int x, int y, short width, short height, PointerRNA *ptr, blender::StringRefNull propname, int index, std::optional< blender::StringRef > tip)
#define UI_UNIT_X
bool add(const Key &key)
Definition BLI_set.hh:248
void append(const T &value)
#define str(s)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
bNodeSocket * node_find_enabled_input_socket(bNode &node, StringRef name)
Definition node.cc:2566
NodeLinkData data[NODELINK_GROUP_SIZE]
Definition drawnode.cc:1863
void node_geometry_add_layer_search_button(const bContext &, const bNode &node, PointerRNA &socket_ptr, uiLayout &layout, const StringRef placeholder)
static Vector< const std::string * > get_layer_names_from_context(const bContext &C, LayerSearchData &data)
static void layer_search_update_fn(const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
static void layer_search_exec_fn(bContext *C, void *data_v, void *item_v)
void grease_pencil_layer_search_add_items(StringRef str, Span< const std::string * > layer_names, uiSearchItems &items, bool is_first)
const char * name
#define UI_MENU_ARROW_SEP
void * data
Definition RNA_types.hh:53
struct bNodeTree * edittree
void * default_value
char identifier[64]
int16_t type_legacy
int32_t identifier
uiBlock * block() const