Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_node_ui_storage.hh18
-rw-r--r--source/blender/blenkernel/intern/node_ui_storage.cc4
-rw-r--r--source/blender/editors/include/UI_interface.h1
-rw-r--r--source/blender/editors/interface/interface.c16
-rw-r--r--source/blender/editors/interface/interface_layout.c1
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.c1
-rw-r--r--source/blender/editors/interface/interface_template_search_operator.c1
-rw-r--r--source/blender/editors/interface/interface_templates.c1
-rw-r--r--source/blender/editors/space_node/node_geometry_attribute_search.cc99
-rw-r--r--source/blender/editors/space_node/node_select.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c10
11 files changed, 109 insertions, 46 deletions
diff --git a/source/blender/blenkernel/BKE_node_ui_storage.hh b/source/blender/blenkernel/BKE_node_ui_storage.hh
index aa7e5180b03..5f9c039ef9e 100644
--- a/source/blender/blenkernel/BKE_node_ui_storage.hh
+++ b/source/blender/blenkernel/BKE_node_ui_storage.hh
@@ -20,7 +20,6 @@
#include "BLI_hash.hh"
#include "BLI_map.hh"
-#include "BLI_multi_value_map.hh"
#include "BLI_session_uuid.h"
#include "BLI_set.hh"
@@ -80,30 +79,37 @@ struct NodeWarning {
};
struct AvailableAttributeInfo {
+ std::string name;
AttributeDomain domain;
CustomDataType data_type;
uint64_t hash() const
{
- uint64_t domain_hash = (uint64_t)domain;
- uint64_t data_type_hash = (uint64_t)data_type;
- return (domain_hash * 33) ^ (data_type_hash * 89);
+ return blender::get_default_hash(name);
}
friend bool operator==(const AvailableAttributeInfo &a, const AvailableAttributeInfo &b)
{
- return a.domain == b.domain && a.data_type == b.data_type;
+ return a.name == b.name;
}
};
struct NodeUIStorage {
blender::Vector<NodeWarning> warnings;
- blender::MultiValueMap<std::string, AvailableAttributeInfo> attribute_hints;
+ blender::Set<AvailableAttributeInfo> attribute_hints;
};
struct NodeTreeUIStorage {
blender::Map<NodeTreeEvaluationContext, blender::Map<std::string, NodeUIStorage>> context_map;
std::mutex context_map_mutex;
+
+ /**
+ * Attribute search uses this to store the fake info for the string typed into a node, in order
+ * to pass the info to the execute callback that sets node socket values. This is mutable since
+ * we can count on only one attribute search being open at a time, and there is no real data
+ * stored here.
+ */
+ mutable AvailableAttributeInfo dummy_info_for_search;
};
const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C,
diff --git a/source/blender/blenkernel/intern/node_ui_storage.cc b/source/blender/blenkernel/intern/node_ui_storage.cc
index f2a152ac00d..cc910bab6ac 100644
--- a/source/blender/blenkernel/intern/node_ui_storage.cc
+++ b/source/blender/blenkernel/intern/node_ui_storage.cc
@@ -163,6 +163,6 @@ void BKE_nodetree_attribute_hint_add(bNodeTree &ntree,
const CustomDataType data_type)
{
NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ntree, context, node);
- node_ui_storage.attribute_hints.add_as(attribute_name,
- AvailableAttributeInfo{domain, data_type});
+ node_ui_storage.attribute_hints.add_as(
+ AvailableAttributeInfo{attribute_name, domain, data_type});
}
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index dfe0898a85b..7a189139358 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1600,6 +1600,7 @@ 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);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 3c0f0587741..90d604b3190 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -6602,6 +6602,8 @@ uiBut *uiDefSearchBut(uiBlock *block,
* \param search_create_fn: Function to create the menu.
* \param search_update_fn: Function to refresh search content after the search text has changed.
* \param arg: user value.
+ * \param free_arg: Set to true if the argument is newly allocated memory for every redraw and
+ * should be freed when the button is destroyed.
* \param search_arg_free_fn: When non-null, use this function to free \a arg.
* \param search_exec_fn: Function that executes the action, gets \a arg as the first argument.
* The second argument as the active item-pointer
@@ -6612,6 +6614,7 @@ 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)
@@ -6647,11 +6650,17 @@ void UI_but_func_search_set(uiBut *but,
}
#endif
/* Handling will pass the active item as arg2 later, so keep it NULL here. */
- UI_but_func_set(but, search_exec_fn, search_but->arg, NULL);
+ if (free_arg) {
+ UI_but_funcN_set(but, search_exec_fn, search_but->arg, NULL);
+ }
+ else {
+ UI_but_func_set(but, search_exec_fn, search_but->arg, NULL);
+ }
}
- /* search buttons show red-alert if item doesn't exist, not for menus */
- if (0 == (but->block->flag & UI_BLOCK_LOOP)) {
+ /* search buttons show red-alert if item doesn't exist, not for menus. Don't do this for
+ * buttons where any result is valid anyway, since any string will be valid anyway. */
+ if (0 == (but->block->flag & UI_BLOCK_LOOP) && !search_but->results_are_suggestions) {
/* skip empty buttons, not all buttons need input, we only show invalid */
if (but->drawstr[0]) {
ui_but_search_refresh(search_but);
@@ -6791,6 +6800,7 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block,
ui_searchbox_create_generic,
operator_enum_search_update_fn,
but,
+ false,
NULL,
operator_enum_search_exec_fn,
NULL);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 4430d00f2e3..cabd98902a6 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -2718,6 +2718,7 @@ uiBut *ui_but_add_search(
ui_searchbox_create_generic,
ui_rna_collection_search_update_fn,
coll_search,
+ false,
ui_rna_collection_search_arg_free_fn,
NULL,
NULL);
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c
index df19bdb650e..91ad6619889 100644
--- a/source/blender/editors/interface/interface_template_search_menu.c
+++ b/source/blender/editors/interface/interface_template_search_menu.c
@@ -1148,6 +1148,7 @@ void UI_but_func_menu_search(uiBut *but)
ui_searchbox_create_menu,
menu_search_update_fn,
data,
+ false,
menu_search_arg_free_fn,
menu_search_exec_fn,
NULL);
diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c
index 2c83f184ff0..2b765a1a2f5 100644
--- a/source/blender/editors/interface/interface_template_search_operator.c
+++ b/source/blender/editors/interface/interface_template_search_operator.c
@@ -121,6 +121,7 @@ void UI_but_func_operator_search(uiBut *but)
operator_search_update_fn,
NULL,
false,
+ NULL,
operator_search_exec_fn,
NULL);
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 2d1663a3ecd..760fbe75688 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -309,6 +309,7 @@ static uiBlock *template_common_search_menu(const bContext *C,
ui_searchbox_create_generic,
search_update_fn,
search_arg,
+ false,
NULL,
search_exec_fn,
active_item);
diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc
index 6d0cd254505..87944842079 100644
--- a/source/blender/editors/space_node/node_geometry_attribute_search.cc
+++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc
@@ -30,6 +30,11 @@
#include "BKE_node_ui_storage.hh"
#include "BKE_object.h"
+#include "RNA_access.h"
+#include "RNA_enum_types.h"
+
+#include "BLT_translation.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
@@ -37,44 +42,77 @@
using blender::IndexRange;
using blender::Map;
-using blender::MultiValueMap;
using blender::Set;
using blender::StringRef;
struct AttributeSearchData {
const bNodeTree &node_tree;
const bNode &node;
+ bNodeSocket &socket;
+};
- uiBut *search_button;
+/* This class must not have a destructor, since it is used by buttons and freed with #MEM_freeN. */
+BLI_STATIC_ASSERT(std::is_trivially_destructible_v<AttributeSearchData>, "");
- /* Used to keep track of a button pointer over multiple redraws. Since the UI code
- * may reallocate the button, without this we might end up with a dangling pointer. */
- uiButStore *button_store;
- uiBlock *button_store_block;
-};
+static StringRef attribute_data_type_string(const CustomDataType type)
+{
+ const char *name = nullptr;
+ RNA_enum_name_from_value(rna_enum_attribute_type_items, type, &name);
+ return StringRef(IFACE_(name));
+}
+
+static StringRef attribute_domain_string(const AttributeDomain domain)
+{
+ const char *name = nullptr;
+ RNA_enum_name_from_value(rna_enum_attribute_domain_items, domain, &name);
+ return StringRef(IFACE_(name));
+}
+
+/* Unicode arrow. */
+#define MENU_SEP "\xe2\x96\xb6"
+
+static bool attribute_search_item_add(uiSearchItems *items, const AvailableAttributeInfo &item)
+{
+ const StringRef data_type_name = attribute_data_type_string(item.data_type);
+ const StringRef domain_name = attribute_domain_string(item.domain);
+ std::string search_item_text = domain_name + " " + MENU_SEP + item.name + UI_SEP_CHAR +
+ data_type_name;
+
+ return UI_search_item_add(
+ items, search_item_text.c_str(), (void *)&item, ICON_NONE, UI_BUT_HAS_SEP_CHAR, 0);
+}
static void attribute_search_update_fn(
const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
{
AttributeSearchData *data = static_cast<AttributeSearchData *>(arg);
+ NodeTreeUIStorage *tree_ui_storage = data->node_tree.ui_storage;
+ if (tree_ui_storage == nullptr) {
+ return;
+ }
const NodeUIStorage *ui_storage = BKE_node_tree_ui_storage_get_from_context(
C, data->node_tree, data->node);
if (ui_storage == nullptr) {
return;
}
- const MultiValueMap<std::string, AvailableAttributeInfo> &attribute_hints =
- ui_storage->attribute_hints;
+ const Set<AvailableAttributeInfo> &attribute_hints = ui_storage->attribute_hints;
- if (str[0] != '\0' && attribute_hints.lookup_as(StringRef(str)).is_empty()) {
- /* Any string may be valid, so add the current search string with the hints. */
- UI_search_item_add(items, str, (void *)str, ICON_ADD, 0, 0);
+ /* Any string may be valid, so add the current search string along with the hints. */
+ if (str[0] != '\0') {
+ /* Note that the attribute domain and data type are dummies, since
+ * #AvailableAttributeInfo equality is only based on the string. */
+ if (!attribute_hints.contains(AvailableAttributeInfo{str, ATTR_DOMAIN_AUTO, CD_PROP_BOOL})) {
+ tree_ui_storage->dummy_info_for_search.name = std::string(str);
+ UI_search_item_add(items, str, &tree_ui_storage->dummy_info_for_search, ICON_ADD, 0, 0);
+ }
}
if (str[0] == '\0' && !is_first) {
/* Allow clearing the text field when the string is empty, but not on the first pass,
* or opening an attribute field for the first time would show this search item. */
- UI_search_item_add(items, str, (void *)str, ICON_X, 0, 0);
+ tree_ui_storage->dummy_info_for_search.name = std::string(str);
+ UI_search_item_add(items, str, &tree_ui_storage->dummy_info_for_search, ICON_X, 0, 0);
}
/* Don't filter when the menu is first opened, but still run the search
@@ -82,16 +120,16 @@ static void attribute_search_update_fn(
const char *string = is_first ? "" : str;
StringSearch *search = BLI_string_search_new();
- for (const std::string &attribute_name : attribute_hints.keys()) {
- BLI_string_search_add(search, attribute_name.c_str(), (void *)&attribute_name);
+ for (const AvailableAttributeInfo &item : attribute_hints) {
+ BLI_string_search_add(search, item.name.c_str(), (void *)&item);
}
- std::string **filtered_items;
+ AvailableAttributeInfo **filtered_items;
const int filtered_amount = BLI_string_search_query(search, string, (void ***)&filtered_items);
for (const int i : IndexRange(filtered_amount)) {
- std::string *item = filtered_items[i];
- if (!UI_search_item_add(items, item->c_str(), item, ICON_NONE, 0, 0)) {
+ const AvailableAttributeInfo *item = filtered_items[i];
+ if (!attribute_search_item_add(items, *item)) {
break;
}
}
@@ -100,12 +138,14 @@ static void attribute_search_update_fn(
BLI_string_search_free(search);
}
-static void attribute_search_free_fn(void *arg)
+static void attribute_search_exec_fn(bContext *UNUSED(C), void *data_v, void *item_v)
{
- AttributeSearchData *data = static_cast<AttributeSearchData *>(arg);
+ AttributeSearchData *data = static_cast<AttributeSearchData *>(data_v);
+ AvailableAttributeInfo *item = static_cast<AvailableAttributeInfo *>(item_v);
- UI_butstore_free(data->button_store_block, data->button_store);
- delete data;
+ bNodeSocket &socket = data->socket;
+ bNodeSocketValueString *value = static_cast<bNodeSocketValueString *>(socket.default_value);
+ BLI_strncpy(value->value, item->name.c_str(), MAX_NAME);
}
void node_geometry_add_attribute_search_button(const bNodeTree *node_tree,
@@ -132,22 +172,17 @@ void node_geometry_add_attribute_search_button(const bNodeTree *node_tree,
0.0f,
"");
- AttributeSearchData *data = new AttributeSearchData{
- *node_tree,
- *node,
- but,
- UI_butstore_create(block),
- block,
- };
-
- UI_butstore_register(data->button_store, &data->search_button);
+ AttributeSearchData *data = OBJECT_GUARDED_NEW(
+ AttributeSearchData, {*node_tree, *node, *static_cast<bNodeSocket *>(socket_ptr->data)});
UI_but_func_search_set_results_are_suggestions(but, true);
+ UI_but_func_search_set_sep_string(but, MENU_SEP);
UI_but_func_search_set(but,
nullptr,
attribute_search_update_fn,
static_cast<void *>(data),
- attribute_search_free_fn,
+ true,
nullptr,
+ attribute_search_exec_fn,
nullptr);
}
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index 6548f6f5775..de63aa07acb 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -1260,7 +1260,8 @@ static uiBlock *node_find_menu(bContext *C, ARegion *region, void *arg_op)
0,
0,
"");
- UI_but_func_search_set(but, NULL, node_find_update_fn, op->type, NULL, node_find_exec_fn, NULL);
+ UI_but_func_search_set(
+ but, NULL, node_find_update_fn, op->type, false, NULL, node_find_exec_fn, NULL);
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
/* fake button, it holds space for search items */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 4159074df9c..c7b46cd640b 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -598,8 +598,14 @@ static uiBlock *merged_element_search_menu(bContext *C, ARegion *region, void *d
short menu_width = 10 * UI_UNIT_X;
but = uiDefSearchBut(
block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, menu_width, UI_UNIT_Y, 0, 0, "");
- UI_but_func_search_set(
- but, NULL, merged_element_search_update_fn, data, NULL, merged_element_search_exec_fn, NULL);
+ UI_but_func_search_set(but,
+ NULL,
+ merged_element_search_update_fn,
+ data,
+ NULL,
+ false,
+ merged_element_search_exec_fn,
+ NULL);
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
/* Fake button to hold space for search items */