Blender V4.5
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
10#include "DNA_node_types.h"
11#include "DNA_space_types.h"
12
13#include "BKE_context.hh"
16#include "BKE_node_runtime.hh"
19
20#include "RNA_access.hh"
21#include "RNA_enum_types.hh"
22
23#include "ED_node.hh"
24#include "ED_screen.hh"
25#include "ED_undo.hh"
26
27#include "UI_interface.hh"
28#include "UI_resources.hh"
29
31#include "NOD_socket.hh"
32
33#include "node_intern.hh"
34
36
38
43
44/* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */
45BLI_STATIC_ASSERT(std::is_trivially_destructible_v<LayerSearchData>, "");
46
49{
50 using namespace nodes::geo_eval_log;
51
52 SpaceNode *snode = CTX_wm_space_node(&C);
53 if (!snode) {
55 return {};
56 }
57 bNodeTree *node_tree = snode->edittree;
58 if (node_tree == nullptr) {
60 return {};
61 }
62 const bNode *node = node_tree->node_by_id(data.node_id);
63 if (node == nullptr) {
65 return {};
66 }
67 const bke::bNodeTreeZones *tree_zones = node_tree->zones();
68 if (!tree_zones) {
69 return {};
70 }
71 const ContextualGeoTreeLogs tree_logs = GeoNodesLog::get_contextual_tree_logs(*snode);
72
73 Set<StringRef> names;
74
75 /* For the named layer selection input node, collect layer names from all nodes in the group. */
78 tree_logs.foreach_tree_log([&](GeoTreeLog &tree_log) {
79 tree_log.ensure_socket_values();
80 tree_log.ensure_layer_names();
81 for (const std::string &name : tree_log.all_layer_names) {
82 if (!names.add(name)) {
83 continue;
84 }
85 layer_names.append(&name);
86 }
87 });
88 return layer_names;
89 }
90 GeoTreeLog *tree_log = tree_logs.get_main_tree_log(*node);
91 if (!tree_log) {
92 return {};
93 }
94 tree_log->ensure_socket_values();
95 GeoNodeLog *node_log = tree_log->nodes.lookup_ptr(node->identifier);
96 if (node_log == nullptr) {
97 return {};
98 }
99
100 Vector<const std::string *> layer_names;
101 for (const bNodeSocket *input_socket : node->input_sockets()) {
102 if (input_socket->type != SOCK_GEOMETRY) {
103 continue;
104 }
105 const ValueLog *value_log = tree_log->find_socket_value_log(*input_socket);
106 if (value_log == nullptr) {
107 continue;
108 }
109 if (const GeometryInfoLog *geo_log = dynamic_cast<const GeometryInfoLog *>(value_log)) {
110 if (const std::optional<GeometryInfoLog::GreasePencilInfo> &grease_pencil_info =
111 geo_log->grease_pencil_info)
112 {
113 for (const std::string &name : grease_pencil_info->layer_names) {
114 if (names.add(name)) {
115 layer_names.append(&name);
116 }
117 }
118 }
119 }
120 }
121 return layer_names;
122}
123
125 const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
126{
128 return;
129 }
130
131 LayerSearchData *data = static_cast<LayerSearchData *>(arg);
132
134
135 BLI_assert(items);
136 ui::grease_pencil_layer_search_add_items(str, names, *items, is_first);
137}
138
139static void layer_search_exec_fn(bContext *C, void *data_v, void *item_v)
140{
142 return;
143 }
144 std::string *item = static_cast<std::string *>(item_v);
145 if (item == nullptr) {
146 return;
147 }
148 SpaceNode *snode = CTX_wm_space_node(C);
149 if (!snode) {
151 return;
152 }
153 bNodeTree *node_tree = snode->edittree;
154 if (node_tree == nullptr) {
156 return;
157 }
158 LayerSearchData *data = static_cast<LayerSearchData *>(data_v);
159 bNode *node = node_tree->node_by_id(data->node_id);
160 if (node == nullptr) {
162 return;
163 }
164
165 bNodeSocket *socket = bke::node_find_enabled_input_socket(*node, data->socket_identifier);
166 if (socket == nullptr) {
168 return;
169 }
170 BLI_assert(socket->type == SOCK_STRING);
171
172 bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket->default_value);
173 BLI_strncpy(value->value, item->c_str(), MAX_NAME);
174
175 ED_undo_push(C, "Assign Layer Name");
176}
177
179 const bNode &node,
180 PointerRNA &socket_ptr,
181 uiLayout &layout,
182 const StringRef placeholder)
183{
184 uiBlock *block = uiLayoutGetBlock(&layout);
185 uiBut *but = uiDefIconTextButR(block,
187 0,
188 ICON_OUTLINER_DATA_GP_LAYER,
189 "",
190 0,
191 0,
192 10 * UI_UNIT_X, /* Dummy value, replaced by layout system. */
193 UI_UNIT_Y,
194 &socket_ptr,
195 "default_value",
196 0,
197 0.0f,
198 0.0f,
199 "");
200 UI_but_placeholder_set(but, placeholder);
201
202 const bNodeSocket &socket = *static_cast<const bNodeSocket *>(socket_ptr.data);
204 data->node_id = node.identifier;
205 STRNCPY(data->socket_identifier, socket.identifier);
206
210 nullptr,
212 static_cast<void *>(data),
213 true,
214 nullptr,
216 nullptr);
217}
218
219} // 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 * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
@ 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:99
#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)
uiBut * uiDefIconTextButR(uiBlock *block, int 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, float min, float max, std::optional< blender::StringRef > tip)
void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string)
#define UI_UNIT_X
@ UI_BTYPE_SEARCH_MENU
uiBlock * uiLayoutGetBlock(uiLayout *layout)
BMesh const char void * data
bool add(const Key &key)
Definition BLI_set.hh:248
void append(const T &value)
#define str(s)
#define MAX_NAME
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:2898
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)
#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