Blender  V3.3
node_geometry_attribute_search.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "BLI_index_range.hh"
4 #include "BLI_listbase.h"
5 #include "BLI_map.hh"
6 #include "BLI_rect.h"
7 #include "BLI_set.hh"
8 #include "BLI_string_ref.hh"
9 #include "BLI_string_search.h"
10 
11 #include "DNA_modifier_types.h"
12 #include "DNA_node_types.h"
13 #include "DNA_object_types.h"
14 #include "DNA_space_types.h"
15 
16 #include "BKE_context.h"
17 #include "BKE_node_tree_update.h"
18 #include "BKE_object.h"
19 
20 #include "RNA_access.h"
21 #include "RNA_enum_types.h"
22 
23 #include "ED_node.h"
24 #include "ED_screen.h"
25 #include "ED_undo.h"
26 
27 #include "BLT_translation.h"
28 
29 #include "UI_interface.h"
30 #include "UI_interface.hh"
31 #include "UI_resources.h"
32 
34 
35 #include "node_intern.hh"
36 
39 
40 namespace blender::ed::space_node {
41 
45 };
46 
47 /* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */
48 BLI_STATIC_ASSERT(std::is_trivially_destructible_v<AttributeSearchData>, "");
49 
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  }
64  if (node == nullptr) {
66  return {};
67  }
68 
69  /* For the attribute input node, collect attribute information from all nodes in the group. */
70  if (node->type == GEO_NODE_INPUT_NAMED_ATTRIBUTE) {
72  *snode);
73  if (tree_log == nullptr) {
74  return {};
75  }
76 
79  tree_log->foreach_node_log([&](const geo_log::NodeLog &node_log) {
80  for (const geo_log::SocketLog &socket_log : node_log.input_logs()) {
81  const geo_log::ValueLog *value_log = socket_log.value();
82  if (const geo_log::GeometryValueLog *geo_value_log =
83  dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) {
84  for (const GeometryAttributeInfo &attribute : geo_value_log->attributes()) {
85  if (bke::allow_procedural_attribute_access(attribute.name)) {
86  if (names.add(attribute.name)) {
87  attributes.append(&attribute);
88  }
89  }
90  }
91  }
92  }
93  });
94  return attributes;
95  }
96 
98  *snode, data.node_name);
99  if (node_log == nullptr) {
100  return {};
101  }
102  return node_log->lookup_available_attributes();
103 }
104 
106  const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
107 {
109  return;
110  }
111 
112  AttributeSearchData *data = static_cast<AttributeSearchData *>(arg);
113 
115 
116  ui::attribute_search_add_items(str, true, infos, items, is_first);
117 }
118 
124 {
125  switch (type) {
126  case CD_PROP_FLOAT:
127  case CD_PROP_INT32:
128  case CD_PROP_FLOAT3:
129  case CD_PROP_COLOR:
130  case CD_PROP_BOOL:
131  return type;
132  case CD_PROP_BYTE_COLOR:
133  return CD_PROP_COLOR;
134  case CD_PROP_STRING:
135  /* Unsupported currently. */
136  return CD_PROP_FLOAT;
137  case CD_PROP_FLOAT2:
138  /* No 2D vector sockets currently. */
139  return CD_PROP_FLOAT3;
140  case CD_PROP_INT8:
141  return CD_PROP_INT32;
142  default:
143  return CD_PROP_FLOAT;
144  }
145 }
146 
147 static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
148 {
150  return;
151  }
153  if (item == nullptr) {
154  return;
155  }
156  SpaceNode *snode = CTX_wm_space_node(C);
157  if (!snode) {
159  return;
160  }
161  bNodeTree *node_tree = snode->edittree;
162  if (node_tree == nullptr) {
164  return;
165  }
166  AttributeSearchData *data = static_cast<AttributeSearchData *>(data_v);
167  bNode *node = nodeFindNodebyName(node_tree, data->node_name);
168  if (node == nullptr) {
170  return;
171  }
172  bNodeSocket *socket = bke::node_find_enabled_input_socket(*node, data->socket_identifier);
173  if (socket == nullptr) {
175  return;
176  }
177  BLI_assert(socket->type == SOCK_STRING);
178 
179  /* For the attribute input node, also adjust the type and links connected to the output. */
180  if (node->type == GEO_NODE_INPUT_NAMED_ATTRIBUTE && item->data_type.has_value()) {
183  if (new_type != storage.data_type) {
184  storage.data_type = new_type;
185  /* Make the output socket with the new type on the attribute input node active. */
186  node->typeinfo->updatefunc(node_tree, node);
187 
188  /* Relink all node links to the newly active output socket. */
189  bNodeSocket *output_socket = bke::node_find_enabled_output_socket(*node, "Attribute");
190  LISTBASE_FOREACH (bNodeLink *, link, &node_tree->links) {
191  if (link->fromnode == node) {
192  link->fromsock = output_socket;
194  }
195  }
196  }
199  }
200 
201  bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket->default_value);
202  BLI_strncpy(value->value, item->name.c_str(), MAX_NAME);
203 
204  ED_undo_push(C, "Assign Attribute Name");
205 }
206 
208  const bNode &node,
209  PointerRNA &socket_ptr,
210  uiLayout &layout)
211 {
212  uiBlock *block = uiLayoutGetBlock(&layout);
213  uiBut *but = uiDefIconTextButR(block,
215  0,
216  ICON_NONE,
217  "",
218  0,
219  0,
220  10 * UI_UNIT_X, /* Dummy value, replaced by layout system. */
221  UI_UNIT_Y,
222  &socket_ptr,
223  "default_value",
224  0,
225  0.0f,
226  0.0f,
227  0.0f,
228  0.0f,
229  "");
230 
231  const bNodeSocket &socket = *static_cast<const bNodeSocket *>(socket_ptr.data);
232  AttributeSearchData *data = MEM_new<AttributeSearchData>(__func__);
233  BLI_strncpy(data->node_name, node.name, sizeof(data->node_name));
234  BLI_strncpy(data->socket_identifier, socket.identifier, sizeof(data->socket_identifier));
235 
239  nullptr,
241  static_cast<void *>(data),
242  true,
243  nullptr,
245  nullptr);
246 }
247 
248 } // namespace blender::ed::space_node
struct SpaceNode * CTX_wm_space_node(const bContext *C)
Definition: context.c:878
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct bNode * nodeFindNodebyName(struct bNodeTree *ntree, const char *name)
Definition: node.cc:1992
#define GEO_NODE_INPUT_NAMED_ATTRIBUTE
Definition: BKE_node.h:1498
void BKE_ntree_update_tag_node_property(struct bNodeTree *ntree, struct bNode *node)
void BKE_ntree_update_tag_link_changed(struct bNodeTree *ntree)
General operations, lookup, etc. for blender objects.
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define UNUSED(x)
eCustomDataType
@ CD_PROP_BYTE_COLOR
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_PROP_COLOR
@ CD_PROP_INT8
@ CD_PROP_INT32
@ CD_PROP_FLOAT2
@ CD_PROP_BOOL
@ CD_PROP_STRING
#define MAX_NAME
Definition: DNA_defs.h:48
@ SOCK_STRING
Object is a sort of wrapper for general info.
void ED_node_tree_propagate_change(const struct bContext *C, struct Main *bmain, struct bNodeTree *ntree)
bScreen * ED_screen_animation_playing(const struct wmWindowManager *wm)
void ED_undo_push(struct bContext *C, const char *str)
Definition: ed_undo.c:100
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
static void attribute_search_update_fn(const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
Definition: MOD_nodes.cc:1352
static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
Definition: MOD_nodes.cc:1383
#define C
Definition: RandGen.cpp:25
#define UI_UNIT_Y
uiBlock * uiLayoutGetBlock(uiLayout *layout)
void UI_but_func_search_set_results_are_suggestions(uiBut *but, bool value)
Definition: interface.cc:6324
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)
Definition: interface.cc:6242
uiBut * uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:5709
void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string)
Definition: interface.cc:6308
#define UI_UNIT_X
@ UI_BTYPE_SEARCH_MENU
Definition: UI_interface.h:372
static const NodeLog * find_node_by_node_editor_context(const SpaceNode &snode, const bNode &node)
static const TreeLog * find_tree_by_node_editor_context(const SpaceNode &snode)
Vector< const GeometryAttributeInfo * > lookup_available_attributes() const
void foreach_node_log(FunctionRef< void(const NodeLog &)> fn) const
OperationNode * node
#define str(s)
static char ** names
Definition: makesdna.c:65
bNodeSocket * node_find_enabled_output_socket(bNode &node, StringRef name)
Definition: node.cc:1482
bNodeSocket * node_find_enabled_input_socket(bNode &node, StringRef name)
Definition: node.cc:1477
BLI_STATIC_ASSERT(std::is_trivially_destructible_v< AttributeSearchData >, "")
void node_geometry_add_attribute_search_button(const bContext &UNUSED(C), const bNode &node, PointerRNA &socket_ptr, uiLayout &layout)
static eCustomDataType data_type_in_attribute_input_node(const eCustomDataType type)
static Vector< const GeometryAttributeInfo * > get_attribute_info_from_context(const bContext &C, AttributeSearchData &data)
void attribute_search_add_items(StringRefNull str, bool can_create_attribute, Span< const nodes::geometry_nodes_eval_log::GeometryAttributeInfo * > infos, uiSearchItems *items, bool is_first)
#define UI_MENU_ARROW_SEP
void * data
Definition: RNA_types.h:38
struct bNodeTree * edittree
void * default_value
char identifier[64]