Blender  V2.93
node_geometry_attribute_search.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #include "BLI_index_range.hh"
18 #include "BLI_listbase.h"
19 #include "BLI_map.hh"
20 #include "BLI_set.hh"
21 #include "BLI_string_ref.hh"
22 #include "BLI_string_search.h"
23 
24 #include "DNA_modifier_types.h"
25 #include "DNA_node_types.h"
26 #include "DNA_object_types.h"
27 #include "DNA_space_types.h"
28 
29 #include "BKE_context.h"
30 #include "BKE_node_ui_storage.hh"
31 #include "BKE_object.h"
32 
33 #include "RNA_access.h"
34 #include "RNA_enum_types.h"
35 
36 #include "ED_undo.h"
37 
38 #include "BLT_translation.h"
39 
40 #include "UI_interface.h"
41 #include "UI_resources.h"
42 
43 #include "node_intern.h"
44 
46 using blender::Map;
47 using blender::Set;
48 using blender::StringRef;
49 
54 };
55 
56 /* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */
57 BLI_STATIC_ASSERT(std::is_trivially_destructible_v<AttributeSearchData>, "");
58 
60 {
61  const char *name = nullptr;
63  return StringRef(IFACE_(name));
64 }
65 
67 {
68  const char *name = nullptr;
70  return StringRef(IFACE_(name));
71 }
72 
73 /* Unicode arrow. */
74 #define MENU_SEP "\xe2\x96\xb6"
75 
77 {
78  const StringRef data_type_name = attribute_data_type_string(item.data_type);
79  const StringRef domain_name = attribute_domain_string(item.domain);
80  std::string search_item_text = domain_name + " " + MENU_SEP + item.name + UI_SEP_CHAR +
81  data_type_name;
82 
83  return UI_search_item_add(
84  items, search_item_text.c_str(), (void *)&item, ICON_NONE, UI_BUT_HAS_SEP_CHAR, 0);
85 }
86 
88  void *arg,
89  const char *str,
90  uiSearchItems *items,
91  const bool is_first)
92 {
93  AttributeSearchData *data = static_cast<AttributeSearchData *>(arg);
94 
95  const Set<AvailableAttributeInfo> &attribute_hints = data->ui_storage.attribute_hints;
96 
97  /* Any string may be valid, so add the current search string along with the hints. */
98  if (str[0] != '\0') {
99  /* Note that the attribute domain and data type are dummies, since
100  * #AvailableAttributeInfo equality is only based on the string. */
101  if (!attribute_hints.contains(AvailableAttributeInfo{str, ATTR_DOMAIN_AUTO, CD_PROP_BOOL})) {
102  data->dummy_info_for_search.name = std::string(str);
103  UI_search_item_add(items, str, &data->dummy_info_for_search, ICON_ADD, 0, 0);
104  }
105  }
106 
107  if (str[0] == '\0' && !is_first) {
108  /* Allow clearing the text field when the string is empty, but not on the first pass,
109  * or opening an attribute field for the first time would show this search item. */
110  data->dummy_info_for_search.name = std::string(str);
111  UI_search_item_add(items, str, &data->dummy_info_for_search, ICON_X, 0, 0);
112  }
113 
114  /* Don't filter when the menu is first opened, but still run the search
115  * so the items are in the same order they will appear in while searching. */
116  const char *string = is_first ? "" : str;
117 
119  for (const AvailableAttributeInfo &item : attribute_hints) {
120  BLI_string_search_add(search, item.name.c_str(), (void *)&item);
121  }
122 
123  AvailableAttributeInfo **filtered_items;
124  const int filtered_amount = BLI_string_search_query(search, string, (void ***)&filtered_items);
125 
126  for (const int i : IndexRange(filtered_amount)) {
127  const AvailableAttributeInfo *item = filtered_items[i];
128  if (!attribute_search_item_add(items, *item)) {
129  break;
130  }
131  }
132 
133  MEM_freeN(filtered_items);
134  BLI_string_search_free(search);
135 }
136 
137 static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
138 {
139  AttributeSearchData *data = static_cast<AttributeSearchData *>(data_v);
140  AvailableAttributeInfo *item = static_cast<AvailableAttributeInfo *>(item_v);
141 
142  bNodeSocket &socket = data->socket;
143  bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket.default_value);
144  BLI_strncpy(value->value, item->name.c_str(), MAX_NAME);
145 
146  ED_undo_push(C, "Assign Attribute Name");
147 }
148 
150  const bNodeTree *node_tree,
151  const bNode *node,
152  PointerRNA *socket_ptr,
153  uiLayout *layout)
154 {
156  C, *node_tree, *node);
157 
158  if (ui_storage == nullptr) {
159  uiItemR(layout, socket_ptr, "default_value", 0, "", 0);
160  return;
161  }
162 
163  const NodeTreeUIStorage *tree_ui_storage = node_tree->ui_storage;
164 
165  uiBlock *block = uiLayoutGetBlock(layout);
166  uiBut *but = uiDefIconTextButR(block,
168  0,
169  ICON_NONE,
170  "",
171  0,
172  0,
173  10 * UI_UNIT_X, /* Dummy value, replaced by layout system. */
174  UI_UNIT_Y,
175  socket_ptr,
176  "default_value",
177  0,
178  0.0f,
179  0.0f,
180  0.0f,
181  0.0f,
182  "");
183 
184  AttributeSearchData *data = OBJECT_GUARDED_NEW(AttributeSearchData,
185  {tree_ui_storage->dummy_info_for_search,
186  *ui_storage,
187  *static_cast<bNodeSocket *>(socket_ptr->data)});
188 
192  nullptr,
194  static_cast<void *>(data),
195  true,
196  nullptr,
198  nullptr);
199 }
AttributeDomain
Definition: BKE_attribute.h:41
const NodeUIStorage * BKE_node_tree_ui_storage_get_from_context(const bContext *C, const bNodeTree &ntree, const bNode &node)
General operations, lookup, etc. for blender objects.
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
void BLI_string_search_free(StringSearch *search)
void BLI_string_search_add(StringSearch *search, const char *str, void *user_data)
StringSearch * BLI_string_search_new(void)
int BLI_string_search_query(StringSearch *search, const char *query, void ***r_data)
#define UNUSED(x)
#define IFACE_(msgid)
CustomDataType
#define MAX_NAME
Definition: DNA_defs.h:62
Object is a sort of wrapper for general info.
void ED_undo_push(struct bContext *C, const char *str)
Definition: ed_undo.c:117
_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
#define C
Definition: RandGen.cpp:39
#define UI_UNIT_Y
uiBlock * uiLayoutGetBlock(uiLayout *layout)
@ UI_BUT_HAS_SEP_CHAR
Definition: UI_interface.h:225
#define UI_SEP_CHAR
Definition: UI_interface.h:86
bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid, int state, const uint8_t name_prefix_offset)
void UI_but_func_search_set(uiBut *but, uiButSearchCreateFn search_create_fn, uiButSearchUpdateFn search_update_fn, void *arg, const bool free_arg, uiButSearchArgFreeFn search_arg_free_fn, uiButHandleFunc search_exec_fn, void *active)
Definition: interface.c:6613
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
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.c:5927
void UI_but_func_search_set_results_are_suggestions(uiBut *but, const bool value)
Definition: interface.c:6699
void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string)
Definition: interface.c:6683
#define UI_UNIT_X
@ UI_BTYPE_SEARCH_MENU
Definition: UI_interface.h:376
bool contains(const Key &key) const
Definition: BLI_set.hh:310
OperationNode * node
#define str(s)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static StringRef attribute_domain_string(const AttributeDomain domain)
BLI_STATIC_ASSERT(std::is_trivially_destructible_v< AttributeSearchData >, "")
static void attribute_search_update_fn(const bContext *UNUSED(C), void *arg, const char *str, uiSearchItems *items, const bool is_first)
static bool attribute_search_item_add(uiSearchItems *items, const AvailableAttributeInfo &item)
static StringRef attribute_data_type_string(const CustomDataType type)
void node_geometry_add_attribute_search_button(const bContext *C, const bNodeTree *node_tree, const bNode *node, PointerRNA *socket_ptr, uiLayout *layout)
static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)
bool RNA_enum_name_from_value(const EnumPropertyItem *item, int value, const char **r_name)
Definition: rna_access.c:6504
const EnumPropertyItem rna_enum_attribute_domain_items[]
Definition: rna_attribute.c:52
const EnumPropertyItem rna_enum_attribute_type_items[]
Definition: rna_attribute.c:40
AvailableAttributeInfo & dummy_info_for_search
AvailableAttributeInfo dummy_info_for_search
void * data
Definition: RNA_types.h:52
void * default_value