Blender V4.3
node_geometry_attribute_search.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_index_range.hh"
6#include "BLI_listbase.h"
7#include "BLI_map.hh"
8#include "BLI_rect.h"
9#include "BLI_set.hh"
10#include "BLI_string.h"
11#include "BLI_string_ref.hh"
12
13#include "DNA_modifier_types.h"
14#include "DNA_node_types.h"
15#include "DNA_object_types.h"
16#include "DNA_space_types.h"
17
18#include "BKE_context.hh"
19#include "BKE_node_runtime.hh"
22#include "BKE_object.hh"
23
24#include "RNA_access.hh"
25#include "RNA_enum_types.hh"
26
27#include "ED_node.hh"
28#include "ED_screen.hh"
29#include "ED_undo.hh"
30
31#include "BLT_translation.hh"
32
33#include "UI_interface.hh"
34#include "UI_resources.hh"
35
37#include "NOD_socket.hh"
38
39#include "node_intern.hh"
40
42
44
49
50/* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */
51BLI_STATIC_ASSERT(std::is_trivially_destructible_v<AttributeSearchData>, "");
52
54 const bContext &C, AttributeSearchData &data)
55{
56 using namespace nodes::geo_eval_log;
57
58 SpaceNode *snode = CTX_wm_space_node(&C);
59 if (!snode) {
61 return {};
62 }
64 if (node_tree == nullptr) {
66 return {};
67 }
68 const bNode *node = node_tree->node_by_id(data.node_id);
69 if (node == nullptr) {
71 return {};
72 }
73 const bke::bNodeTreeZones *tree_zones = node_tree->zones();
74 if (!tree_zones) {
75 return {};
76 }
78 GeoModifierLog::get_tree_log_by_zone_for_node_editor(*snode);
79
80 Set<StringRef> names;
81
82 /* For the attribute input node, collect attribute information from all nodes in the group. */
83 if (node->type == GEO_NODE_INPUT_NAMED_ATTRIBUTE) {
85 for (GeoTreeLog *tree_log : log_by_zone.values()) {
86 tree_log->ensure_socket_values();
87 tree_log->ensure_existing_attributes();
88 for (const GeometryAttributeInfo *attribute : tree_log->existing_attributes) {
89 if (!names.add(attribute->name)) {
90 continue;
91 }
92 if (!bke::allow_procedural_attribute_access(attribute->name)) {
93 continue;
94 }
95 attributes.append(attribute);
96 }
97 }
98 return attributes;
99 }
100 const bke::bNodeTreeZone *zone = tree_zones->get_zone_by_node(node->identifier);
101 GeoTreeLog *tree_log = log_by_zone.lookup_default(zone, nullptr);
102 if (!tree_log) {
103 return {};
104 }
105 tree_log->ensure_socket_values();
106 GeoNodeLog *node_log = tree_log->nodes.lookup_ptr(node->identifier);
107 if (node_log == nullptr) {
108 return {};
109 }
110
112 for (const bNodeSocket *input_socket : node->input_sockets()) {
113 if (input_socket->type != SOCK_GEOMETRY) {
114 continue;
115 }
116 const ValueLog *value_log = tree_log->find_socket_value_log(*input_socket);
117 if (value_log == nullptr) {
118 continue;
119 }
120 if (const GeometryInfoLog *geo_log = dynamic_cast<const GeometryInfoLog *>(value_log)) {
121 for (const GeometryAttributeInfo &attribute : geo_log->attributes) {
122 if (bke::allow_procedural_attribute_access(attribute.name)) {
123 if (names.add(attribute.name)) {
124 attributes.append(&attribute);
125 }
126 }
127 }
128 }
129 }
130 return attributes;
131}
132
134 const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
135{
137 return;
138 }
139
140 AttributeSearchData *data = static_cast<AttributeSearchData *>(arg);
141
143
144 ui::attribute_search_add_items(str, true, infos, items, is_first);
145}
146
152{
153 switch (type) {
154 case CD_PROP_FLOAT:
155 case CD_PROP_INT32:
156 case CD_PROP_FLOAT3:
157 case CD_PROP_COLOR:
158 case CD_PROP_BOOL:
160 case CD_PROP_FLOAT4X4:
161 return type;
163 return CD_PROP_COLOR;
164 case CD_PROP_STRING:
165 /* Unsupported currently. */
166 return CD_PROP_FLOAT;
167 case CD_PROP_FLOAT2:
168 case CD_PROP_INT32_2D:
169 /* No 2D vector sockets currently. */
170 return CD_PROP_FLOAT3;
171 case CD_PROP_INT8:
172 return CD_PROP_INT32;
173 default:
174 return CD_PROP_FLOAT;
175 }
176}
177
178static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
179{
181 return;
182 }
184 if (item == nullptr) {
185 return;
186 }
187 SpaceNode *snode = CTX_wm_space_node(C);
188 if (!snode) {
190 return;
191 }
192 bNodeTree *node_tree = snode->edittree;
193 if (node_tree == nullptr) {
195 return;
196 }
197 AttributeSearchData *data = static_cast<AttributeSearchData *>(data_v);
198 bNode *node = node_tree->node_by_id(data->node_id);
199 if (node == nullptr) {
201 return;
202 }
203
204 /* For the attribute input node, also adjust the type and links connected to the output. */
205 if (node->type == GEO_NODE_INPUT_NAMED_ATTRIBUTE && item->data_type.has_value()) {
207 node->storage);
209 if (new_type != storage.data_type) {
210 storage.data_type = new_type;
211 /* Make the output socket with the new type on the attribute input node active. */
215 }
216 }
217
218 bNodeSocket *socket = bke::node_find_enabled_input_socket(*node, data->socket_identifier);
219 if (socket == nullptr) {
221 return;
222 }
223 BLI_assert(socket->type == SOCK_STRING);
224
225 bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket->default_value);
226 BLI_strncpy(value->value, item->name.c_str(), MAX_NAME);
227
228 ED_undo_push(C, "Assign Attribute Name");
229}
230
232 const bNode &node,
233 PointerRNA &socket_ptr,
234 uiLayout &layout,
235 const StringRefNull placeholder)
236{
237 uiBlock *block = uiLayoutGetBlock(&layout);
238 uiBut *but = uiDefIconTextButR(block,
240 0,
241 ICON_NONE,
242 "",
243 0,
244 0,
245 10 * UI_UNIT_X, /* Dummy value, replaced by layout system. */
246 UI_UNIT_Y,
247 &socket_ptr,
248 "default_value",
249 0,
250 0.0f,
251 0.0f,
252 "");
253 UI_but_placeholder_set(but, placeholder.c_str());
254
255 const bNodeSocket &socket = *static_cast<const bNodeSocket *>(socket_ptr.data);
256 AttributeSearchData *data = MEM_cnew<AttributeSearchData>(__func__);
257 data->node_id = node.identifier;
258 STRNCPY(data->socket_identifier, socket.identifier);
259
263 nullptr,
265 static_cast<void *>(data),
266 true,
267 nullptr,
269 nullptr);
270}
271
272} // namespace blender::ed::space_node
SpaceNode * CTX_wm_space_node(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
void BKE_ntree_update_tag_node_property(bNodeTree *ntree, bNode *node)
General operations, lookup, etc. for blender objects.
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:87
#define BLI_assert(a)
Definition BLI_assert.h:50
#define STRNCPY(dst, src)
Definition BLI_string.h:593
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
@ CD_PROP_BYTE_COLOR
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_PROP_INT32_2D
@ CD_PROP_COLOR
@ CD_PROP_QUATERNION
@ CD_PROP_INT32
@ CD_PROP_FLOAT2
@ CD_PROP_STRING
@ CD_PROP_FLOAT4X4
#define MAX_NAME
Definition DNA_defs.h:50
@ SOCK_GEOMETRY
@ SOCK_STRING
Object is a sort of wrapper for general info.
void ED_node_tree_propagate_change(const bContext *C, Main *bmain, bNodeTree *ntree)
Definition node_edit.cc:492
bScreen * ED_screen_animation_playing(const wmWindowManager *wm)
void ED_undo_push(bContext *C, const char *str)
Definition ed_undo.cc:104
#define UI_UNIT_Y
void UI_but_placeholder_set(uiBut *but, const char *placeholder_text) ATTR_NONNULL(1)
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)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
uiBut * uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, PointerRNA *ptr, const char *propname, int index, float min, float max, const char *tip)
void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string)
#define UI_UNIT_X
@ UI_BTYPE_SEARCH_MENU
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:531
ValueIterator values() const
Definition BLI_map.hh:846
bool add(const Key &key)
Definition BLI_set.hh:248
constexpr const char * c_str() const
void append(const T &value)
const bNodeTreeZone * get_zone_by_node(const int32_t node_id) const
Vector< std::unique_ptr< bNodeTreeZone > > zones
#define str(s)
bNodeSocket * node_find_enabled_input_socket(bNode &node, StringRef name)
Definition node.cc:1863
bool allow_procedural_attribute_access(StringRef attribute_name)
static Vector< const GeometryAttributeInfo * > get_attribute_info_from_context(const bContext &C, AttributeSearchData &data)
static eCustomDataType data_type_in_attribute_input_node(const eCustomDataType type)
static void attribute_search_update_fn(const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
void node_geometry_add_attribute_search_button(const bContext &, const bNode &node, PointerRNA &socket_ptr, uiLayout &layout, const StringRefNull placeholder)
static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
void update_node_declaration_and_sockets(bNodeTree &ntree, bNode &node)
void attribute_search_add_items(StringRefNull str, bool can_create_attribute, Span< const nodes::geo_eval_log::GeometryAttributeInfo * > infos, uiSearchItems *items, bool is_first)
signed int int32_t
Definition stdint.h:77
#define UI_MENU_ARROW_SEP
void * data
Definition RNA_types.hh:42
struct bNodeTree * edittree
void * default_value
char identifier[64]