Files
test2/source/blender/editors/interface/interface_template_attribute_search.cc
Hans Goudey 19001c9e6c Cleanup: Move attribute domain enum to C++ header, use enum class
Each value is now out of the global namespace, so they can be shorter
and easier to read. Most of this commit just adds the necessary casting
and namespace specification. `enum class` can be forward declared since
it has a specified size. We will make use of that in the next commit.
2023-12-20 13:25:28 -05:00

112 lines
3.4 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edinterface
*/
#include "BLI_string_ref.hh"
#include "DNA_customdata_types.h"
#include "RNA_access.hh"
#include "RNA_enum_types.hh"
#include "BLT_translation.h"
#include "BKE_attribute.hh"
#include "NOD_geometry_nodes_log.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
#include "UI_string_search.hh"
using blender::nodes::geo_eval_log::GeometryAttributeInfo;
namespace blender::ui {
static StringRef attribute_data_type_string(const eCustomDataType 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 bke::AttrDomain domain)
{
const char *name = nullptr;
RNA_enum_name_from_value(rna_enum_attribute_domain_items, int(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 can_create_attribute,
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) {
dummy_info.name = str;
UI_search_item_add(seach_items,
str.c_str(),
&dummy_info,
can_create_attribute ? ICON_ADD : ICON_NONE,
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();
ui::string_search::StringSearch<const GeometryAttributeInfo> search;
for (const GeometryAttributeInfo *item : infos) {
if (!bke::allow_procedural_attribute_access(item->name)) {
continue;
}
search.add(item->name, item);
}
const Vector<const GeometryAttributeInfo *> filtered_items = search.query(string);
for (const GeometryAttributeInfo *item : filtered_items) {
if (!attribute_search_item_add(seach_items, *item)) {
break;
}
}
}
} // namespace blender::ui