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:
authorHans Goudey <h.goudey@me.com>2021-10-21 21:54:48 +0300
committerHans Goudey <h.goudey@me.com>2021-10-21 21:54:48 +0300
commit1d96a482675dd2ccad2af31c274f74b9f6603d6b (patch)
treebeb0406f7a9f1e6b826cc590eeab69e361a83b3b /source/blender/editors
parent65490e62708c6bb0c03d9c73fd7179fdf71355a5 (diff)
Geometry Nodes: Attribute search in the modifier
This adds attribute search to the geometry nodes modifier for the input and output attributes. The "New" search item is only shown for the output attributes. Some of the attribute search code is extracted to a new file in the interface code, to avoid some code duplication. The UI code required two fixes so that the search would work for dynamic length strings (IDProperties do not have a fixed size). Since this does changes to the UI layout of the modifier, I also addressed T91485 here. Differential Revisiion: https://developer.blender.org/D12788
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/include/UI_interface.hh14
-rw-r--r--source/blender/editors/interface/CMakeLists.txt3
-rw-r--r--source/blender/editors/interface/interface_region_search.c11
-rw-r--r--source/blender/editors/interface/interface_template_attribute_search.cc125
-rw-r--r--source/blender/editors/space_node/node_geometry_attribute_search.cc78
5 files changed, 151 insertions, 80 deletions
diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh
index 4a583d0225e..5edccfa8c88 100644
--- a/source/blender/editors/include/UI_interface.hh
+++ b/source/blender/editors/include/UI_interface.hh
@@ -24,10 +24,22 @@
#include "BLI_string_ref.hh"
+namespace blender::nodes::geometry_nodes_eval_log {
+struct GeometryAttributeInfo;
+}
+
struct uiBlock;
namespace blender::ui {
class AbstractTreeView;
-}
+
+void attribute_search_add_items(
+ StringRefNull str,
+ const bool is_output,
+ Span<const nodes::geometry_nodes_eval_log::GeometryAttributeInfo *> infos,
+ uiSearchItems *items,
+ const bool is_first);
+
+} // namespace blender::ui
blender::ui::AbstractTreeView *UI_block_add_view(
uiBlock &block,
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 8fcc704a301..b2659f5ed52 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -25,9 +25,11 @@ set(INC
../../depsgraph
../../draw
../../gpu
+ ../../functions
../../imbuf
../../makesdna
../../makesrna
+ ../../nodes
../../python
../../render
../../windowmanager
@@ -69,6 +71,7 @@ set(SRC
interface_style.c
interface_template_asset_view.cc
interface_template_list.cc
+ interface_template_attribute_search.cc
interface_template_search_menu.c
interface_template_search_operator.c
interface_templates.c
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index 1cd3ef89ed3..5bea03dee63 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -316,7 +316,11 @@ bool ui_searchbox_apply(uiBut *but, ARegion *region)
const char *name_sep = data->use_shortcut_sep ? strrchr(name, UI_SEP_CHAR) : NULL;
- BLI_strncpy(but->editstr, name, name_sep ? (name_sep - name) + 1 : data->items.maxstrlen);
+ /* Search button with dynamic string properties may have their own method of applying
+ * the search results, so only copy the result if there is a proper space for it. */
+ if (but->hardmax != 0) {
+ BLI_strncpy(but->editstr, name, name_sep ? (name_sep - name) + 1 : data->items.maxstrlen);
+ }
search_but->item_active = data->items.pointers[data->active];
@@ -878,7 +882,8 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C,
else {
data->items.maxitem = SEARCH_ITEMS;
}
- data->items.maxstrlen = but->hardmax;
+ /* In case the button's string is dynamic, make sure there are buffers available. */
+ data->items.maxstrlen = but->hardmax == 0 ? UI_MAX_NAME_STR : but->hardmax;
data->items.totitem = 0;
data->items.names = MEM_callocN(data->items.maxitem * sizeof(void *), "search names");
data->items.pointers = MEM_callocN(data->items.maxitem * sizeof(void *), "search pointers");
@@ -886,7 +891,7 @@ static ARegion *ui_searchbox_create_generic_ex(bContext *C,
data->items.states = MEM_callocN(data->items.maxitem * sizeof(int), "search flags");
data->items.name_prefix_offsets = NULL; /* Lazy initialized as needed. */
for (int i = 0; i < data->items.maxitem; i++) {
- data->items.names[i] = MEM_callocN(but->hardmax + 1, "search pointers");
+ data->items.names[i] = MEM_callocN(data->items.maxstrlen + 1, "search pointers");
}
return region;
diff --git a/source/blender/editors/interface/interface_template_attribute_search.cc b/source/blender/editors/interface/interface_template_attribute_search.cc
new file mode 100644
index 00000000000..0157d0b66a3
--- /dev/null
+++ b/source/blender/editors/interface/interface_template_attribute_search.cc
@@ -0,0 +1,125 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edinterface
+ */
+
+#include "BLI_string_ref.hh"
+#include "BLI_string_search.h"
+
+#include "DNA_customdata_types.h"
+
+#include "RNA_access.h"
+#include "RNA_enum_types.h"
+
+#include "BLT_translation.h"
+
+#include "NOD_geometry_nodes_eval_log.hh"
+
+#include "UI_interface.h"
+#include "UI_interface.hh"
+#include "UI_resources.h"
+
+using blender::nodes::geometry_nodes_eval_log::GeometryAttributeInfo;
+
+namespace blender::ui {
+
+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));
+}
+
+static bool attribute_search_item_add(uiSearchItems *items, const GeometryAttributeInfo &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 + " " + UI_MENU_ARROW_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);
+}
+
+void attribute_search_add_items(StringRefNull str,
+ const bool is_output,
+ Span<const GeometryAttributeInfo *> infos,
+ uiSearchItems *seach_items,
+ const bool is_first)
+{
+ static GeometryAttributeInfo dummy_info;
+
+ /* Any string may be valid, so add the current search string along with the hints. */
+ if (str[0] != '\0') {
+ bool contained = false;
+ for (const GeometryAttributeInfo *attribute_info : infos) {
+ if (attribute_info->name == str) {
+ contained = true;
+ break;
+ }
+ }
+ if (!contained && is_output) {
+ dummy_info.name = str;
+ UI_search_item_add(seach_items, str.c_str(), &dummy_info, 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. */
+ dummy_info.name = str;
+ UI_search_item_add(seach_items, str.c_str(), &dummy_info, ICON_X, 0, 0);
+ }
+
+ /* Don't filter when the menu is first opened, but still run the search
+ * so the items are in the same order they will appear in while searching. */
+ const char *string = is_first ? "" : str.c_str();
+
+ StringSearch *search = BLI_string_search_new();
+ for (const GeometryAttributeInfo *item : infos) {
+
+ /* Don't show the legacy "normal" attribute. */
+ if (item->name == "normal" && item->domain == ATTR_DOMAIN_FACE) {
+ continue;
+ }
+
+ BLI_string_search_add(search, item->name.c_str(), (void *)item);
+ }
+
+ GeometryAttributeInfo **filtered_items;
+ const int filtered_amount = BLI_string_search_query(search, string, (void ***)&filtered_items);
+
+ for (const int i : IndexRange(filtered_amount)) {
+ const GeometryAttributeInfo *item = filtered_items[i];
+ if (!attribute_search_item_add(seach_items, *item)) {
+ break;
+ }
+ }
+
+ MEM_freeN(filtered_items);
+ BLI_string_search_free(search);
+}
+
+} // namespace blender::ui \ No newline at end of file
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 a69109db69c..d0ccbb03107 100644
--- a/source/blender/editors/space_node/node_geometry_attribute_search.cc
+++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc
@@ -38,6 +38,7 @@
#include "BLT_translation.h"
#include "UI_interface.h"
+#include "UI_interface.hh"
#include "UI_resources.h"
#include "NOD_geometry_nodes_eval_log.hh"
@@ -60,37 +61,6 @@ struct AttributeSearchData {
/* 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>, "");
-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));
-}
-
-static bool attribute_search_item_add(uiSearchItems *items, const GeometryAttributeInfo &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 + " " + UI_MENU_ARROW_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 GeometryAttributeInfo &get_dummy_item_info()
-{
- static GeometryAttributeInfo info;
- return info;
-}
-
static void attribute_search_update_fn(
const bContext *C, void *arg, const char *str, uiSearchItems *items, const bool is_first)
{
@@ -104,51 +74,7 @@ static void attribute_search_update_fn(
}
blender::Vector<const GeometryAttributeInfo *> infos = node_log->lookup_available_attributes();
- GeometryAttributeInfo &dummy_info = get_dummy_item_info();
-
- /* Any string may be valid, so add the current search string along with the hints. */
- if (str[0] != '\0') {
- bool contained = false;
- for (const GeometryAttributeInfo *attribute_info : infos) {
- if (attribute_info->name == str) {
- contained = true;
- break;
- }
- }
- if (!contained) {
- dummy_info.name = str;
- UI_search_item_add(items, str, &dummy_info, 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. */
- dummy_info.name = str;
- UI_search_item_add(items, str, &dummy_info, ICON_X, 0, 0);
- }
-
- /* Don't filter when the menu is first opened, but still run the search
- * so the items are in the same order they will appear in while searching. */
- const char *string = is_first ? "" : str;
-
- StringSearch *search = BLI_string_search_new();
- for (const GeometryAttributeInfo *item : infos) {
- BLI_string_search_add(search, item->name.c_str(), (void *)item);
- }
-
- GeometryAttributeInfo **filtered_items;
- const int filtered_amount = BLI_string_search_query(search, string, (void ***)&filtered_items);
-
- for (const int i : IndexRange(filtered_amount)) {
- const GeometryAttributeInfo *item = filtered_items[i];
- if (!attribute_search_item_add(items, *item)) {
- break;
- }
- }
-
- MEM_freeN(filtered_items);
- BLI_string_search_free(search);
+ blender::ui::attribute_search_add_items(str, true, infos, items, is_first);
}
static void attribute_search_exec_fn(bContext *C, void *data_v, void *item_v)